slicejs-cli 3.3.0 → 3.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +247 -0
- package/LICENSE +21 -21
- package/client.js +663 -626
- package/commands/Print.js +163 -167
- package/commands/Validations.js +92 -103
- package/commands/build/build.js +40 -40
- package/commands/buildProduction/buildProduction.js +576 -579
- package/commands/bundle/bundle.js +234 -235
- package/commands/createComponent/VisualComponentTemplate.js +55 -55
- package/commands/createComponent/createComponent.js +124 -126
- package/commands/deleteComponent/deleteComponent.js +77 -77
- package/commands/doctor/doctor.js +366 -369
- package/commands/getComponent/getComponent.js +684 -747
- package/commands/init/init.js +269 -261
- package/commands/listComponents/listComponents.js +172 -175
- package/commands/startServer/startServer.js +261 -264
- package/commands/startServer/watchServer.js +79 -79
- package/commands/types/types.js +69 -27
- package/commands/utils/LocalCliDelegation.js +53 -53
- package/commands/utils/PathHelper.js +75 -68
- package/commands/utils/VersionChecker.js +167 -167
- package/commands/utils/bundling/BundleGenerator.js +2292 -2292
- package/commands/utils/bundling/DependencyAnalyzer.js +925 -933
- package/commands/utils/loadConfig.js +31 -0
- package/commands/utils/updateManager.js +452 -453
- package/docs/superpowers/specs/2026-05-10-pwa-generate-design.md +105 -105
- package/package.json +58 -46
- package/post.js +66 -65
- package/tests/bundle-generator.test.js +691 -708
- package/tests/bundle-v2-register-output.test.js +470 -470
- package/tests/client-launcher-contract.test.js +211 -211
- package/tests/client-update-flow-contract.test.js +272 -272
- package/tests/component-registry-parse.test.js +34 -0
- package/tests/dependency-analyzer.test.js +24 -24
- package/tests/fixtures/components.js +8 -0
- package/tests/fixtures/sliceConfig.json +74 -0
- package/tests/getcomponent.test.js +407 -0
- package/tests/helpers/setup.js +97 -0
- package/tests/init-command-contract.test.js +46 -0
- package/tests/local-cli-delegation.test.js +81 -79
- package/tests/path-helper.test.js +206 -0
- package/tests/types-breakage.test.js +491 -0
- package/tests/types-generator-errors.test.js +361 -0
- package/tests/types-generator.test.js +172 -184
- package/tests/update-manager-notifications.test.js +88 -88
- package/.github/workflows/docs-render-cicd.yml +0 -65
package/commands/init/init.js
CHANGED
|
@@ -1,261 +1,269 @@
|
|
|
1
|
-
import fs from 'fs-extra';
|
|
2
|
-
import path from 'path';
|
|
3
|
-
import { fileURLToPath } from 'url';
|
|
4
|
-
import ora from 'ora';
|
|
5
|
-
import Print from '../Print.js';
|
|
6
|
-
import { getProjectRoot, getApiPath, getSrcPath } from '../utils/PathHelper.js';
|
|
7
|
-
import { execSync } from 'child_process';
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
await fs.
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
pkg.scripts
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
pkg.scripts['
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
pkg.scripts['
|
|
207
|
-
pkg.scripts['
|
|
208
|
-
pkg.scripts['
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
pkg.scripts['
|
|
212
|
-
pkg.scripts['
|
|
213
|
-
pkg.scripts['
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
pkg.
|
|
218
|
-
pkg.
|
|
219
|
-
|
|
220
|
-
//
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
1
|
+
import fs from 'fs-extra';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import { fileURLToPath } from 'url';
|
|
4
|
+
import ora from 'ora';
|
|
5
|
+
import Print from '../Print.js';
|
|
6
|
+
import { getProjectRoot, getApiPath, getSrcPath, getPath } from '../utils/PathHelper.js';
|
|
7
|
+
import { execSync } from 'child_process';
|
|
8
|
+
|
|
9
|
+
// Import ComponentRegistry class from getComponent
|
|
10
|
+
import { ComponentRegistry } from '../getComponent/getComponent.js';
|
|
11
|
+
|
|
12
|
+
// Visual components used by the App Shell + MultiRoute starter project.
|
|
13
|
+
// We install only these on init; newcomers add more on demand with `slice get <Name>`.
|
|
14
|
+
const STARTER_VISUAL_COMPONENTS = [
|
|
15
|
+
'Button',
|
|
16
|
+
'Link',
|
|
17
|
+
'Loading',
|
|
18
|
+
'MultiRoute',
|
|
19
|
+
'Navbar',
|
|
20
|
+
'NotFound',
|
|
21
|
+
'Route'
|
|
22
|
+
];
|
|
23
|
+
|
|
24
|
+
export default async function initializeProject(projectType) {
|
|
25
|
+
try {
|
|
26
|
+
const projectRoot = getProjectRoot(import.meta.url);
|
|
27
|
+
const destinationApi = getApiPath(import.meta.url);
|
|
28
|
+
const destinationSrc = getSrcPath(import.meta.url);
|
|
29
|
+
|
|
30
|
+
const fwSpinner = ora('Ensuring latest Slice framework...').start();
|
|
31
|
+
let latestVersion = null;
|
|
32
|
+
let sliceBaseDir;
|
|
33
|
+
try {
|
|
34
|
+
const latest = execSync('npm view slicejs-web-framework version', { cwd: projectRoot }).toString().trim();
|
|
35
|
+
latestVersion = latest;
|
|
36
|
+
const installedPkgPath = getPath(import.meta.url, 'node_modules', 'slicejs-web-framework', 'package.json');
|
|
37
|
+
let installed = null;
|
|
38
|
+
if (await fs.pathExists(installedPkgPath)) {
|
|
39
|
+
const pkg = await fs.readJson(installedPkgPath);
|
|
40
|
+
installed = pkg.version;
|
|
41
|
+
}
|
|
42
|
+
if (installed !== latest) {
|
|
43
|
+
execSync(`npm install slicejs-web-framework@${latest} --save`, { cwd: projectRoot, stdio: 'inherit' });
|
|
44
|
+
}
|
|
45
|
+
sliceBaseDir = getPath(import.meta.url, 'node_modules', 'slicejs-web-framework');
|
|
46
|
+
fwSpinner.succeed(`slicejs-web-framework@${latest} ready`);
|
|
47
|
+
} catch (err) {
|
|
48
|
+
// Fallback uses __dirname-style path because it looks for a local development copy,
|
|
49
|
+
// not a project-relative path — npm install failed, so we fall back to monorepo sibling.
|
|
50
|
+
const fallback = path.join(path.dirname(fileURLToPath(import.meta.url)), '../../../slicejs-web-framework');
|
|
51
|
+
if (await fs.pathExists(fallback)) {
|
|
52
|
+
sliceBaseDir = fallback;
|
|
53
|
+
fwSpinner.warn('Using local slicejs-web-framework fallback');
|
|
54
|
+
} else {
|
|
55
|
+
fwSpinner.fail('Failed to ensure latest slicejs-web-framework');
|
|
56
|
+
Print.error(err.message);
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// These derive from sliceBaseDir (which comes from npm install or fallback),
|
|
62
|
+
// so they're already dynamic — no PathHelper needed.
|
|
63
|
+
const apiDir = path.join(sliceBaseDir, 'api');
|
|
64
|
+
const srcDir = path.join(sliceBaseDir, 'src');
|
|
65
|
+
|
|
66
|
+
try {
|
|
67
|
+
if (fs.existsSync(destinationApi)) throw new Error(`The "api" directory already exists: ${destinationApi}`);
|
|
68
|
+
if (fs.existsSync(destinationSrc)) throw new Error(`The "src" directory already exists: ${destinationSrc}`);
|
|
69
|
+
} catch (error) {
|
|
70
|
+
Print.error('Validating destination directories:', error.message);
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// 1. COPY API FOLDER (keep original logic)
|
|
75
|
+
const apiSpinner = ora('Copying API structure...').start();
|
|
76
|
+
try {
|
|
77
|
+
if (!fs.existsSync(apiDir)) throw new Error(`API folder not found: ${apiDir}`);
|
|
78
|
+
await fs.copy(apiDir, destinationApi, { recursive: true });
|
|
79
|
+
apiSpinner.succeed('API structure created successfully');
|
|
80
|
+
} catch (error) {
|
|
81
|
+
apiSpinner.fail('Error copying API structure');
|
|
82
|
+
Print.error(error.message);
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// 2. CREATE BASIC SRC STRUCTURE (without copying Visual components)
|
|
87
|
+
const srcSpinner = ora('Creating src structure...').start();
|
|
88
|
+
try {
|
|
89
|
+
if (!fs.existsSync(srcDir)) throw new Error(`src folder not found: ${srcDir}`);
|
|
90
|
+
|
|
91
|
+
// Copy only base src files, excluding Components/Visual
|
|
92
|
+
await fs.ensureDir(destinationSrc);
|
|
93
|
+
|
|
94
|
+
// Copy src files and folders except Components/Visual
|
|
95
|
+
const srcItems = await fs.readdir(srcDir);
|
|
96
|
+
|
|
97
|
+
for (const item of srcItems) {
|
|
98
|
+
const srcItemPath = path.join(srcDir, item);
|
|
99
|
+
const destItemPath = path.join(destinationSrc, item);
|
|
100
|
+
const stat = await fs.stat(srcItemPath);
|
|
101
|
+
|
|
102
|
+
if (stat.isDirectory()) {
|
|
103
|
+
if (item === 'Components') {
|
|
104
|
+
// Create Components structure but without copying Visual
|
|
105
|
+
await fs.ensureDir(destItemPath);
|
|
106
|
+
|
|
107
|
+
const componentItems = await fs.readdir(srcItemPath);
|
|
108
|
+
for (const componentItem of componentItems) {
|
|
109
|
+
const componentItemPath = path.join(srcItemPath, componentItem);
|
|
110
|
+
const destComponentItemPath = path.join(destItemPath, componentItem);
|
|
111
|
+
|
|
112
|
+
if (componentItem !== 'Visual') {
|
|
113
|
+
// Copy Service and other component types
|
|
114
|
+
await fs.copy(componentItemPath, destComponentItemPath, { recursive: true });
|
|
115
|
+
} else {
|
|
116
|
+
// Only create empty Visual directory
|
|
117
|
+
await fs.ensureDir(destComponentItemPath);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
} else {
|
|
121
|
+
// Copy other folders normally
|
|
122
|
+
await fs.copy(srcItemPath, destItemPath, { recursive: true });
|
|
123
|
+
}
|
|
124
|
+
} else {
|
|
125
|
+
// Copy files normally
|
|
126
|
+
await fs.copy(srcItemPath, destItemPath);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
srcSpinner.succeed('Source structure created successfully');
|
|
131
|
+
} catch (error) {
|
|
132
|
+
srcSpinner.fail('Error creating source structure');
|
|
133
|
+
Print.error(error.message);
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// 3. DOWNLOAD ALL VISUAL COMPONENTS FROM OFFICIAL REPOSITORY
|
|
138
|
+
const componentsSpinner = ora('Loading component registry...').start();
|
|
139
|
+
try {
|
|
140
|
+
const registry = new ComponentRegistry();
|
|
141
|
+
await registry.loadRegistry();
|
|
142
|
+
|
|
143
|
+
// Install only the Visual components the starter project uses.
|
|
144
|
+
const allVisualComponents = STARTER_VISUAL_COMPONENTS;
|
|
145
|
+
Print.info(`Installing ${allVisualComponents.length} starter Visual components: ${allVisualComponents.join(', ')}`);
|
|
146
|
+
|
|
147
|
+
if (allVisualComponents.length > 0) {
|
|
148
|
+
componentsSpinner.text = `Installing ${allVisualComponents.length} starter Visual components...`;
|
|
149
|
+
|
|
150
|
+
const results = await registry.installMultipleComponents(
|
|
151
|
+
allVisualComponents,
|
|
152
|
+
'Visual',
|
|
153
|
+
true // force = true for initial installation
|
|
154
|
+
);
|
|
155
|
+
|
|
156
|
+
const successful = results.filter(r => r.success).length;
|
|
157
|
+
const failed = results.filter(r => !r.success).length;
|
|
158
|
+
|
|
159
|
+
if (successful > 0 && failed === 0) {
|
|
160
|
+
componentsSpinner.succeed(`All ${successful} Visual components installed successfully`);
|
|
161
|
+
} else if (successful > 0) {
|
|
162
|
+
componentsSpinner.warn(`${successful} components installed, ${failed} failed`);
|
|
163
|
+
Print.info('You can install failed components later using "slice get <component-name>"');
|
|
164
|
+
} else {
|
|
165
|
+
componentsSpinner.fail('Failed to install Visual components');
|
|
166
|
+
}
|
|
167
|
+
} else {
|
|
168
|
+
componentsSpinner.warn('No Visual components found in registry');
|
|
169
|
+
Print.info('You can add components later using "slice get <component-name>"');
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
} catch (error) {
|
|
173
|
+
componentsSpinner.fail('Could not download Visual components from official repository');
|
|
174
|
+
Print.error(`Repository error: ${error.message}`);
|
|
175
|
+
Print.info('Project initialized without Visual components');
|
|
176
|
+
Print.info('You can add them later using "slice get <component-name>"');
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
// 4. CONFIGURE SCRIPTS IN PROJECT package.json
|
|
180
|
+
const pkgSpinner = ora('Configuring npm scripts...').start();
|
|
181
|
+
try {
|
|
182
|
+
const projectRoot = getProjectRoot(import.meta.url);
|
|
183
|
+
const pkgPath = getPath(import.meta.url, 'package.json');
|
|
184
|
+
|
|
185
|
+
let pkg;
|
|
186
|
+
if (await fs.pathExists(pkgPath)) {
|
|
187
|
+
pkg = await fs.readJson(pkgPath);
|
|
188
|
+
} else {
|
|
189
|
+
pkg = {
|
|
190
|
+
name: path.basename(projectRoot),
|
|
191
|
+
version: '1.0.0',
|
|
192
|
+
description: 'Slice.js project',
|
|
193
|
+
main: 'api/index.js',
|
|
194
|
+
scripts: {}
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
pkg.scripts = pkg.scripts || {};
|
|
199
|
+
pkg.dependencies = pkg.dependencies || {};
|
|
200
|
+
|
|
201
|
+
// Comandos principales
|
|
202
|
+
pkg.scripts['dev'] = 'slice dev';
|
|
203
|
+
pkg.scripts['start'] = 'slice start';
|
|
204
|
+
|
|
205
|
+
// Component management
|
|
206
|
+
pkg.scripts['component:create'] = 'slice component create';
|
|
207
|
+
pkg.scripts['component:list'] = 'slice component list';
|
|
208
|
+
pkg.scripts['component:delete'] = 'slice component delete';
|
|
209
|
+
|
|
210
|
+
// Atajos de repositorio
|
|
211
|
+
pkg.scripts['get'] = 'slice get';
|
|
212
|
+
pkg.scripts['browse'] = 'slice browse';
|
|
213
|
+
pkg.scripts['sync'] = 'slice sync';
|
|
214
|
+
|
|
215
|
+
// Utilidades
|
|
216
|
+
pkg.scripts['slice:version'] = 'slice version';
|
|
217
|
+
pkg.scripts['slice:update'] = 'slice update';
|
|
218
|
+
pkg.scripts['slice:types'] = 'slice types generate';
|
|
219
|
+
|
|
220
|
+
// Legacy (compatibility)
|
|
221
|
+
pkg.scripts['slice:init'] = 'slice init';
|
|
222
|
+
pkg.scripts['slice:start'] = 'slice start';
|
|
223
|
+
pkg.scripts['slice:dev'] = 'slice dev';
|
|
224
|
+
pkg.scripts['slice:create'] = 'slice component create';
|
|
225
|
+
pkg.scripts['slice:list'] = 'slice component list';
|
|
226
|
+
pkg.scripts['slice:delete'] = 'slice component delete';
|
|
227
|
+
pkg.scripts['slice:get'] = 'slice get';
|
|
228
|
+
pkg.scripts['slice:browse'] = 'slice browse';
|
|
229
|
+
pkg.scripts['slice:sync'] = 'slice sync';
|
|
230
|
+
pkg.scripts['run'] = 'slice dev';
|
|
231
|
+
|
|
232
|
+
// Module configuration
|
|
233
|
+
pkg.type = 'module';
|
|
234
|
+
pkg.engines = pkg.engines || { node: '>=20.0.0' };
|
|
235
|
+
|
|
236
|
+
// Ensure framework dependency is present
|
|
237
|
+
if (!pkg.dependencies['slicejs-web-framework']) {
|
|
238
|
+
pkg.dependencies['slicejs-web-framework'] = latestVersion ? latestVersion : 'latest';
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
await fs.writeFile(pkgPath, JSON.stringify(pkg, null, 2), 'utf8');
|
|
242
|
+
pkgSpinner.succeed('npm scripts configured successfully');
|
|
243
|
+
|
|
244
|
+
Print.title('New recommended commands:');
|
|
245
|
+
console.log(' npm run dev - Start development server');
|
|
246
|
+
console.log(' npm run get - Install components');
|
|
247
|
+
console.log(' npm run browse - Browse components');
|
|
248
|
+
} catch (error) {
|
|
249
|
+
pkgSpinner.fail('Failed to configure npm scripts');
|
|
250
|
+
Print.error(error.message);
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
const projectName = path.basename(process.cwd());
|
|
254
|
+
Print.success(`Project initialized successfully in "${projectName}/"`);
|
|
255
|
+
Print.newLine();
|
|
256
|
+
Print.title('Next steps:');
|
|
257
|
+
console.log(` cd ${projectName}`);
|
|
258
|
+
console.log(' slice browse - View available components');
|
|
259
|
+
console.log(' slice get Button - Install specific components');
|
|
260
|
+
console.log(' slice sync - Update all components to latest versions');
|
|
261
|
+
|
|
262
|
+
} catch (error) {
|
|
263
|
+
Print.error('Unexpected error initializing project:', error.message);
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
// NOTE: `slice init` now installs only STARTER_VISUAL_COMPONENTS (see top of file).
|
|
268
|
+
// To install every registry component instead, iterate
|
|
269
|
+
// `Object.keys(registry.getAvailableComponents('Visual'))`.
|