@embeddables/cli 0.7.10 → 0.7.13

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,
@@ -1018,16 +1018,14 @@ async function loadComputedFields(embeddableId) {
1018
1018
  */
1019
1019
  async function loadDataOutputs(embeddableId, config = null) {
1020
1020
  const actionsDir = path.join('embeddables', embeddableId, 'actions');
1021
- if (!fs.existsSync(actionsDir)) {
1022
- return [];
1023
- }
1021
+ const hasActionsDir = fs.existsSync(actionsDir);
1024
1022
  // Find all JS files in actions directory
1025
- const jsFiles = await fg('**/*.js', {
1026
- cwd: actionsDir,
1027
- dot: false,
1028
- });
1029
- if (jsFiles.length === 0) {
1030
- return [];
1023
+ let jsFiles = [];
1024
+ if (hasActionsDir) {
1025
+ jsFiles = await fg('**/*.js', {
1026
+ cwd: actionsDir,
1027
+ dot: false,
1028
+ });
1031
1029
  }
1032
1030
  // Use provided config or read it if not provided
1033
1031
  if (!config) {
@@ -1042,6 +1040,10 @@ async function loadDataOutputs(embeddableId, config = null) {
1042
1040
  }
1043
1041
  }
1044
1042
  }
1043
+ const hasConfigDataOutputs = config && config.dataOutputs && Array.isArray(config.dataOutputs) && config.dataOutputs.length > 0;
1044
+ if (jsFiles.length === 0 && !hasConfigDataOutputs) {
1045
+ return [];
1046
+ }
1045
1047
  // Build a map of actions by various identifiers for quick lookup
1046
1048
  const dataOutputsMap = new Map();
1047
1049
  for (const jsFile of jsFiles) {
@@ -1 +1 @@
1
- {"version":3,"file":"reverse.d.ts","sourceRoot":"","sources":["../../src/compiler/reverse.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,QAAQ,EAAiB,MAAM,YAAY,CAAA;AAqlBzD,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;IACL,GAAG,CAAC,EAAE,OAAO,CAAA;IACb,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,YAAY,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;CAC5E,iBAoFF;AAgiDD;;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":"AAQA,OAAO,KAAK,EAAE,QAAQ,EAAiB,MAAM,YAAY,CAAA;AAqlBzD,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;IACL,GAAG,CAAC,EAAE,OAAO,CAAA;IACb,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,YAAY,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;CAC5E,iBAoFF;AAggDD;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAKpD"}
@@ -1093,52 +1093,27 @@ function camelCase(str) {
1093
1093
  .join('')
1094
1094
  .replace(/[^a-zA-Z0-9]/g, '');
1095
1095
  }
1096
- function escapeString(str) {
1097
- // Escape backslashes first, then quotes, then all newline variants
1098
- return str
1099
- .replace(/\\/g, '\\\\')
1100
- .replace(/"/g, '\\"')
1101
- .replace(/\r\n/g, '\\n') // Windows line endings
1102
- .replace(/\r/g, '\\n') // Old Mac line endings
1103
- .replace(/\n/g, '\\n'); // Unix line endings
1104
- }
1105
1096
  function escapeStringForJSX(str) {
1106
- // Check if string contains double quotes - if so, use template literals
1107
1097
  const hasDoubleQuotes = str.includes('"');
1108
- if (hasDoubleQuotes) {
1109
- // Use template literals (backticks) - escape backticks, backslashes, and ${
1098
+ const hasNewlines = /[\r\n]/.test(str);
1099
+ // Use a template literal expression {`...`} when JS escape processing is needed:
1100
+ // - String contains double quotes (can't use them as JSX attribute delimiter)
1101
+ // - String contains actual newline characters (JSX attribute strings can't represent these)
1102
+ if (hasDoubleQuotes || hasNewlines) {
1110
1103
  let escaped = str
1111
- .replace(/\\/g, '\\\\') // Escape backslashes first
1104
+ .replace(/\\/g, '\\\\') // Escape backslashes (template literals process escape sequences)
1112
1105
  .replace(/`/g, '\\`') // Escape backticks
1113
1106
  .replace(/\$\{/g, '\\${'); // Escape template literal expressions
1114
- // Escape newlines
1115
1107
  escaped = escaped
1116
1108
  .replace(/\r\n/g, '\\n') // Windows line endings
1117
1109
  .replace(/\r/g, '\\n') // Old Mac line endings
1118
1110
  .replace(/\n/g, '\\n'); // Unix line endings
1119
1111
  return `{\`${escaped}\`}`;
1120
1112
  }
1121
- // No double quotes - use regular quote selection
1122
- const doubleQuoteCount = (str.match(/"/g) || []).length;
1123
- const singleQuoteCount = (str.match(/'/g) || []).length;
1124
- // Escape backslashes first
1125
- let escaped = str.replace(/\\/g, '\\\\');
1126
- // Escape newlines
1127
- escaped = escaped
1128
- .replace(/\r\n/g, '\\n') // Windows line endings
1129
- .replace(/\r/g, '\\n') // Old Mac line endings
1130
- .replace(/\n/g, '\\n'); // Unix line endings
1131
- // Use single quotes if there are more double quotes, otherwise use double quotes
1132
- if (doubleQuoteCount > singleQuoteCount) {
1133
- // Use single quotes and escape single quotes
1134
- escaped = escaped.replace(/'/g, "\\'");
1135
- return `'${escaped}'`;
1136
- }
1137
- else {
1138
- // Use double quotes and escape double quotes
1139
- escaped = escaped.replace(/"/g, '\\"');
1140
- return `"${escaped}"`;
1141
- }
1113
+ // JSX attribute strings treat all characters literally (no escape processing).
1114
+ // Backslashes, \n, etc. are NOT interpreted — they are stored as-is.
1115
+ // Since there are no double quotes in the string, use double quotes as delimiter.
1116
+ return `"${str}"`;
1142
1117
  }
1143
1118
  /**
1144
1119
  * Converts HTML string to JSX children code.
@@ -1244,31 +1219,25 @@ function htmlToJSXChildren(html, indent) {
1244
1219
  // So if the value contains double quotes, use single quotes for the outer delimiter
1245
1220
  const hasDoubleQuotes = attrValue.includes('"');
1246
1221
  const hasSingleQuotes = attrValue.includes("'");
1247
- if (hasDoubleQuotes && !hasSingleQuotes) {
1248
- // Use single quotes - only need to escape backslashes and newlines
1249
- const escapedValue = attrValue
1250
- .replace(/\\/g, '\\\\')
1251
- .replace(/\n/g, '\\n')
1252
- .replace(/\r/g, '\\r');
1253
- attrs.push(`${jsxAttrName}='${escapedValue}'`);
1254
- }
1255
- else if (hasDoubleQuotes && hasSingleQuotes) {
1256
- // Value has both quote types - use JSX expression with template literal
1222
+ const hasNewlines = /[\r\n]/.test(attrValue);
1223
+ if (hasDoubleQuotes && hasSingleQuotes || hasNewlines) {
1224
+ // Use JSX expression with template literal (JS escape processing applies)
1257
1225
  const escapedValue = attrValue
1258
1226
  .replace(/\\/g, '\\\\')
1259
1227
  .replace(/`/g, '\\`')
1260
- .replace(/\$\{/g, '\\${') // Escape template literal expressions
1261
- .replace(/\n/g, '\\n')
1262
- .replace(/\r/g, '\\r');
1228
+ .replace(/\$\{/g, '\\${')
1229
+ .replace(/\r\n/g, '\\n')
1230
+ .replace(/\r/g, '\\n')
1231
+ .replace(/\n/g, '\\n');
1263
1232
  attrs.push(`${jsxAttrName}={\`${escapedValue}\`}`);
1264
1233
  }
1234
+ else if (hasDoubleQuotes) {
1235
+ // JSX attribute strings are literal — no backslash escaping needed
1236
+ attrs.push(`${jsxAttrName}='${attrValue}'`);
1237
+ }
1265
1238
  else {
1266
- // No double quotes - use double quotes as before
1267
- const escapedValue = attrValue
1268
- .replace(/\\/g, '\\\\')
1269
- .replace(/\n/g, '\\n')
1270
- .replace(/\r/g, '\\r');
1271
- attrs.push(`${jsxAttrName}="${escapedValue}"`);
1239
+ // JSX attribute strings are literal no backslash escaping needed
1240
+ attrs.push(`${jsxAttrName}="${attrValue}"`);
1272
1241
  }
1273
1242
  }
1274
1243
  pos += fullMatch.length;
@@ -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;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"}
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,CA2B1F;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"}
@@ -17,6 +17,7 @@ export async function fetchProjectEmbeddables(projectId) {
17
17
  .from('flows')
18
18
  .select('id, title')
19
19
  .eq('project_id', projectId)
20
+ .not('archived', 'is', 'true')
20
21
  .order('title', { ascending: true });
21
22
  if (error) {
22
23
  stdout.warn(pc.yellow(`Could not fetch embeddables: ${error.message}`));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@embeddables/cli",
3
- "version": "0.7.10",
3
+ "version": "0.7.13",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "embeddables": "./bin/embeddables.mjs"