@embeddables/cli 0.8.0 → 0.8.2

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.
Files changed (235) hide show
  1. package/dist/auth/index.d.ts +43 -0
  2. package/dist/auth/index.d.ts.map +1 -0
  3. package/dist/auth/index.js +102 -0
  4. package/dist/cli.d.ts +2 -0
  5. package/dist/cli.d.ts.map +1 -0
  6. package/dist/cli.js +210 -0
  7. package/dist/commands/branch.d.ts +4 -0
  8. package/dist/commands/branch.d.ts.map +1 -0
  9. package/dist/commands/branch.js +67 -0
  10. package/dist/commands/build-workbench.d.ts +5 -0
  11. package/dist/commands/build-workbench.d.ts.map +1 -0
  12. package/dist/commands/build-workbench.js +116 -0
  13. package/dist/commands/build.d.ts +8 -0
  14. package/dist/commands/build.d.ts.map +1 -0
  15. package/dist/commands/build.js +60 -0
  16. package/dist/commands/builder-open.d.ts +4 -0
  17. package/dist/commands/builder-open.d.ts.map +1 -0
  18. package/dist/commands/builder-open.js +74 -0
  19. package/dist/commands/dev.d.ts +12 -0
  20. package/dist/commands/dev.d.ts.map +1 -0
  21. package/dist/commands/dev.js +226 -0
  22. package/dist/commands/experiments-connect.d.ts +6 -0
  23. package/dist/commands/experiments-connect.d.ts.map +1 -0
  24. package/dist/commands/experiments-connect.js +140 -0
  25. package/dist/commands/init.d.ts +5 -0
  26. package/dist/commands/init.d.ts.map +1 -0
  27. package/dist/commands/init.js +384 -0
  28. package/dist/commands/inspect.d.ts +9 -0
  29. package/dist/commands/inspect.d.ts.map +1 -0
  30. package/dist/commands/inspect.js +293 -0
  31. package/dist/commands/login.d.ts +2 -0
  32. package/dist/commands/login.d.ts.map +1 -0
  33. package/dist/commands/login.js +117 -0
  34. package/dist/commands/logout.d.ts +2 -0
  35. package/dist/commands/logout.d.ts.map +1 -0
  36. package/dist/commands/logout.js +19 -0
  37. package/dist/commands/pull.d.ts +16 -0
  38. package/dist/commands/pull.d.ts.map +1 -0
  39. package/dist/commands/pull.js +395 -0
  40. package/dist/commands/save.d.ts +30 -0
  41. package/dist/commands/save.d.ts.map +1 -0
  42. package/dist/commands/save.js +597 -0
  43. package/dist/commands/upgrade.d.ts +2 -0
  44. package/dist/commands/upgrade.d.ts.map +1 -0
  45. package/dist/commands/upgrade.js +50 -0
  46. package/dist/compiler/errors.d.ts +20 -0
  47. package/dist/compiler/errors.d.ts.map +1 -0
  48. package/dist/compiler/errors.js +35 -0
  49. package/dist/compiler/evalStatic.d.ts +3 -0
  50. package/dist/compiler/evalStatic.d.ts.map +1 -0
  51. package/dist/compiler/evalStatic.js +57 -0
  52. package/dist/compiler/helpers/duplicateIds.d.ts +9 -0
  53. package/dist/compiler/helpers/duplicateIds.d.ts.map +1 -0
  54. package/dist/compiler/helpers/duplicateIds.js +71 -0
  55. package/dist/compiler/helpers/numericLeadingKeys.d.ts +8 -0
  56. package/dist/compiler/helpers/numericLeadingKeys.d.ts.map +1 -0
  57. package/dist/compiler/helpers/numericLeadingKeys.js +17 -0
  58. package/dist/compiler/index.d.ts +18 -0
  59. package/dist/compiler/index.d.ts.map +1 -0
  60. package/dist/compiler/index.js +1272 -0
  61. package/dist/compiler/parsePage.d.ts +15 -0
  62. package/dist/compiler/parsePage.d.ts.map +1 -0
  63. package/dist/compiler/parsePage.js +654 -0
  64. package/dist/compiler/registry.d.ts +4 -0
  65. package/dist/compiler/registry.d.ts.map +1 -0
  66. package/dist/compiler/registry.js +44 -0
  67. package/dist/compiler/reverse.d.ts +23 -0
  68. package/dist/compiler/reverse.d.ts.map +1 -0
  69. package/dist/compiler/reverse.js +1938 -0
  70. package/dist/compiler/types.d.ts +21 -0
  71. package/dist/compiler/types.d.ts.map +1 -0
  72. package/dist/compiler/types.js +1 -0
  73. package/dist/components/index.d.ts +21 -0
  74. package/dist/components/index.d.ts.map +1 -0
  75. package/dist/components/index.js +21 -0
  76. package/dist/components/primitives/BaseComponent.d.ts +33 -0
  77. package/dist/components/primitives/BaseComponent.d.ts.map +1 -0
  78. package/dist/components/primitives/BaseComponent.js +26 -0
  79. package/dist/components/primitives/BookMeeting.d.ts +18 -0
  80. package/dist/components/primitives/BookMeeting.d.ts.map +1 -0
  81. package/dist/components/primitives/BookMeeting.js +5 -0
  82. package/dist/components/primitives/Chart.d.ts +41 -0
  83. package/dist/components/primitives/Chart.d.ts.map +1 -0
  84. package/dist/components/primitives/Chart.js +5 -0
  85. package/dist/components/primitives/Container.d.ts +8 -0
  86. package/dist/components/primitives/Container.d.ts.map +1 -0
  87. package/dist/components/primitives/Container.js +5 -0
  88. package/dist/components/primitives/CustomButton.d.ts +37 -0
  89. package/dist/components/primitives/CustomButton.d.ts.map +1 -0
  90. package/dist/components/primitives/CustomButton.js +10 -0
  91. package/dist/components/primitives/CustomHTML.d.ts +8 -0
  92. package/dist/components/primitives/CustomHTML.d.ts.map +1 -0
  93. package/dist/components/primitives/CustomHTML.js +5 -0
  94. package/dist/components/primitives/FileUpload.d.ts +18 -0
  95. package/dist/components/primitives/FileUpload.d.ts.map +1 -0
  96. package/dist/components/primitives/FileUpload.js +16 -0
  97. package/dist/components/primitives/InputBox.d.ts +34 -0
  98. package/dist/components/primitives/InputBox.d.ts.map +1 -0
  99. package/dist/components/primitives/InputBox.js +25 -0
  100. package/dist/components/primitives/Lottie.d.ts +11 -0
  101. package/dist/components/primitives/Lottie.d.ts.map +1 -0
  102. package/dist/components/primitives/Lottie.js +5 -0
  103. package/dist/components/primitives/MediaEmbed.d.ts +13 -0
  104. package/dist/components/primitives/MediaEmbed.d.ts.map +1 -0
  105. package/dist/components/primitives/MediaEmbed.js +6 -0
  106. package/dist/components/primitives/MediaImage.d.ts +8 -0
  107. package/dist/components/primitives/MediaImage.d.ts.map +1 -0
  108. package/dist/components/primitives/MediaImage.js +5 -0
  109. package/dist/components/primitives/OptionSelector.d.ts +38 -0
  110. package/dist/components/primitives/OptionSelector.d.ts.map +1 -0
  111. package/dist/components/primitives/OptionSelector.js +8 -0
  112. package/dist/components/primitives/PaypalCheckout.d.ts +25 -0
  113. package/dist/components/primitives/PaypalCheckout.d.ts.map +1 -0
  114. package/dist/components/primitives/PaypalCheckout.js +5 -0
  115. package/dist/components/primitives/PlainText.d.ts +6 -0
  116. package/dist/components/primitives/PlainText.d.ts.map +1 -0
  117. package/dist/components/primitives/PlainText.js +5 -0
  118. package/dist/components/primitives/ProgressBar.d.ts +15 -0
  119. package/dist/components/primitives/ProgressBar.d.ts.map +1 -0
  120. package/dist/components/primitives/ProgressBar.js +5 -0
  121. package/dist/components/primitives/RichText.d.ts +6 -0
  122. package/dist/components/primitives/RichText.d.ts.map +1 -0
  123. package/dist/components/primitives/RichText.js +5 -0
  124. package/dist/components/primitives/RichTextMarkdown.d.ts +6 -0
  125. package/dist/components/primitives/RichTextMarkdown.d.ts.map +1 -0
  126. package/dist/components/primitives/RichTextMarkdown.js +5 -0
  127. package/dist/components/primitives/Rive.d.ts +16 -0
  128. package/dist/components/primitives/Rive.d.ts.map +1 -0
  129. package/dist/components/primitives/Rive.js +8 -0
  130. package/dist/components/primitives/StripeCheckout.d.ts +52 -0
  131. package/dist/components/primitives/StripeCheckout.d.ts.map +1 -0
  132. package/dist/components/primitives/StripeCheckout.js +5 -0
  133. package/dist/components/primitives/StripeCheckout2.d.ts +30 -0
  134. package/dist/components/primitives/StripeCheckout2.d.ts.map +1 -0
  135. package/dist/components/primitives/StripeCheckout2.js +7 -0
  136. package/dist/config/index.d.ts +23 -0
  137. package/dist/config/index.d.ts.map +1 -0
  138. package/dist/config/index.js +42 -0
  139. package/dist/constants.d.ts +9 -0
  140. package/dist/constants.d.ts.map +1 -0
  141. package/dist/constants.js +9 -0
  142. package/dist/helpers/dates.d.ts +5 -0
  143. package/dist/helpers/dates.d.ts.map +1 -0
  144. package/dist/helpers/dates.js +7 -0
  145. package/dist/helpers/json.d.ts +47 -0
  146. package/dist/helpers/json.d.ts.map +1 -0
  147. package/dist/helpers/json.js +622 -0
  148. package/dist/helpers/prompt.d.ts +15 -0
  149. package/dist/helpers/prompt.d.ts.map +1 -0
  150. package/dist/helpers/prompt.js +35 -0
  151. package/dist/helpers/utils.d.ts +13 -0
  152. package/dist/helpers/utils.d.ts.map +1 -0
  153. package/dist/helpers/utils.js +28 -0
  154. package/dist/logger.d.ts +11 -0
  155. package/dist/logger.d.ts.map +1 -0
  156. package/dist/logger.js +21 -0
  157. package/dist/patches/prompts-escape.d.ts +14 -0
  158. package/dist/patches/prompts-escape.d.ts.map +1 -0
  159. package/dist/patches/prompts-escape.js +23 -0
  160. package/dist/prompts/branches.d.ts +20 -0
  161. package/dist/prompts/branches.d.ts.map +1 -0
  162. package/dist/prompts/branches.js +86 -0
  163. package/dist/prompts/embeddables.d.ts +43 -0
  164. package/dist/prompts/embeddables.d.ts.map +1 -0
  165. package/dist/prompts/embeddables.js +200 -0
  166. package/dist/prompts/experiments.d.ts +28 -0
  167. package/dist/prompts/experiments.d.ts.map +1 -0
  168. package/dist/prompts/experiments.js +89 -0
  169. package/dist/prompts/index.d.ts +11 -0
  170. package/dist/prompts/index.d.ts.map +1 -0
  171. package/dist/prompts/index.js +6 -0
  172. package/dist/prompts/projects.d.ts +22 -0
  173. package/dist/prompts/projects.d.ts.map +1 -0
  174. package/dist/prompts/projects.js +92 -0
  175. package/dist/prompts/versions.d.ts +18 -0
  176. package/dist/prompts/versions.d.ts.map +1 -0
  177. package/dist/prompts/versions.js +95 -0
  178. package/dist/proxy/injectApiInterceptor.d.ts +6 -0
  179. package/dist/proxy/injectApiInterceptor.d.ts.map +1 -0
  180. package/dist/proxy/injectApiInterceptor.js +66 -0
  181. package/dist/proxy/injectReload.d.ts +2 -0
  182. package/dist/proxy/injectReload.d.ts.map +1 -0
  183. package/dist/proxy/injectReload.js +14 -0
  184. package/dist/proxy/injectWorkbench.d.ts +5 -0
  185. package/dist/proxy/injectWorkbench.d.ts.map +1 -0
  186. package/dist/proxy/injectWorkbench.js +22 -0
  187. package/dist/proxy/server.d.ts +11 -0
  188. package/dist/proxy/server.d.ts.map +1 -0
  189. package/dist/proxy/server.js +304 -0
  190. package/dist/proxy/sse.d.ts +5 -0
  191. package/dist/proxy/sse.d.ts.map +1 -0
  192. package/dist/proxy/sse.js +17 -0
  193. package/dist/sentry-context.d.ts +48 -0
  194. package/dist/sentry-context.d.ts.map +1 -0
  195. package/dist/sentry-context.js +156 -0
  196. package/dist/stdout.d.ts +61 -0
  197. package/dist/stdout.d.ts.map +1 -0
  198. package/dist/stdout.js +163 -0
  199. package/dist/types-builder.d.ts +800 -0
  200. package/dist/types-builder.d.ts.map +1 -0
  201. package/dist/types-builder.js +20 -0
  202. package/dist/workbench/ActionsPanel.d.ts +6 -0
  203. package/dist/workbench/ActionsPanel.d.ts.map +1 -0
  204. package/dist/workbench/ActionsPanel.js +47 -0
  205. package/dist/workbench/AutofillPanel.d.ts +6 -0
  206. package/dist/workbench/AutofillPanel.d.ts.map +1 -0
  207. package/dist/workbench/AutofillPanel.js +543 -0
  208. package/dist/workbench/ComputedFieldsPanel.d.ts +6 -0
  209. package/dist/workbench/ComputedFieldsPanel.d.ts.map +1 -0
  210. package/dist/workbench/ComputedFieldsPanel.js +31 -0
  211. package/dist/workbench/ExperimentsPanel.d.ts +6 -0
  212. package/dist/workbench/ExperimentsPanel.d.ts.map +1 -0
  213. package/dist/workbench/ExperimentsPanel.js +182 -0
  214. package/dist/workbench/FieldEditorPanel.d.ts +9 -0
  215. package/dist/workbench/FieldEditorPanel.d.ts.map +1 -0
  216. package/dist/workbench/FieldEditorPanel.js +650 -0
  217. package/dist/workbench/InspectorPanel.d.ts +6 -0
  218. package/dist/workbench/InspectorPanel.d.ts.map +1 -0
  219. package/dist/workbench/InspectorPanel.js +341 -0
  220. package/dist/workbench/PageNavigator.d.ts +6 -0
  221. package/dist/workbench/PageNavigator.d.ts.map +1 -0
  222. package/dist/workbench/PageNavigator.js +123 -0
  223. package/dist/workbench/SchemaPanel.d.ts +6 -0
  224. package/dist/workbench/SchemaPanel.d.ts.map +1 -0
  225. package/dist/workbench/SchemaPanel.js +222 -0
  226. package/dist/workbench/UserDataPanel.d.ts +6 -0
  227. package/dist/workbench/UserDataPanel.d.ts.map +1 -0
  228. package/dist/workbench/UserDataPanel.js +350 -0
  229. package/dist/workbench/WorkbenchApp.d.ts +7 -0
  230. package/dist/workbench/WorkbenchApp.d.ts.map +1 -0
  231. package/dist/workbench/WorkbenchApp.js +193 -0
  232. package/dist/workbench/index.d.ts +10 -0
  233. package/dist/workbench/index.d.ts.map +1 -0
  234. package/dist/workbench/index.js +44 -0
  235. package/package.json +2 -1
@@ -0,0 +1,74 @@
1
+ import { exec } from 'node:child_process';
2
+ import pc from 'picocolors';
3
+ import { isLoggedIn } from '../auth/index.js';
4
+ import { getProjectId, writeProjectConfig } from '../config/index.js';
5
+ import { promptForProject, promptForLocalEmbeddable } from '../prompts/index.js';
6
+ import { createLogger, exit } from '../logger.js';
7
+ import { getSentryContextFromEmbeddableConfig, getSentryContextFromProjectConfig, setSentryContext, } from '../sentry-context.js';
8
+ import * as stdout from '../stdout.js';
9
+ import { inferEmbeddableFromCwd } from '../helpers/utils.js';
10
+ function openUrl(url) {
11
+ const platform = process.platform;
12
+ const cmd = platform === 'darwin' ? 'open' : platform === 'win32' ? 'start' : 'xdg-open';
13
+ exec(`${cmd} ${JSON.stringify(url)}`, (err) => {
14
+ if (err) {
15
+ stdout.warn('Could not open browser automatically. Please open the URL manually.');
16
+ }
17
+ });
18
+ }
19
+ export async function runBuilderOpen(opts) {
20
+ const logger = createLogger('runBuilderOpen');
21
+ const inferred = inferEmbeddableFromCwd();
22
+ let embeddableId = opts.id ?? inferred?.embeddableId;
23
+ if (inferred && !opts.id && embeddableId) {
24
+ process.chdir(inferred.projectRoot);
25
+ }
26
+ setSentryContext(getSentryContextFromProjectConfig());
27
+ let projectId = getProjectId();
28
+ if (!projectId) {
29
+ if (!isLoggedIn()) {
30
+ stdout.warn('No project configured and not logged in.');
31
+ stdout.dim('Run "embeddables login" first, or add a project_id to embeddables.json.');
32
+ logger.error('no project id and not logged in');
33
+ await exit(1);
34
+ return;
35
+ }
36
+ stdout.step('No project configured. Fetching projects…');
37
+ const selectedProject = await promptForProject();
38
+ if (!selectedProject) {
39
+ logger.error('project selection failed');
40
+ await exit(1);
41
+ return;
42
+ }
43
+ projectId = selectedProject.id;
44
+ writeProjectConfig({
45
+ org_id: selectedProject.org_id || undefined,
46
+ org_title: selectedProject.org_title || undefined,
47
+ project_id: projectId,
48
+ project_name: selectedProject.title || undefined,
49
+ });
50
+ stdout.success('Saved project to embeddables.json');
51
+ stdout.gap();
52
+ }
53
+ if (!embeddableId) {
54
+ const selected = await promptForLocalEmbeddable({
55
+ message: 'Select an embeddable to open in the Builder:',
56
+ });
57
+ if (!selected) {
58
+ logger.error('no embeddable selected');
59
+ await exit(1);
60
+ return;
61
+ }
62
+ embeddableId = selected;
63
+ stdout.gap();
64
+ }
65
+ if (embeddableId) {
66
+ setSentryContext({
67
+ embeddable: { id: embeddableId },
68
+ ...getSentryContextFromEmbeddableConfig(embeddableId),
69
+ });
70
+ }
71
+ const url = `https://app.embeddables.com/project/${projectId}/embeddables/${embeddableId}/edit`;
72
+ stdout.success(`Opening Builder: ${pc.underline(url)}`);
73
+ openUrl(url);
74
+ }
@@ -0,0 +1,12 @@
1
+ export declare function runDev(opts: {
2
+ id?: string;
3
+ pages?: string;
4
+ out?: string;
5
+ fix?: boolean;
6
+ local?: boolean;
7
+ engine: string;
8
+ port: string;
9
+ overrideRoute: string;
10
+ pageKeyFrom: 'filename' | 'export';
11
+ }): Promise<void>;
12
+ //# sourceMappingURL=dev.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dev.d.ts","sourceRoot":"","sources":["../../src/commands/dev.ts"],"names":[],"mappings":"AAoHA,wBAAsB,MAAM,CAAC,IAAI,EAAE;IACjC,EAAE,CAAC,EAAE,MAAM,CAAA;IACX,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,GAAG,CAAC,EAAE,OAAO,CAAA;IACb,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,MAAM,EAAE,MAAM,CAAA;IACd,IAAI,EAAE,MAAM,CAAA;IACZ,aAAa,EAAE,MAAM,CAAA;IACrB,WAAW,EAAE,UAAU,GAAG,QAAQ,CAAA;CACnC,iBAwJA"}
@@ -0,0 +1,226 @@
1
+ import fs from 'node:fs';
2
+ import net from 'node:net';
3
+ import path from 'node:path';
4
+ import chokidar from 'chokidar';
5
+ import pc from 'picocolors';
6
+ import { compileAllPages } from '../compiler/index.js';
7
+ import { startProxyServer } from '../proxy/server.js';
8
+ import { formatError } from '../compiler/errors.js';
9
+ import { captureException, createLogger, exit } from '../logger.js';
10
+ import { getSentryContextFromEmbeddableConfig, getSentryContextFromProjectConfig, setSentryContext, } from '../sentry-context.js';
11
+ import * as stdout from '../stdout.js';
12
+ import { inferEmbeddableFromCwd } from '../helpers/utils.js';
13
+ /**
14
+ * Check whether a port is available by attempting to listen on it.
15
+ */
16
+ function isPortAvailable(port) {
17
+ return new Promise((resolve) => {
18
+ const server = net.createServer();
19
+ server.once('error', () => resolve(false));
20
+ server.once('listening', () => {
21
+ server.close(() => resolve(true));
22
+ });
23
+ server.listen(port);
24
+ });
25
+ }
26
+ /**
27
+ * Starting from `startPort`, find the first available port.
28
+ * Tries up to `maxAttempts` consecutive ports.
29
+ */
30
+ async function getAvailablePort(startPort, maxAttempts = 20) {
31
+ for (let i = 0; i < maxAttempts; i++) {
32
+ const port = startPort + i;
33
+ if (await isPortAvailable(port)) {
34
+ return port;
35
+ }
36
+ }
37
+ throw new Error(`Could not find an available port (tried ${startPort}–${startPort + maxAttempts - 1})`);
38
+ }
39
+ async function discoverEmbeddables() {
40
+ const embeddablesDir = 'embeddables';
41
+ if (!fs.existsSync(embeddablesDir)) {
42
+ return [];
43
+ }
44
+ const entries = fs.readdirSync(embeddablesDir, { withFileTypes: true });
45
+ const embeddables = [];
46
+ for (const entry of entries) {
47
+ if (!entry.isDirectory())
48
+ continue;
49
+ const id = entry.name;
50
+ const metadataPath = path.join(embeddablesDir, id, 'metadata.json');
51
+ let title = null;
52
+ if (fs.existsSync(metadataPath)) {
53
+ try {
54
+ const metadata = JSON.parse(fs.readFileSync(metadataPath, 'utf-8'));
55
+ title = metadata.title || null;
56
+ }
57
+ catch {
58
+ // Ignore JSON parse errors
59
+ }
60
+ }
61
+ embeddables.push({ id, title });
62
+ }
63
+ // Sort by title (with title) first, then by id
64
+ return embeddables.sort((a, b) => {
65
+ if (a.title && !b.title)
66
+ return -1;
67
+ if (!a.title && b.title)
68
+ return 1;
69
+ const aLabel = a.title || a.id;
70
+ const bLabel = b.title || b.id;
71
+ return aLabel.localeCompare(bLabel, undefined, { sensitivity: 'base' });
72
+ });
73
+ }
74
+ async function promptForEmbeddable() {
75
+ const embeddables = await discoverEmbeddables();
76
+ if (embeddables.length === 0) {
77
+ stdout.error('No embeddables found in the embeddables/ directory.');
78
+ stdout.dim('Run `embeddables pull --id <id>` to pull an embeddable first.');
79
+ return null;
80
+ }
81
+ const choices = embeddables.map((e) => ({
82
+ title: e.title ? `${e.title} (${e.id})` : e.id,
83
+ value: e.id,
84
+ }));
85
+ const { prompt: promptWithCancel } = await import('../helpers/prompt.js');
86
+ const response = await promptWithCancel({
87
+ type: 'select',
88
+ name: 'id',
89
+ message: 'Select an embeddable to run:',
90
+ choices,
91
+ });
92
+ return response.id || null;
93
+ }
94
+ export async function runDev(opts) {
95
+ const logger = createLogger('runDev');
96
+ const inferred = inferEmbeddableFromCwd();
97
+ let embeddableId = opts.id ?? inferred?.embeddableId;
98
+ if (inferred && !opts.id && embeddableId) {
99
+ process.chdir(inferred.projectRoot);
100
+ }
101
+ setSentryContext(getSentryContextFromProjectConfig());
102
+ if (!embeddableId) {
103
+ const selected = await promptForEmbeddable();
104
+ if (!selected) {
105
+ logger.error('no embeddable selected');
106
+ await exit(1);
107
+ return;
108
+ }
109
+ embeddableId = selected;
110
+ }
111
+ if (embeddableId) {
112
+ setSentryContext({
113
+ embeddable: { id: embeddableId },
114
+ ...getSentryContextFromEmbeddableConfig(embeddableId),
115
+ });
116
+ }
117
+ logger.info('dev started', { engine: opts.engine, port: opts.port });
118
+ const pagesGlob = opts.pages || `embeddables/${embeddableId}/pages/**/*.page.tsx`;
119
+ const outPath = opts.out || path.join('embeddables', embeddableId, '.generated', 'embeddable.json');
120
+ const stylesDir = path.join('embeddables', embeddableId, 'styles');
121
+ const stylesGlob = `embeddables/${embeddableId}/styles/**/*.css`;
122
+ const configPath = path.join('embeddables', embeddableId, 'config.json');
123
+ const globalComponentsGlob = `embeddables/${embeddableId}/global-components/**/*.location.tsx`;
124
+ const computedFieldsGlob = `embeddables/${embeddableId}/computed-fields/**/*.js`;
125
+ const actionsGlob = `embeddables/${embeddableId}/actions/**/*.js`;
126
+ const fixLint = opts.fix ? true : 'prompt';
127
+ // Initial build with spinner
128
+ try {
129
+ await stdout.withSpinner('Building…', async () => {
130
+ await compileAllPages({
131
+ pagesGlob,
132
+ outPath,
133
+ pageKeyFrom: opts.pageKeyFrom,
134
+ stylesDir,
135
+ embeddableId: embeddableId,
136
+ configPath,
137
+ fixLint,
138
+ });
139
+ }, {
140
+ successText: 'Initial build complete',
141
+ });
142
+ }
143
+ catch (e) {
144
+ captureException(e);
145
+ stdout.error(formatError(e));
146
+ logger.error('initial build failed');
147
+ await exit(1);
148
+ }
149
+ // Start proxy — find an available port if the requested one is taken
150
+ const requestedPort = Number(opts.port);
151
+ let port;
152
+ try {
153
+ port = await getAvailablePort(requestedPort);
154
+ }
155
+ catch (e) {
156
+ captureException(e);
157
+ stdout.error(e.message);
158
+ logger.error('no available port', { requestedPort });
159
+ await exit(1);
160
+ return;
161
+ }
162
+ if (port !== requestedPort) {
163
+ stdout.warn(`Port ${requestedPort} is in use, using ${port} instead.`);
164
+ }
165
+ // Mute proxy startup logs (workbench, routes, etc.) — the Dev Server box has all the info
166
+ stdout.mute();
167
+ const proxy = await startProxyServer({
168
+ port,
169
+ engineOrigin: opts.engine,
170
+ overrideRoute: opts.overrideRoute,
171
+ generatedJsonPath: outPath,
172
+ embeddableId,
173
+ watchWorkbench: true,
174
+ });
175
+ stdout.unmute();
176
+ logger.info('dev server running', { port });
177
+ // Watch all source files: pages, styles, config, global components, computed fields, and actions
178
+ const watcher = chokidar.watch([pagesGlob, stylesGlob, configPath, globalComponentsGlob, computedFieldsGlob, actionsGlob], {
179
+ ignoreInitial: true,
180
+ });
181
+ const rebuild = async () => {
182
+ const elapsed = stdout.timer();
183
+ const s = stdout.spinner('Rebuilding…');
184
+ try {
185
+ await compileAllPages({
186
+ pagesGlob,
187
+ outPath,
188
+ pageKeyFrom: opts.pageKeyFrom,
189
+ stylesDir,
190
+ embeddableId: embeddableId,
191
+ configPath,
192
+ fixLint,
193
+ });
194
+ proxy.broadcastReload();
195
+ s.succeed(`Rebuilt in ${elapsed()}`);
196
+ }
197
+ catch (e) {
198
+ // Keep dev server running; compiler errors show in console.
199
+ // (Proxy will still serve the last good JSON.)
200
+ captureException(e);
201
+ s.fail('Rebuild failed');
202
+ stdout.error(formatError(e));
203
+ }
204
+ };
205
+ let t;
206
+ watcher.on('all', () => {
207
+ clearTimeout(t);
208
+ t = setTimeout(rebuild, 80);
209
+ });
210
+ // Embeddable context
211
+ stdout.infoBox(`ID: ${embeddableId} · Engine: ${opts.engine}`);
212
+ // Dev server ready box
213
+ const previewUrl = `http://localhost:${port}?id=${embeddableId}&version=latest`;
214
+ const modeLabel = opts.local
215
+ ? `${pc.blue('Local')} (${opts.engine})`
216
+ : `${pc.yellow('Remote')} (${opts.engine})`;
217
+ const boxContent = [
218
+ `${pc.gray('Mode:')} ${modeLabel}`,
219
+ `${pc.gray('Preview:')} ${pc.underline(pc.cyan(previewUrl))}`,
220
+ '',
221
+ `${pc.gray(`Watching embeddables/${embeddableId}/ for changes…`)}`,
222
+ ].join('\n');
223
+ stdout.gap();
224
+ stdout.box(boxContent, { title: 'Dev Server', borderColor: 'green' });
225
+ stdout.gap();
226
+ }
@@ -0,0 +1,6 @@
1
+ export declare function runExperimentsConnect(opts: {
2
+ id?: string;
3
+ experimentId?: string;
4
+ experimentKey?: string;
5
+ }): Promise<void>;
6
+ //# sourceMappingURL=experiments-connect.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"experiments-connect.d.ts","sourceRoot":"","sources":["../../src/commands/experiments-connect.ts"],"names":[],"mappings":"AAmBA,wBAAsB,qBAAqB,CAAC,IAAI,EAAE;IAChD,EAAE,CAAC,EAAE,MAAM,CAAA;IACX,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,aAAa,CAAC,EAAE,MAAM,CAAA;CACvB,iBAeA"}
@@ -0,0 +1,140 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import { isLoggedIn } from '../auth/index.js';
4
+ import { getProjectId, writeProjectConfig } from '../config/index.js';
5
+ import { promptForProject, promptForLocalEmbeddable, promptForExperiment, } from '../prompts/index.js';
6
+ import { createLogger, exit } from '../logger.js';
7
+ import { getSentryContextFromEmbeddableConfig, getSentryContextFromProjectConfig, setSentryContext, } from '../sentry-context.js';
8
+ import * as stdout from '../stdout.js';
9
+ import { inferEmbeddableFromCwd } from '../helpers/utils.js';
10
+ export async function runExperimentsConnect(opts) {
11
+ const logger = createLogger('runExperimentsConnect');
12
+ try {
13
+ await runExperimentsConnectInner(opts);
14
+ }
15
+ catch (error) {
16
+ if (error instanceof Error) {
17
+ stdout.error(`Connect failed: ${error.message}`);
18
+ }
19
+ else {
20
+ stdout.error('Connect failed with an unexpected error.');
21
+ }
22
+ logger.error('experiments connect failed', {
23
+ message: error instanceof Error ? error.message : 'unexpected error',
24
+ });
25
+ await exit(1);
26
+ }
27
+ }
28
+ async function runExperimentsConnectInner(opts) {
29
+ const logger = createLogger('runExperimentsConnect');
30
+ // 1. Check login (needed for fetching experiments from Supabase)
31
+ if (!isLoggedIn()) {
32
+ stdout.warn('Not logged in.');
33
+ stdout.dim('Run "embeddables login" first.');
34
+ logger.error('not logged in');
35
+ await exit(1);
36
+ }
37
+ // 2. Get project ID (needed for experiment list)
38
+ let projectId = getProjectId();
39
+ if (!projectId) {
40
+ stdout.step('No project configured. Fetching projects…');
41
+ const selectedProject = await promptForProject();
42
+ if (!selectedProject) {
43
+ await exit(1);
44
+ return;
45
+ }
46
+ projectId = selectedProject.id;
47
+ writeProjectConfig({
48
+ org_id: selectedProject.org_id || undefined,
49
+ org_title: selectedProject.org_title || undefined,
50
+ project_id: projectId,
51
+ project_name: selectedProject.title || undefined,
52
+ });
53
+ stdout.success('Saved project to embeddables.json');
54
+ stdout.gap();
55
+ }
56
+ // 4. Get embeddable ID (from option, cwd inference, or interactive prompt)
57
+ const inferred = inferEmbeddableFromCwd();
58
+ let embeddableId = opts.id ?? inferred?.embeddableId;
59
+ if (inferred && !opts.id && embeddableId) {
60
+ process.chdir(inferred.projectRoot);
61
+ }
62
+ setSentryContext(getSentryContextFromProjectConfig());
63
+ if (!embeddableId) {
64
+ const selected = await promptForLocalEmbeddable({
65
+ message: 'Select an embeddable to connect the experiment to:',
66
+ });
67
+ if (!selected) {
68
+ await exit(1);
69
+ return;
70
+ }
71
+ embeddableId = selected;
72
+ stdout.gap();
73
+ }
74
+ if (embeddableId) {
75
+ setSentryContext({
76
+ embeddable: { id: embeddableId },
77
+ ...getSentryContextFromEmbeddableConfig(embeddableId),
78
+ });
79
+ }
80
+ // 5. Get experiment_id and experiment_key (from opts or interactive prompt)
81
+ let experimentId = opts.experimentId;
82
+ let experimentKey = opts.experimentKey;
83
+ if (experimentId && !experimentKey) {
84
+ stdout.error('When using --experiment-id, --experiment-key is also required.');
85
+ logger.error('missing experiment-key flag');
86
+ await exit(1);
87
+ }
88
+ if (experimentKey && !experimentId) {
89
+ stdout.error('When using --experiment-key, --experiment-id is also required.');
90
+ logger.error('missing experiment-id flag');
91
+ await exit(1);
92
+ }
93
+ if (!experimentId || !experimentKey) {
94
+ const selected = await stdout.withSpinner('Fetching experiments…', async () => {
95
+ return promptForExperiment(projectId, {
96
+ message: 'Select an experiment to connect:',
97
+ excludeConnectedTo: embeddableId,
98
+ });
99
+ }, { successText: 'Experiments loaded' });
100
+ if (!selected) {
101
+ await exit(1);
102
+ return;
103
+ }
104
+ experimentId = selected.experiment_id;
105
+ experimentKey = selected.experiment_key;
106
+ stdout.gap();
107
+ }
108
+ // 6. Read config.json
109
+ const configPath = path.join('embeddables', embeddableId, 'config.json');
110
+ if (!fs.existsSync(configPath)) {
111
+ stdout.error(`No config.json found at ${configPath}`);
112
+ stdout.dim('Run "embeddables pull" or "embeddables init" first.');
113
+ logger.error('config not found', { configPath });
114
+ await exit(1);
115
+ }
116
+ let config;
117
+ try {
118
+ const content = fs.readFileSync(configPath, 'utf8');
119
+ config = JSON.parse(content);
120
+ }
121
+ catch {
122
+ stdout.error('Failed to parse config.json.');
123
+ logger.error('failed to parse config');
124
+ await exit(1);
125
+ return;
126
+ }
127
+ // 7. Append to connected_experiments
128
+ const connectedExperiments = Array.isArray(config.connected_experiments) ? [...config.connected_experiments] : [];
129
+ const alreadyConnected = connectedExperiments.some((e) => e.experiment_id === experimentId && e.experiment_key === experimentKey);
130
+ if (alreadyConnected) {
131
+ stdout.warn(`Experiment "${experimentKey}" is already connected to this embeddable.`);
132
+ return;
133
+ }
134
+ connectedExperiments.push({ experiment_id: experimentId, experiment_key: experimentKey });
135
+ config.connected_experiments = connectedExperiments;
136
+ // 8. Write the modified config back
137
+ fs.writeFileSync(configPath, JSON.stringify(config, null, 2), 'utf8');
138
+ stdout.success(`Connected experiment "${experimentKey}" to embeddable`);
139
+ stdout.dim('Run "embeddables save" to persist to the cloud.');
140
+ }
@@ -0,0 +1,5 @@
1
+ export declare function runInit(opts: {
2
+ projectId?: string;
3
+ yes?: boolean;
4
+ }): Promise<void>;
5
+ //# sourceMappingURL=init.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAoIA,wBAAsB,OAAO,CAAC,IAAI,EAAE;IAAE,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,OAAO,CAAA;CAAE,iBAkSxE"}