@embeddables/cli 0.6.10 → 0.7.0
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/custom/build-funnel.md +1 -1
- package/dist/cli.js +7 -10
- package/dist/commands/branch.d.ts.map +1 -1
- package/dist/commands/branch.js +20 -15
- package/dist/commands/build-workbench.d.ts.map +1 -1
- package/dist/commands/build-workbench.js +37 -31
- package/dist/commands/build.d.ts.map +1 -1
- package/dist/commands/build.js +12 -3
- package/dist/commands/dev.d.ts.map +1 -1
- package/dist/commands/dev.js +34 -21
- package/dist/commands/experiments-connect.d.ts.map +1 -1
- package/dist/commands/experiments-connect.js +43 -30
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +49 -48
- package/dist/commands/login.d.ts.map +1 -1
- package/dist/commands/login.js +35 -25
- package/dist/commands/logout.d.ts.map +1 -1
- package/dist/commands/logout.js +10 -6
- package/dist/commands/pull.d.ts +2 -0
- package/dist/commands/pull.d.ts.map +1 -1
- package/dist/commands/pull.js +53 -40
- package/dist/commands/save.d.ts.map +1 -1
- package/dist/commands/save.js +79 -53
- package/dist/compiler/index.d.ts.map +1 -1
- package/dist/compiler/index.js +10 -9
- package/dist/compiler/reverse.d.ts.map +1 -1
- package/dist/compiler/reverse.js +18 -17
- package/dist/logger.d.ts +1 -0
- package/dist/logger.d.ts.map +1 -1
- package/dist/logger.js +4 -0
- package/dist/prompts/branches.d.ts.map +1 -1
- package/dist/prompts/branches.js +3 -2
- package/dist/prompts/embeddables.d.ts.map +1 -1
- package/dist/prompts/embeddables.js +8 -7
- package/dist/prompts/experiments.d.ts.map +1 -1
- package/dist/prompts/experiments.js +5 -4
- package/dist/prompts/projects.d.ts.map +1 -1
- package/dist/prompts/projects.js +4 -3
- package/dist/proxy/server.d.ts.map +1 -1
- package/dist/proxy/server.js +33 -32
- package/package.json +2 -1
|
@@ -3,6 +3,7 @@ import path from 'node:path';
|
|
|
3
3
|
import pc from 'picocolors';
|
|
4
4
|
import prompts from 'prompts';
|
|
5
5
|
import { getAuthenticatedSupabaseClient } from '../auth/index.js';
|
|
6
|
+
import * as stdout from '../stdout.js';
|
|
6
7
|
/**
|
|
7
8
|
* Fetch all embeddables for a project from Supabase
|
|
8
9
|
*/
|
|
@@ -18,7 +19,7 @@ export async function fetchProjectEmbeddables(projectId) {
|
|
|
18
19
|
.eq('project_id', projectId)
|
|
19
20
|
.order('title', { ascending: true });
|
|
20
21
|
if (error) {
|
|
21
|
-
|
|
22
|
+
stdout.warn(pc.yellow(`Could not fetch embeddables: ${error.message}`));
|
|
22
23
|
return [];
|
|
23
24
|
}
|
|
24
25
|
return (data || []).map((row) => ({
|
|
@@ -27,7 +28,7 @@ export async function fetchProjectEmbeddables(projectId) {
|
|
|
27
28
|
}));
|
|
28
29
|
}
|
|
29
30
|
catch (err) {
|
|
30
|
-
|
|
31
|
+
stdout.warn(pc.yellow(`Could not fetch embeddables: ${err}`));
|
|
31
32
|
return [];
|
|
32
33
|
}
|
|
33
34
|
}
|
|
@@ -47,7 +48,7 @@ export async function fetchEmbeddableMetadata(embeddableId) {
|
|
|
47
48
|
.eq('id', embeddableId)
|
|
48
49
|
.single();
|
|
49
50
|
if (error) {
|
|
50
|
-
|
|
51
|
+
stdout.warn(pc.yellow(`Could not fetch embeddable metadata: ${error.message}`));
|
|
51
52
|
return null;
|
|
52
53
|
}
|
|
53
54
|
return {
|
|
@@ -57,7 +58,7 @@ export async function fetchEmbeddableMetadata(embeddableId) {
|
|
|
57
58
|
};
|
|
58
59
|
}
|
|
59
60
|
catch (err) {
|
|
60
|
-
|
|
61
|
+
stdout.warn(pc.yellow(`Could not fetch embeddable metadata: ${err}`));
|
|
61
62
|
return null;
|
|
62
63
|
}
|
|
63
64
|
}
|
|
@@ -69,7 +70,7 @@ export async function promptForEmbeddable(projectId, options = {}) {
|
|
|
69
70
|
const { message = 'Select an embeddable:' } = options;
|
|
70
71
|
const embeddables = await fetchProjectEmbeddables(projectId);
|
|
71
72
|
if (embeddables.length === 0) {
|
|
72
|
-
|
|
73
|
+
stdout.print(pc.yellow('No embeddables found in this project.'));
|
|
73
74
|
return null;
|
|
74
75
|
}
|
|
75
76
|
const choices = embeddables.map((e) => ({
|
|
@@ -137,8 +138,8 @@ export async function promptForLocalEmbeddable(options = {}) {
|
|
|
137
138
|
const { message = 'Select an embeddable:' } = options;
|
|
138
139
|
const embeddables = await discoverLocalEmbeddables();
|
|
139
140
|
if (embeddables.length === 0) {
|
|
140
|
-
|
|
141
|
-
|
|
141
|
+
stdout.error(pc.red('No embeddables found in the embeddables/ directory.'));
|
|
142
|
+
stdout.print(pc.gray('Run `embeddables pull` to pull an embeddable first.'));
|
|
142
143
|
return null;
|
|
143
144
|
}
|
|
144
145
|
const choices = embeddables.map((e) => ({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"experiments.d.ts","sourceRoot":"","sources":["../../src/prompts/experiments.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"experiments.d.ts","sourceRoot":"","sources":["../../src/prompts/experiments.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAA;IACV,aAAa,EAAE,MAAM,CAAA;IACrB,cAAc,EAAE,MAAM,CAAA;IACtB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;IACnB,MAAM,EAAE,MAAM,CAAA;IACd,OAAO,EAAE,MAAM,CAAA;IACf,QAAQ,EAAE,MAAM,EAAE,GAAG,IAAI,CAAA;CAC1B;AAED,MAAM,WAAW,0BAA0B;IACzC,oCAAoC;IACpC,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,qEAAqE;IACrE,kBAAkB,CAAC,EAAE,MAAM,CAAA;CAC5B;AAED;;GAEG;AACH,wBAAsB,uBAAuB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC,CA+B1F;AAED;;;GAGG;AACH,wBAAsB,mBAAmB,CACvC,SAAS,EAAE,MAAM,EACjB,OAAO,GAAE,0BAA+B,GACvC,OAAO,CAAC;IAAE,aAAa,EAAE,MAAM,CAAC;IAAC,cAAc,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAAC,CA4DnE"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import pc from 'picocolors';
|
|
2
2
|
import prompts from 'prompts';
|
|
3
3
|
import { getAuthenticatedSupabaseClient } from '../auth/index.js';
|
|
4
|
+
import * as stdout from '../stdout.js';
|
|
4
5
|
/**
|
|
5
6
|
* Fetch experiments for a project from Supabase (using experiments_extended view)
|
|
6
7
|
*/
|
|
@@ -16,7 +17,7 @@ export async function fetchProjectExperiments(projectId) {
|
|
|
16
17
|
.eq('project_id', projectId)
|
|
17
18
|
.order('name', { ascending: true, nullsFirst: false });
|
|
18
19
|
if (error) {
|
|
19
|
-
|
|
20
|
+
stdout.warn(pc.yellow(`Could not fetch experiments: ${error.message}`));
|
|
20
21
|
return [];
|
|
21
22
|
}
|
|
22
23
|
return (data || []).map((row) => ({
|
|
@@ -30,7 +31,7 @@ export async function fetchProjectExperiments(projectId) {
|
|
|
30
31
|
}));
|
|
31
32
|
}
|
|
32
33
|
catch (err) {
|
|
33
|
-
|
|
34
|
+
stdout.warn(pc.yellow(`Could not fetch experiments: ${err}`));
|
|
34
35
|
return [];
|
|
35
36
|
}
|
|
36
37
|
}
|
|
@@ -50,10 +51,10 @@ export async function promptForExperiment(projectId, options = {}) {
|
|
|
50
51
|
}
|
|
51
52
|
if (filtered.length === 0) {
|
|
52
53
|
if (excludeConnectedTo && experiments.length > 0) {
|
|
53
|
-
|
|
54
|
+
stdout.print(pc.yellow('All experiments in this project are already connected to this embeddable.'));
|
|
54
55
|
}
|
|
55
56
|
else {
|
|
56
|
-
|
|
57
|
+
stdout.print(pc.yellow('No experiments found in this project.'));
|
|
57
58
|
}
|
|
58
59
|
return null;
|
|
59
60
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"projects.d.ts","sourceRoot":"","sources":["../../src/prompts/projects.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"projects.d.ts","sourceRoot":"","sources":["../../src/prompts/projects.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAA;IACV,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;IACpB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;IACrB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;CACzB;AAED,MAAM,WAAW,uBAAuB;IACtC,uDAAuD;IACvD,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,mEAAmE;IACnE,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB;AAED;;GAEG;AACH,wBAAsB,aAAa,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC,CAwC5D;AAED;;;GAGG;AACH,wBAAsB,gBAAgB,CACpC,OAAO,GAAE,uBAA4B,GACpC,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAqD7B"}
|
package/dist/prompts/projects.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import pc from 'picocolors';
|
|
2
2
|
import prompts from 'prompts';
|
|
3
3
|
import { getAuthenticatedSupabaseClient } from '../auth/index.js';
|
|
4
|
+
import * as stdout from '../stdout.js';
|
|
4
5
|
/**
|
|
5
6
|
* Fetch all non-archived projects from Supabase
|
|
6
7
|
*/
|
|
@@ -23,7 +24,7 @@ export async function fetchProjects() {
|
|
|
23
24
|
.not('archived', 'is', 'true')
|
|
24
25
|
.order('title', { ascending: true });
|
|
25
26
|
if (error) {
|
|
26
|
-
|
|
27
|
+
stdout.warn(pc.yellow(`Could not fetch projects: ${error.message}`));
|
|
27
28
|
return [];
|
|
28
29
|
}
|
|
29
30
|
return (data || []).map((row) => ({
|
|
@@ -37,7 +38,7 @@ export async function fetchProjects() {
|
|
|
37
38
|
}));
|
|
38
39
|
}
|
|
39
40
|
catch (err) {
|
|
40
|
-
|
|
41
|
+
stdout.warn(pc.yellow(`Could not fetch projects: ${err}`));
|
|
41
42
|
return [];
|
|
42
43
|
}
|
|
43
44
|
}
|
|
@@ -49,7 +50,7 @@ export async function promptForProject(options = {}) {
|
|
|
49
50
|
const { allowSkip = false, message = 'Select a project:' } = options;
|
|
50
51
|
const projects = await fetchProjects();
|
|
51
52
|
if (projects.length === 0) {
|
|
52
|
-
|
|
53
|
+
stdout.print(pc.yellow('No projects found.'));
|
|
53
54
|
return null;
|
|
54
55
|
}
|
|
55
56
|
const choices = projects.map((p) => ({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/proxy/server.ts"],"names":[],"mappings":"
|
|
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;;GAwTA"}
|
package/dist/proxy/server.js
CHANGED
|
@@ -13,6 +13,7 @@ import { injectWorkbenchHtml } from './injectWorkbench.js';
|
|
|
13
13
|
import { injectReloadScript } from './injectReload.js';
|
|
14
14
|
import { injectApiInterceptor } from './injectApiInterceptor.js';
|
|
15
15
|
import { WORKBENCH_CDN_ORIGIN } from '../constants.js';
|
|
16
|
+
import * as stdout from '../stdout.js';
|
|
16
17
|
// Resolve the CLI package root so workbench paths work regardless of cwd.
|
|
17
18
|
// This file lives at src/proxy/server.ts (or dist/proxy/server.js when compiled),
|
|
18
19
|
// so the package root is two directories up.
|
|
@@ -45,10 +46,10 @@ export async function startProxyServer(opts) {
|
|
|
45
46
|
// string → remote CDN origin (e.g. https://embeddables-workbench.heysavvy.workers.dev)
|
|
46
47
|
const workbenchOrigin = localDev ? undefined : WORKBENCH_CDN_ORIGIN;
|
|
47
48
|
if (localDev) {
|
|
48
|
-
|
|
49
|
+
stdout.print('[Workbench] Local dev mode — building workbench from source');
|
|
49
50
|
}
|
|
50
51
|
else {
|
|
51
|
-
|
|
52
|
+
stdout.print(`[Workbench] Installed mode — loading workbench from CDN (${WORKBENCH_CDN_ORIGIN})`);
|
|
52
53
|
}
|
|
53
54
|
const buildWorkbench = async () => {
|
|
54
55
|
try {
|
|
@@ -74,14 +75,14 @@ export async function startProxyServer(opts) {
|
|
|
74
75
|
});
|
|
75
76
|
workbenchCss = cssResult.css;
|
|
76
77
|
if (workbenchBundle) {
|
|
77
|
-
|
|
78
|
+
stdout.print('[Workbench] Bundle built successfully');
|
|
78
79
|
return true;
|
|
79
80
|
}
|
|
80
|
-
|
|
81
|
+
stdout.warn('[Workbench] Bundle build completed but no output file found');
|
|
81
82
|
return false;
|
|
82
83
|
}
|
|
83
84
|
catch (err) {
|
|
84
|
-
|
|
85
|
+
stdout.warn(`[Workbench] Failed to build Workbench bundle. Workbench UI will be unavailable. ${err instanceof Error ? err.message : String(err)}`);
|
|
85
86
|
workbenchCss = null;
|
|
86
87
|
return false;
|
|
87
88
|
}
|
|
@@ -104,15 +105,15 @@ export async function startProxyServer(opts) {
|
|
|
104
105
|
watcher.on('all', async () => {
|
|
105
106
|
clearTimeout(rebuildTimeout);
|
|
106
107
|
rebuildTimeout = setTimeout(async () => {
|
|
107
|
-
|
|
108
|
+
stdout.print('[Workbench] Files changed, rebuilding bundle...');
|
|
108
109
|
const success = await buildWorkbench();
|
|
109
110
|
if (success) {
|
|
110
111
|
broadcastReload();
|
|
111
|
-
|
|
112
|
+
stdout.print('[Workbench] Bundle rebuilt and reload broadcast');
|
|
112
113
|
}
|
|
113
114
|
}, 100);
|
|
114
115
|
});
|
|
115
|
-
|
|
116
|
+
stdout.print(`[Workbench] Watching ${workbenchGlob} for changes`);
|
|
116
117
|
}
|
|
117
118
|
// Serve the Workbench bundle as a static asset (local-dev mode only)
|
|
118
119
|
if (localDev) {
|
|
@@ -143,13 +144,13 @@ export async function startProxyServer(opts) {
|
|
|
143
144
|
}
|
|
144
145
|
// Intercept GET requests to overrideRoute: convert to POST and add generated JSON to body
|
|
145
146
|
app.get(opts.overrideRoute, async (req, res) => {
|
|
146
|
-
|
|
147
|
+
stdout.print(`[/init] Intercepted GET ${opts.overrideRoute}, query: ${JSON.stringify(req.query)}`);
|
|
147
148
|
try {
|
|
148
149
|
// Load the generated JSON
|
|
149
150
|
const raw = fs.readFileSync(opts.generatedJsonPath, 'utf8');
|
|
150
151
|
const generatedJson = JSON.parse(raw);
|
|
151
152
|
generatedJson.id = opts.embeddableId;
|
|
152
|
-
|
|
153
|
+
stdout.print(`[/init] Loaded local JSON, pages: ${generatedJson.pages?.length ?? 0}`);
|
|
153
154
|
// Create POST request body with the JSON
|
|
154
155
|
const postBody = {
|
|
155
156
|
json: {
|
|
@@ -161,7 +162,7 @@ export async function startProxyServer(opts) {
|
|
|
161
162
|
// Build the target URL with query parameters
|
|
162
163
|
const queryString = new URLSearchParams(req.query).toString();
|
|
163
164
|
const targetUrl = `${opts.engineOrigin}/init${queryString ? `?${queryString}` : ''}`;
|
|
164
|
-
|
|
165
|
+
stdout.print(`[/init] Forwarding to engine: POST ${targetUrl}`);
|
|
165
166
|
// Forward headers from original request (excluding problematic ones)
|
|
166
167
|
const headers = {};
|
|
167
168
|
for (const [key, value] of Object.entries(req.headers)) {
|
|
@@ -183,13 +184,13 @@ export async function startProxyServer(opts) {
|
|
|
183
184
|
});
|
|
184
185
|
// Parse and forward the response
|
|
185
186
|
const responseBody = await engineResponse.json();
|
|
186
|
-
|
|
187
|
+
stdout.print(`[/init] Engine response: status=${engineResponse.status}, hasFlow=${!!responseBody?.flow}, flowPages=${responseBody?.flow?.pages?.length ?? 'N/A'}`);
|
|
187
188
|
res.setHeader('Content-Type', 'application/json; charset=utf-8');
|
|
188
189
|
res.setHeader('Cache-Control', 'no-store');
|
|
189
190
|
return res.status(engineResponse.status).send(JSON.stringify(responseBody));
|
|
190
191
|
}
|
|
191
192
|
catch (err) {
|
|
192
|
-
|
|
193
|
+
stdout.error(`Failed to modify /init request: ${err instanceof Error ? err.message : String(err)}`);
|
|
193
194
|
if (!res.headersSent) {
|
|
194
195
|
res.status(500).json({
|
|
195
196
|
error: 'Failed to modify /init request',
|
|
@@ -204,13 +205,13 @@ export async function startProxyServer(opts) {
|
|
|
204
205
|
app.get('/', async (req, res, next) => {
|
|
205
206
|
const host = (req.headers.host ?? '').toString();
|
|
206
207
|
const isLocalhost = host.startsWith('localhost') || host.startsWith('127.0.0.1');
|
|
207
|
-
|
|
208
|
+
stdout.print(`[Workbench] GET / handler: host=${host}, isLocalhost=${isLocalhost}, url=${req.url}`);
|
|
208
209
|
if (!isLocalhost) {
|
|
209
|
-
|
|
210
|
+
stdout.print('[Workbench] Not localhost, skipping injection');
|
|
210
211
|
return next();
|
|
211
212
|
}
|
|
212
213
|
const targetUrl = `${opts.engineOrigin}${req.url}`;
|
|
213
|
-
|
|
214
|
+
stdout.print(`[Workbench] Fetching from engine: ${targetUrl}`);
|
|
214
215
|
try {
|
|
215
216
|
const headers = {};
|
|
216
217
|
for (const [key, value] of Object.entries(req.headers)) {
|
|
@@ -223,19 +224,19 @@ export async function startProxyServer(opts) {
|
|
|
223
224
|
}
|
|
224
225
|
const engineRes = await fetch(targetUrl, { method: 'GET', headers });
|
|
225
226
|
const contentType = engineRes.headers.get('content-type') ?? '';
|
|
226
|
-
|
|
227
|
+
stdout.print(`[Workbench] Engine response: status=${engineRes.status}, content-type=${contentType}`);
|
|
227
228
|
if (!contentType.includes('text/html')) {
|
|
228
|
-
|
|
229
|
+
stdout.print('[Workbench] Not HTML, proxying normally');
|
|
229
230
|
return next();
|
|
230
231
|
}
|
|
231
232
|
const html = await engineRes.text();
|
|
232
|
-
|
|
233
|
+
stdout.print(`[Workbench] Got HTML (${html.length} chars), injecting Workbench...`);
|
|
233
234
|
let modifiedHtml = html;
|
|
234
235
|
// If proxying to a remote engine, inject API interceptor to rewrite absolute URLs
|
|
235
236
|
const isRemoteEngine = !opts.engineOrigin.includes('localhost') && !opts.engineOrigin.includes('127.0.0.1');
|
|
236
237
|
if (isRemoteEngine) {
|
|
237
238
|
modifiedHtml = injectApiInterceptor(modifiedHtml, opts.engineOrigin);
|
|
238
|
-
|
|
239
|
+
stdout.print(`[Workbench] Injected API interceptor for ${opts.engineOrigin}`);
|
|
239
240
|
}
|
|
240
241
|
modifiedHtml = injectReloadScript(modifiedHtml);
|
|
241
242
|
const includeWorkbench = req.query?.workbench !== 'false';
|
|
@@ -248,13 +249,13 @@ export async function startProxyServer(opts) {
|
|
|
248
249
|
else {
|
|
249
250
|
console.log('[Workbench] Skipping workbench (workbench=false in URL)');
|
|
250
251
|
}
|
|
251
|
-
|
|
252
|
+
stdout.print(`[Workbench] Injection complete (${modifiedHtml.length} chars), sending response`);
|
|
252
253
|
res.setHeader('Content-Type', 'text/html; charset=utf-8');
|
|
253
254
|
res.setHeader('Cache-Control', engineRes.headers.get('cache-control') ?? 'no-store');
|
|
254
255
|
res.status(engineRes.status).send(modifiedHtml);
|
|
255
256
|
}
|
|
256
257
|
catch (err) {
|
|
257
|
-
|
|
258
|
+
stdout.error(`[Workbench] Error fetching/injecting HTML: ${err instanceof Error ? err.message : String(err)}`);
|
|
258
259
|
next();
|
|
259
260
|
}
|
|
260
261
|
});
|
|
@@ -265,7 +266,7 @@ export async function startProxyServer(opts) {
|
|
|
265
266
|
ws: true,
|
|
266
267
|
on: {
|
|
267
268
|
proxyReq: (proxyReq, req) => {
|
|
268
|
-
|
|
269
|
+
stdout.print(`[Proxy] ${req.method} ${req.url} → ${opts.engineOrigin}${req.url}`);
|
|
269
270
|
},
|
|
270
271
|
error: (err, req, res) => {
|
|
271
272
|
// ECONNRESET/ECONNABORTED often happen when the client navigates away or the
|
|
@@ -273,10 +274,10 @@ export async function startProxyServer(opts) {
|
|
|
273
274
|
const code = err?.code ?? err?.errno;
|
|
274
275
|
const isConnectionClosed = code === 'ECONNRESET' || code === 'ECONNABORTED' || code === -54;
|
|
275
276
|
if (isConnectionClosed) {
|
|
276
|
-
|
|
277
|
+
stdout.print(`[Proxy] Connection closed (client or upstream): ${err.message}`);
|
|
277
278
|
}
|
|
278
279
|
else {
|
|
279
|
-
|
|
280
|
+
stdout.error(`[Proxy] Error proxying request: ${err instanceof Error ? err.message : String(err)}`);
|
|
280
281
|
}
|
|
281
282
|
if (!res.headersSent) {
|
|
282
283
|
res.status(500).send('Proxy error');
|
|
@@ -285,16 +286,16 @@ export async function startProxyServer(opts) {
|
|
|
285
286
|
},
|
|
286
287
|
}));
|
|
287
288
|
app.listen(opts.port, () => {
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
289
|
+
stdout.print(`Dev proxy: http://localhost:${opts.port}`);
|
|
290
|
+
stdout.print(` → Engine: ${opts.engineOrigin}`);
|
|
291
|
+
stdout.print(`Override route: GET ${opts.overrideRoute}`);
|
|
292
|
+
stdout.print(`Serving: ${opts.generatedJsonPath}`);
|
|
293
|
+
stdout.print(`Reload SSE: /__embeddables_reload`);
|
|
293
294
|
if (localDev) {
|
|
294
|
-
|
|
295
|
+
stdout.print(`Workbench: built from local source`);
|
|
295
296
|
}
|
|
296
297
|
else {
|
|
297
|
-
|
|
298
|
+
stdout.print(`Workbench: served from ${WORKBENCH_CDN_ORIGIN}`);
|
|
298
299
|
}
|
|
299
300
|
});
|
|
300
301
|
return { broadcastReload };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@embeddables/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"bin": {
|
|
6
6
|
"embeddables": "./bin/embeddables.mjs"
|
|
@@ -51,6 +51,7 @@
|
|
|
51
51
|
"@babel/generator": "^7.28.6",
|
|
52
52
|
"@babel/parser": "^7.26.0",
|
|
53
53
|
"@babel/traverse": "^7.26.0",
|
|
54
|
+
"@sentry/node": "^10.39.0",
|
|
54
55
|
"@supabase/supabase-js": "^2.39.0",
|
|
55
56
|
"@tailwindcss/postcss": "^4.1.18",
|
|
56
57
|
"autoprefixer": "^10.4.23",
|