@embeddables/cli 0.7.5 → 0.7.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/.prompts/embeddables-cli.md +5 -3
- package/dist/cli.js +23 -0
- package/dist/proxy/server.d.ts.map +1 -1
- package/dist/proxy/server.js +15 -1
- package/package.json +1 -1
|
@@ -307,8 +307,10 @@ Note: If you need to use any breakpoints other than 720px and 520px, you must ad
|
|
|
307
307
|
|
|
308
308
|
Whenever you need to insert an image or icon (e.g. a logo, an icon, a larger image) you have the following options:
|
|
309
309
|
|
|
310
|
-
1. `emojiIcon` with an emoji when there is an appropriate emoji that you can use. This can be used in
|
|
311
|
-
2. Image URL.
|
|
310
|
+
1. `emojiIcon` with an emoji when there is an appropriate emoji that you can use. This can be used in CustomButton, or inside OptionSelector buttons.
|
|
311
|
+
2. Image URL. Use **`imageUrl`** (not `imgSrc` or `imageSrc`) for button images: `imageUrl` in CustomButton, or `imageUrl` on each button in OptionSelector. For standalone images use `src` in MediaImage.
|
|
312
|
+
|
|
313
|
+
Using the wrong property name (e.g. `imgSrc`) will cause save/validation errors; the schema only accepts `imageUrl` for buttons.
|
|
312
314
|
|
|
313
315
|
For placeholder images, the recommended service is placehold.co:
|
|
314
316
|
|
|
@@ -358,7 +360,7 @@ Note: button icons and checkboxes are before text in the button, unless you set
|
|
|
358
360
|
| `ButtonText` | `<div>` | `text` set | |
|
|
359
361
|
| `ButtonDescription` | `<div>` | `description` set | |
|
|
360
362
|
| `ButtonIcon` | `<svg>`/`<span>` | `icon` or `emojiIcon` set | If `icon`, must be font-awesome icon name; if `emojiIcon` must be an emoji in text format like 😀 |
|
|
361
|
-
| `ButtonIconImage` | `<span>` | `imageUrl` set |
|
|
363
|
+
| `ButtonIconImage` | `<span>` | `imageUrl` set | Use **`imageUrl`** only (not `imgSrc`). SVG URLs are valid. |
|
|
362
364
|
|
|
363
365
|
### InputBox
|
|
364
366
|
|
package/dist/cli.js
CHANGED
|
@@ -9,9 +9,11 @@ import { createRequire } from 'node:module';
|
|
|
9
9
|
import path from 'node:path';
|
|
10
10
|
import { fileURLToPath } from 'node:url';
|
|
11
11
|
import { Command } from 'commander';
|
|
12
|
+
import pc from 'picocolors';
|
|
12
13
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
13
14
|
const require = createRequire(import.meta.url);
|
|
14
15
|
const pkg = require(path.join(__dirname, '..', 'package.json'));
|
|
16
|
+
import { isLoggedIn } from './auth/index.js';
|
|
15
17
|
import { runBranch } from './commands/branch.js';
|
|
16
18
|
import { runBuild } from './commands/build.js';
|
|
17
19
|
import { runDev } from './commands/dev.js';
|
|
@@ -22,6 +24,20 @@ import { runLogout } from './commands/logout.js';
|
|
|
22
24
|
import { runPull } from './commands/pull.js';
|
|
23
25
|
import { runSave } from './commands/save.js';
|
|
24
26
|
import { runUpgrade } from './commands/upgrade.js';
|
|
27
|
+
import { exit } from './logger.js';
|
|
28
|
+
import * as stdout from './stdout.js';
|
|
29
|
+
/** Only these commands may run without being logged in. All others require login. */
|
|
30
|
+
const COMMANDS_ALLOWED_WITHOUT_LOGIN = new Set(['login', 'logout', 'upgrade']);
|
|
31
|
+
async function requireLogin(commandName) {
|
|
32
|
+
const baseCommand = commandName.split(' ')[0];
|
|
33
|
+
if (COMMANDS_ALLOWED_WITHOUT_LOGIN.has(baseCommand))
|
|
34
|
+
return;
|
|
35
|
+
if (isLoggedIn())
|
|
36
|
+
return;
|
|
37
|
+
stdout.error(pc.red('Not logged in.'));
|
|
38
|
+
stdout.print(pc.gray('Run "embeddables login" first.'));
|
|
39
|
+
await exit(1);
|
|
40
|
+
}
|
|
25
41
|
const program = new Command();
|
|
26
42
|
program
|
|
27
43
|
.name('embeddables')
|
|
@@ -33,6 +49,7 @@ program
|
|
|
33
49
|
.option('-p, --project-id <id>', 'Embeddables project ID')
|
|
34
50
|
.option('-y, --yes', 'Skip prompts and use defaults')
|
|
35
51
|
.action(async (opts) => {
|
|
52
|
+
await requireLogin('init');
|
|
36
53
|
await runInit({ projectId: opts.projectId, yes: opts.yes });
|
|
37
54
|
});
|
|
38
55
|
program
|
|
@@ -43,6 +60,7 @@ program
|
|
|
43
60
|
.option('--fix', 'Apply lint fixes (duplicate IDs, keys/IDs starting with a number)')
|
|
44
61
|
.option('--pageKeyFrom <mode>', 'filename|export', 'filename')
|
|
45
62
|
.action(async (opts) => {
|
|
63
|
+
await requireLogin('build');
|
|
46
64
|
await runBuild(opts);
|
|
47
65
|
});
|
|
48
66
|
program
|
|
@@ -57,6 +75,7 @@ program
|
|
|
57
75
|
.option('--overrideRoute <path>', 'Route to override in proxy (exact match, no wildcards yet)', '/init')
|
|
58
76
|
.option('--pageKeyFrom <mode>', 'filename|export', 'filename')
|
|
59
77
|
.action(async (opts) => {
|
|
78
|
+
await requireLogin('dev');
|
|
60
79
|
// --local flag overrides --engine to use local engine
|
|
61
80
|
if (opts.local) {
|
|
62
81
|
opts.engine = 'http://localhost:8787';
|
|
@@ -84,6 +103,7 @@ program
|
|
|
84
103
|
.option('-f, --fix', 'Fix by removing components missing required props (warn instead of error)')
|
|
85
104
|
.option('-p, --preserve', 'Preserve component order in config for forward compile')
|
|
86
105
|
.action(async (opts) => {
|
|
106
|
+
await requireLogin('pull');
|
|
87
107
|
await runPull(opts);
|
|
88
108
|
});
|
|
89
109
|
program
|
|
@@ -95,6 +115,7 @@ program
|
|
|
95
115
|
.option('-s, --skip-build', 'Skip the build step and use existing compiled JSON')
|
|
96
116
|
.option('--from-version <number>', 'Base version number (auto-detected from local files if not provided)')
|
|
97
117
|
.action(async (opts) => {
|
|
118
|
+
await requireLogin('save');
|
|
98
119
|
await runSave({
|
|
99
120
|
id: opts.id,
|
|
100
121
|
label: opts.label,
|
|
@@ -114,6 +135,7 @@ program
|
|
|
114
135
|
.description('Switch to a different branch of an embeddable')
|
|
115
136
|
.option('-i, --id <id>', 'Embeddable ID (will prompt if not provided)')
|
|
116
137
|
.action(async (opts) => {
|
|
138
|
+
await requireLogin('branch');
|
|
117
139
|
await runBranch(opts);
|
|
118
140
|
});
|
|
119
141
|
const experiments = program.command('experiments').description('Manage embeddable experiments');
|
|
@@ -124,6 +146,7 @@ experiments
|
|
|
124
146
|
.option('--experiment-id <id>', 'Experiment ID (will prompt to choose from project if not provided)')
|
|
125
147
|
.option('--experiment-key <key>', 'Experiment key (required if --experiment-id is set)')
|
|
126
148
|
.action(async (opts) => {
|
|
149
|
+
await requireLogin('experiments connect');
|
|
127
150
|
await runExperimentsConnect({
|
|
128
151
|
id: opts.id,
|
|
129
152
|
experimentId: opts.experimentId,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/proxy/server.ts"],"names":[],"mappings":"AAoCA,wBAAsB,gBAAgB,CAAC,IAAI,EAAE;IAC3C,IAAI,EAAE,MAAM,CAAA;IACZ,YAAY,EAAE,MAAM,CAAA;IACpB,aAAa,EAAE,MAAM,CAAA;IACrB,iBAAiB,EAAE,MAAM,CAAA;IACzB,YAAY,EAAE,MAAM,CAAA;IACpB,cAAc,CAAC,EAAE,OAAO,CAAA;CACzB;;
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/proxy/server.ts"],"names":[],"mappings":"AAoCA,wBAAsB,gBAAgB,CAAC,IAAI,EAAE;IAC3C,IAAI,EAAE,MAAM,CAAA;IACZ,YAAY,EAAE,MAAM,CAAA;IACpB,aAAa,EAAE,MAAM,CAAA;IACrB,iBAAiB,EAAE,MAAM,CAAA;IACzB,YAAY,EAAE,MAAM,CAAA;IACpB,cAAc,CAAC,EAAE,OAAO,CAAA;CACzB;;GA0UA"}
|
package/dist/proxy/server.js
CHANGED
|
@@ -151,10 +151,24 @@ export async function startProxyServer(opts) {
|
|
|
151
151
|
const generatedJson = JSON.parse(raw);
|
|
152
152
|
generatedJson.id = opts.embeddableId;
|
|
153
153
|
stdout.print(`[/init] Loaded local JSON, pages: ${generatedJson.pages?.length ?? 0}`);
|
|
154
|
+
// When the flow has content_sources (CMS), the remote engine needs flow metadata
|
|
155
|
+
// (project_id) to load them. Without an engine that supports dev + CMS, the request
|
|
156
|
+
// fails. So we omit content_sources so the page loads; CMS-backed content will be
|
|
157
|
+
// empty in dev.
|
|
158
|
+
const hasContentSources = Array.isArray(generatedJson.content_sources) && generatedJson.content_sources.length > 0;
|
|
159
|
+
const flowToSend = hasContentSources
|
|
160
|
+
? (() => {
|
|
161
|
+
const { content_sources: _, ...rest } = generatedJson;
|
|
162
|
+
return rest;
|
|
163
|
+
})()
|
|
164
|
+
: generatedJson;
|
|
165
|
+
if (hasContentSources) {
|
|
166
|
+
stdout.print(`[/init] Omitting content_sources so dev loads (CMS content will be empty in preview).`);
|
|
167
|
+
}
|
|
154
168
|
// Create POST request body with the JSON
|
|
155
169
|
const postBody = {
|
|
156
170
|
json: {
|
|
157
|
-
flow:
|
|
171
|
+
flow: flowToSend,
|
|
158
172
|
flowId: generatedJson.id,
|
|
159
173
|
groupId: 'group_test',
|
|
160
174
|
},
|