@embeddables/cli 0.1.0 → 0.3.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.
Files changed (49) hide show
  1. package/.cursor/rules/embeddables-cli.md +679 -0
  2. package/README.md +37 -7
  3. package/dist/auth/index.d.ts +1 -1
  4. package/dist/auth/index.d.ts.map +1 -1
  5. package/dist/auth/index.js +5 -3
  6. package/dist/cli.js +42 -6
  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 +46 -0
  10. package/dist/commands/dev.d.ts +1 -1
  11. package/dist/commands/dev.d.ts.map +1 -1
  12. package/dist/commands/dev.js +48 -9
  13. package/dist/commands/init.d.ts +5 -0
  14. package/dist/commands/init.d.ts.map +1 -0
  15. package/dist/commands/init.js +245 -0
  16. package/dist/commands/pull.d.ts +1 -1
  17. package/dist/commands/pull.d.ts.map +1 -1
  18. package/dist/commands/pull.js +104 -3
  19. package/dist/commands/save.d.ts +8 -0
  20. package/dist/commands/save.d.ts.map +1 -0
  21. package/dist/commands/save.js +269 -0
  22. package/dist/compiler/index.d.ts.map +1 -1
  23. package/dist/compiler/index.js +4 -0
  24. package/dist/compiler/reverse.d.ts.map +1 -1
  25. package/dist/compiler/reverse.js +4 -10
  26. package/dist/config/index.d.ts +23 -0
  27. package/dist/config/index.d.ts.map +1 -0
  28. package/dist/config/index.js +42 -0
  29. package/dist/constants.d.ts +7 -0
  30. package/dist/constants.d.ts.map +1 -0
  31. package/dist/constants.js +6 -0
  32. package/dist/helpers/dates.d.ts +5 -0
  33. package/dist/helpers/dates.d.ts.map +1 -0
  34. package/dist/helpers/dates.js +7 -0
  35. package/dist/prompts/branches.d.ts +20 -0
  36. package/dist/prompts/branches.d.ts.map +1 -0
  37. package/dist/prompts/branches.js +89 -0
  38. package/dist/prompts/embeddables.d.ts +41 -0
  39. package/dist/prompts/embeddables.d.ts.map +1 -0
  40. package/dist/prompts/embeddables.js +161 -0
  41. package/dist/prompts/index.d.ts +7 -0
  42. package/dist/prompts/index.d.ts.map +1 -0
  43. package/dist/prompts/index.js +4 -0
  44. package/dist/prompts/projects.d.ts +22 -0
  45. package/dist/prompts/projects.d.ts.map +1 -0
  46. package/dist/prompts/projects.js +85 -0
  47. package/dist/proxy/server.d.ts.map +1 -1
  48. package/dist/proxy/server.js +10 -4
  49. package/package.json +6 -5
@@ -1,10 +1,52 @@
1
1
  import fs from 'node:fs';
2
2
  import path from 'node:path';
3
3
  import pc from 'picocolors';
4
+ import prompts from 'prompts';
4
5
  import { reverseCompile } from '../compiler/reverse.js';
5
- import { getAccessToken } from '../auth/index.js';
6
+ import { getAccessToken, isLoggedIn } from '../auth/index.js';
7
+ import { getProjectId, writeProjectConfig } from '../config/index.js';
8
+ import { promptForProject, promptForEmbeddable, fetchEmbeddableMetadata } from '../prompts/index.js';
6
9
  export async function runPull(opts) {
7
- const embeddableId = opts.id;
10
+ let embeddableId = opts.id;
11
+ // If no ID provided, try to get it interactively
12
+ if (!embeddableId) {
13
+ if (!isLoggedIn()) {
14
+ console.error(pc.red('No embeddable ID provided and not logged in.'));
15
+ console.log('');
16
+ console.log(pc.gray('Either:'));
17
+ console.log(pc.gray(' 1. Use --id <embeddable-id> to specify an embeddable'));
18
+ console.log(pc.gray(' 2. Run "embeddables login" first for interactive selection'));
19
+ process.exit(1);
20
+ }
21
+ let projectId = getProjectId();
22
+ // If no project ID configured, prompt for project selection
23
+ if (!projectId) {
24
+ console.log(pc.cyan('Fetching projects...'));
25
+ const selectedProject = await promptForProject();
26
+ if (!selectedProject) {
27
+ process.exit(1);
28
+ }
29
+ projectId = selectedProject.id;
30
+ // Save the selected project to config
31
+ writeProjectConfig({
32
+ org_id: selectedProject.org_id || undefined,
33
+ org_title: selectedProject.org_title || undefined,
34
+ project_id: projectId,
35
+ project_name: selectedProject.title || undefined,
36
+ });
37
+ console.log(pc.green(`✓ Saved project to embeddables.json`));
38
+ console.log('');
39
+ }
40
+ console.log(pc.cyan('Fetching embeddables from project...'));
41
+ const selected = await promptForEmbeddable(projectId, {
42
+ message: 'Select an embeddable to pull:',
43
+ });
44
+ if (!selected) {
45
+ process.exit(1);
46
+ }
47
+ embeddableId = selected;
48
+ console.log('');
49
+ }
8
50
  let url = `https://engine.embeddables.com/${embeddableId}?version=latest`;
9
51
  if (opts.branch) {
10
52
  url += `&embeddable_branch=${opts.branch}`;
@@ -44,6 +86,14 @@ export async function runPull(opts) {
44
86
  fs.writeFileSync(versionedPath, flowJson, 'utf8');
45
87
  console.log(pc.cyan(`✓ Saved embeddable JSON to ${versionedPath}`));
46
88
  }
89
+ // Fetch and save flow metadata from DB (title, archived, created_at)
90
+ const metadata = await fetchEmbeddableMetadata(embeddableId);
91
+ if (metadata) {
92
+ const metadataPath = path.join('embeddables', embeddableId, 'metadata.json');
93
+ fs.mkdirSync(path.dirname(metadataPath), { recursive: true });
94
+ fs.writeFileSync(metadataPath, JSON.stringify(metadata, null, 2) + '\n', 'utf8');
95
+ console.log(pc.cyan(`✓ Saved flow metadata to ${metadataPath}`));
96
+ }
47
97
  // Clear existing pages, styles, computed-fields, actions, and global-components before generating new ones
48
98
  const pagesDir = path.join('embeddables', embeddableId, 'pages');
49
99
  const stylesDir = path.join('embeddables', embeddableId, 'styles');
@@ -88,7 +138,58 @@ export async function runPull(opts) {
88
138
  console.log(`${pc.gray(`Cleared ${existingGlobalComponents.length} existing global component(s)`)}`);
89
139
  }
90
140
  // Run reverse compiler
91
- await reverseCompile(flow, embeddableId, { fix: opts.fix });
141
+ try {
142
+ await reverseCompile(flow, embeddableId, { fix: opts.fix });
143
+ }
144
+ catch (compileError) {
145
+ // If fix mode wasn't already enabled, offer to retry with fix mode
146
+ if (!opts.fix && compileError instanceof Error) {
147
+ console.log('');
148
+ console.error(pc.red('Error during reverse compile:'));
149
+ console.error(pc.yellow(` ${compileError.message}`));
150
+ console.log('');
151
+ const response = await prompts({
152
+ type: 'confirm',
153
+ name: 'fix',
154
+ message: 'Would you like to retry with auto-fix enabled? (removes problematic components)',
155
+ initial: true,
156
+ }, {
157
+ onCancel: () => {
158
+ process.exit(1);
159
+ },
160
+ });
161
+ if (response.fix) {
162
+ console.log('');
163
+ console.log(pc.cyan('Retrying with auto-fix enabled...'));
164
+ console.log('');
165
+ await reverseCompile(flow, embeddableId, { fix: true });
166
+ }
167
+ else {
168
+ process.exit(1);
169
+ }
170
+ }
171
+ else {
172
+ throw compileError;
173
+ }
174
+ }
175
+ // Store version number in config.json so save knows the base version
176
+ if (version != null) {
177
+ const versionNumber = typeof version === 'number' ? version : parseInt(String(version), 10);
178
+ if (!isNaN(versionNumber)) {
179
+ const configPath = path.join('embeddables', embeddableId, 'config.json');
180
+ if (fs.existsSync(configPath)) {
181
+ try {
182
+ const configContent = fs.readFileSync(configPath, 'utf8');
183
+ const config = JSON.parse(configContent);
184
+ config._version = versionNumber;
185
+ fs.writeFileSync(configPath, JSON.stringify(config, null, 2), 'utf8');
186
+ }
187
+ catch {
188
+ // Ignore errors updating config.json - versioned files are a fallback
189
+ }
190
+ }
191
+ }
192
+ }
92
193
  }
93
194
  catch (error) {
94
195
  console.error('Error pulling embeddable:', error);
@@ -0,0 +1,8 @@
1
+ export declare function runSave(opts: {
2
+ id?: string;
3
+ label?: string;
4
+ branch?: string;
5
+ skipBuild?: boolean;
6
+ fromVersion?: string;
7
+ }): Promise<void>;
8
+ //# sourceMappingURL=save.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"save.d.ts","sourceRoot":"","sources":["../../src/commands/save.ts"],"names":[],"mappings":"AA+FA,wBAAsB,OAAO,CAAC,IAAI,EAAE;IAClC,EAAE,CAAC,EAAE,MAAM,CAAA;IACX,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB,iBAoPA"}
@@ -0,0 +1,269 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import pc from 'picocolors';
4
+ import prompts from 'prompts';
5
+ import { getAccessToken, isLoggedIn } from '../auth/index.js';
6
+ import { getProjectId, writeProjectConfig } from '../config/index.js';
7
+ import { compileAllPages } from '../compiler/index.js';
8
+ import { formatError } from '../compiler/errors.js';
9
+ import { promptForLocalEmbeddable, promptForProject } from '../prompts/index.js';
10
+ import { WEB_APP_BASE_URL } from '../constants.js';
11
+ /**
12
+ * Read `_version` from config.json for the given embeddable.
13
+ */
14
+ function getVersionFromConfig(embeddableId) {
15
+ const configPath = path.join('embeddables', embeddableId, 'config.json');
16
+ if (!fs.existsSync(configPath)) {
17
+ return null;
18
+ }
19
+ try {
20
+ const config = JSON.parse(fs.readFileSync(configPath, 'utf8'));
21
+ if (typeof config._version === 'number') {
22
+ return config._version;
23
+ }
24
+ }
25
+ catch {
26
+ // Ignore parse errors
27
+ }
28
+ return null;
29
+ }
30
+ /**
31
+ * Update `_version` in config.json for the given embeddable.
32
+ */
33
+ function setVersionInConfig(embeddableId, version) {
34
+ const configPath = path.join('embeddables', embeddableId, 'config.json');
35
+ if (!fs.existsSync(configPath)) {
36
+ return;
37
+ }
38
+ try {
39
+ const config = JSON.parse(fs.readFileSync(configPath, 'utf8'));
40
+ config._version = version;
41
+ fs.writeFileSync(configPath, JSON.stringify(config, null, 2), 'utf8');
42
+ }
43
+ catch {
44
+ // Ignore errors - versioned files are a fallback
45
+ }
46
+ }
47
+ /**
48
+ * Scan the .generated/ directory for versioned files (embeddable-v*.json)
49
+ * and return the highest version number found.
50
+ */
51
+ function getLatestVersionFromFiles(generatedDir) {
52
+ if (!fs.existsSync(generatedDir)) {
53
+ return null;
54
+ }
55
+ const files = fs.readdirSync(generatedDir);
56
+ const versionPattern = /^embeddable-v(\d+)\.json$/;
57
+ let maxVersion = null;
58
+ for (const file of files) {
59
+ const match = file.match(versionPattern);
60
+ if (match) {
61
+ const version = parseInt(match[1], 10);
62
+ if (maxVersion === null || version > maxVersion) {
63
+ maxVersion = version;
64
+ }
65
+ }
66
+ }
67
+ return maxVersion;
68
+ }
69
+ export async function runSave(opts) {
70
+ // 1. Check login
71
+ if (!isLoggedIn()) {
72
+ console.error(pc.red('Not logged in.'));
73
+ console.log(pc.gray('Run "embeddables login" first.'));
74
+ process.exit(1);
75
+ }
76
+ // 2. Get access token
77
+ const accessToken = getAccessToken();
78
+ if (!accessToken) {
79
+ console.error(pc.red('Could not retrieve access token.'));
80
+ console.log(pc.gray('Run "embeddables login" to re-authenticate.'));
81
+ process.exit(1);
82
+ }
83
+ // 3. Get embeddable ID (from option or interactive prompt)
84
+ let embeddableId = opts.id;
85
+ if (!embeddableId) {
86
+ const selected = await promptForLocalEmbeddable({
87
+ message: 'Select an embeddable to save:',
88
+ });
89
+ if (!selected) {
90
+ process.exit(1);
91
+ }
92
+ embeddableId = selected;
93
+ console.log('');
94
+ }
95
+ // 4. Get project ID (from config or interactive prompt)
96
+ let projectId = getProjectId();
97
+ if (!projectId) {
98
+ console.log(pc.cyan('No project configured. Fetching projects...'));
99
+ const selectedProject = await promptForProject();
100
+ if (!selectedProject) {
101
+ process.exit(1);
102
+ }
103
+ projectId = selectedProject.id;
104
+ writeProjectConfig({
105
+ org_id: selectedProject.org_id || undefined,
106
+ org_title: selectedProject.org_title || undefined,
107
+ project_id: projectId,
108
+ project_name: selectedProject.title || undefined,
109
+ });
110
+ console.log(pc.green('✓ Saved project to embeddables.json'));
111
+ console.log('');
112
+ }
113
+ // 5. Build (compile TSX → JSON) unless --skip-build is set
114
+ const generatedDir = path.join('embeddables', embeddableId, '.generated');
115
+ const outPath = path.join(generatedDir, 'embeddable.json');
116
+ if (!opts.skipBuild) {
117
+ const pagesGlob = `embeddables/${embeddableId}/pages/**/*.page.tsx`;
118
+ const stylesDir = path.join('embeddables', embeddableId, 'styles');
119
+ const configPath = path.join('embeddables', embeddableId, 'config.json');
120
+ console.log(pc.cyan('Building embeddable...'));
121
+ try {
122
+ await compileAllPages({
123
+ pagesGlob,
124
+ outPath,
125
+ pageKeyFrom: 'filename',
126
+ stylesDir,
127
+ embeddableId,
128
+ configPath,
129
+ });
130
+ }
131
+ catch (e) {
132
+ console.error(formatError(e));
133
+ process.exit(1);
134
+ }
135
+ console.log(pc.green('✓ Build successful'));
136
+ console.log('');
137
+ }
138
+ // 6. Read the compiled JSON
139
+ if (!fs.existsSync(outPath)) {
140
+ console.error(pc.red(`No compiled embeddable found at ${outPath}`));
141
+ console.log(pc.gray('Run "embeddables build" or "embeddables pull" first.'));
142
+ process.exit(1);
143
+ }
144
+ const jsonContent = fs.readFileSync(outPath, 'utf8');
145
+ let embeddableJson;
146
+ try {
147
+ embeddableJson = JSON.parse(jsonContent);
148
+ }
149
+ catch {
150
+ console.error(pc.red('Failed to parse embeddable JSON.'));
151
+ process.exit(1);
152
+ }
153
+ // Validate that pages array exists and is non-empty
154
+ if (!embeddableJson.pages ||
155
+ !Array.isArray(embeddableJson.pages) ||
156
+ embeddableJson.pages.length === 0) {
157
+ console.error(pc.red('Embeddable JSON must contain a non-empty pages array.'));
158
+ process.exit(1);
159
+ }
160
+ // 7. Determine fromVersionNumber
161
+ let fromVersionNumber;
162
+ if (opts.fromVersion) {
163
+ fromVersionNumber = parseInt(opts.fromVersion, 10);
164
+ if (isNaN(fromVersionNumber)) {
165
+ console.error(pc.red(`Invalid --from-version value: ${opts.fromVersion}`));
166
+ process.exit(1);
167
+ }
168
+ }
169
+ else {
170
+ // Primary: read _version from config.json; fallback: scan .generated/ for versioned files
171
+ const detectedVersion = getVersionFromConfig(embeddableId) ?? getLatestVersionFromFiles(generatedDir);
172
+ if (detectedVersion === null) {
173
+ console.error(pc.red('Could not determine the current version number.'));
174
+ console.log(pc.gray('Make sure you have pulled the embeddable first (embeddables pull), or specify --from-version <number>.'));
175
+ process.exit(1);
176
+ }
177
+ fromVersionNumber = detectedVersion;
178
+ }
179
+ // 8. POST to save-version API
180
+ console.log(pc.cyan(`Saving embeddable (based on v${fromVersionNumber})...`));
181
+ const body = {
182
+ embeddableId,
183
+ jsonString: JSON.stringify(embeddableJson),
184
+ projectId,
185
+ fromVersionNumber,
186
+ };
187
+ if (opts.label) {
188
+ body.label = opts.label;
189
+ }
190
+ if (opts.branch) {
191
+ body.branchId = opts.branch;
192
+ }
193
+ const url = `${WEB_APP_BASE_URL}/api/embeddables/save-version`;
194
+ const headers = {
195
+ Authorization: `Bearer ${accessToken}`,
196
+ 'Content-Type': 'application/json',
197
+ };
198
+ try {
199
+ const response = await fetch(url, {
200
+ method: 'POST',
201
+ headers,
202
+ body: JSON.stringify(body),
203
+ });
204
+ if (response.status === 409) {
205
+ const conflictResult = (await response.json());
206
+ console.log('');
207
+ console.warn(pc.yellow(`⚠ Version conflict: the server has version ${conflictResult.latestVersionNumber}, but you are saving from version ${conflictResult.yourVersionNumber}.`));
208
+ const { forceSave } = await prompts({
209
+ type: 'confirm',
210
+ name: 'forceSave',
211
+ message: 'A newer version exists on the server. Save anyway?',
212
+ initial: false,
213
+ }, {
214
+ onCancel: () => {
215
+ process.exit(1);
216
+ },
217
+ });
218
+ if (!forceSave) {
219
+ console.log(pc.gray('Save cancelled.'));
220
+ process.exit(0);
221
+ }
222
+ // Retry with force flag
223
+ console.log(pc.cyan('Retrying save with force...'));
224
+ const forceResponse = await fetch(url, {
225
+ method: 'POST',
226
+ headers,
227
+ body: JSON.stringify({ ...body, force: true }),
228
+ });
229
+ const forceResult = (await forceResponse.json());
230
+ if (!forceResponse.ok) {
231
+ const errorResult = forceResult;
232
+ throw new Error(errorResult.error || `HTTP ${forceResponse.status}`);
233
+ }
234
+ const successResult = forceResult;
235
+ const { newVersionNumber } = successResult.data;
236
+ console.log(pc.green(`✓ Saved as version ${newVersionNumber}`));
237
+ setVersionInConfig(embeddableId, newVersionNumber);
238
+ const versionedPath = path.join(generatedDir, `embeddable-v${newVersionNumber}.json`);
239
+ fs.mkdirSync(generatedDir, { recursive: true });
240
+ fs.writeFileSync(versionedPath, jsonContent, 'utf8');
241
+ console.log(pc.cyan(`✓ Saved version file to ${versionedPath}`));
242
+ return;
243
+ }
244
+ const result = (await response.json());
245
+ if (!response.ok) {
246
+ const errorResult = result;
247
+ throw new Error(errorResult.error || `HTTP ${response.status}`);
248
+ }
249
+ const successResult = result;
250
+ const { newVersionNumber } = successResult.data;
251
+ console.log(pc.green(`✓ Saved as version ${newVersionNumber}`));
252
+ // Update _version in config.json so future saves know the base version
253
+ setVersionInConfig(embeddableId, newVersionNumber);
254
+ // Also save the versioned file to .generated/ as a snapshot
255
+ const versionedPath = path.join(generatedDir, `embeddable-v${newVersionNumber}.json`);
256
+ fs.mkdirSync(generatedDir, { recursive: true });
257
+ fs.writeFileSync(versionedPath, jsonContent, 'utf8');
258
+ console.log(pc.cyan(`✓ Saved version file to ${versionedPath}`));
259
+ }
260
+ catch (error) {
261
+ if (error instanceof Error) {
262
+ console.error(pc.red(`Save failed: ${error.message}`));
263
+ }
264
+ else {
265
+ console.error(pc.red('Save failed with an unexpected error.'));
266
+ }
267
+ process.exit(1);
268
+ }
269
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/compiler/index.ts"],"names":[],"mappings":"AA+CA;;;;;GAKG;AACH,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,GAAG,OAAO,CA2DlF;AAED,wBAAsB,eAAe,CAAC,IAAI,EAAE;IAC1C,SAAS,EAAE,MAAM,CAAA;IACjB,OAAO,EAAE,MAAM,CAAA;IACf,WAAW,EAAE,UAAU,GAAG,QAAQ,CAAA;IAClC,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB,iBA8WA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/compiler/index.ts"],"names":[],"mappings":"AA+CA;;;;;GAKG;AACH,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,GAAG,OAAO,CA2DlF;AAED,wBAAsB,eAAe,CAAC,IAAI,EAAE;IAC1C,SAAS,EAAE,MAAM,CAAA;IACjB,OAAO,EAAE,MAAM,CAAA;IACf,WAAW,EAAE,UAAU,GAAG,QAAQ,CAAA;IAClC,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB,iBAiXA"}
@@ -329,6 +329,10 @@ export async function compileAllPages(opts) {
329
329
  // Skip styles from config - they will be added from compiled CSS files later
330
330
  continue;
331
331
  }
332
+ else if (key === '_version') {
333
+ // Skip _version - this is CLI metadata (tracked version number), not part of the embeddable
334
+ continue;
335
+ }
332
336
  else if (key === 'computedFields') {
333
337
  // Replace computedFields with loaded computedFields (which include code)
334
338
  if (computedFields.length > 0) {
@@ -1 +1 @@
1
- {"version":3,"file":"reverse.d.ts","sourceRoot":"","sources":["../../src/compiler/reverse.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,QAAQ,EAAiB,MAAM,YAAY,CAAA;AAihBzD,wBAAsB,cAAc,CAClC,UAAU,EAAE;IACV,EAAE,CAAC,EAAE,MAAM,CAAA;IACX,KAAK,EAAE,QAAQ,EAAE,CAAA;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;IAC5B,cAAc,CAAC,EAAE,GAAG,EAAE,CAAA;IACtB,WAAW,CAAC,EAAE,GAAG,EAAE,CAAA;IACnB,UAAU,CAAC,EAAE,GAAG,EAAE,CAAA;IAClB,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAA;CACnB,EACD,YAAY,EAAE,MAAM,EACpB,IAAI,CAAC,EAAE;IAAE,GAAG,CAAC,EAAE,OAAO,CAAA;CAAE,iBAmDzB;AA0yCD;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAKpD"}
1
+ {"version":3,"file":"reverse.d.ts","sourceRoot":"","sources":["../../src/compiler/reverse.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,QAAQ,EAAiB,MAAM,YAAY,CAAA;AAihBzD,wBAAsB,cAAc,CAClC,UAAU,EAAE;IACV,EAAE,CAAC,EAAE,MAAM,CAAA;IACX,KAAK,EAAE,QAAQ,EAAE,CAAA;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;IAC5B,cAAc,CAAC,EAAE,GAAG,EAAE,CAAA;IACtB,WAAW,CAAC,EAAE,GAAG,EAAE,CAAA;IACnB,UAAU,CAAC,EAAE,GAAG,EAAE,CAAA;IAClB,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAA;CACnB,EACD,YAAY,EAAE,MAAM,EACpB,IAAI,CAAC,EAAE;IAAE,GAAG,CAAC,EAAE,OAAO,CAAA;CAAE,iBAmDzB;AAoyCD;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAKpD"}
@@ -578,13 +578,10 @@ function generateTSX(page, tree) {
578
578
  const jsx = generateJSXFromTree(tree, 4, pageKey, nameMap);
579
579
  return `"use client";
580
580
 
581
- import React from "react";
582
- ${imports
583
- .map((imp) => `import { ${imp} } from "../../../src/components/primitives/${imp}";`)
584
- .join('\n')}
581
+ ${imports.map((imp) => `import { ${imp} } from "@embeddables/cli/components";`).join('\n')}
585
582
  ${hasButtons
586
583
  ? `
587
- import type { OptionSelectorButton } from "../../../src/types-builder";`
584
+ import type { OptionSelectorButton } from "@embeddables/cli/types";`
588
585
  : ''}
589
586
 
590
587
  export default function ${pageName}() {
@@ -1604,13 +1601,10 @@ function generateGlobalComponentTSX(components, tree) {
1604
1601
  const jsx = generateJSXFromTree(tree, 2, undefined, nameMap);
1605
1602
  return `"use client";
1606
1603
 
1607
- import React from "react";
1608
- ${imports
1609
- .map((imp) => `import { ${imp} } from "../../../src/components/primitives/${imp}";`)
1610
- .join('\n')}
1604
+ ${imports.map((imp) => `import { ${imp} } from "@embeddables/cli/components";`).join('\n')}
1611
1605
  ${hasButtons
1612
1606
  ? `
1613
- import type { OptionSelectorButton } from "../../../src/types-builder";`
1607
+ import type { OptionSelectorButton } from "@embeddables/cli/types";`
1614
1608
  : ''}
1615
1609
 
1616
1610
  export default function GlobalComponents() {
@@ -0,0 +1,23 @@
1
+ export interface ProjectConfig {
2
+ org_id?: string;
3
+ org_title?: string;
4
+ project_id?: string;
5
+ project_name?: string;
6
+ }
7
+ /**
8
+ * Get the path to the project config file
9
+ */
10
+ export declare function getConfigFilePath(): string;
11
+ /**
12
+ * Read project config from file
13
+ */
14
+ export declare function readProjectConfig(): ProjectConfig | null;
15
+ /**
16
+ * Write project config to file
17
+ */
18
+ export declare function writeProjectConfig(config: ProjectConfig): void;
19
+ /**
20
+ * Get the project ID from config
21
+ */
22
+ export declare function getProjectId(): string | null;
23
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/config/index.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,aAAa;IAC5B,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,YAAY,CAAC,EAAE,MAAM,CAAA;CACtB;AAID;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,MAAM,CAE1C;AAED;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,aAAa,GAAG,IAAI,CAWxD;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,aAAa,GAAG,IAAI,CAQ9D;AAED;;GAEG;AACH,wBAAgB,YAAY,IAAI,MAAM,GAAG,IAAI,CAG5C"}
@@ -0,0 +1,42 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ const CONFIG_FILE = 'embeddables.json';
4
+ /**
5
+ * Get the path to the project config file
6
+ */
7
+ export function getConfigFilePath() {
8
+ return path.join(process.cwd(), CONFIG_FILE);
9
+ }
10
+ /**
11
+ * Read project config from file
12
+ */
13
+ export function readProjectConfig() {
14
+ const configPath = getConfigFilePath();
15
+ try {
16
+ if (!fs.existsSync(configPath)) {
17
+ return null;
18
+ }
19
+ const content = fs.readFileSync(configPath, 'utf8');
20
+ return JSON.parse(content);
21
+ }
22
+ catch {
23
+ return null;
24
+ }
25
+ }
26
+ /**
27
+ * Write project config to file
28
+ */
29
+ export function writeProjectConfig(config) {
30
+ const configPath = getConfigFilePath();
31
+ // Merge with existing config
32
+ const existing = readProjectConfig() || {};
33
+ const merged = { ...existing, ...config };
34
+ fs.writeFileSync(configPath, JSON.stringify(merged, null, 2) + '\n', 'utf8');
35
+ }
36
+ /**
37
+ * Get the project ID from config
38
+ */
39
+ export function getProjectId() {
40
+ const config = readProjectConfig();
41
+ return config?.project_id || null;
42
+ }
@@ -0,0 +1,7 @@
1
+ export declare const BranchStatus: {
2
+ readonly ACTIVE: "ACTIVE";
3
+ readonly MERGED: "MERGED";
4
+ };
5
+ export type BranchStatus = (typeof BranchStatus)[keyof typeof BranchStatus];
6
+ export declare const WEB_APP_BASE_URL = "http://localhost:3000";
7
+ //# sourceMappingURL=constants.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,YAAY;;;CAGf,CAAA;AAEV,MAAM,MAAM,YAAY,GAAG,CAAC,OAAO,YAAY,CAAC,CAAC,MAAM,OAAO,YAAY,CAAC,CAAA;AAG3E,eAAO,MAAM,gBAAgB,0BAA0B,CAAA"}
@@ -0,0 +1,6 @@
1
+ export const BranchStatus = {
2
+ ACTIVE: 'ACTIVE',
3
+ MERGED: 'MERGED',
4
+ };
5
+ // export const WEB_APP_BASE_URL = 'https://app.embeddables.com'
6
+ export const WEB_APP_BASE_URL = 'http://localhost:3000';
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Format a date string or Date object as YYYY-MM-DD.
3
+ */
4
+ export declare function formatDate(date: string | Date): string;
5
+ //# sourceMappingURL=dates.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dates.d.ts","sourceRoot":"","sources":["../../src/helpers/dates.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,CAGtD"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Format a date string or Date object as YYYY-MM-DD.
3
+ */
4
+ export function formatDate(date) {
5
+ const d = typeof date === 'string' ? new Date(date) : date;
6
+ return d.toISOString().slice(0, 10);
7
+ }
@@ -0,0 +1,20 @@
1
+ import { BranchStatus } from '../constants.js';
2
+ export interface BranchInfo {
3
+ id: string;
4
+ name: string;
5
+ status: BranchStatus;
6
+ created_at: string;
7
+ origin_version: number | null;
8
+ origin_branch: string | null;
9
+ }
10
+ /**
11
+ * Fetch all branches for an embeddable from Supabase
12
+ */
13
+ export declare function fetchBranches(flowId: string): Promise<BranchInfo[]>;
14
+ /**
15
+ * Prompt the user to select a branch
16
+ * Returns null if user selects "main" or cancels
17
+ * The "main" option is always included at the top
18
+ */
19
+ export declare function promptForBranch(branches: BranchInfo[]): Promise<BranchInfo | null>;
20
+ //# sourceMappingURL=branches.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"branches.d.ts","sourceRoot":"","sources":["../../src/prompts/branches.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAA;AAG9C,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,YAAY,CAAA;IACpB,UAAU,EAAE,MAAM,CAAA;IAClB,cAAc,EAAE,MAAM,GAAG,IAAI,CAAA;IAC7B,aAAa,EAAE,MAAM,GAAG,IAAI,CAAA;CAC7B;AAED;;GAEG;AACH,wBAAsB,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC,CA8BzE;AAED;;;;GAIG;AACH,wBAAsB,eAAe,CAAC,QAAQ,EAAE,UAAU,EAAE,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CA8DxF"}