slicejs-cli 3.1.0 → 3.3.0

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 (43) hide show
  1. package/.github/ISSUE_TEMPLATE/bug_report.md +29 -0
  2. package/.github/ISSUE_TEMPLATE/feature_request.md +25 -0
  3. package/.github/pull_request_template.md +22 -0
  4. package/.github/workflows/docs-render-cicd.yml +65 -0
  5. package/CODE_OF_CONDUCT.md +126 -0
  6. package/ECOSYSTEM.md +9 -0
  7. package/LICENSE +21 -0
  8. package/README.md +104 -308
  9. package/client.js +644 -557
  10. package/commands/Print.js +167 -167
  11. package/commands/Validations.js +103 -103
  12. package/commands/build/build.js +40 -40
  13. package/commands/buildProduction/buildProduction.js +579 -579
  14. package/commands/bundle/bundle.js +235 -235
  15. package/commands/createComponent/VisualComponentTemplate.js +55 -55
  16. package/commands/createComponent/createComponent.js +126 -126
  17. package/commands/deleteComponent/deleteComponent.js +77 -77
  18. package/commands/doctor/doctor.js +369 -369
  19. package/commands/getComponent/getComponent.js +747 -747
  20. package/commands/init/init.js +261 -261
  21. package/commands/listComponents/listComponents.js +175 -175
  22. package/commands/startServer/startServer.js +264 -264
  23. package/commands/startServer/watchServer.js +79 -79
  24. package/commands/types/types.js +538 -0
  25. package/commands/utils/LocalCliDelegation.js +53 -53
  26. package/commands/utils/PathHelper.js +68 -68
  27. package/commands/utils/VersionChecker.js +167 -167
  28. package/commands/utils/bundling/BundleGenerator.js +2292 -2292
  29. package/commands/utils/bundling/DependencyAnalyzer.js +933 -933
  30. package/commands/utils/updateManager.js +453 -453
  31. package/docs/superpowers/specs/2026-05-10-pwa-generate-design.md +182 -0
  32. package/package.json +46 -46
  33. package/post.js +65 -25
  34. package/tests/bundle-generator.test.js +708 -708
  35. package/tests/bundle-v2-register-output.test.js +470 -470
  36. package/tests/client-launcher-contract.test.js +211 -211
  37. package/tests/client-update-flow-contract.test.js +272 -272
  38. package/tests/dependency-analyzer.test.js +24 -24
  39. package/tests/local-cli-delegation.test.js +79 -79
  40. package/tests/postinstall-command.test.js +72 -0
  41. package/tests/types-generator.test.js +356 -0
  42. package/tests/update-manager-notifications.test.js +88 -88
  43. package/refactor.md +0 -271
@@ -1,53 +1,53 @@
1
- import fs from 'node:fs';
2
- import path from 'node:path';
3
-
4
- function getParentDirectory(dir) {
5
- const parent = path.dirname(dir);
6
- return parent === dir ? null : parent;
7
- }
8
-
9
- export function isLocalDelegationDisabled(env = process.env) {
10
- return env.SLICE_NO_LOCAL_DELEGATION === '1';
11
- }
12
-
13
- export function findNearestLocalCliEntry(startDirectory, resolveCandidate) {
14
- if (!startDirectory || typeof resolveCandidate !== 'function') {
15
- return null;
16
- }
17
-
18
- let current = path.resolve(startDirectory);
19
- while (current) {
20
- const candidate = resolveCandidate(current);
21
- if (candidate) {
22
- return candidate;
23
- }
24
- current = getParentDirectory(current);
25
- }
26
-
27
- return null;
28
- }
29
-
30
- export function resolveLocalCliCandidate(directory) {
31
- const candidate = path.join(directory, 'node_modules', 'slicejs-cli', 'client.js');
32
-
33
- try {
34
- const stats = fs.statSync(candidate);
35
- return stats.isFile() ? candidate : null;
36
- } catch {
37
- return null;
38
- }
39
- }
40
-
41
- export function shouldDelegateToLocalCli(currentEntryPath, localEntryPath) {
42
- if (!localEntryPath) {
43
- return false;
44
- }
45
-
46
- try {
47
- const currentReal = fs.realpathSync(currentEntryPath);
48
- const localReal = fs.realpathSync(localEntryPath);
49
- return currentReal !== localReal;
50
- } catch {
51
- return path.resolve(currentEntryPath) !== path.resolve(localEntryPath);
52
- }
53
- }
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+
4
+ function getParentDirectory(dir) {
5
+ const parent = path.dirname(dir);
6
+ return parent === dir ? null : parent;
7
+ }
8
+
9
+ export function isLocalDelegationDisabled(env = process.env) {
10
+ return env.SLICE_NO_LOCAL_DELEGATION === '1';
11
+ }
12
+
13
+ export function findNearestLocalCliEntry(startDirectory, resolveCandidate) {
14
+ if (!startDirectory || typeof resolveCandidate !== 'function') {
15
+ return null;
16
+ }
17
+
18
+ let current = path.resolve(startDirectory);
19
+ while (current) {
20
+ const candidate = resolveCandidate(current);
21
+ if (candidate) {
22
+ return candidate;
23
+ }
24
+ current = getParentDirectory(current);
25
+ }
26
+
27
+ return null;
28
+ }
29
+
30
+ export function resolveLocalCliCandidate(directory) {
31
+ const candidate = path.join(directory, 'node_modules', 'slicejs-cli', 'client.js');
32
+
33
+ try {
34
+ const stats = fs.statSync(candidate);
35
+ return stats.isFile() ? candidate : null;
36
+ } catch {
37
+ return null;
38
+ }
39
+ }
40
+
41
+ export function shouldDelegateToLocalCli(currentEntryPath, localEntryPath) {
42
+ if (!localEntryPath) {
43
+ return false;
44
+ }
45
+
46
+ try {
47
+ const currentReal = fs.realpathSync(currentEntryPath);
48
+ const localReal = fs.realpathSync(localEntryPath);
49
+ return currentReal !== localReal;
50
+ } catch {
51
+ return path.resolve(currentEntryPath) !== path.resolve(localEntryPath);
52
+ }
53
+ }
@@ -1,68 +1,68 @@
1
- import path from 'path'
2
- import fs from 'fs-extra'
3
- import { fileURLToPath } from 'url'
4
-
5
- const sanitize = (s) => (s || '').replace(/^[/\\]+/, '')
6
- const dirOf = (url) => path.dirname(fileURLToPath(url))
7
-
8
- function candidates(moduleUrl) {
9
- const dir = dirOf(moduleUrl)
10
- return [
11
- path.join(dir, '../../'),
12
- path.join(dir, '../../../../')
13
- ]
14
- }
15
-
16
- function resolveProjectRoot(moduleUrl) {
17
- const initCwd = process.env.INIT_CWD
18
- if (initCwd && fs.pathExistsSync(initCwd)) {
19
- return initCwd
20
- }
21
-
22
- const cwd = process.cwd()
23
- if (cwd && fs.pathExistsSync(cwd)) {
24
- return cwd
25
- }
26
-
27
- const dirs = candidates(moduleUrl)
28
- for (const root of dirs) {
29
- const hasSrc = fs.pathExistsSync(path.join(root, 'src'))
30
- const hasApi = fs.pathExistsSync(path.join(root, 'api'))
31
- if (hasSrc || hasApi) return root
32
- }
33
- return dirs[1]
34
- }
35
-
36
- function joinProject(moduleUrl, ...segments) {
37
- const root = resolveProjectRoot(moduleUrl)
38
- const clean = segments.map(sanitize)
39
- return path.join(root, ...clean)
40
- }
41
-
42
- export function getProjectRoot(moduleUrl) {
43
- return resolveProjectRoot(moduleUrl)
44
- }
45
-
46
- export function getPath(moduleUrl, folder, ...segments) {
47
- return joinProject(moduleUrl, folder, ...segments)
48
- }
49
-
50
- export function getSrcPath(moduleUrl, ...segments) {
51
- return joinProject(moduleUrl, 'src', ...segments)
52
- }
53
-
54
- export function getApiPath(moduleUrl, ...segments) {
55
- return joinProject(moduleUrl, 'api', ...segments)
56
- }
57
-
58
- export function getDistPath(moduleUrl, ...segments) {
59
- return joinProject(moduleUrl, 'dist', ...segments)
60
- }
61
-
62
- export function getConfigPath(moduleUrl) {
63
- return joinProject(moduleUrl, 'src', 'sliceConfig.json')
64
- }
65
-
66
- export function getComponentsJsPath(moduleUrl) {
67
- return joinProject(moduleUrl, 'src', 'Components', 'components.js')
68
- }
1
+ import path from 'path'
2
+ import fs from 'fs-extra'
3
+ import { fileURLToPath } from 'url'
4
+
5
+ const sanitize = (s) => (s || '').replace(/^[/\\]+/, '')
6
+ const dirOf = (url) => path.dirname(fileURLToPath(url))
7
+
8
+ function candidates(moduleUrl) {
9
+ const dir = dirOf(moduleUrl)
10
+ return [
11
+ path.join(dir, '../../'),
12
+ path.join(dir, '../../../../')
13
+ ]
14
+ }
15
+
16
+ function resolveProjectRoot(moduleUrl) {
17
+ const initCwd = process.env.INIT_CWD
18
+ if (initCwd && fs.pathExistsSync(initCwd)) {
19
+ return initCwd
20
+ }
21
+
22
+ const cwd = process.cwd()
23
+ if (cwd && fs.pathExistsSync(cwd)) {
24
+ return cwd
25
+ }
26
+
27
+ const dirs = candidates(moduleUrl)
28
+ for (const root of dirs) {
29
+ const hasSrc = fs.pathExistsSync(path.join(root, 'src'))
30
+ const hasApi = fs.pathExistsSync(path.join(root, 'api'))
31
+ if (hasSrc || hasApi) return root
32
+ }
33
+ return dirs[1]
34
+ }
35
+
36
+ function joinProject(moduleUrl, ...segments) {
37
+ const root = resolveProjectRoot(moduleUrl)
38
+ const clean = segments.map(sanitize)
39
+ return path.join(root, ...clean)
40
+ }
41
+
42
+ export function getProjectRoot(moduleUrl) {
43
+ return resolveProjectRoot(moduleUrl)
44
+ }
45
+
46
+ export function getPath(moduleUrl, folder, ...segments) {
47
+ return joinProject(moduleUrl, folder, ...segments)
48
+ }
49
+
50
+ export function getSrcPath(moduleUrl, ...segments) {
51
+ return joinProject(moduleUrl, 'src', ...segments)
52
+ }
53
+
54
+ export function getApiPath(moduleUrl, ...segments) {
55
+ return joinProject(moduleUrl, 'api', ...segments)
56
+ }
57
+
58
+ export function getDistPath(moduleUrl, ...segments) {
59
+ return joinProject(moduleUrl, 'dist', ...segments)
60
+ }
61
+
62
+ export function getConfigPath(moduleUrl) {
63
+ return joinProject(moduleUrl, 'src', 'sliceConfig.json')
64
+ }
65
+
66
+ export function getComponentsJsPath(moduleUrl) {
67
+ return joinProject(moduleUrl, 'src', 'Components', 'components.js')
68
+ }
@@ -1,167 +1,167 @@
1
- // commands/utils/VersionChecker.js
2
-
3
- import fs from "fs-extra";
4
- import path from "path";
5
- import { fileURLToPath } from "url";
6
- import Print from "../Print.js";
7
- import { getProjectRoot } from "../utils/PathHelper.js";
8
-
9
- const __dirname = path.dirname(fileURLToPath(import.meta.url));
10
-
11
- class VersionChecker {
12
- constructor() {
13
- this.currentCliVersion = null;
14
- this.currentFrameworkVersion = null;
15
- this.latestCliVersion = null;
16
- this.latestFrameworkVersion = null;
17
- }
18
-
19
- async getCurrentVersions() {
20
- try {
21
- // Get CLI version
22
- const cliPackagePath = path.join(__dirname, '../../package.json');
23
- const cliPackage = await fs.readJson(cliPackagePath);
24
- this.currentCliVersion = cliPackage.version;
25
-
26
- // Get Framework version from project node_modules
27
- const projectRoot = getProjectRoot(import.meta.url);
28
- const frameworkPackagePath = path.join(projectRoot, 'node_modules', 'slicejs-web-framework', 'package.json');
29
- if (await fs.pathExists(frameworkPackagePath)) {
30
- const frameworkPackage = await fs.readJson(frameworkPackagePath);
31
- this.currentFrameworkVersion = frameworkPackage.version;
32
- }
33
-
34
- // Get Project's CLI version
35
- const projectPackagePath = path.join(__dirname, '../../../../package.json');
36
- if (await fs.pathExists(projectPackagePath)) {
37
- const projectPackage = await fs.readJson(projectPackagePath);
38
- if (projectPackage.dependencies && projectPackage.dependencies['slicejs-cli']) {
39
- // This could be different from the currently running CLI version
40
- }
41
- }
42
-
43
- return {
44
- cli: this.currentCliVersion,
45
- framework: this.currentFrameworkVersion
46
- };
47
- } catch (error) {
48
- return null;
49
- }
50
- }
51
-
52
- async getLatestVersions() {
53
- try {
54
- // Check CLI version
55
- const cliResponse = await fetch('https://registry.npmjs.org/slicejs-cli/latest', {
56
- headers: { 'Accept': 'application/json' }
57
- });
58
-
59
- if (cliResponse.ok) {
60
- const cliData = await cliResponse.json();
61
- this.latestCliVersion = cliData.version;
62
- }
63
-
64
- // Check Framework version
65
- const frameworkResponse = await fetch('https://registry.npmjs.org/slicejs-web-framework/latest', {
66
- headers: { 'Accept': 'application/json' }
67
- });
68
-
69
- if (frameworkResponse.ok) {
70
- const frameworkData = await frameworkResponse.json();
71
- this.latestFrameworkVersion = frameworkData.version;
72
- }
73
-
74
- return {
75
- cli: this.latestCliVersion,
76
- framework: this.latestFrameworkVersion
77
- };
78
- } catch (error) {
79
- // Silent fail - don't interrupt commands for version check failures
80
- return null;
81
- }
82
- }
83
-
84
- compareVersions(current, latest) {
85
- if (!current || !latest) return null;
86
-
87
- const currentParts = current.split('.').map(Number);
88
- const latestParts = latest.split('.').map(Number);
89
-
90
- for (let i = 0; i < Math.max(currentParts.length, latestParts.length); i++) {
91
- const currentPart = currentParts[i] || 0;
92
- const latestPart = latestParts[i] || 0;
93
-
94
- if (latestPart > currentPart) return 'outdated';
95
- if (currentPart > latestPart) return 'newer';
96
- }
97
-
98
- return 'current';
99
- }
100
-
101
- async checkForUpdates(silent = false) {
102
- try {
103
- const current = await this.getCurrentVersions();
104
- if (!current) return;
105
-
106
- const latest = await this.getLatestVersions();
107
- if (!latest) return;
108
-
109
- const cliStatus = this.compareVersions(current.cli, latest.cli);
110
- const frameworkStatus = this.compareVersions(current.framework, latest.framework);
111
-
112
- if (!silent && (cliStatus === 'outdated' || frameworkStatus === 'outdated')) {
113
- console.log(''); // Line break
114
- Print.warning('šŸ“¦ Available Updates:');
115
-
116
- if (cliStatus === 'outdated') {
117
- console.log(` šŸ”§ CLI: ${current.cli} → ${latest.cli}`);
118
- console.log(` npm update slicejs-cli`);
119
- }
120
-
121
- if (frameworkStatus === 'outdated') {
122
- console.log(` ⚔ Framework: ${current.framework} → ${latest.framework}`);
123
- console.log(` npm update slicejs-web-framework`);
124
- }
125
-
126
- console.log(' šŸ“š Changelog: https://github.com/VKneider/slice.js/releases');
127
- console.log(''); // Line break
128
- }
129
-
130
- return {
131
- cli: { current: current.cli, latest: latest.cli, status: cliStatus },
132
- framework: { current: current.framework, latest: latest.framework, status: frameworkStatus }
133
- };
134
-
135
- } catch (error) {
136
- // Silent fail - don't interrupt commands
137
- return null;
138
- }
139
- }
140
-
141
- async showVersionInfo() {
142
- const current = await this.getCurrentVersions();
143
- const latest = await this.getLatestVersions();
144
-
145
- console.log('\nšŸ“‹ Version Information:');
146
- console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
147
-
148
- if (current?.cli) {
149
- const cliStatus = this.compareVersions(current.cli, latest?.cli);
150
- const statusIcon = cliStatus === 'current' ? 'āœ…' : cliStatus === 'outdated' ? 'šŸ”„' : 'šŸ†•';
151
- console.log(`${statusIcon} CLI: v${current.cli}${latest?.cli && latest.cli !== current.cli ? ` (latest: v${latest.cli})` : ''}`);
152
- }
153
-
154
- if (current?.framework) {
155
- const frameworkStatus = this.compareVersions(current.framework, latest?.framework);
156
- const statusIcon = frameworkStatus === 'current' ? 'āœ…' : frameworkStatus === 'outdated' ? 'šŸ”„' : 'šŸ†•';
157
- console.log(`${statusIcon} Framework: v${current.framework}${latest?.framework && latest.framework !== current.framework ? ` (latest: v${latest.framework})` : ''}`);
158
- }
159
-
160
- console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n');
161
- }
162
- }
163
-
164
- // Singleton instance
165
- const versionChecker = new VersionChecker();
166
-
167
- export default versionChecker;
1
+ // commands/utils/VersionChecker.js
2
+
3
+ import fs from "fs-extra";
4
+ import path from "path";
5
+ import { fileURLToPath } from "url";
6
+ import Print from "../Print.js";
7
+ import { getProjectRoot } from "../utils/PathHelper.js";
8
+
9
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
10
+
11
+ class VersionChecker {
12
+ constructor() {
13
+ this.currentCliVersion = null;
14
+ this.currentFrameworkVersion = null;
15
+ this.latestCliVersion = null;
16
+ this.latestFrameworkVersion = null;
17
+ }
18
+
19
+ async getCurrentVersions() {
20
+ try {
21
+ // Get CLI version
22
+ const cliPackagePath = path.join(__dirname, '../../package.json');
23
+ const cliPackage = await fs.readJson(cliPackagePath);
24
+ this.currentCliVersion = cliPackage.version;
25
+
26
+ // Get Framework version from project node_modules
27
+ const projectRoot = getProjectRoot(import.meta.url);
28
+ const frameworkPackagePath = path.join(projectRoot, 'node_modules', 'slicejs-web-framework', 'package.json');
29
+ if (await fs.pathExists(frameworkPackagePath)) {
30
+ const frameworkPackage = await fs.readJson(frameworkPackagePath);
31
+ this.currentFrameworkVersion = frameworkPackage.version;
32
+ }
33
+
34
+ // Get Project's CLI version
35
+ const projectPackagePath = path.join(__dirname, '../../../../package.json');
36
+ if (await fs.pathExists(projectPackagePath)) {
37
+ const projectPackage = await fs.readJson(projectPackagePath);
38
+ if (projectPackage.dependencies && projectPackage.dependencies['slicejs-cli']) {
39
+ // This could be different from the currently running CLI version
40
+ }
41
+ }
42
+
43
+ return {
44
+ cli: this.currentCliVersion,
45
+ framework: this.currentFrameworkVersion
46
+ };
47
+ } catch (error) {
48
+ return null;
49
+ }
50
+ }
51
+
52
+ async getLatestVersions() {
53
+ try {
54
+ // Check CLI version
55
+ const cliResponse = await fetch('https://registry.npmjs.org/slicejs-cli/latest', {
56
+ headers: { 'Accept': 'application/json' }
57
+ });
58
+
59
+ if (cliResponse.ok) {
60
+ const cliData = await cliResponse.json();
61
+ this.latestCliVersion = cliData.version;
62
+ }
63
+
64
+ // Check Framework version
65
+ const frameworkResponse = await fetch('https://registry.npmjs.org/slicejs-web-framework/latest', {
66
+ headers: { 'Accept': 'application/json' }
67
+ });
68
+
69
+ if (frameworkResponse.ok) {
70
+ const frameworkData = await frameworkResponse.json();
71
+ this.latestFrameworkVersion = frameworkData.version;
72
+ }
73
+
74
+ return {
75
+ cli: this.latestCliVersion,
76
+ framework: this.latestFrameworkVersion
77
+ };
78
+ } catch (error) {
79
+ // Silent fail - don't interrupt commands for version check failures
80
+ return null;
81
+ }
82
+ }
83
+
84
+ compareVersions(current, latest) {
85
+ if (!current || !latest) return null;
86
+
87
+ const currentParts = current.split('.').map(Number);
88
+ const latestParts = latest.split('.').map(Number);
89
+
90
+ for (let i = 0; i < Math.max(currentParts.length, latestParts.length); i++) {
91
+ const currentPart = currentParts[i] || 0;
92
+ const latestPart = latestParts[i] || 0;
93
+
94
+ if (latestPart > currentPart) return 'outdated';
95
+ if (currentPart > latestPart) return 'newer';
96
+ }
97
+
98
+ return 'current';
99
+ }
100
+
101
+ async checkForUpdates(silent = false) {
102
+ try {
103
+ const current = await this.getCurrentVersions();
104
+ if (!current) return;
105
+
106
+ const latest = await this.getLatestVersions();
107
+ if (!latest) return;
108
+
109
+ const cliStatus = this.compareVersions(current.cli, latest.cli);
110
+ const frameworkStatus = this.compareVersions(current.framework, latest.framework);
111
+
112
+ if (!silent && (cliStatus === 'outdated' || frameworkStatus === 'outdated')) {
113
+ console.log(''); // Line break
114
+ Print.warning('šŸ“¦ Available Updates:');
115
+
116
+ if (cliStatus === 'outdated') {
117
+ console.log(` šŸ”§ CLI: ${current.cli} → ${latest.cli}`);
118
+ console.log(` npm update slicejs-cli`);
119
+ }
120
+
121
+ if (frameworkStatus === 'outdated') {
122
+ console.log(` ⚔ Framework: ${current.framework} → ${latest.framework}`);
123
+ console.log(` npm update slicejs-web-framework`);
124
+ }
125
+
126
+ console.log(' šŸ“š Changelog: https://github.com/VKneider/slice.js/releases');
127
+ console.log(''); // Line break
128
+ }
129
+
130
+ return {
131
+ cli: { current: current.cli, latest: latest.cli, status: cliStatus },
132
+ framework: { current: current.framework, latest: latest.framework, status: frameworkStatus }
133
+ };
134
+
135
+ } catch (error) {
136
+ // Silent fail - don't interrupt commands
137
+ return null;
138
+ }
139
+ }
140
+
141
+ async showVersionInfo() {
142
+ const current = await this.getCurrentVersions();
143
+ const latest = await this.getLatestVersions();
144
+
145
+ console.log('\nšŸ“‹ Version Information:');
146
+ console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
147
+
148
+ if (current?.cli) {
149
+ const cliStatus = this.compareVersions(current.cli, latest?.cli);
150
+ const statusIcon = cliStatus === 'current' ? 'āœ…' : cliStatus === 'outdated' ? 'šŸ”„' : 'šŸ†•';
151
+ console.log(`${statusIcon} CLI: v${current.cli}${latest?.cli && latest.cli !== current.cli ? ` (latest: v${latest.cli})` : ''}`);
152
+ }
153
+
154
+ if (current?.framework) {
155
+ const frameworkStatus = this.compareVersions(current.framework, latest?.framework);
156
+ const statusIcon = frameworkStatus === 'current' ? 'āœ…' : frameworkStatus === 'outdated' ? 'šŸ”„' : 'šŸ†•';
157
+ console.log(`${statusIcon} Framework: v${current.framework}${latest?.framework && latest.framework !== current.framework ? ` (latest: v${latest.framework})` : ''}`);
158
+ }
159
+
160
+ console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n');
161
+ }
162
+ }
163
+
164
+ // Singleton instance
165
+ const versionChecker = new VersionChecker();
166
+
167
+ export default versionChecker;