@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 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
- async function setSentryContextForCommand() {
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
- await setSentryUserFromAuth();
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
- await setSentryContextForCommand();
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
- await setSentryContextForCommand();
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
- await setSentryContextForCommand();
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
- await setSentryContextForCommand();
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
- await setSentryContextForCommand();
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
- await setSentryContextForCommand();
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
- await setSentryContextForCommand();
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,iBAyOxE"}
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"}
@@ -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,iBA+SjD"}
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"}
@@ -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;CACjB;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,CAuCxB;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"}
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
- const embeddables = await fetchProjectEmbeddables(projectId);
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, choices) => Promise.resolve(choices.filter((c) => (c.title?.toLowerCase().includes(input.toLowerCase()) ?? false) ||
87
- String(c.value).toLowerCase().includes(input.toLowerCase()))),
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
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@embeddables/cli",
3
- "version": "0.7.9",
3
+ "version": "0.7.11",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "embeddables": "./bin/embeddables.mjs"