@shellui/cli 0.0.11 → 0.0.14
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/package.json +2 -2
- package/src/cli.js +2 -1
- package/src/commands/build.js +1 -3
- package/src/commands/start.js +1 -13
- package/src/utils/index.js +0 -1
- package/src/utils/package-path.js +25 -6
- package/src/utils/vite.js +22 -1
- package/src/utils/inline-lazy-imports-plugin.js +0 -104
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@shellui/cli",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.14",
|
|
4
4
|
"description": "ShellUI CLI - Command-line tool for ShellUI",
|
|
5
5
|
"main": "src/cli.js",
|
|
6
6
|
"type": "module",
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
"tsx": "^4.21.0",
|
|
31
31
|
"vite": "7.3.1",
|
|
32
32
|
"workbox-build": "^7.1.0",
|
|
33
|
-
"@shellui/core": "0.0.
|
|
33
|
+
"@shellui/core": "0.0.14"
|
|
34
34
|
},
|
|
35
35
|
"publishConfig": {
|
|
36
36
|
"access": "public"
|
package/src/cli.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { cac } from 'cac';
|
|
2
2
|
import { startCommand, buildCommand } from './commands/index.js';
|
|
3
|
+
import pkg from '../package.json' with { type: 'json' };
|
|
3
4
|
|
|
4
5
|
const cli = cac('shellui');
|
|
5
6
|
|
|
@@ -10,5 +11,5 @@ cli.command('build [root]', 'Build the shellui application').action(buildCommand
|
|
|
10
11
|
|
|
11
12
|
// Setup CLI metadata
|
|
12
13
|
cli.help();
|
|
13
|
-
cli.version(
|
|
14
|
+
cli.version(pkg.version);
|
|
14
15
|
cli.parse();
|
package/src/commands/build.js
CHANGED
|
@@ -11,7 +11,6 @@ import {
|
|
|
11
11
|
createPostCSSConfig,
|
|
12
12
|
createViteDefine,
|
|
13
13
|
resolvePackagePath,
|
|
14
|
-
inlineLazyImportsPlugin,
|
|
15
14
|
} from '../utils/index.js';
|
|
16
15
|
|
|
17
16
|
/**
|
|
@@ -84,8 +83,7 @@ export async function buildCommand(root = '.') {
|
|
|
84
83
|
// Build main app
|
|
85
84
|
await build({
|
|
86
85
|
root: coreSrcPath,
|
|
87
|
-
|
|
88
|
-
plugins: [inlineLazyImportsPlugin(), react()],
|
|
86
|
+
plugins: [react()],
|
|
89
87
|
define: createViteDefine(config),
|
|
90
88
|
resolve: {
|
|
91
89
|
alias: resolveAlias,
|
package/src/commands/start.js
CHANGED
|
@@ -10,7 +10,6 @@ import {
|
|
|
10
10
|
createPostCSSConfig,
|
|
11
11
|
createViteDefine,
|
|
12
12
|
resolvePackagePath,
|
|
13
|
-
inlineLazyImportsPlugin,
|
|
14
13
|
} from '../utils/index.js';
|
|
15
14
|
import { serviceWorkerDevPlugin } from '../utils/service-worker-plugin.js';
|
|
16
15
|
|
|
@@ -40,12 +39,7 @@ async function startServer(root, cwd, shouldOpen = false) {
|
|
|
40
39
|
|
|
41
40
|
const server = await createServer({
|
|
42
41
|
root: coreSrcPath,
|
|
43
|
-
|
|
44
|
-
plugins: [
|
|
45
|
-
inlineLazyImportsPlugin(),
|
|
46
|
-
react(),
|
|
47
|
-
serviceWorkerDevPlugin(corePackagePath, coreSrcPath),
|
|
48
|
-
],
|
|
42
|
+
plugins: [react(), serviceWorkerDevPlugin(corePackagePath, coreSrcPath)],
|
|
49
43
|
define: createViteDefine(config),
|
|
50
44
|
resolve: {
|
|
51
45
|
alias: createResolveAlias(),
|
|
@@ -59,12 +53,6 @@ async function startServer(root, cwd, shouldOpen = false) {
|
|
|
59
53
|
esbuild: {
|
|
60
54
|
sourcemap: false,
|
|
61
55
|
},
|
|
62
|
-
// Prevent Vite from pre-bundling @shellui/core when it's in node_modules
|
|
63
|
-
// We want our transform plugin to handle lazy imports, not esbuild's pre-bundler
|
|
64
|
-
// This ensures consistent behavior between workspace and npm-installed packages
|
|
65
|
-
optimizeDeps: {
|
|
66
|
-
exclude: ['@shellui/core'],
|
|
67
|
-
},
|
|
68
56
|
server: {
|
|
69
57
|
port: config.port || 3000,
|
|
70
58
|
open: shouldOpen,
|
package/src/utils/index.js
CHANGED
|
@@ -8,19 +8,17 @@ const require = createRequire(import.meta.url);
|
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
10
|
* Resolve the path to a package in the monorepo or node_modules
|
|
11
|
+
* Works in both workspace mode (monorepo) and npm-installed mode
|
|
11
12
|
* @param {string} packageName - The name of the package
|
|
12
13
|
* @returns {string} The absolute path to the package
|
|
13
14
|
*/
|
|
14
15
|
export function resolvePackagePath(packageName) {
|
|
15
16
|
try {
|
|
16
17
|
// Try to resolve the package using require.resolve
|
|
18
|
+
// This works for both workspace packages (via pnpm workspace) and npm-installed packages
|
|
17
19
|
const packageJsonPath = require.resolve(`${packageName}/package.json`);
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
// Fallback: assume workspace structure or pnpm symlinked node_modules
|
|
21
|
-
// Go up from cli/src/utils/package-path.js -> cli/src/utils -> cli/src -> cli -> packages -> packageName
|
|
22
|
-
const packagesDir = path.resolve(__dirname, '../../../');
|
|
23
|
-
const resolved = path.join(packagesDir, packageName.replace('@shellui/', ''));
|
|
20
|
+
const resolved = path.dirname(packageJsonPath);
|
|
21
|
+
|
|
24
22
|
// Resolve symlinks to get the canonical path — pnpm uses symlinks that
|
|
25
23
|
// point to different .pnpm/ directories; Vite resolves real paths so we
|
|
26
24
|
// need to be consistent to avoid mismatched root vs input paths.
|
|
@@ -29,6 +27,27 @@ export function resolvePackagePath(packageName) {
|
|
|
29
27
|
} catch {
|
|
30
28
|
return resolved;
|
|
31
29
|
}
|
|
30
|
+
} catch (e) {
|
|
31
|
+
// Fallback: assume workspace structure (for development in monorepo)
|
|
32
|
+
// Go up from cli/src/utils/package-path.js -> cli/src/utils -> cli/src -> cli -> packages -> packageName
|
|
33
|
+
const packagesDir = path.resolve(__dirname, '../../../');
|
|
34
|
+
const resolved = path.join(packagesDir, packageName.replace('@shellui/', ''));
|
|
35
|
+
|
|
36
|
+
// Only use this fallback if the path exists (workspace mode)
|
|
37
|
+
if (fs.existsSync(resolved)) {
|
|
38
|
+
try {
|
|
39
|
+
return fs.realpathSync(resolved);
|
|
40
|
+
} catch {
|
|
41
|
+
return resolved;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// If we get here, the package wasn't found
|
|
46
|
+
throw new Error(
|
|
47
|
+
`Package "${packageName}" not found. ` +
|
|
48
|
+
`Make sure it's installed (npm/pnpm install) or available in the workspace. ` +
|
|
49
|
+
`Original error: ${e.message}`
|
|
50
|
+
);
|
|
32
51
|
}
|
|
33
52
|
}
|
|
34
53
|
|
package/src/utils/vite.js
CHANGED
|
@@ -1,15 +1,36 @@
|
|
|
1
1
|
import path from 'path';
|
|
2
|
+
import fs from 'fs';
|
|
2
3
|
import tailwindcssPlugin from '@tailwindcss/postcss';
|
|
3
4
|
import autoprefixerPlugin from 'autoprefixer';
|
|
4
5
|
import { resolvePackagePath, resolveSdkEntry } from './index.js';
|
|
5
6
|
|
|
6
7
|
/**
|
|
7
8
|
* Get the path to the core package source directory
|
|
9
|
+
* Works in both workspace mode (monorepo) and npm-installed mode
|
|
8
10
|
* @returns {string} Absolute path to core package src directory
|
|
9
11
|
*/
|
|
10
12
|
export function getCoreSrcPath() {
|
|
11
13
|
const corePackagePath = resolvePackagePath('@shellui/core');
|
|
12
|
-
|
|
14
|
+
const srcPath = path.join(corePackagePath, 'src');
|
|
15
|
+
|
|
16
|
+
// Verify src directory exists (should always exist since it's in package.json files)
|
|
17
|
+
if (!fs.existsSync(srcPath)) {
|
|
18
|
+
throw new Error(
|
|
19
|
+
`Core package src directory not found at ${srcPath}. ` +
|
|
20
|
+
`Make sure @shellui/core is properly installed and includes the src directory.`
|
|
21
|
+
);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// Verify index.html exists (required for dev server)
|
|
25
|
+
const indexHtmlPath = path.join(srcPath, 'index.html');
|
|
26
|
+
if (!fs.existsSync(indexHtmlPath)) {
|
|
27
|
+
throw new Error(
|
|
28
|
+
`Core package index.html not found at ${indexHtmlPath}. ` +
|
|
29
|
+
`Make sure @shellui/core is properly installed.`
|
|
30
|
+
);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
return srcPath;
|
|
13
34
|
}
|
|
14
35
|
|
|
15
36
|
/**
|
|
@@ -1,104 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Plugin that converts lazy(() => import(...)) to direct imports.
|
|
3
|
-
* This prevents Rollup/Vite from creating code-split chunks, ensuring all rendering
|
|
4
|
-
* goes through App.tsx where ConfigProvider wraps everything.
|
|
5
|
-
*
|
|
6
|
-
* This is critical: when the library is consumed via npm, Vite processes the source files.
|
|
7
|
-
* If there are dynamic imports, it creates separate chunks that load separately, causing
|
|
8
|
-
* duplicate module instances and breaking React context (ConfigContext, SettingsContext, etc.).
|
|
9
|
-
*
|
|
10
|
-
* @returns {import('vite').Plugin} Vite plugin
|
|
11
|
-
*/
|
|
12
|
-
export function inlineLazyImportsPlugin() {
|
|
13
|
-
return {
|
|
14
|
-
name: 'inline-lazy-imports',
|
|
15
|
-
// Run before other transforms to ensure lazy imports are inlined early
|
|
16
|
-
enforce: 'pre',
|
|
17
|
-
// Apply to both dev and build modes
|
|
18
|
-
transform(code, id) {
|
|
19
|
-
// Only transform source files from @shellui/core
|
|
20
|
-
// Match paths that contain @shellui/core/src (works for both workspace and npm-installed)
|
|
21
|
-
// Also match router/routes files specifically since those contain the lazy imports
|
|
22
|
-
const isCoreSrc =
|
|
23
|
-
id.includes('@shellui/core/src') ||
|
|
24
|
-
id.includes('@shellui/core\\src') || // Windows paths
|
|
25
|
-
(id.includes('/src/') && id.match(/router[/\\]routes\.tsx?$/)) ||
|
|
26
|
-
(id.includes('/src/') && id.match(/router[/\\]router\.tsx?$/));
|
|
27
|
-
|
|
28
|
-
// Debug logging (remove after fixing)
|
|
29
|
-
if (id.includes('routes') && code.includes('lazy')) {
|
|
30
|
-
console.log(`[inline-lazy-imports] Processing: ${id}, isCoreSrc: ${isCoreSrc}`);
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
if (!isCoreSrc) {
|
|
34
|
-
return null;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
// Check if code contains lazy() calls - if not, skip
|
|
38
|
-
if (!code.includes('lazy(') || !code.includes('import(')) return null;
|
|
39
|
-
|
|
40
|
-
const imports = [];
|
|
41
|
-
let transformed = code;
|
|
42
|
-
let hasChanges = false;
|
|
43
|
-
|
|
44
|
-
// Match the exact pattern: const Name = lazy(() => import('path').then((m) => ({ default: m.Name })),);
|
|
45
|
-
// Strategy: Match the structure step by step, using non-greedy matching to stop at boundaries
|
|
46
|
-
// 1. Match: const Name = lazy(() =>
|
|
47
|
-
// 2. Match: import('path')
|
|
48
|
-
// 3. Match: .then((m) => ({ default: m.Name }))
|
|
49
|
-
// 4. Match: ,); or ); on new line
|
|
50
|
-
const lazyPattern =
|
|
51
|
-
/const\s+(\w+)\s*=\s*lazy\s*\(\s*\(\)\s*=>\s*[\s\n]*import\s*\((['"])([^'"]+)\2\)\s*\.then\s*\([\s\S]*?\(?\s*m\s*\)?\s*=>\s*\([\s\S]*?\{\s*default:\s*m\.(\w+)\s*\}[\s\S]*?\)[\s\S]*?\)\s*,?\s*[\s\n]*\)\s*;?\s*/g;
|
|
52
|
-
|
|
53
|
-
transformed = transformed.replace(
|
|
54
|
-
lazyPattern,
|
|
55
|
-
(fullMatch, varName, quote, importPath, componentName) => {
|
|
56
|
-
hasChanges = true;
|
|
57
|
-
|
|
58
|
-
// Debug: log what we're matching
|
|
59
|
-
if (id.includes('routes')) {
|
|
60
|
-
console.log(
|
|
61
|
-
`[inline-lazy-imports] Matched ${varName}:`,
|
|
62
|
-
fullMatch.replace(/\n/g, '\\n').substring(0, 150),
|
|
63
|
-
);
|
|
64
|
-
console.log(`[inline-lazy-imports] - importPath: ${importPath}`);
|
|
65
|
-
console.log(`[inline-lazy-imports] - componentName: ${componentName}`);
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
// Import with the same name as the variable (they match in the source code)
|
|
69
|
-
const importStatement = `import { ${componentName} as ${varName} } from ${quote}${importPath}${quote};`;
|
|
70
|
-
if (!imports.some((imp) => imp.includes(`${varName}`))) {
|
|
71
|
-
imports.push(importStatement);
|
|
72
|
-
}
|
|
73
|
-
// Remove the entire const declaration - return empty string to completely remove it
|
|
74
|
-
return '';
|
|
75
|
-
},
|
|
76
|
-
);
|
|
77
|
-
|
|
78
|
-
if (!hasChanges || imports.length === 0) return null;
|
|
79
|
-
|
|
80
|
-
// Prepend all imports at the top of the file (after any existing imports)
|
|
81
|
-
// Find the last import statement
|
|
82
|
-
const lastImportMatch = transformed.match(/^import\s+.*$/gm);
|
|
83
|
-
if (lastImportMatch) {
|
|
84
|
-
const lastImportIndex = transformed.lastIndexOf(
|
|
85
|
-
lastImportMatch[lastImportMatch.length - 1],
|
|
86
|
-
);
|
|
87
|
-
const insertIndex = transformed.indexOf('\n', lastImportIndex) + 1;
|
|
88
|
-
transformed =
|
|
89
|
-
transformed.slice(0, insertIndex) +
|
|
90
|
-
imports.join('\n') +
|
|
91
|
-
'\n' +
|
|
92
|
-
transformed.slice(insertIndex);
|
|
93
|
-
} else {
|
|
94
|
-
// No imports found, add at the top
|
|
95
|
-
transformed = imports.join('\n') + '\n' + transformed;
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
return {
|
|
99
|
-
code: transformed,
|
|
100
|
-
map: null,
|
|
101
|
-
};
|
|
102
|
-
},
|
|
103
|
-
};
|
|
104
|
-
}
|