@juuno-sdk/cli 1.0.6 ā 1.0.8
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/bin/cli-router.js +94 -0
- package/bin/cli.js +22 -233
- package/dist/cli/src/deploy/index.d.ts.map +1 -1
- package/dist/cli/src/deploy/index.js +4 -3
- package/dist/cli/src/info/index.d.ts +1 -1
- package/dist/cli/src/info/index.d.ts.map +1 -1
- package/dist/cli/src/info/index.js +8 -8
- package/dist/cli/src/list/index.d.ts +11 -0
- package/dist/cli/src/list/index.d.ts.map +1 -1
- package/dist/cli/src/list/index.js +12 -7
- package/dist/cli/src/simulator/index.d.ts +13 -0
- package/dist/cli/src/simulator/index.d.ts.map +1 -0
- package/dist/cli/src/simulator/index.js +136 -0
- package/dist/cli/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +3 -2
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared simulator logic for launching the app simulator.
|
|
3
|
+
* Used by both cli.js (production) and cli-dev.js (development).
|
|
4
|
+
*/
|
|
5
|
+
import { spawn } from 'child_process';
|
|
6
|
+
import { fileURLToPath } from 'url';
|
|
7
|
+
import { dirname, join } from 'path';
|
|
8
|
+
import { readFileSync, writeFileSync, mkdirSync, copyFileSync, readdirSync, rmSync, existsSync, statSync, } from 'fs';
|
|
9
|
+
import { tmpdir } from 'os';
|
|
10
|
+
/**
|
|
11
|
+
* Copy directory recursively.
|
|
12
|
+
*/
|
|
13
|
+
function copyDir(src, dest) {
|
|
14
|
+
const entries = readdirSync(src, { withFileTypes: true });
|
|
15
|
+
for (const entry of entries) {
|
|
16
|
+
const srcPath = join(src, entry.name);
|
|
17
|
+
const destPath = join(dest, entry.name);
|
|
18
|
+
if (entry.isDirectory()) {
|
|
19
|
+
mkdirSync(destPath, { recursive: true });
|
|
20
|
+
copyDir(srcPath, destPath);
|
|
21
|
+
}
|
|
22
|
+
else {
|
|
23
|
+
copyFileSync(srcPath, destPath);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
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
|
|
33
|
+
*/
|
|
34
|
+
export function launchSimulator(appUrl, port, distPath) {
|
|
35
|
+
// Validate that dist directory exists before attempting to copy.
|
|
36
|
+
if (!existsSync(distPath)) {
|
|
37
|
+
console.error(`Error: Build directory does not exist: ${distPath}`);
|
|
38
|
+
console.error('Please run "pnpm build" or "pnpm build:simulator" first.');
|
|
39
|
+
process.exit(1);
|
|
40
|
+
}
|
|
41
|
+
// Validate that dist path is actually a directory.
|
|
42
|
+
try {
|
|
43
|
+
const stats = statSync(distPath);
|
|
44
|
+
if (!stats.isDirectory()) {
|
|
45
|
+
console.error(`Error: Path exists but is not a directory: ${distPath}`);
|
|
46
|
+
process.exit(1);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
catch (error) {
|
|
50
|
+
console.error(`Error: Cannot access build directory: ${distPath}`);
|
|
51
|
+
console.error(`Details: ${error instanceof Error ? error.message : String(error)}`);
|
|
52
|
+
process.exit(1);
|
|
53
|
+
}
|
|
54
|
+
// Create a temporary directory for the modified dist.
|
|
55
|
+
const tempDir = join(tmpdir(), `juuno-simulator-${Date.now()}`);
|
|
56
|
+
mkdirSync(tempDir, { recursive: true });
|
|
57
|
+
// Copy all files from dist to temp directory.
|
|
58
|
+
copyDir(distPath, tempDir);
|
|
59
|
+
// Inject the app URL and import map CDN URLs into index.html.
|
|
60
|
+
const indexPath = join(tempDir, 'index.html');
|
|
61
|
+
// Verify index.html exists after copy.
|
|
62
|
+
if (!existsSync(indexPath)) {
|
|
63
|
+
console.error(`Error: index.html not found in build directory after copy`);
|
|
64
|
+
console.error(`Expected location: ${indexPath}`);
|
|
65
|
+
console.error('The build directory may be incomplete or corrupted.');
|
|
66
|
+
console.error('Please run "pnpm build" to rebuild the simulator.');
|
|
67
|
+
process.exit(1);
|
|
68
|
+
}
|
|
69
|
+
let indexHtml = readFileSync(indexPath, 'utf-8');
|
|
70
|
+
// Fill in the import map with CDN URLs for vue and @juuno-sdk/app-sdk.
|
|
71
|
+
indexHtml = indexHtml.replace('"vue": ""', '"vue": "https://cdn.jsdelivr.net/npm/vue@3.5.22/dist/vue.esm-browser.prod.js"');
|
|
72
|
+
indexHtml = indexHtml.replace('"@juuno-sdk/app-sdk": ""', '"@juuno-sdk/app-sdk": "https://cdn.jsdelivr.net/npm/@juuno-sdk/app-sdk@1.0.2/dist/index.js"');
|
|
73
|
+
// Fill in CDN URLs for externalized dependencies from the SDK.
|
|
74
|
+
indexHtml = indexHtml.replace('"@vueuse/core": ""', '"@vueuse/core": "https://cdn.jsdelivr.net/npm/@vueuse/core@11.4.1/index.mjs"');
|
|
75
|
+
indexHtml = indexHtml.replace('"@tiptap/vue-3": ""', '"@tiptap/vue-3": "https://cdn.jsdelivr.net/npm/@tiptap/vue-3@2.10.5/dist/index.js"');
|
|
76
|
+
indexHtml = indexHtml.replace('"@tiptap/starter-kit": ""', '"@tiptap/starter-kit": "https://cdn.jsdelivr.net/npm/@tiptap/starter-kit@2.10.5/dist/index.js"');
|
|
77
|
+
indexHtml = indexHtml.replace('"@tiptap/extension-underline": ""', '"@tiptap/extension-underline": "https://cdn.jsdelivr.net/npm/@tiptap/extension-underline@2.10.5/dist/index.js"');
|
|
78
|
+
indexHtml = indexHtml.replace('"lodash-es": ""', '"lodash-es": "https://cdn.jsdelivr.net/npm/lodash-es@4.17.21/lodash.js"');
|
|
79
|
+
indexHtml = indexHtml.replace('"date-fns": ""', '"date-fns": "https://cdn.jsdelivr.net/npm/date-fns@4.1.0/index.mjs"');
|
|
80
|
+
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}/player/index.js"`);
|
|
83
|
+
indexHtml = indexHtml.replace('"external-app/config": ""', `"external-app/config": "${appUrl}/config/index.js"`);
|
|
84
|
+
// Inject the app URL as a global variable before any scripts load.
|
|
85
|
+
const injection = `
|
|
86
|
+
<script>
|
|
87
|
+
window.__JUUNO_EXTERNAL_APP_URL__ = '${appUrl}';
|
|
88
|
+
</script>
|
|
89
|
+
`;
|
|
90
|
+
indexHtml = indexHtml.replace('</head>', `${injection}</head>`);
|
|
91
|
+
writeFileSync(indexPath, indexHtml);
|
|
92
|
+
console.log(`
|
|
93
|
+
š Juuno App Simulator Starting...
|
|
94
|
+
|
|
95
|
+
External App: ${appUrl}
|
|
96
|
+
Simulator URL: http://localhost:${port}
|
|
97
|
+
|
|
98
|
+
Press Ctrl+C to stop
|
|
99
|
+
`);
|
|
100
|
+
// Serve the modified temp directory.
|
|
101
|
+
const server = spawn('npx', ['sirv-cli', tempDir, '--port', port, '--cors', '--single'], {
|
|
102
|
+
stdio: 'inherit',
|
|
103
|
+
shell: true,
|
|
104
|
+
});
|
|
105
|
+
server.on('error', (err) => {
|
|
106
|
+
console.error('Failed to start server:', err);
|
|
107
|
+
process.exit(1);
|
|
108
|
+
});
|
|
109
|
+
server.on('exit', (code) => {
|
|
110
|
+
if (code !== 0) {
|
|
111
|
+
console.error(`Server exited with code ${code}`);
|
|
112
|
+
}
|
|
113
|
+
process.exit(code ?? 0);
|
|
114
|
+
});
|
|
115
|
+
// Cleanup function.
|
|
116
|
+
function cleanup() {
|
|
117
|
+
try {
|
|
118
|
+
rmSync(tempDir, { recursive: true, force: true });
|
|
119
|
+
}
|
|
120
|
+
catch (err) {
|
|
121
|
+
// Ignore cleanup errors.
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
// Handle termination.
|
|
125
|
+
process.on('SIGINT', () => {
|
|
126
|
+
console.log('\n\nš Stopping simulator...');
|
|
127
|
+
server.kill();
|
|
128
|
+
cleanup();
|
|
129
|
+
process.exit(0);
|
|
130
|
+
});
|
|
131
|
+
process.on('SIGTERM', () => {
|
|
132
|
+
server.kill();
|
|
133
|
+
cleanup();
|
|
134
|
+
process.exit(0);
|
|
135
|
+
});
|
|
136
|
+
}
|