@embeddables/cli 0.7.9 → 0.7.11
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/cli.js +10 -10
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +6 -0
- package/dist/commands/pull.d.ts.map +1 -1
- package/dist/commands/pull.js +1 -0
- package/dist/prompts/embeddables.d.ts +2 -0
- package/dist/prompts/embeddables.d.ts.map +1 -1
- package/dist/prompts/embeddables.js +39 -4
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -40,10 +40,10 @@ async function requireLogin(commandName) {
|
|
|
40
40
|
stdout.print(pc.gray('Run "embeddables login" first.'));
|
|
41
41
|
await exit(1);
|
|
42
42
|
}
|
|
43
|
-
/** Set Sentry context from config and auth for the current command. */
|
|
44
|
-
|
|
43
|
+
/** Set Sentry context from config and auth for the current command. Config is set immediately; user is set in background so we don't block on auth. */
|
|
44
|
+
function setSentryContextForCommand() {
|
|
45
45
|
setSentryContext(getSentryContextFromProjectConfig());
|
|
46
|
-
|
|
46
|
+
void setSentryUserFromAuth();
|
|
47
47
|
}
|
|
48
48
|
const program = new Command();
|
|
49
49
|
program
|
|
@@ -57,7 +57,7 @@ program
|
|
|
57
57
|
.option('-y, --yes', 'Skip prompts and use defaults')
|
|
58
58
|
.action(async (opts) => {
|
|
59
59
|
await requireLogin('init');
|
|
60
|
-
|
|
60
|
+
setSentryContextForCommand();
|
|
61
61
|
await runInit({ projectId: opts.projectId, yes: opts.yes });
|
|
62
62
|
});
|
|
63
63
|
program
|
|
@@ -69,7 +69,7 @@ program
|
|
|
69
69
|
.option('--pageKeyFrom <mode>', 'filename|export', 'filename')
|
|
70
70
|
.action(async (opts) => {
|
|
71
71
|
await requireLogin('build');
|
|
72
|
-
|
|
72
|
+
setSentryContextForCommand();
|
|
73
73
|
await runBuild(opts);
|
|
74
74
|
});
|
|
75
75
|
program
|
|
@@ -85,7 +85,7 @@ program
|
|
|
85
85
|
.option('--pageKeyFrom <mode>', 'filename|export', 'filename')
|
|
86
86
|
.action(async (opts) => {
|
|
87
87
|
await requireLogin('dev');
|
|
88
|
-
|
|
88
|
+
setSentryContextForCommand();
|
|
89
89
|
// --local flag overrides --engine to use local engine
|
|
90
90
|
if (opts.local) {
|
|
91
91
|
opts.engine = 'http://localhost:8787';
|
|
@@ -115,7 +115,7 @@ program
|
|
|
115
115
|
.option('-p, --preserve', 'Preserve component order in config for forward compile')
|
|
116
116
|
.action(async (opts) => {
|
|
117
117
|
await requireLogin('pull');
|
|
118
|
-
|
|
118
|
+
setSentryContextForCommand();
|
|
119
119
|
await runPull({
|
|
120
120
|
...opts,
|
|
121
121
|
version: opts.version,
|
|
@@ -131,7 +131,7 @@ program
|
|
|
131
131
|
.option('--from-version <number>', 'Base version number (auto-detected from local files if not provided)')
|
|
132
132
|
.action(async (opts) => {
|
|
133
133
|
await requireLogin('save');
|
|
134
|
-
|
|
134
|
+
setSentryContextForCommand();
|
|
135
135
|
await runSave({
|
|
136
136
|
id: opts.id,
|
|
137
137
|
label: opts.label,
|
|
@@ -152,7 +152,7 @@ program
|
|
|
152
152
|
.option('-i, --id <id>', 'Embeddable ID (will prompt if not provided)')
|
|
153
153
|
.action(async (opts) => {
|
|
154
154
|
await requireLogin('branch');
|
|
155
|
-
|
|
155
|
+
setSentryContextForCommand();
|
|
156
156
|
await runBranch(opts);
|
|
157
157
|
});
|
|
158
158
|
const experiments = program.command('experiments').description('Manage embeddable experiments');
|
|
@@ -164,7 +164,7 @@ experiments
|
|
|
164
164
|
.option('--experiment-key <key>', 'Experiment key (required if --experiment-id is set)')
|
|
165
165
|
.action(async (opts) => {
|
|
166
166
|
await requireLogin('experiments connect');
|
|
167
|
-
|
|
167
|
+
setSentryContextForCommand();
|
|
168
168
|
await runExperimentsConnect({
|
|
169
169
|
id: opts.id,
|
|
170
170
|
experimentId: opts.experimentId,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAwHA,wBAAsB,OAAO,CAAC,IAAI,EAAE;IAAE,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,OAAO,CAAA;CAAE,
|
|
1
|
+
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAwHA,wBAAsB,OAAO,CAAC,IAAI,EAAE;IAAE,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,OAAO,CAAA;CAAE,iBAgPxE"}
|
package/dist/commands/init.js
CHANGED
|
@@ -194,6 +194,12 @@ export async function runInit(opts) {
|
|
|
194
194
|
else {
|
|
195
195
|
stdout.print(pc.gray(' ✓ embeddables/ directory exists'));
|
|
196
196
|
}
|
|
197
|
+
// Remove old .claudefiles folder (replaced by .cursor/ and .claude/)
|
|
198
|
+
const claudefilesDir = path.join(cwd, '.claudefiles');
|
|
199
|
+
if (fs.existsSync(claudefilesDir)) {
|
|
200
|
+
fs.rmSync(claudefilesDir, { recursive: true });
|
|
201
|
+
stdout.print(pc.green(' ✓ Removed old .claudefiles/'));
|
|
202
|
+
}
|
|
197
203
|
// Inject .cursor/ and .claude/ from source .prompts/embeddables-cli.md (or copy if pre-built dirs exist)
|
|
198
204
|
const packageRoot = path.resolve(__dirname, '..', '..');
|
|
199
205
|
const promptsSource = path.join(packageRoot, '.prompts', 'embeddables-cli.md');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pull.d.ts","sourceRoot":"","sources":["../../src/commands/pull.ts"],"names":[],"mappings":"AA6HA,MAAM,MAAM,cAAc,GAAG;IAC3B,EAAE,CAAC,EAAE,MAAM,CAAA;IACX,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,6GAA6G;IAC7G,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;IACzB,iHAAiH;IACjH,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,GAAG,CAAC,EAAE,OAAO,CAAA;IACb,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB,CAAA;AAED,wBAAsB,OAAO,CAAC,IAAI,EAAE,cAAc,
|
|
1
|
+
{"version":3,"file":"pull.d.ts","sourceRoot":"","sources":["../../src/commands/pull.ts"],"names":[],"mappings":"AA6HA,MAAM,MAAM,cAAc,GAAG;IAC3B,EAAE,CAAC,EAAE,MAAM,CAAA;IACX,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,6GAA6G;IAC7G,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;IACzB,iHAAiH;IACjH,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,GAAG,CAAC,EAAE,OAAO,CAAA;IACb,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB,CAAA;AAED,wBAAsB,OAAO,CAAC,IAAI,EAAE,cAAc,iBAgTjD"}
|
package/dist/commands/pull.js
CHANGED
|
@@ -156,6 +156,7 @@ export async function runPull(opts) {
|
|
|
156
156
|
stdout.print(pc.cyan('Fetching embeddables from project...'));
|
|
157
157
|
const selected = await promptForEmbeddable(projectId, {
|
|
158
158
|
message: 'Select an embeddable to pull:',
|
|
159
|
+
prioritizeLocal: true,
|
|
159
160
|
});
|
|
160
161
|
if (!selected) {
|
|
161
162
|
logger.error('embeddable selection failed');
|
|
@@ -14,6 +14,8 @@ export interface LocalEmbeddable {
|
|
|
14
14
|
export interface PromptForEmbeddableOptions {
|
|
15
15
|
/** Custom message for the prompt */
|
|
16
16
|
message?: string;
|
|
17
|
+
/** When true, sort so embeddables already present in embeddables/ appear first */
|
|
18
|
+
prioritizeLocal?: boolean;
|
|
17
19
|
}
|
|
18
20
|
/**
|
|
19
21
|
* Fetch all embeddables for a project from Supabase
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"embeddables.d.ts","sourceRoot":"","sources":["../../src/prompts/embeddables.ts"],"names":[],"mappings":"AAOA,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;
|
|
1
|
+
{"version":3,"file":"embeddables.d.ts","sourceRoot":"","sources":["../../src/prompts/embeddables.ts"],"names":[],"mappings":"AAOA,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,CA0B1F;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,CA4ExB;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,CAuCxB"}
|
|
@@ -67,29 +67,64 @@ export async function fetchEmbeddableMetadata(embeddableId) {
|
|
|
67
67
|
* Returns null if no embeddables found or user cancels
|
|
68
68
|
*/
|
|
69
69
|
export async function promptForEmbeddable(projectId, options = {}) {
|
|
70
|
-
const { message = 'Select an embeddable:' } = options;
|
|
71
|
-
|
|
70
|
+
const { message = 'Select an embeddable:', prioritizeLocal = false } = options;
|
|
71
|
+
let embeddables = await fetchProjectEmbeddables(projectId);
|
|
72
|
+
const SEPARATOR_VALUE = '__separator__';
|
|
73
|
+
let inRepo = [];
|
|
74
|
+
let notInRepo = [];
|
|
75
|
+
if (prioritizeLocal && embeddables.length > 0) {
|
|
76
|
+
const local = await discoverLocalEmbeddables();
|
|
77
|
+
const localIds = new Set(local.map((e) => e.id));
|
|
78
|
+
inRepo = embeddables.filter((e) => localIds.has(e.id));
|
|
79
|
+
notInRepo = embeddables.filter((e) => !localIds.has(e.id));
|
|
80
|
+
embeddables = [...inRepo, ...notInRepo];
|
|
81
|
+
}
|
|
72
82
|
if (embeddables.length === 0) {
|
|
73
83
|
stdout.print(pc.yellow('No embeddables found in this project.'));
|
|
74
84
|
return null;
|
|
75
85
|
}
|
|
86
|
+
const hasTwoSections = prioritizeLocal && inRepo.length > 0 && notInRepo.length > 0;
|
|
87
|
+
const separatorChoice = {
|
|
88
|
+
title: pc.dim('── Other embeddables in project ──'),
|
|
89
|
+
value: SEPARATOR_VALUE,
|
|
90
|
+
disabled: true,
|
|
91
|
+
};
|
|
76
92
|
const choices = embeddables.map((e) => ({
|
|
77
93
|
title: e.title || e.id,
|
|
78
94
|
description: e.id,
|
|
79
95
|
value: e.id,
|
|
80
96
|
}));
|
|
97
|
+
if (hasTwoSections) {
|
|
98
|
+
choices.splice(inRepo.length, 0, separatorChoice);
|
|
99
|
+
}
|
|
81
100
|
const response = await prompts({
|
|
82
101
|
type: 'autocomplete',
|
|
83
102
|
name: 'id',
|
|
84
103
|
message,
|
|
85
104
|
choices,
|
|
86
|
-
suggest: (input,
|
|
87
|
-
|
|
105
|
+
suggest: (input, list) => {
|
|
106
|
+
const realChoices = list.filter((c) => c.value !== SEPARATOR_VALUE);
|
|
107
|
+
const filtered = input
|
|
108
|
+
? realChoices.filter((c) => (c.title?.toLowerCase().includes(input.toLowerCase()) ?? false) ||
|
|
109
|
+
String(c.value).toLowerCase().includes(input.toLowerCase()))
|
|
110
|
+
: realChoices;
|
|
111
|
+
if (hasTwoSections && !input) {
|
|
112
|
+
return Promise.resolve([
|
|
113
|
+
...filtered.slice(0, inRepo.length),
|
|
114
|
+
separatorChoice,
|
|
115
|
+
...filtered.slice(inRepo.length),
|
|
116
|
+
]);
|
|
117
|
+
}
|
|
118
|
+
return Promise.resolve(filtered);
|
|
119
|
+
},
|
|
88
120
|
}, {
|
|
89
121
|
onCancel: () => {
|
|
90
122
|
process.exit(0);
|
|
91
123
|
},
|
|
92
124
|
});
|
|
125
|
+
if (response.id === SEPARATOR_VALUE) {
|
|
126
|
+
return promptForEmbeddable(projectId, options);
|
|
127
|
+
}
|
|
93
128
|
return response.id || null;
|
|
94
129
|
}
|
|
95
130
|
/**
|