@juuno-sdk/cli 1.0.5 ā 1.0.7
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 +204 -20
- package/bin/cli.js +79 -184
- package/dist/assets/main-B8xiNI5_.js +1 -0
- package/dist/assets/main-COSZCfRq.css +1 -0
- package/dist/cli/src/auth/index.d.ts +51 -0
- package/dist/cli/src/auth/index.d.ts.map +1 -0
- package/dist/cli/src/auth/index.js +156 -0
- package/dist/cli/src/deploy/index.d.ts +12 -0
- package/dist/cli/src/deploy/index.d.ts.map +1 -0
- package/dist/cli/src/deploy/index.js +129 -0
- package/dist/cli/src/info/index.d.ts +12 -0
- package/dist/cli/src/info/index.d.ts.map +1 -0
- package/dist/cli/src/info/index.js +111 -0
- package/dist/cli/src/list/index.d.ts +22 -0
- package/dist/cli/src/list/index.d.ts.map +1 -0
- package/dist/cli/src/list/index.js +102 -0
- package/dist/cli/src/login/index.d.ts +12 -0
- package/dist/cli/src/login/index.d.ts.map +1 -0
- package/dist/cli/src/login/index.js +61 -0
- package/dist/cli/src/logout/index.d.ts +5 -0
- package/dist/cli/src/logout/index.d.ts.map +1 -0
- package/dist/cli/src/logout/index.js +26 -0
- 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/src/whoami/index.d.ts +5 -0
- package/dist/cli/src/whoami/index.d.ts.map +1 -0
- package/dist/cli/src/whoami/index.js +24 -0
- package/dist/cli/tsconfig.build.tsbuildinfo +1 -0
- package/dist/index.html +2 -2
- package/package.json +8 -7
- package/dist/assets/main-BIR58A5i.css +0 -1
- package/dist/assets/main-BYDwbwR9.js +0 -1
- package/src/App.vue +0 -350
- package/src/deploy/index.ts +0 -202
- package/src/main.ts +0 -5
package/README.md
CHANGED
|
@@ -31,19 +31,49 @@ npx juuno-cli dev --app http://localhost:3000
|
|
|
31
31
|
npx juuno-cli dev --app https://cdn.example.com/my-app/
|
|
32
32
|
```
|
|
33
33
|
|
|
34
|
+
### Authentication
|
|
35
|
+
|
|
36
|
+
Login once to authenticate with Juuno. Your token will be saved and reused automatically.
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
# Login (one-time setup)
|
|
40
|
+
npx juuno-cli login
|
|
41
|
+
|
|
42
|
+
# Check authentication status
|
|
43
|
+
npx juuno-cli whoami
|
|
44
|
+
|
|
45
|
+
# Logout when needed
|
|
46
|
+
npx juuno-cli logout
|
|
47
|
+
```
|
|
48
|
+
|
|
34
49
|
### Deployment
|
|
35
50
|
|
|
36
|
-
Deploy your app to Juuno
|
|
51
|
+
Deploy your app to Juuno.
|
|
37
52
|
|
|
38
53
|
```bash
|
|
39
|
-
# Deploy
|
|
54
|
+
# Deploy (uses saved credentials from login)
|
|
40
55
|
npx juuno-cli deploy
|
|
41
56
|
|
|
42
57
|
# Specify build directory
|
|
43
58
|
npx juuno-cli deploy --build-dir ./build
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### List Apps
|
|
62
|
+
|
|
63
|
+
View all your deployed apps.
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
# List all apps (uses saved credentials)
|
|
67
|
+
npx juuno-cli list
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### App Info
|
|
71
|
+
|
|
72
|
+
Get detailed information about a specific app.
|
|
44
73
|
|
|
45
|
-
|
|
46
|
-
|
|
74
|
+
```bash
|
|
75
|
+
# Show app details (uses saved credentials)
|
|
76
|
+
npx juuno-cli info app_abc123
|
|
47
77
|
```
|
|
48
78
|
|
|
49
79
|
### npm Scripts
|
|
@@ -64,6 +94,9 @@ Add to your `package.json`:
|
|
|
64
94
|
Then run:
|
|
65
95
|
|
|
66
96
|
```bash
|
|
97
|
+
# One-time setup: Login to Juuno
|
|
98
|
+
npx juuno-cli login
|
|
99
|
+
|
|
67
100
|
# Terminal 1: Your app dev server
|
|
68
101
|
npm run dev
|
|
69
102
|
|
|
@@ -154,6 +187,35 @@ Options:
|
|
|
154
187
|
--help Show help
|
|
155
188
|
```
|
|
156
189
|
|
|
190
|
+
### Login Command
|
|
191
|
+
|
|
192
|
+
```bash
|
|
193
|
+
juuno-cli login [options]
|
|
194
|
+
|
|
195
|
+
Options:
|
|
196
|
+
--email <email> Your Juuno email (will prompt if not provided)
|
|
197
|
+
--password <pwd> Your Juuno password (will prompt if not provided)
|
|
198
|
+
--help Show help
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
Saves credentials to `~/.juuno/credentials.json` for automatic reuse.
|
|
202
|
+
|
|
203
|
+
### Logout Command
|
|
204
|
+
|
|
205
|
+
```bash
|
|
206
|
+
juuno-cli logout
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
Removes stored credentials from `~/.juuno/credentials.json`.
|
|
210
|
+
|
|
211
|
+
### Whoami Command
|
|
212
|
+
|
|
213
|
+
```bash
|
|
214
|
+
juuno-cli whoami
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
Shows current authentication status.
|
|
218
|
+
|
|
157
219
|
### Deploy Command
|
|
158
220
|
|
|
159
221
|
```bash
|
|
@@ -161,34 +223,129 @@ juuno-cli deploy [options]
|
|
|
161
223
|
|
|
162
224
|
Options:
|
|
163
225
|
--build-dir <dir> Build directory to deploy (default: ./dist)
|
|
164
|
-
--
|
|
226
|
+
--token <token> Override with specific token (for CI/CD)
|
|
227
|
+
--email <email> Login with email instead of using saved credentials
|
|
228
|
+
--password <pwd> Use with --email
|
|
229
|
+
--help Show help
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
### List Command
|
|
233
|
+
|
|
234
|
+
```bash
|
|
235
|
+
juuno-cli list [options]
|
|
236
|
+
|
|
237
|
+
Options:
|
|
238
|
+
--token <token> Override with specific token (for CI/CD)
|
|
239
|
+
--email <email> Login with email instead of using saved credentials
|
|
240
|
+
--password <pwd> Use with --email
|
|
165
241
|
--help Show help
|
|
166
242
|
```
|
|
167
243
|
|
|
244
|
+
### Info Command
|
|
245
|
+
|
|
246
|
+
```bash
|
|
247
|
+
juuno-cli info <app-id> [options]
|
|
248
|
+
|
|
249
|
+
Arguments:
|
|
250
|
+
<app-id> The app ID to get information about
|
|
251
|
+
|
|
252
|
+
Options:
|
|
253
|
+
--token <token> Override with specific token (for CI/CD)
|
|
254
|
+
--email <email> Login with email instead of using saved credentials
|
|
255
|
+
--password <pwd> Use with --email
|
|
256
|
+
--help Show help
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
## Environment Variables
|
|
260
|
+
|
|
261
|
+
```bash
|
|
262
|
+
# API endpoint (defaults to production)
|
|
263
|
+
export JUUNO_API_URL=https://api.juuno.co
|
|
264
|
+
|
|
265
|
+
# For staging
|
|
266
|
+
export JUUNO_API_URL=https://api.stage.juuno.co
|
|
267
|
+
|
|
268
|
+
# Authentication token (for CI/CD, overrides saved credentials)
|
|
269
|
+
export JUUNO_API_TOKEN=your-auth-token
|
|
270
|
+
```
|
|
271
|
+
|
|
168
272
|
## Deployment Workflow
|
|
169
273
|
|
|
170
|
-
|
|
171
|
-
2. **Deploy to CDN**: Use `juuno-cli deploy` to upload your app
|
|
172
|
-
3. **Get API key**: Obtain a Juuno API key from your account settings
|
|
173
|
-
4. **Configure in Juuno**: Add the returned manifest URL to your Juuno account
|
|
274
|
+
### Quick Start
|
|
174
275
|
|
|
175
276
|
```bash
|
|
176
|
-
#
|
|
277
|
+
# 1. Login once
|
|
278
|
+
npx juuno-cli login
|
|
279
|
+
|
|
280
|
+
# 2. Build and deploy
|
|
177
281
|
npm run build
|
|
178
282
|
npx juuno-cli deploy
|
|
179
283
|
|
|
180
|
-
#
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
# 3. Add manifest URL to Juuno account (SDK > Custom Apps)
|
|
284
|
+
# Deploy again anytime (no re-authentication needed)
|
|
285
|
+
npm run build
|
|
286
|
+
npx juuno-cli deploy
|
|
184
287
|
```
|
|
185
288
|
|
|
186
|
-
|
|
289
|
+
### Complete Flow
|
|
290
|
+
|
|
291
|
+
1. **Login**: Authenticate once with `juuno-cli login`
|
|
292
|
+
2. **Build**: Run your build command to generate the dist bundle
|
|
293
|
+
3. **Deploy**: Use `juuno-cli deploy` - automatically uses saved credentials
|
|
294
|
+
4. **Success**: Your app is deployed and ready to use
|
|
187
295
|
|
|
296
|
+
The CLI saves your authentication token to `~/.juuno/credentials.json` and reuses it automatically for subsequent commands.
|
|
297
|
+
|
|
298
|
+
## Authentication
|
|
299
|
+
|
|
300
|
+
### Primary Method: Login Command (Recommended)
|
|
301
|
+
|
|
302
|
+
```bash
|
|
303
|
+
# Login once
|
|
304
|
+
npx juuno-cli login
|
|
305
|
+
|
|
306
|
+
# All subsequent commands use saved credentials
|
|
307
|
+
npx juuno-cli deploy
|
|
308
|
+
npx juuno-cli list
|
|
309
|
+
npx juuno-cli info app_abc123
|
|
310
|
+
|
|
311
|
+
# Check login status
|
|
312
|
+
npx juuno-cli whoami
|
|
313
|
+
|
|
314
|
+
# Logout when needed
|
|
315
|
+
npx juuno-cli logout
|
|
188
316
|
```
|
|
189
|
-
|
|
317
|
+
|
|
318
|
+
### Alternative Methods
|
|
319
|
+
|
|
320
|
+
**For CI/CD (environment variable):**
|
|
321
|
+
|
|
322
|
+
```bash
|
|
323
|
+
export JUUNO_API_TOKEN=your-auth-token
|
|
324
|
+
npx juuno-cli deploy
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
**One-off commands (email/password):**
|
|
328
|
+
|
|
329
|
+
```bash
|
|
330
|
+
npx juuno-cli deploy --email user@example.com --password yourpassword
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
**Explicit token override:**
|
|
334
|
+
|
|
335
|
+
```bash
|
|
336
|
+
npx juuno-cli deploy --token your-auth-token
|
|
190
337
|
```
|
|
191
338
|
|
|
339
|
+
### Authentication Priority
|
|
340
|
+
|
|
341
|
+
The CLI checks for credentials in this order:
|
|
342
|
+
|
|
343
|
+
1. `--token` flag (explicit override)
|
|
344
|
+
2. `JUUNO_API_TOKEN` environment variable (CI/CD)
|
|
345
|
+
3. Saved credentials from `~/.juuno/credentials.json` (from `juuno-cli login`)
|
|
346
|
+
4. `--email` and `--password` flags (one-off login)
|
|
347
|
+
5. Error: "Not logged in"
|
|
348
|
+
|
|
192
349
|
## Troubleshooting
|
|
193
350
|
|
|
194
351
|
### CORS Errors
|
|
@@ -219,6 +376,17 @@ export { defaultMeta } from './settings';
|
|
|
219
376
|
|
|
220
377
|
The simulator uses import maps to load dependencies. If you see import errors, check that your app properly externalizes `vue` and `@juuno-sdk/app-sdk`.
|
|
221
378
|
|
|
379
|
+
### Authentication Errors
|
|
380
|
+
|
|
381
|
+
If you get authentication errors:
|
|
382
|
+
|
|
383
|
+
1. Run `juuno-cli login` to authenticate
|
|
384
|
+
2. Check login status with `juuno-cli whoami`
|
|
385
|
+
3. Verify your email and password are correct
|
|
386
|
+
4. Check that you have developer access to your Juuno account
|
|
387
|
+
5. Ensure `JUUNO_API_URL` points to the correct environment (if using staging)
|
|
388
|
+
6. If credentials are corrupted, run `juuno-cli logout` then `juuno-cli login` again
|
|
389
|
+
|
|
222
390
|
## Example
|
|
223
391
|
|
|
224
392
|
See [@juuno-sdk/app-sdk-example](../app-sdk-example) for a complete working example.
|
|
@@ -232,14 +400,30 @@ See [@juuno-sdk/app-sdk-example](../app-sdk-example) for a complete working exam
|
|
|
232
400
|
|
|
233
401
|
The CLI provides both programmatic and command-line interfaces:
|
|
234
402
|
|
|
235
|
-
- **CLI Commands**: `juuno-cli dev`, `juuno-cli deploy`
|
|
236
|
-
- **Programmatic API**: Import
|
|
403
|
+
- **CLI Commands**: `juuno-cli login`, `juuno-cli logout`, `juuno-cli whoami`, `juuno-cli dev`, `juuno-cli deploy`, `juuno-cli list`, `juuno-cli info`
|
|
404
|
+
- **Programmatic API**: Import functions for custom workflows
|
|
237
405
|
|
|
238
406
|
```typescript
|
|
239
|
-
import { deployApp } from '@juuno-sdk/cli';
|
|
407
|
+
import { deployApp, login, logout } from '@juuno-sdk/cli';
|
|
240
408
|
|
|
409
|
+
// Login and save credentials
|
|
410
|
+
await login({
|
|
411
|
+
email: 'user@example.com',
|
|
412
|
+
password: 'yourpassword',
|
|
413
|
+
});
|
|
414
|
+
|
|
415
|
+
// Deploy (uses saved credentials automatically)
|
|
241
416
|
await deployApp({
|
|
242
417
|
buildDir: './dist',
|
|
243
|
-
|
|
418
|
+
});
|
|
419
|
+
|
|
420
|
+
// Or override with specific token
|
|
421
|
+
await deployApp({
|
|
422
|
+
buildDir: './dist',
|
|
423
|
+
token: process.env.JUUNO_API_TOKEN,
|
|
244
424
|
});
|
|
245
425
|
```
|
|
426
|
+
|
|
427
|
+
## Development
|
|
428
|
+
|
|
429
|
+
See [DEVELOPMENT.md](./DEVELOPMENT.md) for local development, building, and publishing guidelines.
|
package/bin/cli.js
CHANGED
|
@@ -1,50 +1,19 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
import { spawn } from 'child_process';
|
|
4
3
|
import { fileURLToPath } from 'url';
|
|
5
4
|
import { dirname, join } from 'path';
|
|
6
|
-
import {
|
|
7
|
-
readFileSync,
|
|
8
|
-
writeFileSync,
|
|
9
|
-
mkdirSync,
|
|
10
|
-
copyFileSync,
|
|
11
|
-
readdirSync,
|
|
12
|
-
rmSync,
|
|
13
|
-
} from 'fs';
|
|
14
|
-
import { tmpdir } from 'os';
|
|
5
|
+
import { runCommand } from './cli-router.js';
|
|
15
6
|
|
|
16
7
|
const __filename = fileURLToPath(import.meta.url);
|
|
17
8
|
const __dirname = dirname(__filename);
|
|
18
9
|
|
|
19
|
-
// Parse command line arguments
|
|
10
|
+
// Parse command line arguments.
|
|
20
11
|
const args = process.argv.slice(2);
|
|
21
12
|
|
|
22
|
-
// Check if first argument is a command
|
|
13
|
+
// Check if first argument is a command.
|
|
23
14
|
const command = args[0];
|
|
24
15
|
|
|
25
|
-
// Handle
|
|
26
|
-
if (command === 'deploy') {
|
|
27
|
-
const { deployApp } = await import('../src/deploy/index.ts');
|
|
28
|
-
|
|
29
|
-
// Parse deploy options
|
|
30
|
-
const buildDirIndex = args.indexOf('--build-dir');
|
|
31
|
-
const apiKeyIndex = args.indexOf('--api-key');
|
|
32
|
-
|
|
33
|
-
const buildDir = buildDirIndex !== -1 ? args[buildDirIndex + 1] : './dist';
|
|
34
|
-
const apiKey = apiKeyIndex !== -1 ? args[apiKeyIndex + 1] : undefined;
|
|
35
|
-
|
|
36
|
-
await deployApp({ buildDir, apiKey });
|
|
37
|
-
process.exit(0);
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
// Handle simulator command (default behavior)
|
|
41
|
-
// Remove the command from args if it was 'dev'
|
|
42
|
-
if (command === 'dev') {
|
|
43
|
-
args.shift();
|
|
44
|
-
}
|
|
45
|
-
const appUrlIndex = args.indexOf('--app');
|
|
46
|
-
const portIndex = args.indexOf('--port');
|
|
47
|
-
|
|
16
|
+
// Handle help command.
|
|
48
17
|
if (args.includes('--help') || args.includes('-h') || command === 'help') {
|
|
49
18
|
console.log(`
|
|
50
19
|
Juuno CLI - Official CLI for Juuno external app development
|
|
@@ -53,30 +22,93 @@ Usage:
|
|
|
53
22
|
juuno-cli <command> [options]
|
|
54
23
|
|
|
55
24
|
Commands:
|
|
25
|
+
login Authenticate with Juuno
|
|
26
|
+
logout Remove stored credentials
|
|
27
|
+
whoami Show authentication status
|
|
56
28
|
dev Launch the app simulator (default)
|
|
57
|
-
deploy Deploy your app to Juuno
|
|
29
|
+
deploy Deploy your app to Juuno
|
|
30
|
+
list List your deployed apps
|
|
31
|
+
info <app-id> Show detailed information about an app
|
|
58
32
|
help Show this help message
|
|
59
33
|
|
|
34
|
+
Authentication Commands:
|
|
35
|
+
login [--email <email>] [--password <pwd>]
|
|
36
|
+
Authenticate and save credentials to ~/.juuno/credentials.json
|
|
37
|
+
Subsequent commands will use the saved token automatically.
|
|
38
|
+
|
|
39
|
+
logout
|
|
40
|
+
Remove stored credentials.
|
|
41
|
+
|
|
42
|
+
whoami
|
|
43
|
+
Show current authentication status.
|
|
44
|
+
|
|
60
45
|
Simulator Options:
|
|
61
46
|
--app <url> URL of your external app (required)
|
|
62
47
|
--port <number> Port for simulator (default: 5004)
|
|
63
48
|
|
|
64
49
|
Deploy Options:
|
|
65
|
-
--build-dir <dir>
|
|
66
|
-
|
|
50
|
+
--build-dir <dir> Build directory to deploy (default: ./dist)
|
|
51
|
+
|
|
52
|
+
Authentication Options (for deploy, list, info):
|
|
53
|
+
By default, these commands use the token saved by 'juuno-cli login'.
|
|
54
|
+
You can override with:
|
|
55
|
+
--token <token> Use specific token (for CI/CD)
|
|
56
|
+
--email <email> Login with email/password (skips saved token)
|
|
57
|
+
--password <pwd> Use with --email
|
|
58
|
+
|
|
59
|
+
Environment Variables:
|
|
60
|
+
JUUNO_API_URL API URL (default: https://api.juuno.co)
|
|
61
|
+
JUUNO_API_TOKEN Authentication token (for CI/CD, skips saved credentials)
|
|
67
62
|
|
|
68
63
|
Examples:
|
|
64
|
+
# Authenticate (one-time setup)
|
|
65
|
+
juuno-cli login
|
|
66
|
+
|
|
69
67
|
# Start simulator
|
|
70
68
|
juuno-cli dev --app http://localhost:3000
|
|
71
|
-
juuno-cli --app http://localhost:3000
|
|
72
69
|
|
|
73
|
-
# Deploy app
|
|
70
|
+
# Deploy app (uses saved credentials)
|
|
74
71
|
juuno-cli deploy
|
|
75
|
-
juuno-cli deploy --build-dir ./dist
|
|
72
|
+
juuno-cli deploy --build-dir ./dist
|
|
73
|
+
|
|
74
|
+
# List apps (uses saved credentials)
|
|
75
|
+
juuno-cli list
|
|
76
|
+
|
|
77
|
+
# Show app info (uses saved credentials)
|
|
78
|
+
juuno-cli info app_abc123
|
|
79
|
+
|
|
80
|
+
# Check authentication status
|
|
81
|
+
juuno-cli whoami
|
|
82
|
+
|
|
83
|
+
# Logout
|
|
84
|
+
juuno-cli logout
|
|
76
85
|
`);
|
|
77
86
|
process.exit(0);
|
|
78
87
|
}
|
|
79
88
|
|
|
89
|
+
// Handle commands via shared router (uses built JS imports for production).
|
|
90
|
+
if (
|
|
91
|
+
command === 'login' ||
|
|
92
|
+
command === 'logout' ||
|
|
93
|
+
command === 'whoami' ||
|
|
94
|
+
command === 'deploy' ||
|
|
95
|
+
command === 'list' ||
|
|
96
|
+
command === 'info'
|
|
97
|
+
) {
|
|
98
|
+
const exitCode = await runCommand(command, args, '../dist/cli/src/');
|
|
99
|
+
process.exit(exitCode);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// Handle simulator command (default behavior).
|
|
103
|
+
// Remove the command from args if it was 'dev'.
|
|
104
|
+
let simulatorArgs = args;
|
|
105
|
+
if (command === 'dev') {
|
|
106
|
+
simulatorArgs = args.slice(1);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
const appUrlIndex = simulatorArgs.indexOf('--app');
|
|
110
|
+
const portIndex = simulatorArgs.indexOf('--port');
|
|
111
|
+
|
|
80
112
|
if (appUrlIndex === -1) {
|
|
81
113
|
console.error('Error: --app parameter is required for simulator');
|
|
82
114
|
console.error('Usage: juuno-cli dev --app <url>');
|
|
@@ -84,154 +116,17 @@ if (appUrlIndex === -1) {
|
|
|
84
116
|
process.exit(1);
|
|
85
117
|
}
|
|
86
118
|
|
|
87
|
-
const appUrl =
|
|
88
|
-
const port = portIndex !== -1 ?
|
|
119
|
+
const appUrl = simulatorArgs[appUrlIndex + 1];
|
|
120
|
+
const port = portIndex !== -1 ? simulatorArgs[portIndex + 1] : '5004';
|
|
89
121
|
|
|
90
122
|
if (!appUrl) {
|
|
91
123
|
console.error('Error: --app parameter requires a URL value');
|
|
92
124
|
process.exit(1);
|
|
93
125
|
}
|
|
94
126
|
|
|
95
|
-
// Path to the built dist directory
|
|
127
|
+
// Path to the built dist directory.
|
|
96
128
|
const distPath = join(__dirname, '..', 'dist');
|
|
97
129
|
|
|
98
|
-
//
|
|
99
|
-
const
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
// Copy all files from dist to temp directory
|
|
103
|
-
function copyDir(src, dest) {
|
|
104
|
-
const entries = readdirSync(src, { withFileTypes: true });
|
|
105
|
-
|
|
106
|
-
for (const entry of entries) {
|
|
107
|
-
const srcPath = join(src, entry.name);
|
|
108
|
-
const destPath = join(dest, entry.name);
|
|
109
|
-
|
|
110
|
-
if (entry.isDirectory()) {
|
|
111
|
-
mkdirSync(destPath, { recursive: true });
|
|
112
|
-
copyDir(srcPath, destPath);
|
|
113
|
-
} else {
|
|
114
|
-
copyFileSync(srcPath, destPath);
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
copyDir(distPath, tempDir);
|
|
120
|
-
|
|
121
|
-
// Inject the app URL and import map CDN URLs into index.html
|
|
122
|
-
const indexPath = join(tempDir, 'index.html');
|
|
123
|
-
let indexHtml = readFileSync(indexPath, 'utf-8');
|
|
124
|
-
|
|
125
|
-
// Fill in the import map with CDN URLs for vue and @juuno-sdk/app-sdk
|
|
126
|
-
indexHtml = indexHtml.replace(
|
|
127
|
-
'"vue": ""',
|
|
128
|
-
'"vue": "https://cdn.jsdelivr.net/npm/vue@3.5.22/dist/vue.esm-browser.prod.js"',
|
|
129
|
-
);
|
|
130
|
-
indexHtml = indexHtml.replace(
|
|
131
|
-
'"@juuno-sdk/app-sdk": ""',
|
|
132
|
-
'"@juuno-sdk/app-sdk": "https://cdn.jsdelivr.net/npm/@juuno-sdk/app-sdk@1.0.2/dist/index.js"',
|
|
133
|
-
);
|
|
134
|
-
|
|
135
|
-
// Fill in CDN URLs for externalized dependencies from the SDK
|
|
136
|
-
indexHtml = indexHtml.replace(
|
|
137
|
-
'"@vueuse/core": ""',
|
|
138
|
-
'"@vueuse/core": "https://cdn.jsdelivr.net/npm/@vueuse/core@11.4.1/index.mjs"',
|
|
139
|
-
);
|
|
140
|
-
indexHtml = indexHtml.replace(
|
|
141
|
-
'"@tiptap/vue-3": ""',
|
|
142
|
-
'"@tiptap/vue-3": "https://cdn.jsdelivr.net/npm/@tiptap/vue-3@2.10.5/dist/index.js"',
|
|
143
|
-
);
|
|
144
|
-
indexHtml = indexHtml.replace(
|
|
145
|
-
'"@tiptap/starter-kit": ""',
|
|
146
|
-
'"@tiptap/starter-kit": "https://cdn.jsdelivr.net/npm/@tiptap/starter-kit@2.10.5/dist/index.js"',
|
|
147
|
-
);
|
|
148
|
-
indexHtml = indexHtml.replace(
|
|
149
|
-
'"@tiptap/extension-underline": ""',
|
|
150
|
-
'"@tiptap/extension-underline": "https://cdn.jsdelivr.net/npm/@tiptap/extension-underline@2.10.5/dist/index.js"',
|
|
151
|
-
);
|
|
152
|
-
indexHtml = indexHtml.replace(
|
|
153
|
-
'"lodash-es": ""',
|
|
154
|
-
'"lodash-es": "https://cdn.jsdelivr.net/npm/lodash-es@4.17.21/lodash.js"',
|
|
155
|
-
);
|
|
156
|
-
indexHtml = indexHtml.replace(
|
|
157
|
-
'"date-fns": ""',
|
|
158
|
-
'"date-fns": "https://cdn.jsdelivr.net/npm/date-fns@4.1.0/index.mjs"',
|
|
159
|
-
);
|
|
160
|
-
indexHtml = indexHtml.replace(
|
|
161
|
-
'"url-parse": ""',
|
|
162
|
-
'"url-parse": "https://cdn.jsdelivr.net/npm/url-parse@1.5.10/dist/url-parse.min.js"',
|
|
163
|
-
);
|
|
164
|
-
|
|
165
|
-
// Fill in the import map with external app entrypoints
|
|
166
|
-
indexHtml = indexHtml.replace(
|
|
167
|
-
'"external-app/player": ""',
|
|
168
|
-
`"external-app/player": "${appUrl}/player/index.js"`,
|
|
169
|
-
);
|
|
170
|
-
indexHtml = indexHtml.replace(
|
|
171
|
-
'"external-app/config": ""',
|
|
172
|
-
`"external-app/config": "${appUrl}/config/index.js"`,
|
|
173
|
-
);
|
|
174
|
-
|
|
175
|
-
// Inject the app URL as a global variable before any scripts load
|
|
176
|
-
const injection = `
|
|
177
|
-
<script>
|
|
178
|
-
window.__JUUNO_EXTERNAL_APP_URL__ = '${appUrl}';
|
|
179
|
-
</script>
|
|
180
|
-
`;
|
|
181
|
-
|
|
182
|
-
indexHtml = indexHtml.replace('</head>', `${injection}</head>`);
|
|
183
|
-
writeFileSync(indexPath, indexHtml);
|
|
184
|
-
|
|
185
|
-
console.log(`
|
|
186
|
-
š Juuno App Simulator Starting...
|
|
187
|
-
|
|
188
|
-
External App: ${appUrl}
|
|
189
|
-
Simulator URL: http://localhost:${port}
|
|
190
|
-
|
|
191
|
-
Press Ctrl+C to stop
|
|
192
|
-
`);
|
|
193
|
-
|
|
194
|
-
// Serve the modified temp directory
|
|
195
|
-
const server = spawn(
|
|
196
|
-
'npx',
|
|
197
|
-
['sirv-cli', tempDir, '--port', port, '--cors', '--single'],
|
|
198
|
-
{
|
|
199
|
-
stdio: 'inherit',
|
|
200
|
-
shell: true,
|
|
201
|
-
},
|
|
202
|
-
);
|
|
203
|
-
|
|
204
|
-
server.on('error', (err) => {
|
|
205
|
-
console.error('Failed to start server:', err);
|
|
206
|
-
process.exit(1);
|
|
207
|
-
});
|
|
208
|
-
|
|
209
|
-
server.on('exit', (code) => {
|
|
210
|
-
if (code !== 0) {
|
|
211
|
-
console.error(`Server exited with code ${code}`);
|
|
212
|
-
}
|
|
213
|
-
process.exit(code);
|
|
214
|
-
});
|
|
215
|
-
|
|
216
|
-
// Cleanup function
|
|
217
|
-
function cleanup() {
|
|
218
|
-
try {
|
|
219
|
-
rmSync(tempDir, { recursive: true, force: true });
|
|
220
|
-
} catch (err) {
|
|
221
|
-
// Ignore cleanup errors
|
|
222
|
-
}
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
// Handle termination
|
|
226
|
-
process.on('SIGINT', () => {
|
|
227
|
-
console.log('\n\nš Stopping simulator...');
|
|
228
|
-
server.kill();
|
|
229
|
-
cleanup();
|
|
230
|
-
process.exit(0);
|
|
231
|
-
});
|
|
232
|
-
|
|
233
|
-
process.on('SIGTERM', () => {
|
|
234
|
-
server.kill();
|
|
235
|
-
cleanup();
|
|
236
|
-
process.exit(0);
|
|
237
|
-
});
|
|
130
|
+
// Launch simulator (imports from built JS).
|
|
131
|
+
const { launchSimulator } = await import('../dist/cli/src/simulator/index.js');
|
|
132
|
+
launchSimulator(appUrl, port, distPath);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{defineComponent as A,ref as g,shallowRef as y,reactive as P,onMounted as k,createElementBlock as f,openBlock as d,createElementVNode as t,toDisplayString as _,createTextVNode as h,createBlock as E,resolveDynamicComponent as x,createApp as O}from"vue";import{provideAppConfigContext as I}from"@juuno-sdk/app-sdk";(function(){const a=document.createElement("link").relList;if(a&&a.supports&&a.supports("modulepreload"))return;for(const o of document.querySelectorAll('link[rel="modulepreload"]'))u(o);new MutationObserver(o=>{for(const r of o)if(r.type==="childList")for(const l of r.addedNodes)l.tagName==="LINK"&&l.rel==="modulepreload"&&u(l)}).observe(document,{childList:!0,subtree:!0});function i(o){const r={};return o.integrity&&(r.integrity=o.integrity),o.referrerPolicy&&(r.referrerPolicy=o.referrerPolicy),o.crossOrigin==="use-credentials"?r.credentials="include":o.crossOrigin==="anonymous"?r.credentials="omit":r.credentials="same-origin",r}function u(o){if(o.ep)return;o.ep=!0;const r=i(o);fetch(o.href,r)}})();const b="modulepreload",R=function(p){return"/"+p},C={},L=function(a,i,u){let o=Promise.resolve();if(i&&i.length>0){let l=function(n){return Promise.all(n.map(e=>Promise.resolve(e).then(m=>({status:"fulfilled",value:m}),m=>({status:"rejected",reason:m}))))};document.getElementsByTagName("link");const s=document.querySelector("meta[property=csp-nonce]"),v=(s==null?void 0:s.nonce)||(s==null?void 0:s.getAttribute("nonce"));o=l(i.map(n=>{if(n=R(n),n in C)return;C[n]=!0;const e=n.endsWith(".css"),m=e?'[rel="stylesheet"]':"";if(document.querySelector(`link[href="${n}"]${m}`))return;const c=document.createElement("link");if(c.rel=e?"stylesheet":b,e||(c.as="script"),c.crossOrigin="",c.href=n,v&&c.setAttribute("nonce",v),document.head.appendChild(c),e)return new Promise((w,S)=>{c.addEventListener("load",w),c.addEventListener("error",()=>S(new Error(`Unable to preload CSS for ${n}`)))})}))}function r(l){const s=new Event("vite:preloadError",{cancelable:!0});if(s.payload=l,window.dispatchEvent(s),!s.defaultPrevented)throw l}return o.then(l=>{for(const s of l||[])s.status==="rejected"&&r(s.reason);return a().catch(r)})},U={class:"juuno-cli"},N={class:"header"},T={class:"header-content"},j={class:"header-info"},D={class:"app-url"},V={key:0,class:"loading-state"},q={class:"url-info"},B={key:1,class:"error-state"},F={class:"error-message"},J={class:"error-details"},$={key:2,class:"container"},M={class:"player-section"},K={class:"player-preview"},W={key:1,class:"placeholder"},X={class:"config-section"},z={class:"config-panel"},G={key:1,class:"placeholder"},H={name:"JuunoCLI"},Q=A({...H,setup(p){const a=g(window.__JUUNO_EXTERNAL_APP_URL__||"http://localhost:5002/index.js"),i=y(null),u=y(null),o=g(!0),r=g(null),l=P({idx:"simulator-scene-1",name:"Simulator Test Scene",app:null,app_idx:"simulator-app-1",created_at:new Date().toISOString(),display_time:5e3,language:"en",order:0,playlist_idx:"simulator-playlist-1",updated_at:new Date().toISOString(),translations:{},meta:{title:"Test App",backgroundColor:"#2c3e50",textColor:"#ecf0f1"},mediaAssets:[]}),v=I({async save(n){console.log("Simulator: Scene updated",n),Object.assign(l,n)}},{scene:l});return k(async()=>{try{o.value=!0,r.value=null,console.log(`Loading external app from: ${a.value}`);const n=await L(()=>import("external-app/player"),[]);if(i.value=n.default,!i.value)throw new Error("External app must export a default component from /player");try{const e=await L(()=>import("external-app/config"),[]);u.value=e.default||null}catch(e){console.warn("Config component not found or failed to load:",e),u.value=null}v.load(l),console.log("ā
External app loaded successfully"),o.value=!1}catch(n){console.error("Failed to load external app:",n),r.value=n instanceof Error?n.message:"Failed to load external app",o.value=!1}}),(n,e)=>(d(),f("div",U,[t("header",N,[t("div",T,[e[0]||(e[0]=t("h1",null,"Juuno CLI",-1)),t("div",j,[t("span",D,_(a.value),1)])])]),o.value?(d(),f("div",V,[e[1]||(e[1]=t("div",{class:"spinner"},null,-1)),e[2]||(e[2]=t("p",null,"Loading external app...",-1)),t("p",q,_(a.value),1)])):r.value?(d(),f("div",B,[e[6]||(e[6]=t("div",{class:"error-icon"},"ā ļø",-1)),e[7]||(e[7]=t("h2",null,"Failed to Load App",-1)),t("p",F,_(r.value),1),t("div",J,[t("p",null,[e[3]||(e[3]=t("strong",null,"App URL:",-1)),h(" "+_(a.value),1)]),e[4]||(e[4]=t("p",null,[t("strong",null,"Common Issues:")],-1)),e[5]||(e[5]=t("ul",null,[t("li",null,"App dev server not running"),t("li",null,"CORS not enabled on app dev server"),t("li",null," App doesn't export required components from /player and /config "),t("li",null,"Incorrect URL provided"),t("li",null,"Missing exports field in package.json")],-1))])])):(d(),f("div",$,[t("div",M,[e[8]||(e[8]=t("h2",null,"Player View",-1)),t("div",K,[i.value?(d(),E(x(i.value),{key:0,scene:l},null,8,["scene"])):(d(),f("div",W,"No player component found"))])]),t("div",X,[e[9]||(e[9]=t("h2",null,"Configuration UI",-1)),t("div",z,[u.value?(d(),E(x(u.value),{key:0})):(d(),f("div",G,"No config component found"))])])])),e[10]||(e[10]=t("footer",{class:"footer"},[t("p",null,[t("strong",null,"Juuno CLI"),h(" - Test your external app in a production-like environment ")])],-1))]))}}),Y=(p,a)=>{const i=p.__vccOpts||p;for(const[u,o]of a)i[u]=o;return i},Z=Y(Q,[["__scopeId","data-v-5e08f5e3"]]),ee=O(Z);ee.mount("#app");
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
[data-v-5e08f5e3]{box-sizing:border-box}.juuno-cli[data-v-5e08f5e3]{min-height:100vh;display:flex;flex-direction:column;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,sans-serif;background-color:#f5f5f5}.header[data-v-5e08f5e3]{background:linear-gradient(135deg,#667eea,#764ba2);color:#fff;padding:1.5rem 2rem;box-shadow:0 2px 4px #0000001a}.header-content[data-v-5e08f5e3]{max-width:1600px;margin:0 auto}.header h1[data-v-5e08f5e3]{margin:0 0 .5rem;font-size:1.75rem;font-weight:600}.header-info[data-v-5e08f5e3]{display:flex;justify-content:space-between;align-items:center;gap:1rem}.app-url[data-v-5e08f5e3]{font-size:.875rem;opacity:.9;font-family:Courier New,monospace}.loading-state[data-v-5e08f5e3],.error-state[data-v-5e08f5e3]{flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;padding:3rem;text-align:center}.spinner[data-v-5e08f5e3]{width:50px;height:50px;border:4px solid #f3f3f3;border-top:4px solid #667eea;border-radius:50%;animation:spin-5e08f5e3 1s linear infinite}@keyframes spin-5e08f5e3{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.url-info[data-v-5e08f5e3]{margin-top:1rem;font-size:.875rem;color:#666;font-family:Courier New,monospace}.error-icon[data-v-5e08f5e3]{font-size:4rem;margin-bottom:1rem}.error-message[data-v-5e08f5e3]{color:#d32f2f;font-weight:500;margin:1rem 0}.error-details[data-v-5e08f5e3]{background:#fff;border-radius:8px;padding:1.5rem;margin-top:2rem;text-align:left;max-width:600px}.error-details ul[data-v-5e08f5e3]{margin:.5rem 0 0 1.5rem;padding:0}.error-details li[data-v-5e08f5e3]{margin:.25rem 0}.container[data-v-5e08f5e3]{flex:1;display:grid;grid-template-columns:1fr 1fr;gap:2rem;padding:2rem;max-width:1600px;margin:0 auto;width:100%}.player-section[data-v-5e08f5e3],.config-section[data-v-5e08f5e3]{background:#fff;border-radius:8px;padding:1.5rem;box-shadow:0 1px 3px #0000001a}.player-section h2[data-v-5e08f5e3],.config-section h2[data-v-5e08f5e3]{margin:0 0 1rem;font-size:1.25rem;font-weight:600;color:#333}.player-preview[data-v-5e08f5e3]{aspect-ratio:16 / 9;background:#000;border-radius:4px;overflow:hidden;box-shadow:0 4px 6px #0000001a}.config-panel[data-v-5e08f5e3]{background:#fafafa;border-radius:4px;padding:1rem;min-height:400px}.placeholder[data-v-5e08f5e3]{display:flex;align-items:center;justify-content:center;height:100%;color:#999;font-style:italic}.footer[data-v-5e08f5e3]{background:#fff;padding:1.5rem;text-align:center;border-top:1px solid #e0e0e0;color:#666;font-size:.875rem}.footer p[data-v-5e08f5e3]{margin:0}@media (max-width: 1200px){.container[data-v-5e08f5e3]{grid-template-columns:1fr}}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Authentication credentials for the developer API.
|
|
3
|
+
*/
|
|
4
|
+
export interface AuthCredentials {
|
|
5
|
+
email: string;
|
|
6
|
+
password: string;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Authentication token response from the API.
|
|
10
|
+
*/
|
|
11
|
+
export interface AuthTokenResponse {
|
|
12
|
+
success: boolean;
|
|
13
|
+
token: string;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Options for authentication.
|
|
17
|
+
*/
|
|
18
|
+
export interface AuthOptions {
|
|
19
|
+
email?: string;
|
|
20
|
+
password?: string;
|
|
21
|
+
token?: string;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Saves authentication token to local credentials file.
|
|
25
|
+
*/
|
|
26
|
+
export declare function saveToken(token: string): void;
|
|
27
|
+
/**
|
|
28
|
+
* Loads authentication token from local credentials file.
|
|
29
|
+
*/
|
|
30
|
+
export declare function loadToken(): string | null;
|
|
31
|
+
/**
|
|
32
|
+
* Removes stored credentials file.
|
|
33
|
+
*/
|
|
34
|
+
export declare function removeToken(): void;
|
|
35
|
+
/**
|
|
36
|
+
* Checks if user is currently logged in.
|
|
37
|
+
*/
|
|
38
|
+
export declare function isLoggedIn(): boolean;
|
|
39
|
+
/**
|
|
40
|
+
* Gets the API URL from environment or uses default.
|
|
41
|
+
*/
|
|
42
|
+
export declare function getApiUrl(): string;
|
|
43
|
+
/**
|
|
44
|
+
* Gets the authentication token from options, environment, or stored credentials.
|
|
45
|
+
*/
|
|
46
|
+
export declare function getAuthToken(options: AuthOptions): Promise<string>;
|
|
47
|
+
/**
|
|
48
|
+
* Authenticates with the developer API using email and password.
|
|
49
|
+
*/
|
|
50
|
+
export declare function loginWithCredentials(credentials: AuthCredentials): Promise<string>;
|
|
51
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/auth/index.ts"],"names":[],"mappings":"AAWA;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;CACf;AAED;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AA6BD;;GAEG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAa7C;AAED;;GAEG;AACH,wBAAgB,SAAS,IAAI,MAAM,GAAG,IAAI,CAczC;AAED;;GAEG;AACH,wBAAgB,WAAW,IAAI,IAAI,CAMlC;AAED;;GAEG;AACH,wBAAgB,UAAU,IAAI,OAAO,CAEpC;AAED;;GAEG;AACH,wBAAgB,SAAS,IAAI,MAAM,CAElC;AAED;;GAEG;AACH,wBAAsB,YAAY,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,CAuBxE;AAiCD;;GAEG;AACH,wBAAsB,oBAAoB,CACxC,WAAW,EAAE,eAAe,GAC3B,OAAO,CAAC,MAAM,CAAC,CAoCjB"}
|