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.
Files changed (46) hide show
  1. package/AGENTS.md +247 -0
  2. package/LICENSE +21 -21
  3. package/client.js +663 -626
  4. package/commands/Print.js +163 -167
  5. package/commands/Validations.js +92 -103
  6. package/commands/build/build.js +40 -40
  7. package/commands/buildProduction/buildProduction.js +576 -579
  8. package/commands/bundle/bundle.js +234 -235
  9. package/commands/createComponent/VisualComponentTemplate.js +55 -55
  10. package/commands/createComponent/createComponent.js +124 -126
  11. package/commands/deleteComponent/deleteComponent.js +77 -77
  12. package/commands/doctor/doctor.js +366 -369
  13. package/commands/getComponent/getComponent.js +684 -747
  14. package/commands/init/init.js +269 -261
  15. package/commands/listComponents/listComponents.js +172 -175
  16. package/commands/startServer/startServer.js +261 -264
  17. package/commands/startServer/watchServer.js +79 -79
  18. package/commands/types/types.js +69 -27
  19. package/commands/utils/LocalCliDelegation.js +53 -53
  20. package/commands/utils/PathHelper.js +75 -68
  21. package/commands/utils/VersionChecker.js +167 -167
  22. package/commands/utils/bundling/BundleGenerator.js +2292 -2292
  23. package/commands/utils/bundling/DependencyAnalyzer.js +925 -933
  24. package/commands/utils/loadConfig.js +31 -0
  25. package/commands/utils/updateManager.js +452 -453
  26. package/docs/superpowers/specs/2026-05-10-pwa-generate-design.md +105 -105
  27. package/package.json +58 -46
  28. package/post.js +66 -65
  29. package/tests/bundle-generator.test.js +691 -708
  30. package/tests/bundle-v2-register-output.test.js +470 -470
  31. package/tests/client-launcher-contract.test.js +211 -211
  32. package/tests/client-update-flow-contract.test.js +272 -272
  33. package/tests/component-registry-parse.test.js +34 -0
  34. package/tests/dependency-analyzer.test.js +24 -24
  35. package/tests/fixtures/components.js +8 -0
  36. package/tests/fixtures/sliceConfig.json +74 -0
  37. package/tests/getcomponent.test.js +407 -0
  38. package/tests/helpers/setup.js +97 -0
  39. package/tests/init-command-contract.test.js +46 -0
  40. package/tests/local-cli-delegation.test.js +81 -79
  41. package/tests/path-helper.test.js +206 -0
  42. package/tests/types-breakage.test.js +491 -0
  43. package/tests/types-generator-errors.test.js +361 -0
  44. package/tests/types-generator.test.js +172 -184
  45. package/tests/update-manager-notifications.test.js +88 -88
  46. package/.github/workflows/docs-render-cicd.yml +0 -65
@@ -1,211 +1,211 @@
1
- import { test } from 'node:test';
2
- import assert from 'node:assert/strict';
3
- import fs from 'node:fs';
4
- import path from 'node:path';
5
- import { fileURLToPath } from 'node:url';
6
- import { parse } from '@babel/parser';
7
- import babelTraverse from '@babel/traverse';
8
-
9
- const __dirname = path.dirname(fileURLToPath(import.meta.url));
10
- const clientPath = path.join(__dirname, '..', 'client.js');
11
- const source = fs.readFileSync(clientPath, 'utf-8');
12
- const ast = parse(source, {
13
- sourceType: 'module',
14
- plugins: []
15
- });
16
- const traverse = babelTraverse.default || babelTraverse;
17
-
18
- function walk(node, visit) {
19
- if (!node || typeof node !== 'object') {
20
- return;
21
- }
22
-
23
- visit(node);
24
-
25
- for (const value of Object.values(node)) {
26
- if (Array.isArray(value)) {
27
- for (const item of value) {
28
- walk(item, visit);
29
- }
30
- continue;
31
- }
32
-
33
- walk(value, visit);
34
- }
35
- }
36
-
37
- function getImportedBindings(fromSource) {
38
- const bindings = new Map();
39
-
40
- for (const statement of ast.program.body) {
41
- if (statement.type !== 'ImportDeclaration') {
42
- continue;
43
- }
44
-
45
- if (statement.source.value !== fromSource) {
46
- continue;
47
- }
48
-
49
- for (const specifier of statement.specifiers) {
50
- if (specifier.type === 'ImportSpecifier' && specifier.imported.type === 'Identifier') {
51
- bindings.set(specifier.imported.name, specifier.local.name);
52
- }
53
- }
54
- }
55
-
56
- return bindings;
57
- }
58
-
59
- function getBoundImportedCallPositions(fromSource, importedName) {
60
- const positions = [];
61
- const importedBindings = getImportedBindings(fromSource);
62
- const localName = importedBindings.get(importedName);
63
-
64
- if (!localName) {
65
- return positions;
66
- }
67
-
68
- traverse(ast, {
69
- CallExpression(callPath) {
70
- if (callPath.node.callee.type !== 'Identifier') {
71
- return;
72
- }
73
-
74
- if (callPath.node.callee.name !== localName) {
75
- return;
76
- }
77
-
78
- const binding = callPath.scope.getBinding(localName);
79
- if (!binding) {
80
- return;
81
- }
82
-
83
- if (binding.path.node.type !== 'ImportSpecifier') {
84
- return;
85
- }
86
-
87
- if (binding.path.parent.type !== 'ImportDeclaration') {
88
- return;
89
- }
90
-
91
- if (binding.path.parent.source.value !== fromSource) {
92
- return;
93
- }
94
-
95
- if (binding.path.node.imported.type !== 'Identifier') {
96
- return;
97
- }
98
-
99
- if (binding.path.node.imported.name !== importedName) {
100
- return;
101
- }
102
-
103
- positions.push(callPath.node.start);
104
- }
105
- });
106
-
107
- return positions;
108
- }
109
-
110
- function getCommandRegistrationPositions() {
111
- const positions = [];
112
-
113
- walk(ast.program, (node) => {
114
- if (node.type !== 'CallExpression') {
115
- return;
116
- }
117
-
118
- if (
119
- node.callee.type === 'MemberExpression' &&
120
- !node.callee.computed &&
121
- node.callee.property.type === 'Identifier' &&
122
- node.callee.property.name === 'command'
123
- ) {
124
- positions.push(node.start);
125
- }
126
- });
127
-
128
- return positions;
129
- }
130
-
131
- const launcherModulePath = './commands/utils/LocalCliDelegation.js';
132
- const commandRegistrationPositions = getCommandRegistrationPositions();
133
- const firstCommandRegistrationPos = Math.min(...commandRegistrationPositions);
134
-
135
- test('client imports LocalCliDelegation utility', () => {
136
- const importedBindings = getImportedBindings(launcherModulePath);
137
-
138
- assert.ok(
139
- importedBindings.size > 0,
140
- 'Contract clause failed: client.js must import launcher helpers from ./commands/utils/LocalCliDelegation.js'
141
- );
142
-
143
- for (const requiredImport of [
144
- 'isLocalDelegationDisabled',
145
- 'findNearestLocalCliEntry',
146
- 'shouldDelegateToLocalCli'
147
- ]) {
148
- assert.ok(
149
- importedBindings.has(requiredImport),
150
- `Contract clause failed: client.js must import ${requiredImport} from ${launcherModulePath}`
151
- );
152
- }
153
- });
154
-
155
- test('client checks SLICE_NO_LOCAL_DELEGATION behavior before command runtime', () => {
156
- const isDisabledCalls = getBoundImportedCallPositions(
157
- launcherModulePath,
158
- 'isLocalDelegationDisabled'
159
- );
160
-
161
- assert.ok(
162
- isDisabledCalls.length > 0,
163
- 'Contract clause failed: client.js must call imported isLocalDelegationDisabled() in launcher path'
164
- );
165
-
166
- assert.ok(
167
- commandRegistrationPositions.length > 0,
168
- 'Contract clause failed: client.js must define at least one .command(...) registration before launcher ordering checks'
169
- );
170
-
171
- assert.ok(
172
- isDisabledCalls.some((pos) => pos < firstCommandRegistrationPos),
173
- 'Contract clause failed: isLocalDelegationDisabled() must be evaluated before command registration/runtime wiring'
174
- );
175
- });
176
-
177
- test('client performs local candidate resolution and delegation decision', () => {
178
- const findNearestCalls = getBoundImportedCallPositions(
179
- launcherModulePath,
180
- 'findNearestLocalCliEntry'
181
- );
182
- const shouldDelegateCalls = getBoundImportedCallPositions(
183
- launcherModulePath,
184
- 'shouldDelegateToLocalCli'
185
- );
186
-
187
- assert.ok(
188
- findNearestCalls.length > 0,
189
- 'Contract clause failed: client.js must call imported findNearestLocalCliEntry() to resolve local CLI candidate in launcher path'
190
- );
191
-
192
- assert.ok(
193
- shouldDelegateCalls.length > 0,
194
- 'Contract clause failed: client.js must call imported shouldDelegateToLocalCli() to gate delegation in launcher path'
195
- );
196
-
197
- assert.ok(
198
- commandRegistrationPositions.length > 0,
199
- 'Contract clause failed: client.js must define at least one .command(...) registration before launcher ordering checks'
200
- );
201
-
202
- assert.ok(
203
- findNearestCalls.some((pos) => pos < firstCommandRegistrationPos),
204
- 'Contract clause failed: findNearestLocalCliEntry() must execute before command registration/runtime wiring'
205
- );
206
-
207
- assert.ok(
208
- shouldDelegateCalls.some((pos) => pos < firstCommandRegistrationPos),
209
- 'Contract clause failed: shouldDelegateToLocalCli() must execute before command registration/runtime wiring'
210
- );
211
- });
1
+ import { test } from 'node:test';
2
+ import assert from 'node:assert/strict';
3
+ import fs from 'node:fs';
4
+ import path from 'node:path';
5
+ import { fileURLToPath } from 'node:url';
6
+ import { parse } from '@babel/parser';
7
+ import babelTraverse from '@babel/traverse';
8
+
9
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
10
+ const clientPath = path.join(__dirname, '..', 'client.js');
11
+ const source = fs.readFileSync(clientPath, 'utf-8');
12
+ const ast = parse(source, {
13
+ sourceType: 'module',
14
+ plugins: []
15
+ });
16
+ const traverse = babelTraverse.default || babelTraverse;
17
+
18
+ function walk(node, visit) {
19
+ if (!node || typeof node !== 'object') {
20
+ return;
21
+ }
22
+
23
+ visit(node);
24
+
25
+ for (const value of Object.values(node)) {
26
+ if (Array.isArray(value)) {
27
+ for (const item of value) {
28
+ walk(item, visit);
29
+ }
30
+ continue;
31
+ }
32
+
33
+ walk(value, visit);
34
+ }
35
+ }
36
+
37
+ function getImportedBindings(fromSource) {
38
+ const bindings = new Map();
39
+
40
+ for (const statement of ast.program.body) {
41
+ if (statement.type !== 'ImportDeclaration') {
42
+ continue;
43
+ }
44
+
45
+ if (statement.source.value !== fromSource) {
46
+ continue;
47
+ }
48
+
49
+ for (const specifier of statement.specifiers) {
50
+ if (specifier.type === 'ImportSpecifier' && specifier.imported.type === 'Identifier') {
51
+ bindings.set(specifier.imported.name, specifier.local.name);
52
+ }
53
+ }
54
+ }
55
+
56
+ return bindings;
57
+ }
58
+
59
+ function getBoundImportedCallPositions(fromSource, importedName) {
60
+ const positions = [];
61
+ const importedBindings = getImportedBindings(fromSource);
62
+ const localName = importedBindings.get(importedName);
63
+
64
+ if (!localName) {
65
+ return positions;
66
+ }
67
+
68
+ traverse(ast, {
69
+ CallExpression(callPath) {
70
+ if (callPath.node.callee.type !== 'Identifier') {
71
+ return;
72
+ }
73
+
74
+ if (callPath.node.callee.name !== localName) {
75
+ return;
76
+ }
77
+
78
+ const binding = callPath.scope.getBinding(localName);
79
+ if (!binding) {
80
+ return;
81
+ }
82
+
83
+ if (binding.path.node.type !== 'ImportSpecifier') {
84
+ return;
85
+ }
86
+
87
+ if (binding.path.parent.type !== 'ImportDeclaration') {
88
+ return;
89
+ }
90
+
91
+ if (binding.path.parent.source.value !== fromSource) {
92
+ return;
93
+ }
94
+
95
+ if (binding.path.node.imported.type !== 'Identifier') {
96
+ return;
97
+ }
98
+
99
+ if (binding.path.node.imported.name !== importedName) {
100
+ return;
101
+ }
102
+
103
+ positions.push(callPath.node.start);
104
+ }
105
+ });
106
+
107
+ return positions;
108
+ }
109
+
110
+ function getCommandRegistrationPositions() {
111
+ const positions = [];
112
+
113
+ walk(ast.program, (node) => {
114
+ if (node.type !== 'CallExpression') {
115
+ return;
116
+ }
117
+
118
+ if (
119
+ node.callee.type === 'MemberExpression' &&
120
+ !node.callee.computed &&
121
+ node.callee.property.type === 'Identifier' &&
122
+ node.callee.property.name === 'command'
123
+ ) {
124
+ positions.push(node.start);
125
+ }
126
+ });
127
+
128
+ return positions;
129
+ }
130
+
131
+ const launcherModulePath = './commands/utils/LocalCliDelegation.js';
132
+ const commandRegistrationPositions = getCommandRegistrationPositions();
133
+ const firstCommandRegistrationPos = Math.min(...commandRegistrationPositions);
134
+
135
+ test('client imports LocalCliDelegation utility', () => {
136
+ const importedBindings = getImportedBindings(launcherModulePath);
137
+
138
+ assert.ok(
139
+ importedBindings.size > 0,
140
+ 'Contract clause failed: client.js must import launcher helpers from ./commands/utils/LocalCliDelegation.js'
141
+ );
142
+
143
+ for (const requiredImport of [
144
+ 'isLocalDelegationDisabled',
145
+ 'findNearestLocalCliEntry',
146
+ 'shouldDelegateToLocalCli'
147
+ ]) {
148
+ assert.ok(
149
+ importedBindings.has(requiredImport),
150
+ `Contract clause failed: client.js must import ${requiredImport} from ${launcherModulePath}`
151
+ );
152
+ }
153
+ });
154
+
155
+ test('client checks SLICE_NO_LOCAL_DELEGATION behavior before command runtime', () => {
156
+ const isDisabledCalls = getBoundImportedCallPositions(
157
+ launcherModulePath,
158
+ 'isLocalDelegationDisabled'
159
+ );
160
+
161
+ assert.ok(
162
+ isDisabledCalls.length > 0,
163
+ 'Contract clause failed: client.js must call imported isLocalDelegationDisabled() in launcher path'
164
+ );
165
+
166
+ assert.ok(
167
+ commandRegistrationPositions.length > 0,
168
+ 'Contract clause failed: client.js must define at least one .command(...) registration before launcher ordering checks'
169
+ );
170
+
171
+ assert.ok(
172
+ isDisabledCalls.some((pos) => pos < firstCommandRegistrationPos),
173
+ 'Contract clause failed: isLocalDelegationDisabled() must be evaluated before command registration/runtime wiring'
174
+ );
175
+ });
176
+
177
+ test('client performs local candidate resolution and delegation decision', () => {
178
+ const findNearestCalls = getBoundImportedCallPositions(
179
+ launcherModulePath,
180
+ 'findNearestLocalCliEntry'
181
+ );
182
+ const shouldDelegateCalls = getBoundImportedCallPositions(
183
+ launcherModulePath,
184
+ 'shouldDelegateToLocalCli'
185
+ );
186
+
187
+ assert.ok(
188
+ findNearestCalls.length > 0,
189
+ 'Contract clause failed: client.js must call imported findNearestLocalCliEntry() to resolve local CLI candidate in launcher path'
190
+ );
191
+
192
+ assert.ok(
193
+ shouldDelegateCalls.length > 0,
194
+ 'Contract clause failed: client.js must call imported shouldDelegateToLocalCli() to gate delegation in launcher path'
195
+ );
196
+
197
+ assert.ok(
198
+ commandRegistrationPositions.length > 0,
199
+ 'Contract clause failed: client.js must define at least one .command(...) registration before launcher ordering checks'
200
+ );
201
+
202
+ assert.ok(
203
+ findNearestCalls.some((pos) => pos < firstCommandRegistrationPos),
204
+ 'Contract clause failed: findNearestLocalCliEntry() must execute before command registration/runtime wiring'
205
+ );
206
+
207
+ assert.ok(
208
+ shouldDelegateCalls.some((pos) => pos < firstCommandRegistrationPos),
209
+ 'Contract clause failed: shouldDelegateToLocalCli() must execute before command registration/runtime wiring'
210
+ );
211
+ });