@embeddables/cli 0.8.0 → 0.8.1
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/dist/auth/index.d.ts +43 -0
- package/dist/auth/index.d.ts.map +1 -0
- package/dist/auth/index.js +102 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +210 -0
- package/dist/command-history.d.ts +13 -0
- package/dist/command-history.d.ts.map +1 -0
- package/dist/command-history.js +34 -0
- package/dist/commands/branch.d.ts +4 -0
- package/dist/commands/branch.d.ts.map +1 -0
- package/dist/commands/branch.js +67 -0
- package/dist/commands/build-workbench.d.ts +5 -0
- package/dist/commands/build-workbench.d.ts.map +1 -0
- package/dist/commands/build-workbench.js +116 -0
- package/dist/commands/build.d.ts +8 -0
- package/dist/commands/build.d.ts.map +1 -0
- package/dist/commands/build.js +60 -0
- package/dist/commands/builder-open.d.ts +4 -0
- package/dist/commands/builder-open.d.ts.map +1 -0
- package/dist/commands/builder-open.js +74 -0
- package/dist/commands/dev.d.ts +12 -0
- package/dist/commands/dev.d.ts.map +1 -0
- package/dist/commands/dev.js +226 -0
- package/dist/commands/diff.d.ts +76 -0
- package/dist/commands/diff.d.ts.map +1 -0
- package/dist/commands/diff.js +653 -0
- package/dist/commands/experiments-connect.d.ts +6 -0
- package/dist/commands/experiments-connect.d.ts.map +1 -0
- package/dist/commands/experiments-connect.js +140 -0
- package/dist/commands/feedback.d.ts +29 -0
- package/dist/commands/feedback.d.ts.map +1 -0
- package/dist/commands/feedback.js +267 -0
- package/dist/commands/init.d.ts +5 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +384 -0
- package/dist/commands/inspect.d.ts +9 -0
- package/dist/commands/inspect.d.ts.map +1 -0
- package/dist/commands/inspect.js +293 -0
- package/dist/commands/login.d.ts +2 -0
- package/dist/commands/login.d.ts.map +1 -0
- package/dist/commands/login.js +117 -0
- package/dist/commands/logout.d.ts +2 -0
- package/dist/commands/logout.d.ts.map +1 -0
- package/dist/commands/logout.js +19 -0
- package/dist/commands/pull.d.ts +16 -0
- package/dist/commands/pull.d.ts.map +1 -0
- package/dist/commands/pull.js +395 -0
- package/dist/commands/save.d.ts +30 -0
- package/dist/commands/save.d.ts.map +1 -0
- package/dist/commands/save.js +597 -0
- package/dist/commands/upgrade.d.ts +2 -0
- package/dist/commands/upgrade.d.ts.map +1 -0
- package/dist/commands/upgrade.js +50 -0
- package/dist/compiler/errors.d.ts +20 -0
- package/dist/compiler/errors.d.ts.map +1 -0
- package/dist/compiler/errors.js +35 -0
- package/dist/compiler/evalStatic.d.ts +3 -0
- package/dist/compiler/evalStatic.d.ts.map +1 -0
- package/dist/compiler/evalStatic.js +57 -0
- package/dist/compiler/flatten.js +1 -0
- package/dist/compiler/helpers/duplicateIds.d.ts +9 -0
- package/dist/compiler/helpers/duplicateIds.d.ts.map +1 -0
- package/dist/compiler/helpers/duplicateIds.js +71 -0
- package/dist/compiler/helpers/numericLeadingKeys.d.ts +8 -0
- package/dist/compiler/helpers/numericLeadingKeys.d.ts.map +1 -0
- package/dist/compiler/helpers/numericLeadingKeys.js +17 -0
- package/dist/compiler/index.d.ts +18 -0
- package/dist/compiler/index.d.ts.map +1 -0
- package/dist/compiler/index.js +1272 -0
- package/dist/compiler/parsePage.d.ts +15 -0
- package/dist/compiler/parsePage.d.ts.map +1 -0
- package/dist/compiler/parsePage.js +654 -0
- package/dist/compiler/registry.d.ts +4 -0
- package/dist/compiler/registry.d.ts.map +1 -0
- package/dist/compiler/registry.js +44 -0
- package/dist/compiler/reverse.d.ts +23 -0
- package/dist/compiler/reverse.d.ts.map +1 -0
- package/dist/compiler/reverse.js +1920 -0
- package/dist/compiler/types.d.ts +21 -0
- package/dist/compiler/types.d.ts.map +1 -0
- package/dist/compiler/types.js +1 -0
- package/dist/components/index.d.ts +21 -0
- package/dist/components/index.d.ts.map +1 -0
- package/dist/components/index.js +21 -0
- package/dist/components/primitives/BaseComponent.d.ts +33 -0
- package/dist/components/primitives/BaseComponent.d.ts.map +1 -0
- package/dist/components/primitives/BaseComponent.js +26 -0
- package/dist/components/primitives/BookMeeting.d.ts +18 -0
- package/dist/components/primitives/BookMeeting.d.ts.map +1 -0
- package/dist/components/primitives/BookMeeting.js +5 -0
- package/dist/components/primitives/Chart.d.ts +41 -0
- package/dist/components/primitives/Chart.d.ts.map +1 -0
- package/dist/components/primitives/Chart.js +5 -0
- package/dist/components/primitives/Container.d.ts +8 -0
- package/dist/components/primitives/Container.d.ts.map +1 -0
- package/dist/components/primitives/Container.js +5 -0
- package/dist/components/primitives/CustomButton.d.ts +37 -0
- package/dist/components/primitives/CustomButton.d.ts.map +1 -0
- package/dist/components/primitives/CustomButton.js +10 -0
- package/dist/components/primitives/CustomHTML.d.ts +8 -0
- package/dist/components/primitives/CustomHTML.d.ts.map +1 -0
- package/dist/components/primitives/CustomHTML.js +5 -0
- package/dist/components/primitives/FileUpload.d.ts +18 -0
- package/dist/components/primitives/FileUpload.d.ts.map +1 -0
- package/dist/components/primitives/FileUpload.js +16 -0
- package/dist/components/primitives/InputBox.d.ts +34 -0
- package/dist/components/primitives/InputBox.d.ts.map +1 -0
- package/dist/components/primitives/InputBox.js +25 -0
- package/dist/components/primitives/Lottie.d.ts +11 -0
- package/dist/components/primitives/Lottie.d.ts.map +1 -0
- package/dist/components/primitives/Lottie.js +5 -0
- package/dist/components/primitives/MediaEmbed.d.ts +13 -0
- package/dist/components/primitives/MediaEmbed.d.ts.map +1 -0
- package/dist/components/primitives/MediaEmbed.js +6 -0
- package/dist/components/primitives/MediaImage.d.ts +8 -0
- package/dist/components/primitives/MediaImage.d.ts.map +1 -0
- package/dist/components/primitives/MediaImage.js +5 -0
- package/dist/components/primitives/OptionSelector.d.ts +38 -0
- package/dist/components/primitives/OptionSelector.d.ts.map +1 -0
- package/dist/components/primitives/OptionSelector.js +8 -0
- package/dist/components/primitives/PaypalCheckout.d.ts +25 -0
- package/dist/components/primitives/PaypalCheckout.d.ts.map +1 -0
- package/dist/components/primitives/PaypalCheckout.js +5 -0
- package/dist/components/primitives/PlainText.d.ts +6 -0
- package/dist/components/primitives/PlainText.d.ts.map +1 -0
- package/dist/components/primitives/PlainText.js +5 -0
- package/dist/components/primitives/ProgressBar.d.ts +15 -0
- package/dist/components/primitives/ProgressBar.d.ts.map +1 -0
- package/dist/components/primitives/ProgressBar.js +5 -0
- package/dist/components/primitives/RichText.d.ts +6 -0
- package/dist/components/primitives/RichText.d.ts.map +1 -0
- package/dist/components/primitives/RichText.js +5 -0
- package/dist/components/primitives/RichTextMarkdown.d.ts +6 -0
- package/dist/components/primitives/RichTextMarkdown.d.ts.map +1 -0
- package/dist/components/primitives/RichTextMarkdown.js +5 -0
- package/dist/components/primitives/Rive.d.ts +16 -0
- package/dist/components/primitives/Rive.d.ts.map +1 -0
- package/dist/components/primitives/Rive.js +8 -0
- package/dist/components/primitives/StripeCheckout.d.ts +52 -0
- package/dist/components/primitives/StripeCheckout.d.ts.map +1 -0
- package/dist/components/primitives/StripeCheckout.js +5 -0
- package/dist/components/primitives/StripeCheckout2.d.ts +30 -0
- package/dist/components/primitives/StripeCheckout2.d.ts.map +1 -0
- package/dist/components/primitives/StripeCheckout2.js +7 -0
- package/dist/config/index.d.ts +23 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +42 -0
- package/dist/constants.d.ts +9 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +9 -0
- package/dist/helpers/TEMP helpers file.d.ts +1 -0
- package/dist/helpers/TEMP helpers file.d.ts.map +1 -0
- package/dist/helpers/TEMP helpers file.js +1 -0
- package/dist/helpers/dates.d.ts +5 -0
- package/dist/helpers/dates.d.ts.map +1 -0
- package/dist/helpers/dates.js +7 -0
- package/dist/helpers/json.d.ts +47 -0
- package/dist/helpers/json.d.ts.map +1 -0
- package/dist/helpers/json.js +622 -0
- package/dist/helpers/prompt.d.ts +15 -0
- package/dist/helpers/prompt.d.ts.map +1 -0
- package/dist/helpers/prompt.js +35 -0
- package/dist/helpers/utils.d.ts +13 -0
- package/dist/helpers/utils.d.ts.map +1 -0
- package/dist/helpers/utils.js +28 -0
- package/dist/logger.d.ts +11 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +21 -0
- package/dist/patches/prompts-escape.d.ts +14 -0
- package/dist/patches/prompts-escape.d.ts.map +1 -0
- package/dist/patches/prompts-escape.js +23 -0
- package/dist/prompts/branches.d.ts +20 -0
- package/dist/prompts/branches.d.ts.map +1 -0
- package/dist/prompts/branches.js +86 -0
- package/dist/prompts/embeddables.d.ts +43 -0
- package/dist/prompts/embeddables.d.ts.map +1 -0
- package/dist/prompts/embeddables.js +200 -0
- package/dist/prompts/experiments.d.ts +28 -0
- package/dist/prompts/experiments.d.ts.map +1 -0
- package/dist/prompts/experiments.js +89 -0
- package/dist/prompts/index.d.ts +11 -0
- package/dist/prompts/index.d.ts.map +1 -0
- package/dist/prompts/index.js +6 -0
- package/dist/prompts/projects.d.ts +22 -0
- package/dist/prompts/projects.d.ts.map +1 -0
- package/dist/prompts/projects.js +92 -0
- package/dist/prompts/versions.d.ts +18 -0
- package/dist/prompts/versions.d.ts.map +1 -0
- package/dist/prompts/versions.js +95 -0
- package/dist/proxy/injectApiInterceptor.d.ts +6 -0
- package/dist/proxy/injectApiInterceptor.d.ts.map +1 -0
- package/dist/proxy/injectApiInterceptor.js +66 -0
- package/dist/proxy/injectReload.d.ts +2 -0
- package/dist/proxy/injectReload.d.ts.map +1 -0
- package/dist/proxy/injectReload.js +14 -0
- package/dist/proxy/injectWorkbench.d.ts +5 -0
- package/dist/proxy/injectWorkbench.d.ts.map +1 -0
- package/dist/proxy/injectWorkbench.js +22 -0
- package/dist/proxy/server.d.ts +11 -0
- package/dist/proxy/server.d.ts.map +1 -0
- package/dist/proxy/server.js +304 -0
- package/dist/proxy/sse.d.ts +5 -0
- package/dist/proxy/sse.d.ts.map +1 -0
- package/dist/proxy/sse.js +17 -0
- package/dist/sentry-context.d.ts +48 -0
- package/dist/sentry-context.d.ts.map +1 -0
- package/dist/sentry-context.js +156 -0
- package/dist/stdout.d.ts +61 -0
- package/dist/stdout.d.ts.map +1 -0
- package/dist/stdout.js +163 -0
- package/dist/types-builder.d.ts +800 -0
- package/dist/types-builder.d.ts.map +1 -0
- package/dist/types-builder.js +20 -0
- package/dist/workbench/ActionsPanel.d.ts +6 -0
- package/dist/workbench/ActionsPanel.d.ts.map +1 -0
- package/dist/workbench/ActionsPanel.js +47 -0
- package/dist/workbench/AutofillPanel.d.ts +6 -0
- package/dist/workbench/AutofillPanel.d.ts.map +1 -0
- package/dist/workbench/AutofillPanel.js +543 -0
- package/dist/workbench/ComputedFieldsPanel.d.ts +6 -0
- package/dist/workbench/ComputedFieldsPanel.d.ts.map +1 -0
- package/dist/workbench/ComputedFieldsPanel.js +31 -0
- package/dist/workbench/ExperimentsPanel.d.ts +6 -0
- package/dist/workbench/ExperimentsPanel.d.ts.map +1 -0
- package/dist/workbench/ExperimentsPanel.js +182 -0
- package/dist/workbench/FieldEditorPanel.d.ts +9 -0
- package/dist/workbench/FieldEditorPanel.d.ts.map +1 -0
- package/dist/workbench/FieldEditorPanel.js +650 -0
- package/dist/workbench/InspectorPanel.d.ts +6 -0
- package/dist/workbench/InspectorPanel.d.ts.map +1 -0
- package/dist/workbench/InspectorPanel.js +341 -0
- package/dist/workbench/PageNavigator.d.ts +6 -0
- package/dist/workbench/PageNavigator.d.ts.map +1 -0
- package/dist/workbench/PageNavigator.js +123 -0
- package/dist/workbench/SchemaPanel.d.ts +6 -0
- package/dist/workbench/SchemaPanel.d.ts.map +1 -0
- package/dist/workbench/SchemaPanel.js +222 -0
- package/dist/workbench/UserDataPanel.d.ts +6 -0
- package/dist/workbench/UserDataPanel.d.ts.map +1 -0
- package/dist/workbench/UserDataPanel.js +350 -0
- package/dist/workbench/WorkbenchApp.d.ts +7 -0
- package/dist/workbench/WorkbenchApp.d.ts.map +1 -0
- package/dist/workbench/WorkbenchApp.js +193 -0
- package/dist/workbench/cloudflare-worker/README.md +31 -0
- package/dist/workbench/cloudflare-worker/public/workbench.css +1614 -0
- package/dist/workbench/cloudflare-worker/public/workbench.js +77 -0
- package/dist/workbench/cloudflare-worker/worker.js +40 -0
- package/dist/workbench/cloudflare-worker/wrangler.toml +10 -0
- package/dist/workbench/index.d.ts +10 -0
- package/dist/workbench/index.d.ts.map +1 -0
- package/dist/workbench/index.js +44 -0
- package/dist/workbench/workbench.css +1614 -0
- package/dist/workbench/workbench.js +77 -0
- package/package.json +1 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/helpers/utils.ts"],"names":[],"mappings":"AAEA,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,UAIxC;AAED;;;;;;GAMG;AACH,wBAAgB,sBAAsB,IAAI;IAAE,YAAY,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAc7F"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
export function generateId(prefix) {
|
|
3
|
+
const randomString = Math.random().toString(20).slice(2) + Math.random().toString(20).slice(2);
|
|
4
|
+
return prefix ? `${prefix}_${randomString}` : `_${randomString}`;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* If the current working directory is inside embeddables/<id>/ (or a subfolder),
|
|
8
|
+
* returns that embeddable id and the project root (the directory containing the
|
|
9
|
+
* embeddables/ folder). Otherwise returns null.
|
|
10
|
+
* When using the inferred id, callers should chdir(projectRoot) so relative
|
|
11
|
+
* paths like embeddables/<id>/... resolve correctly.
|
|
12
|
+
*/
|
|
13
|
+
export function inferEmbeddableFromCwd() {
|
|
14
|
+
let current = path.resolve(process.cwd());
|
|
15
|
+
for (;;) {
|
|
16
|
+
const parent = path.dirname(current);
|
|
17
|
+
if (parent === current)
|
|
18
|
+
break;
|
|
19
|
+
if (path.basename(parent) === 'embeddables') {
|
|
20
|
+
return {
|
|
21
|
+
embeddableId: path.basename(current),
|
|
22
|
+
projectRoot: path.dirname(parent),
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
current = parent;
|
|
26
|
+
}
|
|
27
|
+
return null;
|
|
28
|
+
}
|
package/dist/logger.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
type LogContext = Record<string, string | number | boolean | null | undefined>;
|
|
2
|
+
export interface Logger {
|
|
3
|
+
info(message: string, ctx?: LogContext): void;
|
|
4
|
+
warn(message: string, ctx?: LogContext): void;
|
|
5
|
+
error(message: string, ctx?: LogContext): void;
|
|
6
|
+
}
|
|
7
|
+
export declare function createLogger(fn: string): Logger;
|
|
8
|
+
export declare function captureException(error: unknown): void;
|
|
9
|
+
export declare function exit(code: number): Promise<never>;
|
|
10
|
+
export {};
|
|
11
|
+
//# sourceMappingURL=logger.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAEA,KAAK,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,GAAG,SAAS,CAAC,CAAA;AAE9E,MAAM,WAAW,MAAM;IACrB,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,UAAU,GAAG,IAAI,CAAA;IAC7C,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,UAAU,GAAG,IAAI,CAAA;IAC7C,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,UAAU,GAAG,IAAI,CAAA;CAC/C;AAED,wBAAgB,YAAY,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAY/C;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,CAErD;AAED,wBAAsB,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC,CAGvD"}
|
package/dist/logger.js
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import * as Sentry from '@sentry/node';
|
|
2
|
+
export function createLogger(fn) {
|
|
3
|
+
return {
|
|
4
|
+
info(message, ctx) {
|
|
5
|
+
Sentry.logger.info(message, { fn, ...ctx });
|
|
6
|
+
},
|
|
7
|
+
warn(message, ctx) {
|
|
8
|
+
Sentry.logger.warn(message, { fn, ...ctx });
|
|
9
|
+
},
|
|
10
|
+
error(message, ctx) {
|
|
11
|
+
Sentry.logger.error(message, { fn, ...ctx });
|
|
12
|
+
},
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
export function captureException(error) {
|
|
16
|
+
Sentry.captureException(error);
|
|
17
|
+
}
|
|
18
|
+
export async function exit(code) {
|
|
19
|
+
await Sentry.flush(2000);
|
|
20
|
+
process.exit(code);
|
|
21
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Patch the `prompts` library so that pressing ESC on an autocomplete prompt
|
|
3
|
+
* aborts (triggering onCancel) instead of silently resolving with the
|
|
4
|
+
* currently highlighted value.
|
|
5
|
+
*
|
|
6
|
+
* Background: In the prompts library, ESC maps to the `exit` action.
|
|
7
|
+
* SelectPrompt, ConfirmPrompt, and TextPrompt all route exit() → abort(),
|
|
8
|
+
* but AutocompletePrompt.exit() resolves the promise as if the user submitted.
|
|
9
|
+
* This patch aligns AutocompletePrompt with every other prompt type.
|
|
10
|
+
*
|
|
11
|
+
* Import this module once at the CLI entry point before any prompts are shown.
|
|
12
|
+
*/
|
|
13
|
+
export {};
|
|
14
|
+
//# sourceMappingURL=prompts-escape.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prompts-escape.d.ts","sourceRoot":"","sources":["../../src/patches/prompts-escape.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Patch the `prompts` library so that pressing ESC on an autocomplete prompt
|
|
3
|
+
* aborts (triggering onCancel) instead of silently resolving with the
|
|
4
|
+
* currently highlighted value.
|
|
5
|
+
*
|
|
6
|
+
* Background: In the prompts library, ESC maps to the `exit` action.
|
|
7
|
+
* SelectPrompt, ConfirmPrompt, and TextPrompt all route exit() → abort(),
|
|
8
|
+
* but AutocompletePrompt.exit() resolves the promise as if the user submitted.
|
|
9
|
+
* This patch aligns AutocompletePrompt with every other prompt type.
|
|
10
|
+
*
|
|
11
|
+
* Import this module once at the CLI entry point before any prompts are shown.
|
|
12
|
+
*/
|
|
13
|
+
import { createRequire } from 'node:module';
|
|
14
|
+
const require = createRequire(import.meta.url);
|
|
15
|
+
const Autocomplete = require('prompts/lib/elements/autocomplete');
|
|
16
|
+
Autocomplete.prototype.exit = function () {
|
|
17
|
+
if (this.clearFirst && this.input.length > 0) {
|
|
18
|
+
this.reset();
|
|
19
|
+
}
|
|
20
|
+
else {
|
|
21
|
+
this.abort();
|
|
22
|
+
}
|
|
23
|
+
};
|
|
@@ -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":"AAKA,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,CAuDxF"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import pc from 'picocolors';
|
|
2
|
+
import { getAuthenticatedSupabaseClient } from '../auth/index.js';
|
|
3
|
+
import { prompt } from '../helpers/prompt.js';
|
|
4
|
+
import * as stdout from '../stdout.js';
|
|
5
|
+
import { BranchStatus } from '../constants.js';
|
|
6
|
+
import { formatDate } from '../helpers/dates.js';
|
|
7
|
+
/**
|
|
8
|
+
* Fetch all branches for an embeddable from Supabase
|
|
9
|
+
*/
|
|
10
|
+
export async function fetchBranches(flowId) {
|
|
11
|
+
const supabase = await getAuthenticatedSupabaseClient();
|
|
12
|
+
if (!supabase) {
|
|
13
|
+
return [];
|
|
14
|
+
}
|
|
15
|
+
try {
|
|
16
|
+
const { data, error } = await supabase
|
|
17
|
+
.from('branches')
|
|
18
|
+
.select('id, name, status, created_at, origin_version, origin_branch')
|
|
19
|
+
.eq('flow_id', flowId)
|
|
20
|
+
.order('created_at', { ascending: false });
|
|
21
|
+
if (error) {
|
|
22
|
+
stdout.warn(pc.yellow(`Could not fetch branches: ${error.message}`));
|
|
23
|
+
return [];
|
|
24
|
+
}
|
|
25
|
+
return (data || []).map((row) => ({
|
|
26
|
+
id: row.id,
|
|
27
|
+
name: row.name,
|
|
28
|
+
status: row.status,
|
|
29
|
+
created_at: row.created_at,
|
|
30
|
+
origin_version: row.origin_version,
|
|
31
|
+
origin_branch: row.origin_branch,
|
|
32
|
+
}));
|
|
33
|
+
}
|
|
34
|
+
catch (err) {
|
|
35
|
+
stdout.warn(pc.yellow(`Could not fetch branches: ${err}`));
|
|
36
|
+
return [];
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Prompt the user to select a branch
|
|
41
|
+
* Returns null if user selects "main" or cancels
|
|
42
|
+
* The "main" option is always included at the top
|
|
43
|
+
*/
|
|
44
|
+
export async function promptForBranch(branches) {
|
|
45
|
+
// Separate active and merged branches
|
|
46
|
+
const activeBranches = branches.filter((b) => b.status === BranchStatus.ACTIVE);
|
|
47
|
+
const mergedBranches = branches.filter((b) => b.status === BranchStatus.MERGED);
|
|
48
|
+
const choices = [];
|
|
49
|
+
// Add "main" option first
|
|
50
|
+
choices.push({
|
|
51
|
+
title: pc.bold('main'),
|
|
52
|
+
value: 'main',
|
|
53
|
+
description: 'Latest published version',
|
|
54
|
+
});
|
|
55
|
+
// Add active branches
|
|
56
|
+
for (const branch of activeBranches) {
|
|
57
|
+
const date = formatDate(branch.created_at);
|
|
58
|
+
choices.push({
|
|
59
|
+
title: branch.name,
|
|
60
|
+
value: branch.id,
|
|
61
|
+
description: `Active · Created ${date}`,
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
// Add merged branches (dimmed)
|
|
65
|
+
for (const branch of mergedBranches) {
|
|
66
|
+
const date = formatDate(branch.created_at);
|
|
67
|
+
choices.push({
|
|
68
|
+
title: pc.dim(branch.name),
|
|
69
|
+
value: branch.id,
|
|
70
|
+
description: pc.dim(`Merged · Created ${date}`),
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
const response = await prompt({
|
|
74
|
+
type: 'autocomplete',
|
|
75
|
+
name: 'branchId',
|
|
76
|
+
message: 'Select a branch:',
|
|
77
|
+
choices,
|
|
78
|
+
suggest: (input, choices) => Promise.resolve(choices.filter((c) => c.value === 'main' ||
|
|
79
|
+
(c.title?.toLowerCase().includes(input.toLowerCase()) ?? false) ||
|
|
80
|
+
String(c.value).toLowerCase().includes(input.toLowerCase()))),
|
|
81
|
+
});
|
|
82
|
+
if (!response.branchId || response.branchId === 'main') {
|
|
83
|
+
return null;
|
|
84
|
+
}
|
|
85
|
+
return branches.find((b) => b.id === response.branchId) || null;
|
|
86
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
export interface EmbeddableInfo {
|
|
2
|
+
id: string;
|
|
3
|
+
title: string | null;
|
|
4
|
+
}
|
|
5
|
+
export interface EmbeddableMetadata {
|
|
6
|
+
title: string | null;
|
|
7
|
+
archived: boolean;
|
|
8
|
+
created_at: string | null;
|
|
9
|
+
}
|
|
10
|
+
export interface LocalEmbeddable {
|
|
11
|
+
id: string;
|
|
12
|
+
title: string | null;
|
|
13
|
+
}
|
|
14
|
+
export interface PromptForEmbeddableOptions {
|
|
15
|
+
/** Custom message for the prompt */
|
|
16
|
+
message?: string;
|
|
17
|
+
/** When true, sort so embeddables already present in embeddables/ appear first */
|
|
18
|
+
prioritizeLocal?: boolean;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Fetch all embeddables for a project from Supabase
|
|
22
|
+
*/
|
|
23
|
+
export declare function fetchProjectEmbeddables(projectId: string): Promise<EmbeddableInfo[]>;
|
|
24
|
+
/**
|
|
25
|
+
* Fetch metadata for a single embeddable from the flows table.
|
|
26
|
+
* Returns title, archived, and created_at from the DB (not from the version-specific embeddable.json).
|
|
27
|
+
*/
|
|
28
|
+
export declare function fetchEmbeddableMetadata(embeddableId: string): Promise<EmbeddableMetadata | null>;
|
|
29
|
+
/**
|
|
30
|
+
* Prompt the user to select an embeddable from a project
|
|
31
|
+
* Returns null if no embeddables found or user cancels
|
|
32
|
+
*/
|
|
33
|
+
export declare function promptForEmbeddable(projectId: string, options?: PromptForEmbeddableOptions): Promise<string | null>;
|
|
34
|
+
/**
|
|
35
|
+
* Discover embeddables in the local embeddables/ directory
|
|
36
|
+
*/
|
|
37
|
+
export declare function discoverLocalEmbeddables(): Promise<LocalEmbeddable[]>;
|
|
38
|
+
/**
|
|
39
|
+
* Prompt the user to select a local embeddable
|
|
40
|
+
* Returns null if no embeddables found or user cancels
|
|
41
|
+
*/
|
|
42
|
+
export declare function promptForLocalEmbeddable(options?: PromptForEmbeddableOptions): Promise<string | null>;
|
|
43
|
+
//# sourceMappingURL=embeddables.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"embeddables.d.ts","sourceRoot":"","sources":["../../src/prompts/embeddables.ts"],"names":[],"mappings":"AAQA,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAA;IACV,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;CACrB;AAED,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;IACpB,QAAQ,EAAE,OAAO,CAAA;IACjB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;CAC1B;AAED,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAA;IACV,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;CACrB;AAED,MAAM,WAAW,0BAA0B;IACzC,oCAAoC;IACpC,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,kFAAkF;IAClF,eAAe,CAAC,EAAE,OAAO,CAAA;CAC1B;AAED;;GAEG;AACH,wBAAsB,uBAAuB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC,CAqC1F;AAED;;;GAGG;AACH,wBAAsB,uBAAuB,CAC3C,YAAY,EAAE,MAAM,GACnB,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAC,CA2BpC;AAED;;;GAGG;AACH,wBAAsB,mBAAmB,CACvC,SAAS,EAAE,MAAM,EACjB,OAAO,GAAE,0BAA+B,GACvC,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAqExB;AAED;;GAEG;AACH,wBAAsB,wBAAwB,IAAI,OAAO,CAAC,eAAe,EAAE,CAAC,CAqC3E;AAED;;;GAGG;AACH,wBAAsB,wBAAwB,CAC5C,OAAO,GAAE,0BAA+B,GACvC,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAgCxB"}
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import pc from 'picocolors';
|
|
4
|
+
import { getAuthenticatedSupabaseClient } from '../auth/index.js';
|
|
5
|
+
import { prompt } from '../helpers/prompt.js';
|
|
6
|
+
import * as stdout from '../stdout.js';
|
|
7
|
+
/**
|
|
8
|
+
* Fetch all embeddables for a project from Supabase
|
|
9
|
+
*/
|
|
10
|
+
export async function fetchProjectEmbeddables(projectId) {
|
|
11
|
+
const supabase = await getAuthenticatedSupabaseClient();
|
|
12
|
+
if (!supabase) {
|
|
13
|
+
return [];
|
|
14
|
+
}
|
|
15
|
+
try {
|
|
16
|
+
const { data, error } = await supabase
|
|
17
|
+
.from('flows')
|
|
18
|
+
.select('id, title')
|
|
19
|
+
.eq('project_id', projectId)
|
|
20
|
+
.not('archived', 'is', 'true')
|
|
21
|
+
.order('title', { ascending: true });
|
|
22
|
+
if (error) {
|
|
23
|
+
stdout.warn(pc.yellow(`Could not fetch embeddables: ${error.message}`));
|
|
24
|
+
return [];
|
|
25
|
+
}
|
|
26
|
+
const embeddables = (data || []).map((row) => ({
|
|
27
|
+
id: row.id,
|
|
28
|
+
title: row.title || null,
|
|
29
|
+
}));
|
|
30
|
+
embeddables.sort((a, b) => {
|
|
31
|
+
if (a.title && !b.title)
|
|
32
|
+
return -1;
|
|
33
|
+
if (!a.title && b.title)
|
|
34
|
+
return 1;
|
|
35
|
+
const aLabel = a.title || a.id;
|
|
36
|
+
const bLabel = b.title || b.id;
|
|
37
|
+
return aLabel.localeCompare(bLabel, undefined, { sensitivity: 'base' });
|
|
38
|
+
});
|
|
39
|
+
return embeddables;
|
|
40
|
+
}
|
|
41
|
+
catch (err) {
|
|
42
|
+
stdout.warn(pc.yellow(`Could not fetch embeddables: ${err}`));
|
|
43
|
+
return [];
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Fetch metadata for a single embeddable from the flows table.
|
|
48
|
+
* Returns title, archived, and created_at from the DB (not from the version-specific embeddable.json).
|
|
49
|
+
*/
|
|
50
|
+
export async function fetchEmbeddableMetadata(embeddableId) {
|
|
51
|
+
const supabase = await getAuthenticatedSupabaseClient();
|
|
52
|
+
if (!supabase) {
|
|
53
|
+
return null;
|
|
54
|
+
}
|
|
55
|
+
try {
|
|
56
|
+
const { data, error } = await supabase
|
|
57
|
+
.from('flows')
|
|
58
|
+
.select('title, archived, created_at')
|
|
59
|
+
.eq('id', embeddableId)
|
|
60
|
+
.single();
|
|
61
|
+
if (error) {
|
|
62
|
+
stdout.warn(pc.yellow(`Could not fetch embeddable metadata: ${error.message}`));
|
|
63
|
+
return null;
|
|
64
|
+
}
|
|
65
|
+
return {
|
|
66
|
+
title: data.title || null,
|
|
67
|
+
archived: data.archived ?? false,
|
|
68
|
+
created_at: data.created_at || null,
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
catch (err) {
|
|
72
|
+
stdout.warn(pc.yellow(`Could not fetch embeddable metadata: ${err}`));
|
|
73
|
+
return null;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Prompt the user to select an embeddable from a project
|
|
78
|
+
* Returns null if no embeddables found or user cancels
|
|
79
|
+
*/
|
|
80
|
+
export async function promptForEmbeddable(projectId, options = {}) {
|
|
81
|
+
const { message = 'Select an embeddable:', prioritizeLocal = false } = options;
|
|
82
|
+
let embeddables = await fetchProjectEmbeddables(projectId);
|
|
83
|
+
const SEPARATOR_VALUE = '__separator__';
|
|
84
|
+
let inRepo = [];
|
|
85
|
+
let notInRepo = [];
|
|
86
|
+
if (prioritizeLocal && embeddables.length > 0) {
|
|
87
|
+
const local = await discoverLocalEmbeddables();
|
|
88
|
+
const localIds = new Set(local.map((e) => e.id));
|
|
89
|
+
inRepo = embeddables.filter((e) => localIds.has(e.id));
|
|
90
|
+
notInRepo = embeddables.filter((e) => !localIds.has(e.id));
|
|
91
|
+
embeddables = [...inRepo, ...notInRepo];
|
|
92
|
+
}
|
|
93
|
+
if (embeddables.length === 0) {
|
|
94
|
+
stdout.print(pc.yellow('No embeddables found in this project.'));
|
|
95
|
+
return null;
|
|
96
|
+
}
|
|
97
|
+
const hasTwoSections = prioritizeLocal && inRepo.length > 0 && notInRepo.length > 0;
|
|
98
|
+
const separatorChoice = {
|
|
99
|
+
title: pc.dim('── Other embeddables in project ──'),
|
|
100
|
+
value: SEPARATOR_VALUE,
|
|
101
|
+
disabled: true,
|
|
102
|
+
};
|
|
103
|
+
const choices = embeddables.map((e) => ({
|
|
104
|
+
title: e.title || e.id,
|
|
105
|
+
description: e.id,
|
|
106
|
+
value: e.id,
|
|
107
|
+
}));
|
|
108
|
+
if (hasTwoSections) {
|
|
109
|
+
choices.splice(inRepo.length, 0, separatorChoice);
|
|
110
|
+
}
|
|
111
|
+
const response = await prompt({
|
|
112
|
+
type: 'autocomplete',
|
|
113
|
+
name: 'id',
|
|
114
|
+
message,
|
|
115
|
+
choices,
|
|
116
|
+
suggest: (input, list) => {
|
|
117
|
+
const realChoices = list.filter((c) => c.value !== SEPARATOR_VALUE);
|
|
118
|
+
const filtered = input
|
|
119
|
+
? realChoices.filter((c) => (c.title?.toLowerCase().includes(input.toLowerCase()) ?? false) ||
|
|
120
|
+
String(c.value).toLowerCase().includes(input.toLowerCase()))
|
|
121
|
+
: realChoices;
|
|
122
|
+
if (hasTwoSections && !input) {
|
|
123
|
+
return Promise.resolve([
|
|
124
|
+
...filtered.slice(0, inRepo.length),
|
|
125
|
+
separatorChoice,
|
|
126
|
+
...filtered.slice(inRepo.length),
|
|
127
|
+
]);
|
|
128
|
+
}
|
|
129
|
+
return Promise.resolve(filtered);
|
|
130
|
+
},
|
|
131
|
+
});
|
|
132
|
+
if (response.id === SEPARATOR_VALUE) {
|
|
133
|
+
return promptForEmbeddable(projectId, options);
|
|
134
|
+
}
|
|
135
|
+
return response.id || null;
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Discover embeddables in the local embeddables/ directory
|
|
139
|
+
*/
|
|
140
|
+
export async function discoverLocalEmbeddables() {
|
|
141
|
+
const embeddablesDir = 'embeddables';
|
|
142
|
+
if (!fs.existsSync(embeddablesDir)) {
|
|
143
|
+
return [];
|
|
144
|
+
}
|
|
145
|
+
const entries = fs.readdirSync(embeddablesDir, { withFileTypes: true });
|
|
146
|
+
const embeddables = [];
|
|
147
|
+
for (const entry of entries) {
|
|
148
|
+
if (!entry.isDirectory())
|
|
149
|
+
continue;
|
|
150
|
+
const id = entry.name;
|
|
151
|
+
const metadataPath = path.join(embeddablesDir, id, 'metadata.json');
|
|
152
|
+
let title = null;
|
|
153
|
+
if (fs.existsSync(metadataPath)) {
|
|
154
|
+
try {
|
|
155
|
+
const metadata = JSON.parse(fs.readFileSync(metadataPath, 'utf-8'));
|
|
156
|
+
title = metadata.title || null;
|
|
157
|
+
}
|
|
158
|
+
catch {
|
|
159
|
+
// Ignore JSON parse errors
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
embeddables.push({ id, title });
|
|
163
|
+
}
|
|
164
|
+
// Sort by title first, then by id
|
|
165
|
+
return embeddables.sort((a, b) => {
|
|
166
|
+
if (a.title && !b.title)
|
|
167
|
+
return -1;
|
|
168
|
+
if (!a.title && b.title)
|
|
169
|
+
return 1;
|
|
170
|
+
const aLabel = a.title || a.id;
|
|
171
|
+
const bLabel = b.title || b.id;
|
|
172
|
+
return aLabel.localeCompare(bLabel, undefined, { sensitivity: 'base' });
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Prompt the user to select a local embeddable
|
|
177
|
+
* Returns null if no embeddables found or user cancels
|
|
178
|
+
*/
|
|
179
|
+
export async function promptForLocalEmbeddable(options = {}) {
|
|
180
|
+
const { message = 'Select an embeddable:' } = options;
|
|
181
|
+
const embeddables = await discoverLocalEmbeddables();
|
|
182
|
+
if (embeddables.length === 0) {
|
|
183
|
+
stdout.error(pc.red('No embeddables found in the embeddables/ directory.'));
|
|
184
|
+
stdout.print(pc.gray('Run `embeddables pull` to pull an embeddable first.'));
|
|
185
|
+
return null;
|
|
186
|
+
}
|
|
187
|
+
const choices = embeddables.map((e) => ({
|
|
188
|
+
title: e.title ? `${e.title} (${e.id})` : e.id,
|
|
189
|
+
value: e.id,
|
|
190
|
+
}));
|
|
191
|
+
const response = await prompt({
|
|
192
|
+
type: 'autocomplete',
|
|
193
|
+
name: 'id',
|
|
194
|
+
message,
|
|
195
|
+
choices,
|
|
196
|
+
suggest: (input, choices) => Promise.resolve(choices.filter((c) => (c.title?.toLowerCase().includes(input.toLowerCase()) ?? false) ||
|
|
197
|
+
String(c.value).toLowerCase().includes(input.toLowerCase()))),
|
|
198
|
+
});
|
|
199
|
+
return response.id || null;
|
|
200
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export interface ExperimentInfo {
|
|
2
|
+
id: string;
|
|
3
|
+
experiment_id: string;
|
|
4
|
+
experiment_key: string;
|
|
5
|
+
name: string | null;
|
|
6
|
+
status: string;
|
|
7
|
+
flow_id: string;
|
|
8
|
+
flow_ids: string[] | null;
|
|
9
|
+
}
|
|
10
|
+
export interface PromptForExperimentOptions {
|
|
11
|
+
/** Custom message for the prompt */
|
|
12
|
+
message?: string;
|
|
13
|
+
/** Filter out experiments already connected to this embeddable ID */
|
|
14
|
+
excludeConnectedTo?: string;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Fetch experiments for a project from Supabase (using experiments_extended view)
|
|
18
|
+
*/
|
|
19
|
+
export declare function fetchProjectExperiments(projectId: string): Promise<ExperimentInfo[]>;
|
|
20
|
+
/**
|
|
21
|
+
* Prompt the user to select an experiment from the project
|
|
22
|
+
* Returns null if no experiments found or user cancels
|
|
23
|
+
*/
|
|
24
|
+
export declare function promptForExperiment(projectId: string, options?: PromptForExperimentOptions): Promise<{
|
|
25
|
+
experiment_id: string;
|
|
26
|
+
experiment_key: string;
|
|
27
|
+
} | null>;
|
|
28
|
+
//# sourceMappingURL=experiments.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"experiments.d.ts","sourceRoot":"","sources":["../../src/prompts/experiments.ts"],"names":[],"mappings":"AAMA,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,CAuC1F;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,CAqDnE"}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import pc from 'picocolors';
|
|
2
|
+
import { getAuthenticatedSupabaseClient } from '../auth/index.js';
|
|
3
|
+
import { prompt } from '../helpers/prompt.js';
|
|
4
|
+
import * as stdout from '../stdout.js';
|
|
5
|
+
/**
|
|
6
|
+
* Fetch experiments for a project from Supabase (using experiments_extended view)
|
|
7
|
+
*/
|
|
8
|
+
export async function fetchProjectExperiments(projectId) {
|
|
9
|
+
const supabase = await getAuthenticatedSupabaseClient();
|
|
10
|
+
if (!supabase) {
|
|
11
|
+
return [];
|
|
12
|
+
}
|
|
13
|
+
try {
|
|
14
|
+
const { data, error } = await supabase
|
|
15
|
+
.from('experiments_extended')
|
|
16
|
+
.select('id, experiment_id, experiment_key, name, status, flow_id, flow_ids')
|
|
17
|
+
.eq('project_id', projectId)
|
|
18
|
+
.order('name', { ascending: true, nullsFirst: false });
|
|
19
|
+
if (error) {
|
|
20
|
+
stdout.warn(pc.yellow(`Could not fetch experiments: ${error.message}`));
|
|
21
|
+
return [];
|
|
22
|
+
}
|
|
23
|
+
const experiments = (data || []).map((row) => ({
|
|
24
|
+
id: row.id,
|
|
25
|
+
experiment_id: row.experiment_id,
|
|
26
|
+
experiment_key: row.experiment_key,
|
|
27
|
+
name: row.name || null,
|
|
28
|
+
status: row.status || 'draft',
|
|
29
|
+
flow_id: row.flow_id,
|
|
30
|
+
flow_ids: row.flow_ids || null,
|
|
31
|
+
}));
|
|
32
|
+
experiments.sort((a, b) => {
|
|
33
|
+
const aLabel = a.name || a.experiment_key;
|
|
34
|
+
const bLabel = b.name || b.experiment_key;
|
|
35
|
+
return aLabel.localeCompare(bLabel, undefined, { sensitivity: 'base' });
|
|
36
|
+
});
|
|
37
|
+
return experiments;
|
|
38
|
+
}
|
|
39
|
+
catch (err) {
|
|
40
|
+
stdout.warn(pc.yellow(`Could not fetch experiments: ${err}`));
|
|
41
|
+
return [];
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Prompt the user to select an experiment from the project
|
|
46
|
+
* Returns null if no experiments found or user cancels
|
|
47
|
+
*/
|
|
48
|
+
export async function promptForExperiment(projectId, options = {}) {
|
|
49
|
+
const { message = 'Select an experiment to connect:', excludeConnectedTo } = options;
|
|
50
|
+
const experiments = await fetchProjectExperiments(projectId);
|
|
51
|
+
let filtered = experiments;
|
|
52
|
+
if (excludeConnectedTo) {
|
|
53
|
+
filtered = experiments.filter((e) => {
|
|
54
|
+
const connected = e.flow_ids ?? [e.flow_id];
|
|
55
|
+
return !connected.includes(excludeConnectedTo);
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
if (filtered.length === 0) {
|
|
59
|
+
if (excludeConnectedTo && experiments.length > 0) {
|
|
60
|
+
stdout.print(pc.yellow('All experiments in this project are already connected to this embeddable.'));
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
63
|
+
stdout.print(pc.yellow('No experiments found in this project.'));
|
|
64
|
+
}
|
|
65
|
+
return null;
|
|
66
|
+
}
|
|
67
|
+
const choices = filtered.map((e) => ({
|
|
68
|
+
title: e.name || e.experiment_key,
|
|
69
|
+
description: `${e.experiment_key} (${e.experiment_id})`,
|
|
70
|
+
value: e,
|
|
71
|
+
}));
|
|
72
|
+
const response = await prompt({
|
|
73
|
+
type: 'autocomplete',
|
|
74
|
+
name: 'experiment',
|
|
75
|
+
message,
|
|
76
|
+
choices,
|
|
77
|
+
suggest: (input, choices) => Promise.resolve(choices.filter((c) => (c.title?.toLowerCase().includes(input.toLowerCase()) ?? false) ||
|
|
78
|
+
String(c.value.experiment_key).toLowerCase().includes(input.toLowerCase()) ||
|
|
79
|
+
String(c.value.experiment_id).toLowerCase().includes(input.toLowerCase()))),
|
|
80
|
+
});
|
|
81
|
+
const selected = response.experiment;
|
|
82
|
+
if (!selected) {
|
|
83
|
+
return null;
|
|
84
|
+
}
|
|
85
|
+
return {
|
|
86
|
+
experiment_id: selected.experiment_id,
|
|
87
|
+
experiment_key: selected.experiment_key,
|
|
88
|
+
};
|
|
89
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export { fetchProjects, promptForProject } from './projects.js';
|
|
2
|
+
export type { ProjectInfo, PromptForProjectOptions } from './projects.js';
|
|
3
|
+
export { fetchProjectEmbeddables, fetchEmbeddableMetadata, promptForEmbeddable, discoverLocalEmbeddables, promptForLocalEmbeddable, } from './embeddables.js';
|
|
4
|
+
export type { EmbeddableInfo, EmbeddableMetadata, LocalEmbeddable, PromptForEmbeddableOptions, } from './embeddables.js';
|
|
5
|
+
export { fetchBranches, promptForBranch } from './branches.js';
|
|
6
|
+
export type { BranchInfo } from './branches.js';
|
|
7
|
+
export { fetchRecentVersions, promptForVersion } from './versions.js';
|
|
8
|
+
export type { VersionInfo } from './versions.js';
|
|
9
|
+
export { fetchProjectExperiments, promptForExperiment, } from './experiments.js';
|
|
10
|
+
export type { ExperimentInfo, PromptForExperimentOptions } from './experiments.js';
|
|
11
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/prompts/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAA;AAC/D,YAAY,EAAE,WAAW,EAAE,uBAAuB,EAAE,MAAM,eAAe,CAAA;AAEzE,OAAO,EACL,uBAAuB,EACvB,uBAAuB,EACvB,mBAAmB,EACnB,wBAAwB,EACxB,wBAAwB,GACzB,MAAM,kBAAkB,CAAA;AACzB,YAAY,EACV,cAAc,EACd,kBAAkB,EAClB,eAAe,EACf,0BAA0B,GAC3B,MAAM,kBAAkB,CAAA;AAEzB,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AAC9D,YAAY,EAAE,UAAU,EAAE,MAAM,eAAe,CAAA;AAE/C,OAAO,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAA;AACrE,YAAY,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAEhD,OAAO,EACL,uBAAuB,EACvB,mBAAmB,GACpB,MAAM,kBAAkB,CAAA;AACzB,YAAY,EAAE,cAAc,EAAE,0BAA0B,EAAE,MAAM,kBAAkB,CAAA"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
// Centralized prompts for CLI commands
|
|
2
|
+
export { fetchProjects, promptForProject } from './projects.js';
|
|
3
|
+
export { fetchProjectEmbeddables, fetchEmbeddableMetadata, promptForEmbeddable, discoverLocalEmbeddables, promptForLocalEmbeddable, } from './embeddables.js';
|
|
4
|
+
export { fetchBranches, promptForBranch } from './branches.js';
|
|
5
|
+
export { fetchRecentVersions, promptForVersion } from './versions.js';
|
|
6
|
+
export { fetchProjectExperiments, promptForExperiment, } from './experiments.js';
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export interface ProjectInfo {
|
|
2
|
+
id: string;
|
|
3
|
+
title: string | null;
|
|
4
|
+
org_id: string | null;
|
|
5
|
+
org_title: string | null;
|
|
6
|
+
}
|
|
7
|
+
export interface PromptForProjectOptions {
|
|
8
|
+
/** Include a "Skip for now" option (default: false) */
|
|
9
|
+
allowSkip?: boolean;
|
|
10
|
+
/** Custom message for the prompt (default: "Select a project:") */
|
|
11
|
+
message?: string;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Fetch all non-archived projects from Supabase
|
|
15
|
+
*/
|
|
16
|
+
export declare function fetchProjects(): Promise<ProjectInfo[]>;
|
|
17
|
+
/**
|
|
18
|
+
* Prompt the user to select a project from the list
|
|
19
|
+
* Returns null if no projects found, user cancels, or user selects "skip"
|
|
20
|
+
*/
|
|
21
|
+
export declare function promptForProject(options?: PromptForProjectOptions): Promise<ProjectInfo | null>;
|
|
22
|
+
//# sourceMappingURL=projects.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"projects.d.ts","sourceRoot":"","sources":["../../src/prompts/projects.ts"],"names":[],"mappings":"AAMA,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,CAkD5D;AAED;;;GAGG;AACH,wBAAsB,gBAAgB,CACpC,OAAO,GAAE,uBAA4B,GACpC,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CA8C7B"}
|