slicejs-cli 2.9.5 → 3.0.2
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/README.md +33 -5
- package/client.js +35 -5
- package/commands/utils/LocalCliDelegation.js +53 -0
- package/commands/utils/bundling/BundleGenerator.js +395 -36
- package/commands/utils/updateManager.js +19 -3
- package/package.json +1 -1
- package/tests/bundle-generator.test.js +168 -0
- package/tests/bundle-v2-register-output.test.js +141 -0
- package/tests/client-launcher-contract.test.js +211 -0
- package/tests/client-update-flow-contract.test.js +272 -0
- package/tests/local-cli-delegation.test.js +79 -0
- package/tests/update-manager-notifications.test.js +88 -0
package/README.md
CHANGED
|
@@ -45,6 +45,29 @@ npm run dev
|
|
|
45
45
|
npm run slice -- get Button
|
|
46
46
|
```
|
|
47
47
|
|
|
48
|
+
4. Use `slice` directly when the launcher command is available on your system
|
|
49
|
+
(commonly after a global install that puts `slice` in your PATH).
|
|
50
|
+
The launcher delegates to your nearest project-local `node_modules/slicejs-cli`
|
|
51
|
+
so project-pinned behavior is used from the project root and subdirectories.
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
slice dev
|
|
55
|
+
slice build
|
|
56
|
+
slice version
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
If `slice` is not available in your shell, use:
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
npx slicejs-cli dev
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
You can disable launcher delegation for a command when needed:
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
SLICE_NO_LOCAL_DELEGATION=1 slice version
|
|
69
|
+
```
|
|
70
|
+
|
|
48
71
|
### Global (Not Recommended)
|
|
49
72
|
|
|
50
73
|
Global installations can lead to version mismatches and "works on my machine" issues.
|
|
@@ -55,7 +78,10 @@ npm install -g slicejs-cli
|
|
|
55
78
|
|
|
56
79
|
## Usage
|
|
57
80
|
|
|
58
|
-
After installation,
|
|
81
|
+
After installation, prefer your project-local CLI. When the `slice` launcher command is
|
|
82
|
+
available, it automatically delegates to the nearest local `slicejs-cli` install.
|
|
83
|
+
|
|
84
|
+
Use the `slice` command directly:
|
|
59
85
|
|
|
60
86
|
```bash
|
|
61
87
|
slice [command] [options]
|
|
@@ -67,6 +93,8 @@ Or with npx (without global install):
|
|
|
67
93
|
npx slicejs-cli [command]
|
|
68
94
|
```
|
|
69
95
|
|
|
96
|
+
Use `npx slicejs-cli [command]` as a fallback when the `slice` launcher command is unavailable.
|
|
97
|
+
|
|
70
98
|
## Essential Commands
|
|
71
99
|
|
|
72
100
|
### Initialize a project
|
|
@@ -154,7 +182,7 @@ slice sync
|
|
|
154
182
|
```bash
|
|
155
183
|
# Version info
|
|
156
184
|
slice version
|
|
157
|
-
slice
|
|
185
|
+
slice v
|
|
158
186
|
|
|
159
187
|
# Updates (CLI and Framework)
|
|
160
188
|
slice update # Check and prompt to update
|
|
@@ -325,16 +353,16 @@ slice init
|
|
|
325
353
|
### Command not found
|
|
326
354
|
|
|
327
355
|
```bash
|
|
328
|
-
#
|
|
356
|
+
# If the launcher command is unavailable, run the local CLI via npx
|
|
329
357
|
npx slicejs-cli dev
|
|
330
358
|
|
|
331
|
-
#
|
|
359
|
+
# Optional: install globally to expose the slice launcher command
|
|
332
360
|
npm install -g slicejs-cli
|
|
333
361
|
```
|
|
334
362
|
|
|
335
363
|
## Links
|
|
336
364
|
|
|
337
|
-
- 📘 Documentation: https://slice-js-docs.vercel.app/
|
|
365
|
+
- 📘 CLI Documentation: https://slice-js-docs.vercel.app/Documentation/CLI
|
|
338
366
|
- 🐙 GitHub: https://github.com/VKneider/slice-cli
|
|
339
367
|
- 📦 npm: https://www.npmjs.com/package/slicejs-cli
|
|
340
368
|
|
package/client.js
CHANGED
|
@@ -14,12 +14,18 @@ import fs from "fs";
|
|
|
14
14
|
import path from "path";
|
|
15
15
|
import { fileURLToPath } from "url";
|
|
16
16
|
import { getConfigPath, getProjectRoot } from "./commands/utils/PathHelper.js";
|
|
17
|
-
import { exec } from "child_process";
|
|
17
|
+
import { exec, spawnSync } from "node:child_process";
|
|
18
18
|
import { promisify } from "util";
|
|
19
19
|
import validations from "./commands/Validations.js";
|
|
20
20
|
import Print from "./commands/Print.js";
|
|
21
21
|
import build from './commands/build/build.js';
|
|
22
22
|
import { cleanBundles, bundleInfo } from './commands/bundle/bundle.js';
|
|
23
|
+
import {
|
|
24
|
+
isLocalDelegationDisabled,
|
|
25
|
+
findNearestLocalCliEntry,
|
|
26
|
+
resolveLocalCliCandidate,
|
|
27
|
+
shouldDelegateToLocalCli
|
|
28
|
+
} from './commands/utils/LocalCliDelegation.js';
|
|
23
29
|
|
|
24
30
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
25
31
|
|
|
@@ -84,10 +90,7 @@ async function runWithVersionCheck(commandFunction, ...args) {
|
|
|
84
90
|
} catch {}
|
|
85
91
|
})();
|
|
86
92
|
|
|
87
|
-
|
|
88
|
-
if (updateInfo && updateInfo.hasUpdates) {
|
|
89
|
-
await updateManager.checkAndPromptUpdates({});
|
|
90
|
-
}
|
|
93
|
+
updateManager.notifyAvailableUpdates().catch(() => {});
|
|
91
94
|
|
|
92
95
|
const result = await commandFunction(...args);
|
|
93
96
|
|
|
@@ -102,6 +105,33 @@ async function runWithVersionCheck(commandFunction, ...args) {
|
|
|
102
105
|
}
|
|
103
106
|
}
|
|
104
107
|
|
|
108
|
+
function maybeDelegateToLocalCli() {
|
|
109
|
+
if (isLocalDelegationDisabled(process.env)) {
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
const currentEntryPath = fileURLToPath(import.meta.url);
|
|
114
|
+
const localEntryPath = findNearestLocalCliEntry(process.cwd(), resolveLocalCliCandidate);
|
|
115
|
+
|
|
116
|
+
if (!shouldDelegateToLocalCli(currentEntryPath, localEntryPath)) {
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
const child = spawnSync(
|
|
121
|
+
process.execPath,
|
|
122
|
+
[localEntryPath, ...process.argv.slice(2)],
|
|
123
|
+
{
|
|
124
|
+
stdio: 'inherit',
|
|
125
|
+
cwd: process.cwd(),
|
|
126
|
+
env: process.env
|
|
127
|
+
}
|
|
128
|
+
);
|
|
129
|
+
|
|
130
|
+
process.exit(child.status ?? 1);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
maybeDelegateToLocalCli();
|
|
134
|
+
|
|
105
135
|
const sliceClient = program;
|
|
106
136
|
|
|
107
137
|
try {
|
|
@@ -0,0 +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
|
+
}
|