slicejs-cli 3.6.2 → 3.6.4

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.
@@ -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,148 +1,148 @@
1
- // commands/utils/PackageManager.js
2
- //
3
- // Package manager detection and command building (pnpm / npm).
4
- // Resolution priority for an existing project:
5
- // 1. "packageManager" field in the project package.json (corepack convention)
6
- // 2. Lockfile present at the project root
7
- // 3. npm_config_user_agent (set when the CLI runs via `npx` / `pnpm dlx` / a PM script)
8
- // 4. The only PM binary available on PATH (if exactly one)
9
- // When everything is ambiguous, detectPackageManager() returns null so callers
10
- // can prompt the user (interactive init) or fall back to pnpm (non-interactive).
11
-
12
- import fs from 'fs-extra'
13
- import path from 'path'
14
- import { spawnSync } from 'node:child_process'
15
-
16
- export const SUPPORTED_PACKAGE_MANAGERS = ['pnpm', 'npm']
17
-
18
- const LOCKFILES = {
19
- 'pnpm-lock.yaml': 'pnpm',
20
- 'package-lock.json': 'npm'
21
- }
22
-
23
- export function parseUserAgent(userAgent = process.env.npm_config_user_agent) {
24
- if (!userAgent) return null
25
- const match = userAgent.match(/^(npm|pnpm)\/(\S+)/)
26
- if (!match) return null
27
- return { name: match[1], version: match[2], source: 'user-agent' }
28
- }
29
-
30
- export function fromPackageManagerField(projectRoot) {
31
- try {
32
- const pkgPath = path.join(projectRoot, 'package.json')
33
- if (!fs.pathExistsSync(pkgPath)) return null
34
- const pkg = fs.readJsonSync(pkgPath)
35
- if (typeof pkg.packageManager !== 'string') return null
36
- const match = pkg.packageManager.match(/^(npm|pnpm)@(\S+)/)
37
- if (!match) return null
38
- return { name: match[1], version: match[2], source: 'package-manager-field' }
39
- } catch {
40
- return null
41
- }
42
- }
43
-
44
- export function fromLockfile(projectRoot) {
45
- for (const [lockfile, name] of Object.entries(LOCKFILES)) {
46
- if (fs.pathExistsSync(path.join(projectRoot, lockfile))) {
47
- return { name, version: null, source: `lockfile (${lockfile})` }
48
- }
49
- }
50
- return null
51
- }
52
-
53
- function runPmBinary(name, args) {
54
- // On Windows the PM entry points are .cmd shims, which require shell resolution.
55
- const isWindows = process.platform === 'win32'
56
- return spawnSync(name, args, {
57
- stdio: ['ignore', 'pipe', 'ignore'],
58
- shell: isWindows,
59
- encoding: 'utf-8'
60
- })
61
- }
62
-
63
- export function isPackageManagerAvailable(name) {
64
- try {
65
- const result = runPmBinary(name, ['--version'])
66
- return result.status === 0
67
- } catch {
68
- return false
69
- }
70
- }
71
-
72
- export function getPackageManagerVersion(name) {
73
- try {
74
- const result = runPmBinary(name, ['--version'])
75
- if (result.status !== 0) return null
76
- return (result.stdout || '').toString().trim() || null
77
- } catch {
78
- return null
79
- }
80
- }
81
-
82
- export function getAvailablePackageManagers() {
83
- return SUPPORTED_PACKAGE_MANAGERS.filter(isPackageManagerAvailable)
84
- }
85
-
86
- /**
87
- * Detect the package manager for a project.
88
- * Returns { name, version, source } or null when genuinely ambiguous.
89
- */
90
- export function detectPackageManager(projectRoot, { userAgent = process.env.npm_config_user_agent } = {}) {
91
- if (projectRoot) {
92
- const fromField = fromPackageManagerField(projectRoot)
93
- if (fromField) return fromField
94
-
95
- const fromLock = fromLockfile(projectRoot)
96
- if (fromLock) return fromLock
97
- }
98
-
99
- const fromUa = parseUserAgent(userAgent)
100
- if (fromUa) return fromUa
101
-
102
- const available = getAvailablePackageManagers()
103
- if (available.length === 1) {
104
- return { name: available[0], version: null, source: 'only available binary' }
105
- }
106
-
107
- return null
108
- }
109
-
110
- /**
111
- * Non-interactive resolution: detection first, then pnpm if available,
112
- * then whatever binary exists. Never returns null so update/doctor flows
113
- * always have a usable PM name (commands fail later with a clear error
114
- * if no PM is actually installed).
115
- */
116
- export function resolvePackageManager(projectRoot, options = {}) {
117
- const detected = detectPackageManager(projectRoot, options)
118
- if (detected) return detected
119
-
120
- const available = getAvailablePackageManagers()
121
- if (available.includes('pnpm')) return { name: 'pnpm', version: null, source: 'fallback' }
122
- if (available.includes('npm')) return { name: 'npm', version: null, source: 'fallback' }
123
- if (available.length > 0) return { name: available[0], version: null, source: 'fallback' }
124
- return { name: 'pnpm', version: null, source: 'fallback (none detected)' }
125
- }
126
-
127
- export function installCommand(pmName, packages, { dev = false, global: isGlobal = false } = {}) {
128
- const pkgs = Array.isArray(packages) ? packages.join(' ') : packages
129
- const flags = [isGlobal ? '-g' : '', dev ? '-D' : ''].filter(Boolean).join(' ')
130
- const flagSuffix = flags ? ` ${flags}` : ''
131
- if (pmName === 'pnpm') {
132
- return `${pmName} add${flagSuffix} ${pkgs}`
133
- }
134
- return `npm install${flagSuffix} ${pkgs}`
135
- }
136
-
137
- export function uninstallCommand(pmName, packages, { global: isGlobal = false } = {}) {
138
- const pkgs = Array.isArray(packages) ? packages.join(' ') : packages
139
- const flagSuffix = isGlobal ? ' -g' : ''
140
- if (pmName === 'pnpm') {
141
- return `${pmName} remove${flagSuffix} ${pkgs}`
142
- }
143
- return `npm uninstall${flagSuffix} ${pkgs}`
144
- }
145
-
146
- export function runScriptCommand(pmName, script) {
147
- return `${pmName} run ${script}`
148
- }
1
+ // commands/utils/PackageManager.js
2
+ //
3
+ // Package manager detection and command building (pnpm / npm).
4
+ // Resolution priority for an existing project:
5
+ // 1. "packageManager" field in the project package.json (corepack convention)
6
+ // 2. Lockfile present at the project root
7
+ // 3. npm_config_user_agent (set when the CLI runs via `npx` / `pnpm dlx` / a PM script)
8
+ // 4. The only PM binary available on PATH (if exactly one)
9
+ // When everything is ambiguous, detectPackageManager() returns null so callers
10
+ // can prompt the user (interactive init) or fall back to pnpm (non-interactive).
11
+
12
+ import fs from 'fs-extra'
13
+ import path from 'path'
14
+ import { spawnSync } from 'node:child_process'
15
+
16
+ export const SUPPORTED_PACKAGE_MANAGERS = ['pnpm', 'npm']
17
+
18
+ const LOCKFILES = {
19
+ 'pnpm-lock.yaml': 'pnpm',
20
+ 'package-lock.json': 'npm'
21
+ }
22
+
23
+ export function parseUserAgent(userAgent = process.env.npm_config_user_agent) {
24
+ if (!userAgent) return null
25
+ const match = userAgent.match(/^(npm|pnpm)\/(\S+)/)
26
+ if (!match) return null
27
+ return { name: match[1], version: match[2], source: 'user-agent' }
28
+ }
29
+
30
+ export function fromPackageManagerField(projectRoot) {
31
+ try {
32
+ const pkgPath = path.join(projectRoot, 'package.json')
33
+ if (!fs.pathExistsSync(pkgPath)) return null
34
+ const pkg = fs.readJsonSync(pkgPath)
35
+ if (typeof pkg.packageManager !== 'string') return null
36
+ const match = pkg.packageManager.match(/^(npm|pnpm)@(\S+)/)
37
+ if (!match) return null
38
+ return { name: match[1], version: match[2], source: 'package-manager-field' }
39
+ } catch {
40
+ return null
41
+ }
42
+ }
43
+
44
+ export function fromLockfile(projectRoot) {
45
+ for (const [lockfile, name] of Object.entries(LOCKFILES)) {
46
+ if (fs.pathExistsSync(path.join(projectRoot, lockfile))) {
47
+ return { name, version: null, source: `lockfile (${lockfile})` }
48
+ }
49
+ }
50
+ return null
51
+ }
52
+
53
+ function runPmBinary(name, args) {
54
+ // On Windows the PM entry points are .cmd shims, which require shell resolution.
55
+ const isWindows = process.platform === 'win32'
56
+ return spawnSync(name, args, {
57
+ stdio: ['ignore', 'pipe', 'ignore'],
58
+ shell: isWindows,
59
+ encoding: 'utf-8'
60
+ })
61
+ }
62
+
63
+ export function isPackageManagerAvailable(name) {
64
+ try {
65
+ const result = runPmBinary(name, ['--version'])
66
+ return result.status === 0
67
+ } catch {
68
+ return false
69
+ }
70
+ }
71
+
72
+ export function getPackageManagerVersion(name) {
73
+ try {
74
+ const result = runPmBinary(name, ['--version'])
75
+ if (result.status !== 0) return null
76
+ return (result.stdout || '').toString().trim() || null
77
+ } catch {
78
+ return null
79
+ }
80
+ }
81
+
82
+ export function getAvailablePackageManagers() {
83
+ return SUPPORTED_PACKAGE_MANAGERS.filter(isPackageManagerAvailable)
84
+ }
85
+
86
+ /**
87
+ * Detect the package manager for a project.
88
+ * Returns { name, version, source } or null when genuinely ambiguous.
89
+ */
90
+ export function detectPackageManager(projectRoot, { userAgent = process.env.npm_config_user_agent } = {}) {
91
+ if (projectRoot) {
92
+ const fromField = fromPackageManagerField(projectRoot)
93
+ if (fromField) return fromField
94
+
95
+ const fromLock = fromLockfile(projectRoot)
96
+ if (fromLock) return fromLock
97
+ }
98
+
99
+ const fromUa = parseUserAgent(userAgent)
100
+ if (fromUa) return fromUa
101
+
102
+ const available = getAvailablePackageManagers()
103
+ if (available.length === 1) {
104
+ return { name: available[0], version: null, source: 'only available binary' }
105
+ }
106
+
107
+ return null
108
+ }
109
+
110
+ /**
111
+ * Non-interactive resolution: detection first, then pnpm if available,
112
+ * then whatever binary exists. Never returns null so update/doctor flows
113
+ * always have a usable PM name (commands fail later with a clear error
114
+ * if no PM is actually installed).
115
+ */
116
+ export function resolvePackageManager(projectRoot, options = {}) {
117
+ const detected = detectPackageManager(projectRoot, options)
118
+ if (detected) return detected
119
+
120
+ const available = getAvailablePackageManagers()
121
+ if (available.includes('pnpm')) return { name: 'pnpm', version: null, source: 'fallback' }
122
+ if (available.includes('npm')) return { name: 'npm', version: null, source: 'fallback' }
123
+ if (available.length > 0) return { name: available[0], version: null, source: 'fallback' }
124
+ return { name: 'pnpm', version: null, source: 'fallback (none detected)' }
125
+ }
126
+
127
+ export function installCommand(pmName, packages, { dev = false, global: isGlobal = false } = {}) {
128
+ const pkgs = Array.isArray(packages) ? packages.join(' ') : packages
129
+ const flags = [isGlobal ? '-g' : '', dev ? '-D' : ''].filter(Boolean).join(' ')
130
+ const flagSuffix = flags ? ` ${flags}` : ''
131
+ if (pmName === 'pnpm') {
132
+ return `${pmName} add${flagSuffix} ${pkgs}`
133
+ }
134
+ return `npm install${flagSuffix} ${pkgs}`
135
+ }
136
+
137
+ export function uninstallCommand(pmName, packages, { global: isGlobal = false } = {}) {
138
+ const pkgs = Array.isArray(packages) ? packages.join(' ') : packages
139
+ const flagSuffix = isGlobal ? ' -g' : ''
140
+ if (pmName === 'pnpm') {
141
+ return `${pmName} remove${flagSuffix} ${pkgs}`
142
+ }
143
+ return `npm uninstall${flagSuffix} ${pkgs}`
144
+ }
145
+
146
+ export function runScriptCommand(pmName, script) {
147
+ return `${pmName} run ${script}`
148
+ }
@@ -1,75 +1,75 @@
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, root) {
63
- if (root) return path.join(root, 'src', 'sliceConfig.json')
64
- return joinProject(moduleUrl, 'src', 'sliceConfig.json')
65
- }
66
-
67
- export function getComponentsJsPath(moduleUrl, root) {
68
- if (root) return path.join(root, 'src', 'Components', 'components.js')
69
- return joinProject(moduleUrl, 'src', 'Components', 'components.js')
70
- }
71
-
72
- export function joinRoot(root, ...segments) {
73
- const clean = segments.map(sanitize)
74
- return path.join(root, ...clean)
75
- }
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, root) {
63
+ if (root) return path.join(root, 'src', 'sliceConfig.json')
64
+ return joinProject(moduleUrl, 'src', 'sliceConfig.json')
65
+ }
66
+
67
+ export function getComponentsJsPath(moduleUrl, root) {
68
+ if (root) return path.join(root, 'src', 'Components', 'components.js')
69
+ return joinProject(moduleUrl, 'src', 'Components', 'components.js')
70
+ }
71
+
72
+ export function joinRoot(root, ...segments) {
73
+ const clean = segments.map(sanitize)
74
+ return path.join(root, ...clean)
75
+ }