@juuno-sdk/cli 1.0.7 → 1.0.10
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 +80 -41
- package/bin/cli-router.js +94 -0
- package/bin/cli.js +62 -36
- package/dist/assets/main-B2BPnfea.js +1 -0
- package/dist/assets/main-Bf2N9gBQ.js +1 -0
- package/dist/assets/main-Bo8Yyr87.js +1 -0
- package/dist/assets/main-C3hW0d-b.css +1 -0
- package/dist/assets/main-C6ZAJydH.js +1 -0
- package/dist/assets/main-CCYNXtGp.css +1 -0
- package/dist/assets/main-CnpUG-52.js +1 -0
- package/dist/assets/main-D0353jp3.js +1 -0
- package/dist/assets/main-D7UD6CXw.css +1 -0
- package/dist/assets/main-DC3n4QV-.css +1 -0
- package/dist/assets/main-DWrNgA-L.js +1 -0
- package/dist/assets/main-HbFBqUMx.js +1 -0
- package/dist/assets/main-jQYqLcLk.js +1 -0
- package/dist/assets/main-n0Bs5Mcx.css +1 -0
- package/dist/cli/src/deploy/index.d.ts.map +1 -1
- package/dist/cli/src/deploy/index.js +84 -9
- package/dist/cli/src/dev/index.d.ts +24 -0
- package/dist/cli/src/dev/index.d.ts.map +1 -0
- package/dist/cli/src/dev/index.js +197 -0
- package/dist/cli/src/monorepo/index.d.ts +37 -0
- package/dist/cli/src/monorepo/index.d.ts.map +1 -0
- package/dist/cli/src/monorepo/index.js +94 -0
- package/dist/cli/src/simulator/index.d.ts +18 -7
- package/dist/cli/src/simulator/index.d.ts.map +1 -1
- package/dist/cli/src/simulator/index.js +47 -21
- package/dist/cli/src/utils/fs.d.ts +12 -0
- package/dist/cli/src/utils/fs.d.ts.map +1 -0
- package/dist/cli/src/utils/fs.js +29 -0
- package/dist/cli/tsconfig.build.tsbuildinfo +1 -1
- package/dist/index.html +2 -2
- package/package.json +14 -12
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Monorepo detection and Vite dev server launcher for internal app development.
|
|
3
|
+
*
|
|
4
|
+
* When running in the Juuno monorepo, this uses Vite's dev server instead of
|
|
5
|
+
* the built simulator, allowing local @juuno/* packages to be resolved from
|
|
6
|
+
* the workspace.
|
|
7
|
+
*/
|
|
8
|
+
import { spawn } from 'child_process';
|
|
9
|
+
import { existsSync } from 'fs';
|
|
10
|
+
import { join, resolve } from 'path';
|
|
11
|
+
import { findFileUpward } from '../utils/fs.js';
|
|
12
|
+
/**
|
|
13
|
+
* Detect if we're running in the Juuno monorepo.
|
|
14
|
+
*/
|
|
15
|
+
export function detectMonorepo(cwd) {
|
|
16
|
+
// Look for pnpm-workspace.yaml which indicates monorepo root.
|
|
17
|
+
const workspaceFile = findFileUpward(cwd, 'pnpm-workspace.yaml');
|
|
18
|
+
if (!workspaceFile) {
|
|
19
|
+
return { isMonorepo: false, workspaceRoot: null, cliPath: null };
|
|
20
|
+
}
|
|
21
|
+
const workspaceRoot = resolve(workspaceFile, '..');
|
|
22
|
+
// Check if the CLI package exists in the expected location.
|
|
23
|
+
const cliPath = join(workspaceRoot, 'external', 'cli');
|
|
24
|
+
if (!existsSync(join(cliPath, 'package.json'))) {
|
|
25
|
+
return { isMonorepo: false, workspaceRoot: null, cliPath: null };
|
|
26
|
+
}
|
|
27
|
+
// Check for key monorepo packages to confirm it's the Juuno monorepo.
|
|
28
|
+
const hasCore = existsSync(join(workspaceRoot, 'packages', 'core'));
|
|
29
|
+
const hasCommon = existsSync(join(workspaceRoot, 'packages', 'common'));
|
|
30
|
+
if (!hasCore || !hasCommon) {
|
|
31
|
+
return { isMonorepo: false, workspaceRoot: null, cliPath: null };
|
|
32
|
+
}
|
|
33
|
+
return { isMonorepo: true, workspaceRoot, cliPath };
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Fetch the app manifest to get actual resource paths.
|
|
37
|
+
*/
|
|
38
|
+
async function fetchManifest(appUrl) {
|
|
39
|
+
try {
|
|
40
|
+
const response = await fetch(`${appUrl}/manifest.json`);
|
|
41
|
+
if (!response.ok) {
|
|
42
|
+
return null;
|
|
43
|
+
}
|
|
44
|
+
return await response.json();
|
|
45
|
+
}
|
|
46
|
+
catch {
|
|
47
|
+
return null;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Launch the simulator service (monorepo mode).
|
|
52
|
+
*
|
|
53
|
+
* This uses the internal simulator service which has full monorepo support
|
|
54
|
+
* for @juuno/* packages, GraphQL, Sass, etc.
|
|
55
|
+
*/
|
|
56
|
+
export async function launchMonorepoSimulator(options) {
|
|
57
|
+
const { appUrl, port, workspaceRoot, watchDir } = options;
|
|
58
|
+
// Fetch manifest to get actual resource paths.
|
|
59
|
+
console.log('📦 Fetching app manifest...');
|
|
60
|
+
const manifest = await fetchManifest(appUrl);
|
|
61
|
+
const playerPath = manifest?.resources?.player?.[0] || '/player/index.js';
|
|
62
|
+
const configPath = manifest?.resources?.config?.[0] || '/config/index.js';
|
|
63
|
+
console.log(`
|
|
64
|
+
🚀 Juuno App Simulator (Monorepo Mode)
|
|
65
|
+
|
|
66
|
+
External App: ${appUrl}
|
|
67
|
+
Player: ${appUrl}${playerPath}
|
|
68
|
+
Config: ${appUrl}${configPath}
|
|
69
|
+
Simulator: http://localhost:${port}
|
|
70
|
+
Watching: ${watchDir || 'disabled'}
|
|
71
|
+
Mode: Internal simulator service (full @juuno/* support)
|
|
72
|
+
|
|
73
|
+
Press Ctrl+C to stop
|
|
74
|
+
`);
|
|
75
|
+
// Set environment variables for the simulator service.
|
|
76
|
+
const env = {
|
|
77
|
+
...process.env,
|
|
78
|
+
VITE_EXTERNAL_APP_URL: appUrl,
|
|
79
|
+
VITE_EXTERNAL_PLAYER_PATH: playerPath,
|
|
80
|
+
VITE_EXTERNAL_CONFIG_PATH: configPath,
|
|
81
|
+
VITE_WATCH_DIR: watchDir || '',
|
|
82
|
+
};
|
|
83
|
+
// Run the simulator service from the workspace root.
|
|
84
|
+
const simulatorProcess = spawn('pnpm', ['--filter', '@juuno/simulator', 'run', 'dev', '--port', port], {
|
|
85
|
+
cwd: workspaceRoot,
|
|
86
|
+
stdio: 'inherit',
|
|
87
|
+
shell: false,
|
|
88
|
+
env,
|
|
89
|
+
});
|
|
90
|
+
simulatorProcess.on('error', (err) => {
|
|
91
|
+
console.error(`[simulator] Error: ${err.message}`);
|
|
92
|
+
});
|
|
93
|
+
return simulatorProcess;
|
|
94
|
+
}
|
|
@@ -1,13 +1,24 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Simulator logic for launching the app simulator.
|
|
3
3
|
* Used by both cli.js (production) and cli-dev.js (development).
|
|
4
4
|
*/
|
|
5
5
|
/**
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* @param appUrl - URL of the external app to load
|
|
9
|
-
* @param port - Port to run the simulator on
|
|
10
|
-
* @param distPath - Path to the built dist directory
|
|
6
|
+
* Options for launching the simulator.
|
|
11
7
|
*/
|
|
12
|
-
export
|
|
8
|
+
export interface SimulatorOptions {
|
|
9
|
+
/** URL of the external app to load. */
|
|
10
|
+
appUrl: string;
|
|
11
|
+
/** Port to run the simulator on. */
|
|
12
|
+
port: string;
|
|
13
|
+
/** Path to the built simulator dist directory. */
|
|
14
|
+
distPath: string;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Launch the app simulator with optional live reload.
|
|
18
|
+
*/
|
|
19
|
+
export declare function launchSimulator(appUrl: string, port: string, distPath: string): Promise<void>;
|
|
20
|
+
/**
|
|
21
|
+
* Launch the app simulator with full options object.
|
|
22
|
+
*/
|
|
23
|
+
export declare function launchSimulatorWithOptions(options: SimulatorOptions): Promise<void>;
|
|
13
24
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/simulator/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/simulator/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAmCH;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,uCAAuC;IACvC,MAAM,EAAE,MAAM,CAAC;IACf,oCAAoC;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,kDAAkD;IAClD,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;GAEG;AACH,wBAAgB,eAAe,CAC7B,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,iBAGjB;AA2BD;;GAEG;AACH,wBAAsB,0BAA0B,CAAC,OAAO,EAAE,gBAAgB,iBAyKzE"}
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Simulator logic for launching the app simulator.
|
|
3
3
|
* Used by both cli.js (production) and cli-dev.js (development).
|
|
4
4
|
*/
|
|
5
5
|
import { spawn } from 'child_process';
|
|
6
|
-
import {
|
|
7
|
-
import { dirname, join } from 'path';
|
|
6
|
+
import { join } from 'path';
|
|
8
7
|
import { readFileSync, writeFileSync, mkdirSync, copyFileSync, readdirSync, rmSync, existsSync, statSync, } from 'fs';
|
|
9
8
|
import { tmpdir } from 'os';
|
|
10
9
|
/**
|
|
@@ -25,13 +24,37 @@ function copyDir(src, dest) {
|
|
|
25
24
|
}
|
|
26
25
|
}
|
|
27
26
|
/**
|
|
28
|
-
* Launch the app simulator.
|
|
29
|
-
*
|
|
30
|
-
* @param appUrl - URL of the external app to load
|
|
31
|
-
* @param port - Port to run the simulator on
|
|
32
|
-
* @param distPath - Path to the built dist directory
|
|
27
|
+
* Launch the app simulator with optional live reload.
|
|
33
28
|
*/
|
|
34
29
|
export function launchSimulator(appUrl, port, distPath) {
|
|
30
|
+
return launchSimulatorWithOptions({ appUrl, port, distPath });
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Fetch the app manifest to get actual resource paths.
|
|
34
|
+
*/
|
|
35
|
+
async function fetchManifest(appUrl) {
|
|
36
|
+
try {
|
|
37
|
+
const response = await fetch(`${appUrl}/manifest.json`);
|
|
38
|
+
if (!response.ok) {
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
return await response.json();
|
|
42
|
+
}
|
|
43
|
+
catch {
|
|
44
|
+
return null;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Launch the app simulator with full options object.
|
|
49
|
+
*/
|
|
50
|
+
export async function launchSimulatorWithOptions(options) {
|
|
51
|
+
const { appUrl, port, distPath } = options;
|
|
52
|
+
// Fetch manifest to get actual resource paths.
|
|
53
|
+
const manifest = await fetchManifest(appUrl);
|
|
54
|
+
const playerJs = manifest?.resources?.player?.find((p) => p.endsWith('.js'));
|
|
55
|
+
const configJs = manifest?.resources?.config?.find((p) => p.endsWith('.js'));
|
|
56
|
+
const playerPath = playerJs || '/player.js';
|
|
57
|
+
const configPath = configJs || '/config.js';
|
|
35
58
|
// Validate that dist directory exists before attempting to copy.
|
|
36
59
|
if (!existsSync(distPath)) {
|
|
37
60
|
console.error(`Error: Build directory does not exist: ${distPath}`);
|
|
@@ -78,29 +101,31 @@ export function launchSimulator(appUrl, port, distPath) {
|
|
|
78
101
|
indexHtml = indexHtml.replace('"lodash-es": ""', '"lodash-es": "https://cdn.jsdelivr.net/npm/lodash-es@4.17.21/lodash.js"');
|
|
79
102
|
indexHtml = indexHtml.replace('"date-fns": ""', '"date-fns": "https://cdn.jsdelivr.net/npm/date-fns@4.1.0/index.mjs"');
|
|
80
103
|
indexHtml = indexHtml.replace('"url-parse": ""', '"url-parse": "https://cdn.jsdelivr.net/npm/url-parse@1.5.10/dist/url-parse.min.js"');
|
|
81
|
-
// Fill in the import map with external app entrypoints.
|
|
82
|
-
indexHtml = indexHtml.replace('"external-app/player": ""', `"external-app/player": "${appUrl}
|
|
83
|
-
indexHtml = indexHtml.replace('"external-app/config": ""', `"external-app/config": "${appUrl}
|
|
84
|
-
// Inject the app URL as a global variable
|
|
85
|
-
|
|
104
|
+
// Fill in the import map with external app entrypoints (from manifest or defaults).
|
|
105
|
+
indexHtml = indexHtml.replace('"external-app/player": ""', `"external-app/player": "${appUrl}${playerPath}"`);
|
|
106
|
+
indexHtml = indexHtml.replace('"external-app/config": ""', `"external-app/config": "${appUrl}${configPath}"`);
|
|
107
|
+
// Inject the app URL as a global variable.
|
|
108
|
+
// Use JSON.stringify for safe injection into JavaScript.
|
|
109
|
+
const appUrlScript = `
|
|
86
110
|
<script>
|
|
87
|
-
window.__JUUNO_EXTERNAL_APP_URL__ =
|
|
111
|
+
window.__JUUNO_EXTERNAL_APP_URL__ = ${JSON.stringify(appUrl)};
|
|
88
112
|
</script>
|
|
89
113
|
`;
|
|
90
|
-
indexHtml = indexHtml.replace('</head>', `${
|
|
114
|
+
indexHtml = indexHtml.replace('</head>', `${appUrlScript}</head>`);
|
|
91
115
|
writeFileSync(indexPath, indexHtml);
|
|
92
116
|
console.log(`
|
|
93
|
-
🚀 Juuno App Simulator
|
|
117
|
+
🚀 Juuno App Simulator
|
|
94
118
|
|
|
95
|
-
External App:
|
|
96
|
-
Simulator
|
|
119
|
+
External App: ${appUrl}
|
|
120
|
+
Simulator: http://localhost:${port}
|
|
97
121
|
|
|
98
122
|
Press Ctrl+C to stop
|
|
99
123
|
`);
|
|
100
124
|
// Serve the modified temp directory.
|
|
101
|
-
|
|
125
|
+
// Use npx serve with --single for SPA routing.
|
|
126
|
+
const server = spawn('npx', ['-y', 'serve', tempDir, '-l', port, '--cors', '--single'], {
|
|
102
127
|
stdio: 'inherit',
|
|
103
|
-
shell:
|
|
128
|
+
shell: false,
|
|
104
129
|
});
|
|
105
130
|
server.on('error', (err) => {
|
|
106
131
|
console.error('Failed to start server:', err);
|
|
@@ -114,10 +139,11 @@ export function launchSimulator(appUrl, port, distPath) {
|
|
|
114
139
|
});
|
|
115
140
|
// Cleanup function.
|
|
116
141
|
function cleanup() {
|
|
142
|
+
// Remove temp directory.
|
|
117
143
|
try {
|
|
118
144
|
rmSync(tempDir, { recursive: true, force: true });
|
|
119
145
|
}
|
|
120
|
-
catch
|
|
146
|
+
catch {
|
|
121
147
|
// Ignore cleanup errors.
|
|
122
148
|
}
|
|
123
149
|
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* File system utilities for the Juuno CLI.
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Find a file by walking up the directory tree.
|
|
6
|
+
*
|
|
7
|
+
* @param startDir - The directory to start searching from.
|
|
8
|
+
* @param filename - The name of the file to find.
|
|
9
|
+
* @returns The full path to the file if found, or null if not found.
|
|
10
|
+
*/
|
|
11
|
+
export declare function findFileUpward(startDir: string, filename: string): string | null;
|
|
12
|
+
//# sourceMappingURL=fs.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fs.d.ts","sourceRoot":"","sources":["../../../../src/utils/fs.ts"],"names":[],"mappings":"AAAA;;GAEG;AAKH;;;;;;GAMG;AACH,wBAAgB,cAAc,CAC5B,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,GACf,MAAM,GAAG,IAAI,CAkBf"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* File system utilities for the Juuno CLI.
|
|
3
|
+
*/
|
|
4
|
+
import { existsSync } from 'fs';
|
|
5
|
+
import { join, resolve } from 'path';
|
|
6
|
+
/**
|
|
7
|
+
* Find a file by walking up the directory tree.
|
|
8
|
+
*
|
|
9
|
+
* @param startDir - The directory to start searching from.
|
|
10
|
+
* @param filename - The name of the file to find.
|
|
11
|
+
* @returns The full path to the file if found, or null if not found.
|
|
12
|
+
*/
|
|
13
|
+
export function findFileUpward(startDir, filename) {
|
|
14
|
+
let dir = startDir;
|
|
15
|
+
const root = '/';
|
|
16
|
+
while (dir !== root) {
|
|
17
|
+
const filePath = join(dir, filename);
|
|
18
|
+
if (existsSync(filePath)) {
|
|
19
|
+
return filePath;
|
|
20
|
+
}
|
|
21
|
+
const parent = resolve(dir, '..');
|
|
22
|
+
// Prevent infinite loop if we can't go up further.
|
|
23
|
+
if (parent === dir) {
|
|
24
|
+
break;
|
|
25
|
+
}
|
|
26
|
+
dir = parent;
|
|
27
|
+
}
|
|
28
|
+
return null;
|
|
29
|
+
}
|