@juuno-sdk/cli 1.0.5 ā 1.0.6
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 +147 -41
- 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 +128 -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 +11 -0
- package/dist/cli/src/list/index.d.ts.map +1 -0
- package/dist/cli/src/list/index.js +97 -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/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
|
@@ -16,35 +16,26 @@ import { tmpdir } from 'os';
|
|
|
16
16
|
const __filename = fileURLToPath(import.meta.url);
|
|
17
17
|
const __dirname = dirname(__filename);
|
|
18
18
|
|
|
19
|
-
// Parse command line arguments
|
|
19
|
+
// Parse command line arguments.
|
|
20
20
|
const args = process.argv.slice(2);
|
|
21
21
|
|
|
22
|
-
// Check if first argument is a command
|
|
22
|
+
// Check if first argument is a command.
|
|
23
23
|
const command = args[0];
|
|
24
24
|
|
|
25
|
-
//
|
|
26
|
-
|
|
27
|
-
const
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
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();
|
|
25
|
+
// Helper function to parse auth options from args.
|
|
26
|
+
function parseAuthOptions(args) {
|
|
27
|
+
const emailIndex = args.indexOf('--email');
|
|
28
|
+
const passwordIndex = args.indexOf('--password');
|
|
29
|
+
const tokenIndex = args.indexOf('--token');
|
|
30
|
+
|
|
31
|
+
return {
|
|
32
|
+
email: emailIndex !== -1 ? args[emailIndex + 1] : undefined,
|
|
33
|
+
password: passwordIndex !== -1 ? args[passwordIndex + 1] : undefined,
|
|
34
|
+
token: tokenIndex !== -1 ? args[tokenIndex + 1] : undefined,
|
|
35
|
+
};
|
|
44
36
|
}
|
|
45
|
-
const appUrlIndex = args.indexOf('--app');
|
|
46
|
-
const portIndex = args.indexOf('--port');
|
|
47
37
|
|
|
38
|
+
// Handle help command.
|
|
48
39
|
if (args.includes('--help') || args.includes('-h') || command === 'help') {
|
|
49
40
|
console.log(`
|
|
50
41
|
Juuno CLI - Official CLI for Juuno external app development
|
|
@@ -53,30 +44,145 @@ Usage:
|
|
|
53
44
|
juuno-cli <command> [options]
|
|
54
45
|
|
|
55
46
|
Commands:
|
|
47
|
+
login Authenticate with Juuno
|
|
48
|
+
logout Remove stored credentials
|
|
49
|
+
whoami Show authentication status
|
|
56
50
|
dev Launch the app simulator (default)
|
|
57
|
-
deploy Deploy your app to Juuno
|
|
51
|
+
deploy Deploy your app to Juuno
|
|
52
|
+
list List your deployed apps
|
|
53
|
+
info <app-id> Show detailed information about an app
|
|
58
54
|
help Show this help message
|
|
59
55
|
|
|
56
|
+
Authentication Commands:
|
|
57
|
+
login [--email <email>] [--password <pwd>]
|
|
58
|
+
Authenticate and save credentials to ~/.juuno/credentials.json
|
|
59
|
+
Subsequent commands will use the saved token automatically.
|
|
60
|
+
|
|
61
|
+
logout
|
|
62
|
+
Remove stored credentials.
|
|
63
|
+
|
|
64
|
+
whoami
|
|
65
|
+
Show current authentication status.
|
|
66
|
+
|
|
60
67
|
Simulator Options:
|
|
61
68
|
--app <url> URL of your external app (required)
|
|
62
69
|
--port <number> Port for simulator (default: 5004)
|
|
63
70
|
|
|
64
71
|
Deploy Options:
|
|
65
|
-
--build-dir <dir>
|
|
66
|
-
|
|
72
|
+
--build-dir <dir> Build directory to deploy (default: ./dist)
|
|
73
|
+
|
|
74
|
+
Authentication Options (for deploy, list, info):
|
|
75
|
+
By default, these commands use the token saved by 'juuno-cli login'.
|
|
76
|
+
You can override with:
|
|
77
|
+
--token <token> Use specific token (for CI/CD)
|
|
78
|
+
--email <email> Login with email/password (skips saved token)
|
|
79
|
+
--password <pwd> Use with --email
|
|
80
|
+
|
|
81
|
+
Environment Variables:
|
|
82
|
+
JUUNO_API_URL API URL (default: https://api.juuno.co)
|
|
83
|
+
JUUNO_API_TOKEN Authentication token (for CI/CD, skips saved credentials)
|
|
67
84
|
|
|
68
85
|
Examples:
|
|
86
|
+
# Authenticate (one-time setup)
|
|
87
|
+
juuno-cli login
|
|
88
|
+
|
|
69
89
|
# Start simulator
|
|
70
90
|
juuno-cli dev --app http://localhost:3000
|
|
71
|
-
juuno-cli --app http://localhost:3000
|
|
72
91
|
|
|
73
|
-
# Deploy app
|
|
92
|
+
# Deploy app (uses saved credentials)
|
|
74
93
|
juuno-cli deploy
|
|
75
|
-
juuno-cli deploy --build-dir ./dist
|
|
94
|
+
juuno-cli deploy --build-dir ./dist
|
|
95
|
+
|
|
96
|
+
# List apps (uses saved credentials)
|
|
97
|
+
juuno-cli list
|
|
98
|
+
|
|
99
|
+
# Show app info (uses saved credentials)
|
|
100
|
+
juuno-cli info app_abc123
|
|
101
|
+
|
|
102
|
+
# Check authentication status
|
|
103
|
+
juuno-cli whoami
|
|
104
|
+
|
|
105
|
+
# Logout
|
|
106
|
+
juuno-cli logout
|
|
76
107
|
`);
|
|
77
108
|
process.exit(0);
|
|
78
109
|
}
|
|
79
110
|
|
|
111
|
+
// Handle login command.
|
|
112
|
+
if (command === 'login') {
|
|
113
|
+
const { login } = await import('../dist/cli/src/login/index.js');
|
|
114
|
+
|
|
115
|
+
const authOptions = parseAuthOptions(args);
|
|
116
|
+
|
|
117
|
+
await login({ email: authOptions.email, password: authOptions.password });
|
|
118
|
+
process.exit(0);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// Handle logout command.
|
|
122
|
+
if (command === 'logout') {
|
|
123
|
+
const { logout } = await import('../dist/cli/src/logout/index.js');
|
|
124
|
+
|
|
125
|
+
await logout();
|
|
126
|
+
process.exit(0);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// Handle whoami command.
|
|
130
|
+
if (command === 'whoami') {
|
|
131
|
+
const { whoami } = await import('../dist/cli/src/whoami/index.js');
|
|
132
|
+
|
|
133
|
+
await whoami();
|
|
134
|
+
process.exit(0);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// Handle deploy command.
|
|
138
|
+
if (command === 'deploy') {
|
|
139
|
+
const { deployApp } = await import('../dist/cli/src/deploy/index.js');
|
|
140
|
+
|
|
141
|
+
const buildDirIndex = args.indexOf('--build-dir');
|
|
142
|
+
const buildDir = buildDirIndex !== -1 ? args[buildDirIndex + 1] : './dist';
|
|
143
|
+
|
|
144
|
+
const authOptions = parseAuthOptions(args);
|
|
145
|
+
|
|
146
|
+
await deployApp({ buildDir, ...authOptions });
|
|
147
|
+
process.exit(0);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// Handle list command.
|
|
151
|
+
if (command === 'list') {
|
|
152
|
+
const { listApps } = await import('../dist/cli/src/list/index.js');
|
|
153
|
+
|
|
154
|
+
const authOptions = parseAuthOptions(args);
|
|
155
|
+
|
|
156
|
+
await listApps(authOptions);
|
|
157
|
+
process.exit(0);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// Handle info command.
|
|
161
|
+
if (command === 'info') {
|
|
162
|
+
const { getAppInfo } = await import('../dist/cli/src/info/index.js');
|
|
163
|
+
|
|
164
|
+
const appIdx = args[1];
|
|
165
|
+
|
|
166
|
+
if (!appIdx || appIdx.startsWith('--')) {
|
|
167
|
+
console.error('Error: App ID is required');
|
|
168
|
+
console.error('Usage: juuno-cli info <app-id> [options]');
|
|
169
|
+
process.exit(1);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
const authOptions = parseAuthOptions(args);
|
|
173
|
+
|
|
174
|
+
await getAppInfo({ appIdx, ...authOptions });
|
|
175
|
+
process.exit(0);
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
// Handle simulator command (default behavior).
|
|
179
|
+
// Remove the command from args if it was 'dev'.
|
|
180
|
+
if (command === 'dev') {
|
|
181
|
+
args.shift();
|
|
182
|
+
}
|
|
183
|
+
const appUrlIndex = args.indexOf('--app');
|
|
184
|
+
const portIndex = args.indexOf('--port');
|
|
185
|
+
|
|
80
186
|
if (appUrlIndex === -1) {
|
|
81
187
|
console.error('Error: --app parameter is required for simulator');
|
|
82
188
|
console.error('Usage: juuno-cli dev --app <url>');
|
|
@@ -92,14 +198,14 @@ if (!appUrl) {
|
|
|
92
198
|
process.exit(1);
|
|
93
199
|
}
|
|
94
200
|
|
|
95
|
-
// Path to the built dist directory
|
|
201
|
+
// Path to the built dist directory.
|
|
96
202
|
const distPath = join(__dirname, '..', 'dist');
|
|
97
203
|
|
|
98
|
-
// Create a temporary directory for the modified dist
|
|
204
|
+
// Create a temporary directory for the modified dist.
|
|
99
205
|
const tempDir = join(tmpdir(), `juuno-simulator-${Date.now()}`);
|
|
100
206
|
mkdirSync(tempDir, { recursive: true });
|
|
101
207
|
|
|
102
|
-
// Copy all files from dist to temp directory
|
|
208
|
+
// Copy all files from dist to temp directory.
|
|
103
209
|
function copyDir(src, dest) {
|
|
104
210
|
const entries = readdirSync(src, { withFileTypes: true });
|
|
105
211
|
|
|
@@ -118,11 +224,11 @@ function copyDir(src, dest) {
|
|
|
118
224
|
|
|
119
225
|
copyDir(distPath, tempDir);
|
|
120
226
|
|
|
121
|
-
// Inject the app URL and import map CDN URLs into index.html
|
|
227
|
+
// Inject the app URL and import map CDN URLs into index.html.
|
|
122
228
|
const indexPath = join(tempDir, 'index.html');
|
|
123
229
|
let indexHtml = readFileSync(indexPath, 'utf-8');
|
|
124
230
|
|
|
125
|
-
// Fill in the import map with CDN URLs for vue and @juuno-sdk/app-sdk
|
|
231
|
+
// Fill in the import map with CDN URLs for vue and @juuno-sdk/app-sdk.
|
|
126
232
|
indexHtml = indexHtml.replace(
|
|
127
233
|
'"vue": ""',
|
|
128
234
|
'"vue": "https://cdn.jsdelivr.net/npm/vue@3.5.22/dist/vue.esm-browser.prod.js"',
|
|
@@ -132,7 +238,7 @@ indexHtml = indexHtml.replace(
|
|
|
132
238
|
'"@juuno-sdk/app-sdk": "https://cdn.jsdelivr.net/npm/@juuno-sdk/app-sdk@1.0.2/dist/index.js"',
|
|
133
239
|
);
|
|
134
240
|
|
|
135
|
-
// Fill in CDN URLs for externalized dependencies from the SDK
|
|
241
|
+
// Fill in CDN URLs for externalized dependencies from the SDK.
|
|
136
242
|
indexHtml = indexHtml.replace(
|
|
137
243
|
'"@vueuse/core": ""',
|
|
138
244
|
'"@vueuse/core": "https://cdn.jsdelivr.net/npm/@vueuse/core@11.4.1/index.mjs"',
|
|
@@ -162,7 +268,7 @@ indexHtml = indexHtml.replace(
|
|
|
162
268
|
'"url-parse": "https://cdn.jsdelivr.net/npm/url-parse@1.5.10/dist/url-parse.min.js"',
|
|
163
269
|
);
|
|
164
270
|
|
|
165
|
-
// Fill in the import map with external app entrypoints
|
|
271
|
+
// Fill in the import map with external app entrypoints.
|
|
166
272
|
indexHtml = indexHtml.replace(
|
|
167
273
|
'"external-app/player": ""',
|
|
168
274
|
`"external-app/player": "${appUrl}/player/index.js"`,
|
|
@@ -172,7 +278,7 @@ indexHtml = indexHtml.replace(
|
|
|
172
278
|
`"external-app/config": "${appUrl}/config/index.js"`,
|
|
173
279
|
);
|
|
174
280
|
|
|
175
|
-
// Inject the app URL as a global variable before any scripts load
|
|
281
|
+
// Inject the app URL as a global variable before any scripts load.
|
|
176
282
|
const injection = `
|
|
177
283
|
<script>
|
|
178
284
|
window.__JUUNO_EXTERNAL_APP_URL__ = '${appUrl}';
|
|
@@ -191,7 +297,7 @@ console.log(`
|
|
|
191
297
|
Press Ctrl+C to stop
|
|
192
298
|
`);
|
|
193
299
|
|
|
194
|
-
// Serve the modified temp directory
|
|
300
|
+
// Serve the modified temp directory.
|
|
195
301
|
const server = spawn(
|
|
196
302
|
'npx',
|
|
197
303
|
['sirv-cli', tempDir, '--port', port, '--cors', '--single'],
|
|
@@ -213,16 +319,16 @@ server.on('exit', (code) => {
|
|
|
213
319
|
process.exit(code);
|
|
214
320
|
});
|
|
215
321
|
|
|
216
|
-
// Cleanup function
|
|
322
|
+
// Cleanup function.
|
|
217
323
|
function cleanup() {
|
|
218
324
|
try {
|
|
219
325
|
rmSync(tempDir, { recursive: true, force: true });
|
|
220
326
|
} catch (err) {
|
|
221
|
-
// Ignore cleanup errors
|
|
327
|
+
// Ignore cleanup errors.
|
|
222
328
|
}
|
|
223
329
|
}
|
|
224
330
|
|
|
225
|
-
// Handle termination
|
|
331
|
+
// Handle termination.
|
|
226
332
|
process.on('SIGINT', () => {
|
|
227
333
|
console.log('\n\nš Stopping simulator...');
|
|
228
334
|
server.kill();
|
|
@@ -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"}
|