@contentful/experience-design-system-cli 2.37.1-dev-build-2be54904.0 → 2.37.1-dev-build-c299dd61.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.
package/dist/app.js CHANGED
@@ -821,6 +821,16 @@ var init_parse_map_token_prop_tool_calls = __esm({
821
821
 
822
822
  // packages/experience-design-system-backend-pipeline/dist/src/agents/services/run-agent.js
823
823
  import { spawn } from "node:child_process";
824
+ function killProcessTree(pid, signal) {
825
+ try {
826
+ process.kill(-pid, signal);
827
+ } catch {
828
+ try {
829
+ process.kill(pid, signal);
830
+ } catch {
831
+ }
832
+ }
833
+ }
824
834
  async function runAgent(options) {
825
835
  const { agent, prompt, timeoutMs, model, onOutput, promptViaStdin, onDebugEvent } = options;
826
836
  const bedrock = options.bedrock ?? process.env.EDS_BEDROCK === "1";
@@ -837,10 +847,11 @@ async function runAgent(options) {
837
847
  promptLen: prompt.length,
838
848
  promptHead: prompt.slice(0, 500)
839
849
  });
840
- return new Promise((resolve28) => {
850
+ return new Promise((resolve29) => {
841
851
  const bedrockEnv = bedrock ? BEDROCK_ENV_BY_AGENT[agent] : void 0;
842
852
  const child = spawn(binary, args, {
843
853
  stdio: ["pipe", "pipe", "pipe"],
854
+ detached: true,
844
855
  ...bedrockEnv ? { env: { ...process.env, ...bedrockEnv } } : {}
845
856
  });
846
857
  if (useStdin2 && child.stdin) {
@@ -852,50 +863,87 @@ async function runAgent(options) {
852
863
  } else {
853
864
  child.stdin?.end();
854
865
  }
855
- let stdout = "";
856
- let stderr = "";
866
+ const stdoutChunks = [];
867
+ const stderrChunks = [];
857
868
  let timedOut = false;
858
- const timer = setTimeout(() => {
869
+ let settled = false;
870
+ const pid = child.pid;
871
+ const settle = (result) => {
872
+ if (settled)
873
+ return;
874
+ settled = true;
875
+ clearTimeout(softTimer);
876
+ clearTimeout(hardTimer);
877
+ onDebugEvent?.("run.end", {
878
+ agent,
879
+ model,
880
+ durationMs: Date.now() - startedAt,
881
+ exitCode: result.exitCode,
882
+ timedOut: result.timedOut,
883
+ stdoutLen: result.stdout.length,
884
+ stderrLen: result.stderr.length,
885
+ stderrTail: result.stderr.slice(-1e3)
886
+ });
887
+ resolve29(result);
888
+ };
889
+ const softTimer = setTimeout(() => {
859
890
  timedOut = true;
860
- child.kill("SIGTERM");
891
+ if (pid)
892
+ killProcessTree(pid, "SIGTERM");
861
893
  }, timeoutMs);
894
+ const hardTimer = setTimeout(() => {
895
+ if (settled)
896
+ return;
897
+ if (pid)
898
+ killProcessTree(pid, "SIGKILL");
899
+ try {
900
+ child.stdout?.destroy();
901
+ child.stderr?.destroy();
902
+ child.stdin?.destroy();
903
+ } catch {
904
+ }
905
+ settle({
906
+ exitCode: 1,
907
+ stdout: Buffer.concat(stdoutChunks).toString("utf8"),
908
+ stderr: Buffer.concat(stderrChunks).toString("utf8"),
909
+ timedOut: true
910
+ });
911
+ }, timeoutMs + WATCHDOG_GRACE_MS);
862
912
  child.stdout?.on("data", (chunk) => {
863
- const text = chunk.toString();
864
- stdout += text;
865
- onOutput?.(text);
913
+ stdoutChunks.push(chunk);
914
+ if (onOutput)
915
+ onOutput(chunk.toString("utf8"));
866
916
  });
867
917
  child.stderr?.on("data", (chunk) => {
868
- stderr += chunk.toString();
918
+ stderrChunks.push(chunk);
919
+ });
920
+ child.on("error", (err) => {
921
+ settle({
922
+ exitCode: 1,
923
+ stdout: Buffer.concat(stdoutChunks).toString("utf8"),
924
+ stderr: `${err instanceof Error ? err.message : String(err)}
925
+ ${Buffer.concat(stderrChunks).toString("utf8")}`,
926
+ timedOut
927
+ });
869
928
  });
870
929
  child.on("close", (code, signal) => {
871
- clearTimeout(timer);
872
- const result = {
930
+ settle({
873
931
  exitCode: signal ? 1 : code ?? 1,
874
- stdout,
875
- stderr,
932
+ stdout: Buffer.concat(stdoutChunks).toString("utf8"),
933
+ stderr: Buffer.concat(stderrChunks).toString("utf8"),
876
934
  timedOut
877
- };
878
- onDebugEvent?.("run.end", {
879
- agent,
880
- model,
881
- durationMs: Date.now() - startedAt,
882
- exitCode: result.exitCode,
883
- signal,
884
- timedOut,
885
- stdoutLen: stdout.length,
886
- stderrLen: stderr.length,
887
- stderrTail: stderr.slice(-1e3)
888
935
  });
889
- resolve28(result);
890
936
  });
891
937
  });
892
938
  }
939
+ var WATCHDOG_GRACE_MS;
893
940
  var init_run_agent = __esm({
894
941
  "packages/experience-design-system-backend-pipeline/dist/src/agents/services/run-agent.js"() {
895
942
  "use strict";
896
943
  init_bedrock();
897
944
  init_build_agent_args();
898
945
  init_resolve_binary();
946
+ WATCHDOG_GRACE_MS = 10 * 1e3;
899
947
  }
900
948
  });
901
949
 
@@ -908,7 +956,7 @@ async function checkAgentAuth(agent) {
908
956
  return "not-found";
909
957
  if (agent !== "claude")
910
958
  return "ok";
911
- return new Promise((resolve28) => {
959
+ return new Promise((resolve29) => {
912
960
  const child = spawn2(binary, ["auth", "status", "--json"], { stdio: ["ignore", "pipe", "pipe"] });
913
961
  let stdout = "";
914
962
  let done = false;
@@ -917,7 +965,7 @@ async function checkAgentAuth(agent) {
917
965
  return;
918
966
  done = true;
919
967
  child.kill("SIGTERM");
920
- resolve28("unauthenticated");
968
+ resolve29("unauthenticated");
921
969
  }, 5e3);
922
970
  child.stdout?.on("data", (chunk) => {
923
971
  stdout += chunk.toString();
@@ -928,14 +976,14 @@ async function checkAgentAuth(agent) {
928
976
  done = true;
929
977
  clearTimeout(timer);
930
978
  if (code !== 0) {
931
- resolve28("unauthenticated");
979
+ resolve29("unauthenticated");
932
980
  return;
933
981
  }
934
982
  try {
935
983
  const status = JSON.parse(stdout);
936
- resolve28(status.loggedIn ? "ok" : "unauthenticated");
984
+ resolve29(status.loggedIn ? "ok" : "unauthenticated");
937
985
  } catch {
938
- resolve28("unauthenticated");
986
+ resolve29("unauthenticated");
939
987
  }
940
988
  });
941
989
  });
@@ -945,9 +993,9 @@ async function binaryIsOnPath(binary) {
945
993
  const fs = await import("node:fs/promises");
946
994
  return fs.access(binary).then(() => true, () => false);
947
995
  }
948
- return new Promise((resolve28) => {
996
+ return new Promise((resolve29) => {
949
997
  const child = spawn2(process.platform === "win32" ? "where" : "which", [binary], { stdio: "ignore" });
950
- child.on("close", (code) => resolve28(code === 0));
998
+ child.on("close", (code) => resolve29(code === 0));
951
999
  });
952
1000
  }
953
1001
  var init_check_agent_auth = __esm({
@@ -1584,7 +1632,8 @@ var init_infer_fence_lang = __esm({
1584
1632
  sass: "scss",
1585
1633
  css: "css",
1586
1634
  json: "json",
1587
- json5: "json"
1635
+ json5: "json",
1636
+ html: "html"
1588
1637
  };
1589
1638
  }
1590
1639
  });
@@ -2083,22 +2132,22 @@ var init_cache_keys = __esm({
2083
2132
 
2084
2133
  // packages/experience-design-system-types/dist/src/config/index.js
2085
2134
  import { randomBytes as randomBytes4 } from "node:crypto";
2086
- import { mkdir as mkdir6, readFile as readFile18, rename as rename2, writeFile as writeFile6 } from "node:fs/promises";
2135
+ import { mkdir as mkdir6, readFile as readFile20, rename as rename2, writeFile as writeFile6 } from "node:fs/promises";
2087
2136
  import { homedir as homedir3 } from "node:os";
2088
- import { dirname as dirname13, join as join16 } from "node:path";
2137
+ import { dirname as dirname14, join as join16 } from "node:path";
2089
2138
  function configRoot2() {
2090
2139
  return process.env["EDS_HOME"] || join16(homedir3(), ".contentful", "experience-design-system-cli");
2091
2140
  }
2092
2141
  async function readSettings2() {
2093
2142
  try {
2094
- return JSON.parse(await readFile18(configFilePath2(), "utf8"));
2143
+ return JSON.parse(await readFile20(configFilePath2(), "utf8"));
2095
2144
  } catch {
2096
2145
  return {};
2097
2146
  }
2098
2147
  }
2099
2148
  async function writeSettings2(settings) {
2100
2149
  const path5 = configFilePath2();
2101
- await mkdir6(dirname13(path5), { recursive: true });
2150
+ await mkdir6(dirname14(path5), { recursive: true });
2102
2151
  const tmp = `${path5}.${process.pid}.${randomBytes4(4).toString("hex")}.tmp`;
2103
2152
  await writeFile6(tmp, `${JSON.stringify(settings, null, 2)}
2104
2153
  `, { mode: 384 });
@@ -2142,7 +2191,7 @@ var init_debug_mode_store = __esm({
2142
2191
 
2143
2192
  // packages/experience-design-system-cli/src/tui/debug-prune.ts
2144
2193
  import { readdir as readdir2, rm, rmdir, stat as stat4 } from "node:fs/promises";
2145
- import { dirname as dirname16, join as join23 } from "node:path";
2194
+ import { dirname as dirname17, join as join23 } from "node:path";
2146
2195
  async function logFilesIn(dir) {
2147
2196
  const entries = await readdir2(dir, { withFileTypes: true });
2148
2197
  const nested = await Promise.all(
@@ -2165,7 +2214,7 @@ async function removeEmptyFolders(from, stop) {
2165
2214
  }
2166
2215
  removed += 1;
2167
2216
  if (dir === stop) return removed;
2168
- dir = dirname16(dir);
2217
+ dir = dirname17(dir);
2169
2218
  }
2170
2219
  }
2171
2220
  async function pruneExpiredLogs(base, retentionDays, now = Date.now()) {
@@ -2181,7 +2230,7 @@ async function pruneExpiredLogs(base, retentionDays, now = Date.now()) {
2181
2230
  if ((await stat4(file)).mtimeMs >= cutoff) continue;
2182
2231
  await rm(file);
2183
2232
  result.logs += 1;
2184
- result.folders += await removeEmptyFolders(dirname16(file), join23(contentfulDir, session));
2233
+ result.folders += await removeEmptyFolders(dirname17(file), join23(contentfulDir, session));
2185
2234
  } catch {
2186
2235
  }
2187
2236
  }
@@ -2211,7 +2260,7 @@ __export(debug_store_exports, {
2211
2260
  });
2212
2261
  import { mkdir as mkdir9, writeFile as writeFile8 } from "node:fs/promises";
2213
2262
  import { existsSync as existsSync9, readdirSync as readdirSync4 } from "node:fs";
2214
- import { join as join24, resolve as resolve26 } from "node:path";
2263
+ import { join as join24, resolve as resolve27 } from "node:path";
2215
2264
  function generateRunId() {
2216
2265
  const now = /* @__PURE__ */ new Date();
2217
2266
  const pad = (n) => String(n).padStart(2, "0");
@@ -2227,7 +2276,7 @@ function slugify(value) {
2227
2276
  async function readBaseDir() {
2228
2277
  try {
2229
2278
  const dir = (await readSettings2())["contentfulBaseDir"];
2230
- return typeof dir === "string" && dir !== "" ? resolve26(dir) : void 0;
2279
+ return typeof dir === "string" && dir !== "" ? resolve27(dir) : void 0;
2231
2280
  } catch {
2232
2281
  return void 0;
2233
2282
  }
@@ -2256,7 +2305,7 @@ function currentSessionDir() {
2256
2305
  async function startDebugSessionIn(base, { replace = false } = {}) {
2257
2306
  try {
2258
2307
  if (!await isDebugModeEnabled()) return;
2259
- await mkdir9(join24(startSession(resolve26(base), { replace }), "debug"), { recursive: true });
2308
+ await mkdir9(join24(startSession(resolve27(base), { replace }), "debug"), { recursive: true });
2260
2309
  } catch {
2261
2310
  }
2262
2311
  }
@@ -2270,7 +2319,7 @@ function nextImportRunDir(session) {
2270
2319
  }
2271
2320
  async function startImportRun(projectPath) {
2272
2321
  await startDebugSessionIn(projectPath);
2273
- if (!sessionDir) return join24(resolve26(projectPath), ".contentful");
2322
+ if (!sessionDir) return join24(resolve27(projectPath), ".contentful");
2274
2323
  const dir = nextImportRunDir(sessionDir);
2275
2324
  await mkdir9(dir, { recursive: true });
2276
2325
  return dir;
@@ -11982,6 +12031,690 @@ function mergeSlots2(fromSnippetProps, fromTemplate) {
11982
12031
  return { slots: [...byName.values()], mixedWarning: mixed };
11983
12032
  }
11984
12033
 
12034
+ // packages/experience-design-system-backend-pipeline/dist/src/steps/extraction/src/framework-adapters/angular/extract-angular-components.js
12035
+ import { readFile as readFile8 } from "node:fs/promises";
12036
+ import { ModuleKind as ModuleKind2, Project as Project7, ScriptTarget as ScriptTarget2 } from "ts-morph";
12037
+
12038
+ // packages/experience-design-system-backend-pipeline/dist/src/steps/extraction/src/framework-adapters/angular/helpers/find-component-decorator.js
12039
+ import { Node as Node10 } from "ts-morph";
12040
+ function resolveToObjectLiteral(expr, depth = 0) {
12041
+ if (!expr || depth > 3)
12042
+ return null;
12043
+ if (Node10.isObjectLiteralExpression(expr))
12044
+ return expr;
12045
+ if (Node10.isIdentifier(expr)) {
12046
+ const defs = expr.getDefinitions();
12047
+ for (const def of defs) {
12048
+ const node = def.getDeclarationNode();
12049
+ if (node && Node10.isVariableDeclaration(node)) {
12050
+ const init = node.getInitializer();
12051
+ const resolved = resolveToObjectLiteral(init, depth + 1);
12052
+ if (resolved)
12053
+ return resolved;
12054
+ }
12055
+ }
12056
+ }
12057
+ return null;
12058
+ }
12059
+ function findComponentDecorator(cls) {
12060
+ const decorator = cls.getDecorator("Component");
12061
+ if (!decorator)
12062
+ return null;
12063
+ const [arg] = decorator.getArguments();
12064
+ return resolveToObjectLiteral(arg);
12065
+ }
12066
+ function hasComponentDecorator(cls) {
12067
+ return cls.getDecorator("Component") !== void 0;
12068
+ }
12069
+
12070
+ // packages/experience-design-system-backend-pipeline/dist/src/steps/extraction/src/framework-adapters/angular/helpers/props/extract-decorator-input.js
12071
+ import { Node as Node12 } from "ts-morph";
12072
+
12073
+ // packages/experience-design-system-backend-pipeline/dist/src/steps/extraction/src/framework-adapters/angular/helpers/props/resolve-prop-type.js
12074
+ import { Node as Node11 } from "ts-morph";
12075
+ function resolvePropType(typeNode) {
12076
+ if (!typeNode) {
12077
+ return { text: "any", allowedValues: null, isTemplateRef: false };
12078
+ }
12079
+ const text = typeNode.getText();
12080
+ const members = extractStringLiteralUnion(typeNode);
12081
+ const isTemplateRef = containsTemplateRef(typeNode);
12082
+ return {
12083
+ text,
12084
+ allowedValues: members.length > 0 ? members : null,
12085
+ isTemplateRef
12086
+ };
12087
+ }
12088
+ function extractStringLiteralUnion(typeNode) {
12089
+ if (Node11.isLiteralTypeNode(typeNode)) {
12090
+ const lit = typeNode.getLiteral();
12091
+ if (Node11.isStringLiteral(lit) || Node11.isNoSubstitutionTemplateLiteral(lit)) {
12092
+ return [lit.getLiteralText()];
12093
+ }
12094
+ return [];
12095
+ }
12096
+ if (Node11.isUnionTypeNode(typeNode)) {
12097
+ const out = [];
12098
+ for (const member of typeNode.getTypeNodes()) {
12099
+ const sub = extractStringLiteralUnion(member);
12100
+ if (sub.length === 0 && !isNullOrUndefinedLiteral(member)) {
12101
+ return [];
12102
+ }
12103
+ out.push(...sub);
12104
+ }
12105
+ return out;
12106
+ }
12107
+ return [];
12108
+ }
12109
+ function isNullOrUndefinedLiteral(typeNode) {
12110
+ if (Node11.isLiteralTypeNode(typeNode)) {
12111
+ const lit = typeNode.getLiteral();
12112
+ if (Node11.isNullLiteral(lit))
12113
+ return true;
12114
+ }
12115
+ const t = typeNode.getText();
12116
+ return t === "null" || t === "undefined";
12117
+ }
12118
+ function containsTemplateRef(typeNode) {
12119
+ const text = typeNode.getText();
12120
+ return /\bTemplateRef\b/.test(text);
12121
+ }
12122
+
12123
+ // packages/experience-design-system-backend-pipeline/dist/src/steps/extraction/src/framework-adapters/angular/helpers/props/extract-decorator-input.js
12124
+ function extractDecoratorInput(field) {
12125
+ const decorator = field.getDecorator("Input");
12126
+ if (!decorator)
12127
+ return null;
12128
+ const fieldName = field.getName();
12129
+ const args = decorator.getArguments();
12130
+ let alias = null;
12131
+ let required = false;
12132
+ let transformIsBoolean = false;
12133
+ let transformIsNumber = false;
12134
+ if (args.length === 1) {
12135
+ const arg = args[0];
12136
+ if (Node12.isStringLiteral(arg) || Node12.isNoSubstitutionTemplateLiteral(arg)) {
12137
+ alias = arg.getLiteralText();
12138
+ } else if (Node12.isObjectLiteralExpression(arg)) {
12139
+ const aliasProp = arg.getProperty("alias");
12140
+ if (aliasProp && Node12.isPropertyAssignment(aliasProp)) {
12141
+ const init = aliasProp.getInitializer();
12142
+ if (init && (Node12.isStringLiteral(init) || Node12.isNoSubstitutionTemplateLiteral(init))) {
12143
+ alias = init.getLiteralText();
12144
+ }
12145
+ }
12146
+ const requiredProp = arg.getProperty("required");
12147
+ if (requiredProp && Node12.isPropertyAssignment(requiredProp)) {
12148
+ const init = requiredProp.getInitializer();
12149
+ if (init?.getText() === "true")
12150
+ required = true;
12151
+ }
12152
+ const transformProp = arg.getProperty("transform");
12153
+ if (transformProp && Node12.isPropertyAssignment(transformProp)) {
12154
+ const transformText = transformProp.getInitializer()?.getText() ?? "";
12155
+ if (/\bbooleanAttribute\b/.test(transformText))
12156
+ transformIsBoolean = true;
12157
+ if (/\bnumberAttribute\b/.test(transformText))
12158
+ transformIsNumber = true;
12159
+ }
12160
+ }
12161
+ }
12162
+ let typeNode;
12163
+ let defaultValue;
12164
+ if (Node12.isSetAccessorDeclaration(field)) {
12165
+ const param = field.getParameters()[0];
12166
+ typeNode = param?.getTypeNode();
12167
+ } else if (Node12.isGetAccessorDeclaration(field)) {
12168
+ const parent = field.getParent();
12169
+ const companionSetter = parent && Node12.isClassDeclaration(parent) ? parent.getSetAccessor(fieldName) : void 0;
12170
+ if (companionSetter) {
12171
+ typeNode = companionSetter.getParameters()[0]?.getTypeNode();
12172
+ }
12173
+ if (!typeNode)
12174
+ typeNode = field.getReturnTypeNode();
12175
+ } else {
12176
+ typeNode = field.getTypeNode();
12177
+ const initializer = field.getInitializer();
12178
+ if (initializer)
12179
+ defaultValue = initializer.getText();
12180
+ }
12181
+ const resolved = resolvePropType(typeNode);
12182
+ const typeText = transformIsBoolean ? "boolean" : transformIsNumber ? "number" : resolved.text;
12183
+ const name = alias ?? fieldName;
12184
+ const prop = {
12185
+ name,
12186
+ type: typeText,
12187
+ required,
12188
+ sourceStartLine: field.getStartLineNumber(),
12189
+ sourceEndLine: field.getEndLineNumber()
12190
+ };
12191
+ if (defaultValue !== void 0)
12192
+ prop.defaultValue = defaultValue;
12193
+ if (resolved.allowedValues && !transformIsBoolean && !transformIsNumber) {
12194
+ prop.allowedValues = resolved.allowedValues;
12195
+ }
12196
+ return prop;
12197
+ }
12198
+
12199
+ // packages/experience-design-system-backend-pipeline/dist/src/steps/extraction/src/framework-adapters/angular/helpers/props/extract-signal-input.js
12200
+ import { Node as Node13 } from "ts-morph";
12201
+ function extractSignalInput(field) {
12202
+ const init = field.getInitializer();
12203
+ if (!init || !Node13.isCallExpression(init))
12204
+ return null;
12205
+ const callee = init.getExpression();
12206
+ let required = false;
12207
+ if (Node13.isIdentifier(callee)) {
12208
+ if (callee.getText() !== "input")
12209
+ return null;
12210
+ } else if (Node13.isPropertyAccessExpression(callee)) {
12211
+ const left = callee.getExpression();
12212
+ const right = callee.getName();
12213
+ if (!Node13.isIdentifier(left) || left.getText() !== "input" || right !== "required")
12214
+ return null;
12215
+ required = true;
12216
+ } else {
12217
+ return null;
12218
+ }
12219
+ const fieldName = field.getName();
12220
+ const args = init.getArguments();
12221
+ let defaultValue;
12222
+ let configArg;
12223
+ if (required) {
12224
+ configArg = args[0];
12225
+ } else {
12226
+ const first = args[0];
12227
+ if (first) {
12228
+ defaultValue = first.getText();
12229
+ configArg = args[1];
12230
+ }
12231
+ }
12232
+ let alias = null;
12233
+ let transformIsBoolean = false;
12234
+ let transformIsNumber = false;
12235
+ if (configArg && Node13.isObjectLiteralExpression(configArg)) {
12236
+ const aliasProp = configArg.getProperty("alias");
12237
+ if (aliasProp && Node13.isPropertyAssignment(aliasProp)) {
12238
+ const aliasInit = aliasProp.getInitializer();
12239
+ if (aliasInit && (Node13.isStringLiteral(aliasInit) || Node13.isNoSubstitutionTemplateLiteral(aliasInit))) {
12240
+ alias = aliasInit.getLiteralText();
12241
+ }
12242
+ }
12243
+ const transformProp = configArg.getProperty("transform");
12244
+ if (transformProp && Node13.isPropertyAssignment(transformProp)) {
12245
+ const transformText = transformProp.getInitializer()?.getText() ?? "";
12246
+ if (/\bbooleanAttribute\b/.test(transformText))
12247
+ transformIsBoolean = true;
12248
+ if (/\bnumberAttribute\b/.test(transformText))
12249
+ transformIsNumber = true;
12250
+ }
12251
+ }
12252
+ const typeArg = init.getTypeArguments()[0];
12253
+ const resolved = resolvePropType(typeArg);
12254
+ const typeText = transformIsBoolean ? "boolean" : transformIsNumber ? "number" : resolved.text;
12255
+ const name = alias ?? fieldName;
12256
+ const prop = {
12257
+ name,
12258
+ type: typeText,
12259
+ required,
12260
+ sourceStartLine: field.getStartLineNumber(),
12261
+ sourceEndLine: field.getEndLineNumber()
12262
+ };
12263
+ if (defaultValue !== void 0)
12264
+ prop.defaultValue = defaultValue;
12265
+ if (resolved.allowedValues && !transformIsBoolean && !transformIsNumber) {
12266
+ prop.allowedValues = resolved.allowedValues;
12267
+ }
12268
+ return prop;
12269
+ }
12270
+
12271
+ // packages/experience-design-system-backend-pipeline/dist/src/steps/extraction/src/framework-adapters/angular/helpers/props/parse-inputs-array-entry.js
12272
+ function parseInputsArrayEntry(entry) {
12273
+ const trimmed = entry.trim();
12274
+ if (!trimmed)
12275
+ return null;
12276
+ const parts = trimmed.split(":");
12277
+ if (parts.length === 1) {
12278
+ return { fieldName: parts[0].trim(), alias: null };
12279
+ }
12280
+ if (parts.length === 2) {
12281
+ const field = parts[0].trim();
12282
+ const alias = parts[1].trim();
12283
+ if (!field || !alias)
12284
+ return null;
12285
+ return { fieldName: field, alias };
12286
+ }
12287
+ return null;
12288
+ }
12289
+
12290
+ // packages/experience-design-system-backend-pipeline/dist/src/steps/extraction/src/framework-adapters/angular/helpers/props/extract-props.js
12291
+ var MAX_BASE_CHAIN = 10;
12292
+ function collectClassChain(cls) {
12293
+ const chain = [cls];
12294
+ const seen = /* @__PURE__ */ new Set([cls]);
12295
+ let current = cls;
12296
+ for (let i = 0; i < MAX_BASE_CHAIN; i++) {
12297
+ let base;
12298
+ try {
12299
+ base = current.getBaseClass();
12300
+ } catch {
12301
+ break;
12302
+ }
12303
+ if (!base || seen.has(base))
12304
+ break;
12305
+ chain.push(base);
12306
+ seen.add(base);
12307
+ current = base;
12308
+ }
12309
+ return chain;
12310
+ }
12311
+ function extractProps2(cls, meta) {
12312
+ const byName = /* @__PURE__ */ new Map();
12313
+ const chain = collectClassChain(cls);
12314
+ for (const klass of chain) {
12315
+ for (const field of klass.getProperties()) {
12316
+ const prop = extractDecoratorInput(field);
12317
+ if (prop && !byName.has(prop.name))
12318
+ byName.set(prop.name, prop);
12319
+ }
12320
+ for (const setter of klass.getSetAccessors()) {
12321
+ const prop = extractDecoratorInput(setter);
12322
+ if (prop && !byName.has(prop.name))
12323
+ byName.set(prop.name, prop);
12324
+ }
12325
+ for (const getter of klass.getGetAccessors()) {
12326
+ const prop = extractDecoratorInput(getter);
12327
+ if (prop && !byName.has(prop.name))
12328
+ byName.set(prop.name, prop);
12329
+ }
12330
+ for (const field of klass.getProperties()) {
12331
+ const prop = extractSignalInput(field);
12332
+ if (prop && !byName.has(prop.name))
12333
+ byName.set(prop.name, prop);
12334
+ }
12335
+ }
12336
+ for (const entry of meta.inputsArray) {
12337
+ const parsed = parseInputsArrayEntry(entry);
12338
+ if (!parsed)
12339
+ continue;
12340
+ const name = parsed.alias ?? parsed.fieldName;
12341
+ if (byName.has(name))
12342
+ continue;
12343
+ byName.set(name, { name, type: "any", required: false });
12344
+ }
12345
+ return [...byName.values()];
12346
+ }
12347
+
12348
+ // packages/experience-design-system-backend-pipeline/dist/src/steps/extraction/src/framework-adapters/angular/helpers/read-component-metadata.js
12349
+ import { dirname as dirname10, resolve as resolve12 } from "node:path";
12350
+
12351
+ // packages/experience-design-system-backend-pipeline/dist/src/steps/extraction/src/framework-adapters/angular/helpers/resolution/normalize-component-name.js
12352
+ var SUFFIXES = ["Component", "Directive"];
12353
+ function normalizeComponentName2(className) {
12354
+ for (const suffix of SUFFIXES) {
12355
+ if (className.endsWith(suffix) && className.length > suffix.length) {
12356
+ return className.slice(0, -suffix.length);
12357
+ }
12358
+ }
12359
+ return className;
12360
+ }
12361
+
12362
+ // packages/experience-design-system-backend-pipeline/dist/src/steps/extraction/src/framework-adapters/angular/helpers/read-decorator-string.js
12363
+ import { Node as Node14 } from "ts-morph";
12364
+ function readDecoratorString(obj, propName) {
12365
+ const prop = obj.getProperty(propName);
12366
+ if (!prop || !Node14.isPropertyAssignment(prop))
12367
+ return null;
12368
+ const init = prop.getInitializer();
12369
+ if (!init)
12370
+ return null;
12371
+ if (Node14.isStringLiteral(init) || Node14.isNoSubstitutionTemplateLiteral(init)) {
12372
+ return init.getLiteralText();
12373
+ }
12374
+ return null;
12375
+ }
12376
+ function readDecoratorStringArray(obj, propName) {
12377
+ const prop = obj.getProperty(propName);
12378
+ if (!prop || !Node14.isPropertyAssignment(prop))
12379
+ return [];
12380
+ const init = prop.getInitializer();
12381
+ if (!init || !Node14.isArrayLiteralExpression(init))
12382
+ return [];
12383
+ const out = [];
12384
+ for (const el of init.getElements()) {
12385
+ if (Node14.isStringLiteral(el) || Node14.isNoSubstitutionTemplateLiteral(el)) {
12386
+ out.push(el.getLiteralText());
12387
+ }
12388
+ }
12389
+ return out;
12390
+ }
12391
+
12392
+ // packages/experience-design-system-backend-pipeline/dist/src/steps/extraction/src/framework-adapters/angular/helpers/read-component-metadata.js
12393
+ function readComponentMetadata(cls, sourceFilePath) {
12394
+ const obj = findComponentDecorator(cls);
12395
+ if (!obj)
12396
+ return null;
12397
+ const className = cls.getName();
12398
+ if (!className)
12399
+ return null;
12400
+ const rawSelector = readDecoratorString(obj, "selector");
12401
+ const inlineTemplate = readDecoratorString(obj, "template");
12402
+ const templateUrlRel = readDecoratorString(obj, "templateUrl");
12403
+ const inputsArray = readDecoratorStringArray(obj, "inputs");
12404
+ const templatePath = templateUrlRel ? resolve12(dirname10(sourceFilePath), templateUrlRel) : null;
12405
+ const decorator = cls.getDecorator("Component");
12406
+ const decoratorLine = decorator?.getStartLineNumber() ?? cls.getStartLineNumber();
12407
+ return {
12408
+ className,
12409
+ normalizedName: normalizeComponentName2(className),
12410
+ rawSelector,
12411
+ inlineTemplate,
12412
+ templatePath,
12413
+ inputsArray,
12414
+ decoratorLine
12415
+ };
12416
+ }
12417
+
12418
+ // packages/experience-design-system-backend-pipeline/dist/src/steps/extraction/src/framework-adapters/angular/helpers/template/parse-ng-content-elements.js
12419
+ function parseNgContentElements(templateHtml) {
12420
+ const out = [];
12421
+ const tagRe = /<ng-content\b([^>]*?)\/?>/gi;
12422
+ for (const match2 of templateHtml.matchAll(tagRe)) {
12423
+ const attrs = match2[1] ?? "";
12424
+ const selectMatch = attrs.match(/\bselect\s*=\s*(?:"([^"]*)"|'([^']*)')/);
12425
+ const rawSelect = selectMatch ? selectMatch[1] ?? selectMatch[2] ?? null : null;
12426
+ const sourceLine = countLines(templateHtml, match2.index ?? 0);
12427
+ out.push({ rawSelect, sourceLine });
12428
+ }
12429
+ return out;
12430
+ }
12431
+ function countLines(text, offset) {
12432
+ let line = 1;
12433
+ for (let i = 0; i < offset && i < text.length; i++) {
12434
+ if (text.charCodeAt(i) === 10)
12435
+ line++;
12436
+ }
12437
+ return line;
12438
+ }
12439
+
12440
+ // packages/experience-design-system-backend-pipeline/dist/src/steps/extraction/src/framework-adapters/angular/helpers/template/resolve-template-source.js
12441
+ import { readFile as readFile7 } from "node:fs/promises";
12442
+ async function resolveTemplateSource(meta) {
12443
+ if (meta.inlineTemplate !== null)
12444
+ return meta.inlineTemplate;
12445
+ if (meta.templatePath === null)
12446
+ return null;
12447
+ try {
12448
+ return await readFile7(meta.templatePath, "utf8");
12449
+ } catch {
12450
+ return null;
12451
+ }
12452
+ }
12453
+
12454
+ // packages/experience-design-system-backend-pipeline/dist/src/steps/extraction/src/framework-adapters/angular/helpers/resolution/strip-library-prefix.js
12455
+ var KNOWN_PREFIXES = ["Mat", "Cdk", "Nz", "Cds", "Ibm", "Clr", "Hlm", "Brn", "Tui", "Nb", "Fd", "P", "Ng"];
12456
+ function stripLibraryPrefix(name) {
12457
+ for (const prefix of KNOWN_PREFIXES) {
12458
+ if (name.startsWith(prefix) && name.length > prefix.length) {
12459
+ const rest = name.slice(prefix.length);
12460
+ if (rest[0] && rest[0] === rest[0].toUpperCase()) {
12461
+ return rest;
12462
+ }
12463
+ }
12464
+ }
12465
+ return name;
12466
+ }
12467
+
12468
+ // packages/experience-design-system-backend-pipeline/dist/src/steps/extraction/src/framework-adapters/angular/helpers/slots/derive-slot-name.js
12469
+ function deriveSlotName(rawSelect, parentNormalizedName) {
12470
+ if (!rawSelect || rawSelect.trim() === "")
12471
+ return "children";
12472
+ if (rawSelect.includes(",")) {
12473
+ const first = rawSelect.split(",")[0].trim();
12474
+ return deriveSingleSelectorName(first, parentNormalizedName);
12475
+ }
12476
+ return deriveSingleSelectorName(rawSelect.trim(), parentNormalizedName);
12477
+ }
12478
+ function deriveSingleSelectorName(sel, parentNormalizedName) {
12479
+ const slotAttrMatch = sel.match(/^\[\s*slot\s*=\s*['"]?([^'"\]]+)['"]?\s*\]$/);
12480
+ if (slotAttrMatch)
12481
+ return slotAttrMatch[1].trim();
12482
+ if (sel.startsWith(".")) {
12483
+ const last = sel.slice(1).split("-").pop() ?? sel.slice(1);
12484
+ return kebabToCamel2(last);
12485
+ }
12486
+ const attrMatch = sel.match(/^\[([^=\]]+)\]$/);
12487
+ if (attrMatch) {
12488
+ const attr = attrMatch[1].trim();
12489
+ const stripped = tryStripSubComponentOrLibraryPrefix(attr, parentNormalizedName);
12490
+ return stripped || kebabToCamel2(attr);
12491
+ }
12492
+ const elMatch = sel.match(/^([a-zA-Z][a-zA-Z0-9-]*)/);
12493
+ if (elMatch) {
12494
+ const tag = elMatch[1];
12495
+ const stripped = tryStripSubComponentOrLibraryPrefix(tag, parentNormalizedName);
12496
+ return stripped || kebabToCamel2(tag);
12497
+ }
12498
+ return sel.replace(/\s+/g, "");
12499
+ }
12500
+ function tryStripSubComponentOrLibraryPrefix(ident, parentNormalizedName) {
12501
+ const parentKebab = pascalToKebab(parentNormalizedName);
12502
+ if (parentKebab && ident.startsWith(`${parentKebab}-`)) {
12503
+ return kebabToCamel2(ident.slice(parentKebab.length + 1));
12504
+ }
12505
+ const asPascal = kebabToPascal2(ident);
12506
+ const stripped = stripLibraryPrefix(asPascal);
12507
+ if (stripped !== asPascal) {
12508
+ return stripped.charAt(0).toLowerCase() + stripped.slice(1);
12509
+ }
12510
+ return null;
12511
+ }
12512
+ function kebabToCamel2(s) {
12513
+ return s.replace(/-([a-z])/g, (_, c2) => c2.toUpperCase());
12514
+ }
12515
+ function kebabToPascal2(s) {
12516
+ const camel = kebabToCamel2(s);
12517
+ return camel.charAt(0).toUpperCase() + camel.slice(1);
12518
+ }
12519
+ function pascalToKebab(s) {
12520
+ return s.replace(/([a-z0-9])([A-Z])/g, "$1-$2").toLowerCase();
12521
+ }
12522
+
12523
+ // packages/experience-design-system-backend-pipeline/dist/src/steps/extraction/src/framework-adapters/angular/helpers/slots/extract-content-child-queries.js
12524
+ import { Node as Node15 } from "ts-morph";
12525
+ function extractContentChildQueries(cls) {
12526
+ const out = [];
12527
+ for (const field of cls.getProperties()) {
12528
+ const fieldName = field.getName();
12529
+ const init = field.getInitializer();
12530
+ if (init && Node15.isCallExpression(init)) {
12531
+ const callee = init.getExpression();
12532
+ if (Node15.isIdentifier(callee)) {
12533
+ const name = callee.getText();
12534
+ if (name === "contentChild" || name === "contentChildren") {
12535
+ const first = init.getArguments()[0];
12536
+ const allowed = resolveClassIdentifierArg(first);
12537
+ out.push(buildSlot(fieldName, allowed));
12538
+ continue;
12539
+ }
12540
+ }
12541
+ }
12542
+ for (const decName of ["ContentChild", "ContentChildren"]) {
12543
+ const dec = field.getDecorator(decName);
12544
+ if (dec) {
12545
+ const first = dec.getArguments()[0];
12546
+ const allowed = resolveClassIdentifierArg(first);
12547
+ out.push(buildSlot(fieldName, allowed));
12548
+ break;
12549
+ }
12550
+ }
12551
+ }
12552
+ return out;
12553
+ }
12554
+ function resolveClassIdentifierArg(arg) {
12555
+ if (!arg)
12556
+ return [];
12557
+ if (Node15.isStringLiteral(arg) || Node15.isNoSubstitutionTemplateLiteral(arg))
12558
+ return [];
12559
+ if (Node15.isIdentifier(arg))
12560
+ return [arg.getText()];
12561
+ return [];
12562
+ }
12563
+ function buildSlot(name, allowed) {
12564
+ const slot = {
12565
+ name,
12566
+ isDefault: false
12567
+ };
12568
+ if (allowed.length > 0)
12569
+ slot.allowedComponents = allowed;
12570
+ return slot;
12571
+ }
12572
+
12573
+ // packages/experience-design-system-backend-pipeline/dist/src/steps/extraction/src/framework-adapters/angular/helpers/slots/extract-template-ref-slots.js
12574
+ function extractTemplateRefSlots(props) {
12575
+ const nextProps = [];
12576
+ const slots = [];
12577
+ for (const prop of props) {
12578
+ const type = prop.type;
12579
+ const hasTemplateRef = /\bTemplateRef\b/.test(type);
12580
+ if (!hasTemplateRef) {
12581
+ nextProps.push(prop);
12582
+ continue;
12583
+ }
12584
+ const isPureTemplateRef = /^\s*TemplateRef<[^>]*>\s*(\|\s*(null|undefined)\s*)*$/.test(type);
12585
+ if (!isPureTemplateRef) {
12586
+ nextProps.push(prop);
12587
+ }
12588
+ slots.push({ name: prop.name, isDefault: false });
12589
+ }
12590
+ return { props: nextProps, slots };
12591
+ }
12592
+
12593
+ // packages/experience-design-system-backend-pipeline/dist/src/steps/extraction/src/framework-adapters/angular/helpers/slots/extract-slots.js
12594
+ async function extractSlots3(cls, meta, props) {
12595
+ const byName = /* @__PURE__ */ new Map();
12596
+ const template = await resolveTemplateSource(meta);
12597
+ if (template) {
12598
+ for (const el of parseNgContentElements(template)) {
12599
+ const name = deriveSlotName(el.rawSelect, meta.normalizedName);
12600
+ if (byName.has(name))
12601
+ continue;
12602
+ byName.set(name, {
12603
+ name,
12604
+ isDefault: el.rawSelect === null
12605
+ });
12606
+ }
12607
+ }
12608
+ for (const slot of extractContentChildQueries(cls)) {
12609
+ if (!byName.has(slot.name))
12610
+ byName.set(slot.name, slot);
12611
+ }
12612
+ const split = extractTemplateRefSlots(props);
12613
+ for (const slot of split.slots) {
12614
+ if (!byName.has(slot.name))
12615
+ byName.set(slot.name, slot);
12616
+ }
12617
+ return { props: split.props, slots: [...byName.values()] };
12618
+ }
12619
+
12620
+ // packages/experience-design-system-backend-pipeline/dist/src/steps/extraction/src/framework-adapters/angular/extract-angular-components.js
12621
+ async function extractAngularComponents(filePaths, onProgress, _opts) {
12622
+ const components = [];
12623
+ const warnings = [];
12624
+ let filesProcessed = 0;
12625
+ const project = new Project7({
12626
+ useInMemoryFileSystem: false,
12627
+ skipAddingFilesFromTsConfig: true,
12628
+ compilerOptions: {
12629
+ target: ScriptTarget2.ES2022,
12630
+ module: ModuleKind2.ESNext,
12631
+ experimentalDecorators: true,
12632
+ emitDecoratorMetadata: false,
12633
+ allowJs: false
12634
+ }
12635
+ });
12636
+ for (const filePath of filePaths) {
12637
+ try {
12638
+ const source = await readFile8(filePath, "utf8");
12639
+ const sourceFile = project.createSourceFile(filePath, source, { overwrite: true });
12640
+ for (const cls of sourceFile.getClasses()) {
12641
+ if (!hasComponentDecorator(cls))
12642
+ continue;
12643
+ if (!findComponentDecorator(cls)) {
12644
+ warnings.push(`${filePath}: ${cls.getName() ?? "<anonymous>"} has @Component with a non-literal argument; skipped.`);
12645
+ continue;
12646
+ }
12647
+ const meta = readComponentMetadata(cls, filePath);
12648
+ if (!meta)
12649
+ continue;
12650
+ const propsOnly = extractProps2(cls, meta);
12651
+ const { props, slots } = await extractSlots3(cls, meta, propsOnly);
12652
+ const partial = {
12653
+ name: meta.className,
12654
+ source: filePath,
12655
+ framework: "angular",
12656
+ props,
12657
+ slots: normalizeSlots(slots),
12658
+ sourcePath: filePath
12659
+ };
12660
+ const score = computeExtractionScore(partial);
12661
+ partial.extractionConfidence = score.confidence;
12662
+ partial.reviewReasons = score.reasons;
12663
+ partial.needsReview = deriveNeedsReview(score.confidence);
12664
+ components.push(partial);
12665
+ }
12666
+ sourceFile.forget();
12667
+ } catch (err) {
12668
+ warnings.push(`${filePath}: Angular extractor failed \u2014 ${err instanceof Error ? err.message : String(err)}`);
12669
+ } finally {
12670
+ filesProcessed++;
12671
+ if (onProgress)
12672
+ onProgress({ filesProcessed, componentsFound: components.length });
12673
+ }
12674
+ }
12675
+ return {
12676
+ components: components.sort((a, b) => a.name.localeCompare(b.name)),
12677
+ warnings
12678
+ };
12679
+ }
12680
+ function normalizeSlots(slots) {
12681
+ let fallbackIndex = 0;
12682
+ return slots.map((slot) => {
12683
+ if (slot.name.trim())
12684
+ return slot;
12685
+ const name = fallbackIndex === 0 ? "children" : `slot_${fallbackIndex}`;
12686
+ fallbackIndex++;
12687
+ return { ...slot, name };
12688
+ });
12689
+ }
12690
+
12691
+ // packages/experience-design-system-backend-pipeline/dist/src/steps/extraction/src/framework-adapters/angular/helpers/is-angular-source-file.js
12692
+ import { openSync, readSync, closeSync, statSync as statSync4 } from "node:fs";
12693
+ var HEAD_BYTES = 32 * 1024;
12694
+ var buffer = Buffer.alloc(HEAD_BYTES);
12695
+ function isAngularSourceFile(filePath) {
12696
+ if (!/\.[cm]?ts$/.test(filePath))
12697
+ return false;
12698
+ if (filePath.endsWith(".d.ts"))
12699
+ return false;
12700
+ try {
12701
+ const stats = statSync4(filePath);
12702
+ const toRead = Math.min(HEAD_BYTES, stats.size);
12703
+ if (toRead === 0)
12704
+ return false;
12705
+ const fd = openSync(filePath, "r");
12706
+ try {
12707
+ const bytesRead = readSync(fd, buffer, 0, toRead, 0);
12708
+ const head = buffer.subarray(0, bytesRead).toString("utf8");
12709
+ return head.includes("@angular/core");
12710
+ } finally {
12711
+ closeSync(fd);
12712
+ }
12713
+ } catch {
12714
+ return false;
12715
+ }
12716
+ }
12717
+
11985
12718
  // packages/experience-design-system-backend-pipeline/dist/src/steps/extraction/src/services/run-extraction-service.js
11986
12719
  var extractors = [
11987
12720
  {
@@ -12009,6 +12742,13 @@ var extractors = [
12009
12742
  fileFilter: (f) => f.endsWith(".astro"),
12010
12743
  extract: extractAstroComponents
12011
12744
  },
12745
+ {
12746
+ // Must run BEFORE web-components (both claim bare .ts). The sniff reads
12747
+ // the file head looking for `@angular/core` so we only claim real Angular files.
12748
+ name: "angular",
12749
+ fileFilter: (f) => isAngularSourceFile(f),
12750
+ extract: extractAngularComponents
12751
+ },
12012
12752
  {
12013
12753
  name: "web-components",
12014
12754
  fileFilter: (f) => /\.[jt]s$/.test(f) && !/\.[jt]sx$/.test(f) && !f.endsWith(".d.ts"),
@@ -12484,16 +13224,16 @@ function applyCompositionEdges(components, edges) {
12484
13224
 
12485
13225
  // packages/experience-design-system-backend-pipeline/dist/src/steps/composition/src/helpers/prompt/prompt-loader.js
12486
13226
  import { existsSync as existsSync7, readFileSync as readFileSync7 } from "node:fs";
12487
- import { dirname as dirname10, join as join10, resolve as resolve12 } from "node:path";
13227
+ import { dirname as dirname11, join as join10, resolve as resolve13 } from "node:path";
12488
13228
  import { fileURLToPath as fileURLToPath3 } from "node:url";
12489
13229
  function resolvePromptPath(fileName) {
12490
- const thisDir = dirname10(fileURLToPath3(import.meta.url));
13230
+ const thisDir = dirname11(fileURLToPath3(import.meta.url));
12491
13231
  let dir = thisDir;
12492
13232
  for (; ; ) {
12493
13233
  const candidate = join10(dir, "prompts");
12494
13234
  if (existsSync7(candidate))
12495
13235
  return join10(candidate, fileName);
12496
- const parent = resolve12(dir, "..");
13236
+ const parent = resolve13(dir, "..");
12497
13237
  if (parent === dir) {
12498
13238
  throw new Error(`prompt file missing from package installation (could not locate prompts/ directory from: ${thisDir})`);
12499
13239
  }
@@ -12573,14 +13313,31 @@ ${f.content}`).join("\n\n");
12573
13313
  }
12574
13314
 
12575
13315
  // packages/experience-design-system-backend-pipeline/dist/src/steps/composition/src/constants/candidate-files.js
12576
- var CANDIDATE_NAME_PATTERNS = [/mapping/i, /meta/i, /registry/i, /schema/i, /composition/i];
13316
+ var CANDIDATE_NAME_PATTERNS = [
13317
+ /mapping/i,
13318
+ /meta/i,
13319
+ /registry/i,
13320
+ /schema/i,
13321
+ /composition/i,
13322
+ /\.module\.ts$/i,
13323
+ /\.component\.ts$/i,
13324
+ /public[-_]api\.ts$/i,
13325
+ /^index\.ts$/i
13326
+ ];
12577
13327
  var CANDIDATE_CONTENT_MARKERS = [
12578
13328
  "requiredParent",
12579
13329
  "withParentType",
12580
13330
  "allowedTagNames",
12581
13331
  "createContext",
12582
13332
  "MappingContext",
12583
- "allowedComponents"
13333
+ "allowedComponents",
13334
+ "TemplateRef",
13335
+ "NG_VALUE_ACCESSOR",
13336
+ "ContentChild",
13337
+ "contentChild",
13338
+ "ng-content",
13339
+ "@NgModule",
13340
+ "standalone: true"
12584
13341
  ];
12585
13342
  var PROMPT_CANDIDATE_TOKEN_BUDGET = 8e4;
12586
13343
 
@@ -12641,8 +13398,8 @@ ${fileDigest}`);
12641
13398
  }
12642
13399
 
12643
13400
  // packages/experience-design-system-backend-pipeline/dist/src/steps/composition/src/helpers/edges/manifest-doc-evidence.js
12644
- import { dirname as dirname11 } from "node:path";
12645
- function kebabToPascal2(name) {
13401
+ import { dirname as dirname12 } from "node:path";
13402
+ function kebabToPascal3(name) {
12646
13403
  return name.split("-").filter(Boolean).map((seg) => seg.charAt(0).toUpperCase() + seg.slice(1)).join("");
12647
13404
  }
12648
13405
  function collectManifestEdges(files, componentNames) {
@@ -12664,7 +13421,7 @@ function collectManifestEdges(files, componentNames) {
12664
13421
  const rawParentName = typeof component === "object" && component !== null && typeof component.name === "string" ? component.name : void 0;
12665
13422
  if (!rawParentName)
12666
13423
  continue;
12667
- const parent = kebabToPascal2(rawParentName);
13424
+ const parent = kebabToPascal3(rawParentName);
12668
13425
  if (!componentNames.has(parent))
12669
13426
  continue;
12670
13427
  const variantsMeta = root.variantsMeta;
@@ -12684,7 +13441,7 @@ function collectManifestEdges(files, componentNames) {
12684
13441
  const rawChildName = value.name;
12685
13442
  if (typeof rawChildName !== "string")
12686
13443
  continue;
12687
- const child = kebabToPascal2(rawChildName);
13444
+ const child = kebabToPascal3(rawChildName);
12688
13445
  if (!componentNames.has(child) || child === parent)
12689
13446
  continue;
12690
13447
  const key = `${parent}::${child}`;
@@ -12705,8 +13462,8 @@ function collectAgentsDocEdges(files, components, componentNames) {
12705
13462
  for (const file of files) {
12706
13463
  if (!file.path.endsWith("AGENTS.md"))
12707
13464
  continue;
12708
- const docDir = dirname11(file.path);
12709
- const parent = components.find((c2) => c2.sourcePath && dirname11(c2.sourcePath) === docDir)?.name;
13465
+ const docDir = dirname12(file.path);
13466
+ const parent = components.find((c2) => c2.sourcePath && dirname12(c2.sourcePath) === docDir)?.name;
12710
13467
  if (!parent || !componentNames.has(parent))
12711
13468
  continue;
12712
13469
  for (const line of file.content.split("\n")) {
@@ -12715,7 +13472,7 @@ function collectAgentsDocEdges(files, components, componentNames) {
12715
13472
  continue;
12716
13473
  for (const match2 of line.matchAll(BOLD_BACKTICK)) {
12717
13474
  const raw = match2[1];
12718
- const candidate = componentNames.has(raw) ? raw : kebabToPascal2(raw);
13475
+ const candidate = componentNames.has(raw) ? raw : kebabToPascal3(raw);
12719
13476
  if (!componentNames.has(candidate) || candidate === parent)
12720
13477
  continue;
12721
13478
  const key = `${parent}::${candidate}`;
@@ -13031,7 +13788,7 @@ function validateExtractedComponents(components) {
13031
13788
  }
13032
13789
 
13033
13790
  // packages/experience-design-system-backend-pipeline/dist/src/persistence/src/review-session/helpers/load-review-input.js
13034
- import { resolve as resolve14 } from "node:path";
13791
+ import { resolve as resolve15 } from "node:path";
13035
13792
 
13036
13793
  // packages/experience-design-system-backend-pipeline/dist/src/persistence/src/review-session/helpers/create-component-id.js
13037
13794
  import { createHash as createHash7 } from "node:crypto";
@@ -13042,7 +13799,7 @@ function createComponentId(name, resolvedSourcePath) {
13042
13799
 
13043
13800
  // packages/experience-design-system-backend-pipeline/dist/src/persistence/src/review-session/helpers/resolve-component-source-path.js
13044
13801
  import { access } from "node:fs/promises";
13045
- import { isAbsolute, relative, resolve as resolve13 } from "node:path";
13802
+ import { isAbsolute, relative, resolve as resolve14 } from "node:path";
13046
13803
  async function resolveComponentSourcePath(source, reviewRoot) {
13047
13804
  if (isAbsolute(source)) {
13048
13805
  try {
@@ -13052,7 +13809,7 @@ async function resolveComponentSourcePath(source, reviewRoot) {
13052
13809
  throw new Error(`Unable to access component source at ${source}`);
13053
13810
  }
13054
13811
  }
13055
- const candidate = resolve13(reviewRoot, source);
13812
+ const candidate = resolve14(reviewRoot, source);
13056
13813
  const relativeToRoot = relative(reviewRoot, candidate);
13057
13814
  if (relativeToRoot.startsWith("..") || relativeToRoot === ".." || isAbsolute(relativeToRoot)) {
13058
13815
  throw new Error(`Resolved component source is outside the review root: ${source}. Pass --project-root <path> to set the correct base.`);
@@ -13067,7 +13824,7 @@ async function resolveComponentSourcePath(source, reviewRoot) {
13067
13824
 
13068
13825
  // packages/experience-design-system-backend-pipeline/dist/src/persistence/src/review-session/helpers/load-review-input.js
13069
13826
  async function loadReviewInput(components, options = {}) {
13070
- const reviewRoot = resolve14(options.reviewRoot ?? process.cwd());
13827
+ const reviewRoot = resolve15(options.reviewRoot ?? process.cwd());
13071
13828
  const records = await Promise.all(components.map(async (component) => {
13072
13829
  let resolvedSourcePath;
13073
13830
  try {
@@ -13102,19 +13859,19 @@ async function loadAndValidateForReview(sessionId, projectRoot) {
13102
13859
  }
13103
13860
 
13104
13861
  // packages/experience-design-system-backend-pipeline/dist/src/steps/selection/src/controller/review/merge-preview-validation-errors-into-review-session.js
13105
- import { access as access3, readFile as readFile8 } from "node:fs/promises";
13862
+ import { access as access3, readFile as readFile10 } from "node:fs/promises";
13106
13863
 
13107
13864
  // packages/experience-design-system-backend-pipeline/dist/src/persistence/src/review-session/repositories/ensure-review-session.js
13108
- import { access as access2, mkdir, readFile as readFile7, writeFile } from "node:fs/promises";
13865
+ import { access as access2, mkdir, readFile as readFile9, writeFile } from "node:fs/promises";
13109
13866
 
13110
13867
  // packages/experience-design-system-backend-pipeline/dist/src/persistence/src/review-session/repositories/review-session-paths.js
13111
- import { resolve as resolve15 } from "node:path";
13868
+ import { resolve as resolve16 } from "node:path";
13112
13869
  async function getRefineSessionPaths(sessionId, artifactsRoot) {
13113
- const sessionDir2 = resolve15(artifactsRoot, sessionId);
13870
+ const sessionDir2 = resolve16(artifactsRoot, sessionId);
13114
13871
  return {
13115
13872
  sessionDir: sessionDir2,
13116
- eventsPath: resolve15(sessionDir2, "events.jsonl"),
13117
- statePath: resolve15(sessionDir2, "current-review-state.json")
13873
+ eventsPath: resolve16(sessionDir2, "events.jsonl"),
13874
+ statePath: resolve16(sessionDir2, "current-review-state.json")
13118
13875
  };
13119
13876
  }
13120
13877
 
@@ -13124,7 +13881,7 @@ async function ensureRefineSession(sessionId, artifactsRoot, initialSnapshot) {
13124
13881
  await mkdir(paths.sessionDir, { recursive: true });
13125
13882
  try {
13126
13883
  await access2(paths.statePath);
13127
- const savedState = await readFile7(paths.statePath, "utf8");
13884
+ const savedState = await readFile9(paths.statePath, "utf8");
13128
13885
  return JSON.parse(savedState);
13129
13886
  } catch {
13130
13887
  await writeFile(paths.statePath, JSON.stringify(initialSnapshot, null, 2), "utf8");
@@ -13134,12 +13891,12 @@ async function ensureRefineSession(sessionId, artifactsRoot, initialSnapshot) {
13134
13891
  }
13135
13892
 
13136
13893
  // packages/experience-design-system-backend-pipeline/dist/src/persistence/src/review-session/repositories/review-artifacts-root.js
13137
- import { resolve as resolve16 } from "node:path";
13894
+ import { resolve as resolve17 } from "node:path";
13138
13895
  function getRefineArtifactsRoot() {
13139
13896
  if (process.env["EDS_REVIEW_ARTIFACTS_DIR"]) {
13140
- return resolve16(process.env["EDS_REVIEW_ARTIFACTS_DIR"]);
13897
+ return resolve17(process.env["EDS_REVIEW_ARTIFACTS_DIR"]);
13141
13898
  }
13142
- return resolve16(configRoot(), "reviews");
13899
+ return resolve17(configRoot(), "reviews");
13143
13900
  }
13144
13901
 
13145
13902
  // packages/experience-design-system-backend-pipeline/dist/src/persistence/src/review-session/repositories/save-review-state.js
@@ -13155,7 +13912,7 @@ async function mergePreviewValidationErrorsIntoReviewSession(sessionId, errors,
13155
13912
  let snapshot;
13156
13913
  try {
13157
13914
  await access3(paths.statePath);
13158
- snapshot = JSON.parse(await readFile8(paths.statePath, "utf8"));
13915
+ snapshot = JSON.parse(await readFile10(paths.statePath, "utf8"));
13159
13916
  } catch {
13160
13917
  snapshot = await loadAndValidateForReview(sessionId, void 0);
13161
13918
  snapshot = await ensureRefineSession(sessionId, artifactsRoot, snapshot);
@@ -13193,7 +13950,7 @@ async function mergePreviewValidationErrorsIntoReviewSession(sessionId, errors,
13193
13950
  }
13194
13951
 
13195
13952
  // packages/experience-design-system-backend-pipeline/dist/src/steps/selection/src/controller/review/reject-components-by-name.js
13196
- import { readFile as readFile9 } from "node:fs/promises";
13953
+ import { readFile as readFile11 } from "node:fs/promises";
13197
13954
  async function rejectComponentsByName(sessionId, names, opts = {}) {
13198
13955
  if (names.length === 0)
13199
13956
  return;
@@ -13209,7 +13966,7 @@ async function rejectComponentsByName(sessionId, names, opts = {}) {
13209
13966
  const nameSet = new Set(names);
13210
13967
  let snapshot;
13211
13968
  try {
13212
- snapshot = JSON.parse(await readFile9(paths.statePath, "utf8"));
13969
+ snapshot = JSON.parse(await readFile11(paths.statePath, "utf8"));
13213
13970
  } catch {
13214
13971
  return;
13215
13972
  }
@@ -13218,7 +13975,7 @@ async function rejectComponentsByName(sessionId, names, opts = {}) {
13218
13975
  }
13219
13976
 
13220
13977
  // packages/experience-design-system-backend-pipeline/dist/src/persistence/src/helpers/collect-files/collect-files.js
13221
- import { statSync as statSync4 } from "node:fs";
13978
+ import { statSync as statSync5 } from "node:fs";
13222
13979
  import path4 from "node:path";
13223
13980
 
13224
13981
  // packages/experience-design-system-backend-pipeline/dist/src/persistence/src/helpers/collect-files/build-scan-warnings.js
@@ -13273,7 +14030,9 @@ var EXCLUDED_SUFFIXES = [
13273
14030
  ".spec.ts",
13274
14031
  ".spec.tsx",
13275
14032
  ".test.ts",
13276
- ".test.tsx"
14033
+ ".test.tsx",
14034
+ ".harness.ts",
14035
+ ".harness.tsx"
13277
14036
  ];
13278
14037
  var IGNORED_DIRS = /* @__PURE__ */ new Set([
13279
14038
  ".changeset",
@@ -13291,9 +14050,12 @@ var IGNORED_DIRS = /* @__PURE__ */ new Set([
13291
14050
  "dist",
13292
14051
  "example",
13293
14052
  "examples",
14053
+ "harness",
14054
+ "harnesses",
13294
14055
  "node_modules",
13295
14056
  "out",
13296
- "storybook-static"
14057
+ "storybook-static",
14058
+ "testing"
13297
14059
  ]);
13298
14060
  var DENYLISTED_EXACT_FILE_NAMES = /* @__PURE__ */ new Set([
13299
14061
  "package.json",
@@ -13405,7 +14167,7 @@ function collectFiles(root, options = {}) {
13405
14167
  const resolved = path4.resolve(root);
13406
14168
  let stat5;
13407
14169
  try {
13408
- stat5 = statSync4(resolved);
14170
+ stat5 = statSync5(resolved);
13409
14171
  } catch (err) {
13410
14172
  return { ok: false, failure: classifyStatError(err.code), rootPath: resolved };
13411
14173
  }
@@ -13461,7 +14223,7 @@ function generateUlid(now = Date.now()) {
13461
14223
  }
13462
14224
 
13463
14225
  // packages/experience-design-system-backend-pipeline/dist/src/persistence/src/runs/repositories/read-runs-file.js
13464
- import { readFile as readFile10 } from "node:fs/promises";
14226
+ import { readFile as readFile12 } from "node:fs/promises";
13465
14227
 
13466
14228
  // packages/experience-design-system-backend-pipeline/dist/src/persistence/src/runs/helpers/migrate-record.js
13467
14229
  function migrateRecord(rec) {
@@ -13480,7 +14242,7 @@ var READABLE_VERSIONS = /* @__PURE__ */ new Set([1, 2, 3]);
13480
14242
  // packages/experience-design-system-backend-pipeline/dist/src/persistence/src/runs/repositories/read-runs-file.js
13481
14243
  async function readRunsFileMaybe() {
13482
14244
  try {
13483
- const raw = await readFile10(runsFilePath(), "utf8");
14245
+ const raw = await readFile12(runsFilePath(), "utf8");
13484
14246
  const parsed = JSON.parse(raw);
13485
14247
  if (!READABLE_VERSIONS.has(parsed.version)) {
13486
14248
  throw new Error(`runs.json version mismatch: file is v${parsed.version}, this CLI expects v${RUNS_FILE_VERSION} (also reads: ${[...READABLE_VERSIONS].join(", ")}). Back up and remove the file to start fresh.`);
@@ -13497,9 +14259,9 @@ async function readRunsFileMaybe() {
13497
14259
 
13498
14260
  // packages/experience-design-system-backend-pipeline/dist/src/persistence/src/runs/repositories/write-runs-file.js
13499
14261
  import { mkdir as mkdir2, rename, writeFile as writeFile3 } from "node:fs/promises";
13500
- import { dirname as dirname12 } from "node:path";
14262
+ import { dirname as dirname13 } from "node:path";
13501
14263
  async function writeRunsFileAtomic(file) {
13502
- await mkdir2(dirname12(runsFilePath()), { recursive: true });
14264
+ await mkdir2(dirname13(runsFilePath()), { recursive: true });
13503
14265
  const body = JSON.stringify(file, null, 2) + "\n";
13504
14266
  const tmp = `${runsFilePath()}.${process.pid}.${Date.now()}.tmp`;
13505
14267
  await writeFile3(tmp, body, { mode: 384 });
@@ -13539,8 +14301,8 @@ async function updateRun(id, patch) {
13539
14301
  }
13540
14302
 
13541
14303
  // packages/experience-design-system-backend-pipeline/dist/src/persistence/src/runs/services/build-source-fingerprint.js
13542
- import { readFile as readFile11, stat } from "node:fs/promises";
13543
- import { resolve as resolve17 } from "node:path";
14304
+ import { readFile as readFile13, stat } from "node:fs/promises";
14305
+ import { resolve as resolve18 } from "node:path";
13544
14306
 
13545
14307
  // packages/experience-design-system-backend-pipeline/dist/src/persistence/src/runs/helpers/sha256-hex.js
13546
14308
  import { createHash as createHash8 } from "node:crypto";
@@ -13562,7 +14324,7 @@ async function buildSourceFingerprint(opts) {
13562
14324
  const name = rowField(row, "name");
13563
14325
  if (!sourcePath)
13564
14326
  continue;
13565
- const abs = resolve17(sourcePath);
14327
+ const abs = resolve18(sourcePath);
13566
14328
  if (seen.has(abs))
13567
14329
  continue;
13568
14330
  seen.add(abs);
@@ -13579,10 +14341,10 @@ async function buildSourceFingerprint(opts) {
13579
14341
  let rawTokensMtime = null;
13580
14342
  let rawTokensContentHash = null;
13581
14343
  if (opts.rawTokensPath) {
13582
- const abs = resolve17(opts.rawTokensPath);
14344
+ const abs = resolve18(opts.rawTokensPath);
13583
14345
  rawTokensPath = abs;
13584
14346
  try {
13585
- const [st, buf] = await Promise.all([stat(abs), readFile11(abs)]);
14347
+ const [st, buf] = await Promise.all([stat(abs), readFile13(abs)]);
13586
14348
  rawTokensMtime = st.mtime.toISOString();
13587
14349
  rawTokensContentHash = sha256Hex(buf);
13588
14350
  } catch {
@@ -13664,12 +14426,12 @@ async function writeScopeDecisionsSnapshot(db, sessionId, decisions) {
13664
14426
  }
13665
14427
 
13666
14428
  // packages/experience-design-system-backend-pipeline/dist/src/persistence/src/review-session/repositories/load-accepted-names.js
13667
- import { readFile as readFile12 } from "node:fs/promises";
14429
+ import { readFile as readFile14 } from "node:fs/promises";
13668
14430
  async function loadAcceptedNames(sessionId) {
13669
14431
  try {
13670
14432
  const artifactsRoot = getRefineArtifactsRoot();
13671
14433
  const paths = await getRefineSessionPaths(sessionId, artifactsRoot);
13672
- const raw = await readFile12(paths.statePath, "utf8");
14434
+ const raw = await readFile14(paths.statePath, "utf8");
13673
14435
  const snapshot = JSON.parse(raw);
13674
14436
  const accepted = snapshot.components.filter((c2) => c2.status === "accepted").map((c2) => c2.name);
13675
14437
  if (accepted.length === 0)
@@ -14367,7 +15129,7 @@ function errorMessage(error) {
14367
15129
  return error instanceof Error && error.message ? error.message : String(error);
14368
15130
  }
14369
15131
  function defaultSleep(delayMs) {
14370
- return new Promise((resolve28) => setTimeout(resolve28, delayMs));
15132
+ return new Promise((resolve29) => setTimeout(resolve29, delayMs));
14371
15133
  }
14372
15134
 
14373
15135
  // packages/experience-design-system-backend-pipeline/dist/src/steps/apply/src/helpers/sanitize-preview.js
@@ -14608,7 +15370,7 @@ var ApiClient = class {
14608
15370
  const progress = maxAttempts > 1 ? attempt / (maxAttempts - 1) : 0;
14609
15371
  const baseDelay = intervalMs + (maxIntervalMs - intervalMs) * progress;
14610
15372
  const jitter = Math.random() * baseDelay * 0.15;
14611
- await new Promise((resolve28) => setTimeout(resolve28, baseDelay + jitter));
15373
+ await new Promise((resolve29) => setTimeout(resolve29, baseDelay + jitter));
14612
15374
  }
14613
15375
  }
14614
15376
  throw new Error(`Operation ${operationId} timed out after ${maxAttempts} attempts`);
@@ -14995,7 +15757,7 @@ function formatApiError2(request) {
14995
15757
 
14996
15758
  // packages/experience-design-system-backend-pipeline/dist/src/steps/apply/src/helpers/tokens/read-tokens-from-path.js
14997
15759
  init_shared();
14998
- import { readFile as readFile13, stat as stat3 } from "node:fs/promises";
15760
+ import { readFile as readFile15, stat as stat3 } from "node:fs/promises";
14999
15761
 
15000
15762
  // packages/experience-design-system-backend-pipeline/dist/src/steps/apply/src/helpers/tokens/collect-json-files.js
15001
15763
  import { readdir, stat as stat2 } from "node:fs/promises";
@@ -15054,7 +15816,7 @@ async function readMergedFromDir(flag, dir) {
15054
15816
  const merged = {};
15055
15817
  for (const file of files.sort()) {
15056
15818
  try {
15057
- const text = await readFile13(file, "utf8");
15819
+ const text = await readFile15(file, "utf8");
15058
15820
  const parsed = JSON.parse(text);
15059
15821
  if (typeof parsed === "object" && parsed !== null && !Array.isArray(parsed)) {
15060
15822
  Object.assign(merged, parsed);
@@ -15068,7 +15830,7 @@ async function readMergedFromDir(flag, dir) {
15068
15830
  async function readSingleFile(flag, p) {
15069
15831
  let text;
15070
15832
  try {
15071
- text = await readFile13(p, "utf8");
15833
+ text = await readFile15(p, "utf8");
15072
15834
  } catch {
15073
15835
  throw new Error(`file not found: ${p} (from ${flag})`);
15074
15836
  }
@@ -15159,12 +15921,12 @@ async function fetchAndPersistExistingContentfulEntities(request) {
15159
15921
  }
15160
15922
 
15161
15923
  // packages/experience-design-system-backend-pipeline/dist/src/steps/generation/src/controller/existing-entities/read-from-session.js
15162
- import { readFile as readFile14 } from "node:fs/promises";
15924
+ import { readFile as readFile16 } from "node:fs/promises";
15163
15925
  async function readExistingContentfulEntitiesFromSession(request) {
15164
15926
  if (!request.path)
15165
15927
  return void 0;
15166
15928
  try {
15167
- const raw = await readFile14(request.path, "utf8");
15929
+ const raw = await readFile16(request.path, "utf8");
15168
15930
  const parsed = JSON.parse(raw);
15169
15931
  if (!Array.isArray(parsed.components) || !Array.isArray(parsed.tokens))
15170
15932
  return void 0;
@@ -15504,7 +16266,7 @@ init_describe_agent_failure();
15504
16266
  init_resolve_binary();
15505
16267
  init_resolve_skill_path();
15506
16268
  init_parse_map_token_prop_tool_calls();
15507
- import { resolve as resolve18 } from "node:path";
16269
+ import { resolve as resolve19 } from "node:path";
15508
16270
  init_cache_keys();
15509
16271
 
15510
16272
  // packages/experience-design-system-backend-pipeline/dist/src/agents/helpers/resolution/binary-exists.js
@@ -15559,6 +16321,7 @@ function analyticsEnabled() {
15559
16321
  import { Analytics } from "@segment/analytics-node";
15560
16322
  var DEFAULT_WRITE_KEY = "6DmxiEPN3SV1vbRTTMcNqDzCvkfwT06N";
15561
16323
  var analyticsClient = null;
16324
+ var flushChain = Promise.resolve();
15562
16325
  function resolveWriteKey() {
15563
16326
  const key = (process.env["SEGMENT_WRITE_KEY"] ?? "").trim();
15564
16327
  return key.length > 0 ? key : DEFAULT_WRITE_KEY;
@@ -15593,14 +16356,17 @@ async function trackEvent(event, properties, anonymousId, options) {
15593
16356
  }
15594
16357
  }
15595
16358
  async function flushAnalytics() {
15596
- if (!analyticsClient)
15597
- return;
15598
- try {
15599
- await analyticsClient.closeAndFlush();
15600
- } catch {
15601
- } finally {
16359
+ flushChain = flushChain.then(async () => {
16360
+ const client2 = analyticsClient;
16361
+ if (!client2)
16362
+ return;
15602
16363
  analyticsClient = null;
15603
- }
16364
+ try {
16365
+ await client2.closeAndFlush();
16366
+ } catch {
16367
+ }
16368
+ });
16369
+ return flushChain;
15604
16370
  }
15605
16371
 
15606
16372
  // packages/experience-design-system-backend-pipeline/dist/src/analytics/constants.js
@@ -15809,7 +16575,7 @@ async function runMapTokens(request) {
15809
16575
  outDir: process.cwd(),
15810
16576
  existingTokensInline: request.existingEntitiesInline,
15811
16577
  ...request.skillContentOverride !== void 0 ? { skillContentOverride: request.skillContentOverride } : {},
15812
- ...request.skillContentOverride === void 0 && request.skillPathOverride ? { skillPathOverride: resolve18(request.skillPathOverride) } : {}
16578
+ ...request.skillContentOverride === void 0 && request.skillPathOverride ? { skillPathOverride: resolve19(request.skillPathOverride) } : {}
15813
16579
  });
15814
16580
  if (request.printPrompt) {
15815
16581
  const prompt2 = await buildMapPrompt();
@@ -15925,7 +16691,7 @@ function hasNoAuthoringSurface(component) {
15925
16691
  }
15926
16692
 
15927
16693
  // packages/experience-design-system-backend-pipeline/dist/src/steps/extraction/src/helpers/evidence/source-inspection.js
15928
- import { readFile as readFile15 } from "node:fs/promises";
16694
+ import { readFile as readFile17 } from "node:fs/promises";
15929
16695
 
15930
16696
  // packages/experience-design-system-backend-pipeline/dist/src/steps/extraction/src/constants/review-reasons.js
15931
16697
  var HIGH_CONFIDENCE_DATA_FETCH_WRAPPER_REASON = "data-fetch-wrapper";
@@ -15997,7 +16763,14 @@ function hasSiblingForwardRender(sourceText, siblingImports) {
15997
16763
  });
15998
16764
  }
15999
16765
  function hasVisibleUiRender(sourceText) {
16000
- return /return\s*(?:\(|<)/.test(sourceText) && VISIBLE_UI_TAG_PATTERN.test(sourceText);
16766
+ if (/return\s*(?:\(|<)/.test(sourceText) && VISIBLE_UI_TAG_PATTERN.test(sourceText))
16767
+ return true;
16768
+ if (/template\s*:\s*[`'"][\s\S]*?[`'"]/.test(sourceText)) {
16769
+ const inlineMatch = sourceText.match(/template\s*:\s*[`'"]([\s\S]*?)[`'"]/);
16770
+ if (inlineMatch && VISIBLE_UI_TAG_PATTERN.test(inlineMatch[1]))
16771
+ return true;
16772
+ }
16773
+ return /templateUrl\s*:\s*['"]/.test(sourceText);
16001
16774
  }
16002
16775
  function infraPropNames(component) {
16003
16776
  const props = component.props.map((prop) => prop.name);
@@ -16020,7 +16793,7 @@ function dedupeReasons(reasons) {
16020
16793
  async function inspectComponentSource(component) {
16021
16794
  let sourceText = "";
16022
16795
  try {
16023
- sourceText = await readFile15(component.source, "utf8");
16796
+ sourceText = await readFile17(component.source, "utf8");
16024
16797
  } catch {
16025
16798
  return {
16026
16799
  wrapperConfidence: 0,
@@ -16427,7 +17200,7 @@ async function retryDatabaseWrite(operation, attempts = 8) {
16427
17200
  const message = error instanceof Error ? error.message : String(error);
16428
17201
  if (!/database is locked|database is busy/i.test(message) || attempt >= attempts)
16429
17202
  throw error;
16430
- await new Promise((resolve28) => setTimeout(resolve28, Math.min(250 * attempt, 2e3)));
17203
+ await new Promise((resolve29) => setTimeout(resolve29, Math.min(250 * attempt, 2e3)));
16431
17204
  }
16432
17205
  }
16433
17206
  }
@@ -16459,7 +17232,7 @@ function resolveCompositionAgentName(flagValue) {
16459
17232
  }
16460
17233
 
16461
17234
  // packages/experience-design-system-backend-pipeline/dist/src/orchestrators/run-extract-and-compose-session/helpers/read-candidate-files.js
16462
- import { readFile as readFile16 } from "node:fs/promises";
17235
+ import { readFile as readFile18 } from "node:fs/promises";
16463
17236
  async function readCandidateFiles(components, extraFiles = []) {
16464
17237
  const paths = new Set(extraFiles);
16465
17238
  for (const c2 of components) {
@@ -16469,7 +17242,7 @@ async function readCandidateFiles(components, extraFiles = []) {
16469
17242
  const out = [];
16470
17243
  await Promise.all([...paths].map(async (p) => {
16471
17244
  try {
16472
- const content = await readFile16(p, "utf8");
17245
+ const content = await readFile18(p, "utf8");
16473
17246
  out.push({ path: p, content });
16474
17247
  } catch {
16475
17248
  }
@@ -16640,7 +17413,7 @@ init_build_prompt();
16640
17413
  init_create_local_cli_agent_invoker();
16641
17414
  init_invoke_agent_with_output();
16642
17415
  init_parse_token_tool_calls();
16643
- import { readFile as readFile17 } from "node:fs/promises";
17416
+ import { readFile as readFile19 } from "node:fs/promises";
16644
17417
  import { basename as basename5, resolve as pathResolve } from "node:path";
16645
17418
  init_cache_keys();
16646
17419
  init_parse_prompt_overrides();
@@ -16673,7 +17446,7 @@ async function runGenerateTokensSession(request) {
16673
17446
  throw new Error(`Prompt override error(s): ${promptErrors.join("; ")}`);
16674
17447
  const tokensOverride = overridesMap.get("tokens");
16675
17448
  const skillContentOverride = tokensOverride ? await resolvePromptOverride(tokensOverride) : void 0;
16676
- const rawTokensInline = await readFile17(pathResolve(rawTokensPath), "utf8");
17449
+ const rawTokensInline = await readFile19(pathResolve(rawTokensPath), "utf8");
16677
17450
  const tokenInputHash = hashTokenContent(rawTokensInline);
16678
17451
  const db = openPipelineDb();
16679
17452
  try {
@@ -16790,7 +17563,7 @@ async function readExistingEntities(request) {
16790
17563
  // packages/experience-design-system-backend-pipeline/dist/src/orchestrators/run-generate-components-session/helpers/resolve-generate-prompt.js
16791
17564
  init_parse_prompt_overrides();
16792
17565
  init_resolve_prompt_override();
16793
- import { resolve as resolve19 } from "node:path";
17566
+ import { resolve as resolve20 } from "node:path";
16794
17567
  async function resolveGeneratePrompt(overrides) {
16795
17568
  const { overrides: parsed, errors } = parsePromptOverrides(overrides);
16796
17569
  if (errors.length > 0)
@@ -16801,7 +17574,7 @@ async function resolveGeneratePrompt(overrides) {
16801
17574
  const text = await resolvePromptOverride(entry);
16802
17575
  if (entry.kind === "text")
16803
17576
  return { text };
16804
- return { path: resolve19(entry.value), text };
17577
+ return { path: resolve20(entry.value), text };
16805
17578
  }
16806
17579
 
16807
17580
  // packages/experience-design-system-backend-pipeline/dist/src/orchestrators/run-generate-components-session/helpers/run-one-generate-component.js
@@ -17709,19 +18482,19 @@ import { useEffect as useEffect5, useRef as useRef3, useState as useState10 } fr
17709
18482
 
17710
18483
  // packages/experience-design-system-cli/src/tui/import/steps/06-extraction/run.ts
17711
18484
  import { mkdir as mkdir7 } from "node:fs/promises";
17712
- import { join as join18, resolve as resolve22 } from "node:path";
18485
+ import { join as join18, resolve as resolve23 } from "node:path";
17713
18486
 
17714
18487
  // packages/experience-design-system-cli/src/tui/import/steps/06-extraction/find-skill-path.ts
17715
18488
  import { existsSync as existsSync8 } from "node:fs";
17716
- import { dirname as dirname14, join as join17, resolve as resolve20 } from "node:path";
18489
+ import { dirname as dirname15, join as join17, resolve as resolve21 } from "node:path";
17717
18490
  import { fileURLToPath as fileURLToPath4 } from "node:url";
17718
18491
  function findSkillPath(fileName) {
17719
- const thisDir = dirname14(fileURLToPath4(import.meta.url));
18492
+ const thisDir = dirname15(fileURLToPath4(import.meta.url));
17720
18493
  let dir = thisDir;
17721
18494
  for (; ; ) {
17722
18495
  const candidate = join17(dir, "skills", fileName);
17723
18496
  if (existsSync8(candidate)) return candidate;
17724
- const parent = resolve20(dir, "..");
18497
+ const parent = resolve21(dir, "..");
17725
18498
  if (parent === dir) {
17726
18499
  throw new Error(`skill file not found (looked for skills/${fileName} from ${thisDir})`);
17727
18500
  }
@@ -17730,11 +18503,11 @@ function findSkillPath(fileName) {
17730
18503
  }
17731
18504
 
17732
18505
  // packages/experience-design-system-cli/src/tui/import/steps/06-extraction/selection.ts
17733
- import { resolve as resolve21 } from "node:path";
18506
+ import { resolve as resolve22 } from "node:path";
17734
18507
  var SELECT_SKILL_PATH = findSkillPath("select-components.md");
17735
18508
  var DEFAULT_TIMEOUT_MS5 = Number(process.env.EDS_AGENT_TIMEOUT_MS ?? 5 * 60 * 1e3);
17736
18509
  async function hashSelectPrompt(options) {
17737
- const promptHash = options.promptText ? hashContent(options.promptText) : options.promptPath ? await hashFile(resolve21(options.promptPath)) : await hashFile(SELECT_SKILL_PATH);
18510
+ const promptHash = options.promptText ? hashContent(options.promptText) : options.promptPath ? await hashFile(resolve22(options.promptPath)) : await hashFile(SELECT_SKILL_PATH);
17738
18511
  return hashContent(`${promptHash}|${options.agent}|${options.model ?? ""}`);
17739
18512
  }
17740
18513
  async function runSelection(options) {
@@ -17829,7 +18602,7 @@ var realDeps = {
17829
18602
  var fail = (step, message) => ({ ok: false, step, message });
17830
18603
  var errorMessage2 = (error) => error instanceof Error ? error.message : String(error);
17831
18604
  async function runExtraction(input, onProgress, deps = realDeps) {
17832
- const outDir = input.outDir ?? join18(resolve22(input.projectPath), ".contentful");
18605
+ const outDir = input.outDir ?? join18(resolve23(input.projectPath), ".contentful");
17833
18606
  let progress = initialProgress({
17834
18607
  hasCredentials: input.credentials !== null,
17835
18608
  hasRawTokens: input.rawTokensPath !== ""
@@ -17953,7 +18726,7 @@ async function resolveSelectionPrompt(overrides) {
17953
18726
  if (select?.kind === "text") return { promptText: select.value };
17954
18727
  if (select?.kind === "path") {
17955
18728
  await resolvePromptOverride(select);
17956
- return { promptPath: resolve22(select.value) };
18729
+ return { promptPath: resolve23(select.value) };
17957
18730
  }
17958
18731
  return {};
17959
18732
  }
@@ -20912,7 +21685,7 @@ function GenerationScreen({
20912
21685
  import { useEffect as useEffect10, useRef as useRef8, useState as useState17 } from "react";
20913
21686
 
20914
21687
  // packages/experience-design-system-cli/src/tui/import/steps/08-generation/run.ts
20915
- import { resolve as resolve23 } from "node:path";
21688
+ import { resolve as resolve24 } from "node:path";
20916
21689
 
20917
21690
  // packages/experience-design-system-cli/src/tui/import/steps/08-generation/map-tokens.ts
20918
21691
  async function prepareMapTokens(input, generatedSessionId) {
@@ -21047,7 +21820,7 @@ async function buildMapTokensOptions(input) {
21047
21820
  if (mapOverride?.kind === "text") prompt.skillContentOverride = mapOverride.value;
21048
21821
  if (mapOverride?.kind === "path") {
21049
21822
  await resolvePromptOverride(mapOverride);
21050
- prompt.skillPathOverride = resolve23(mapOverride.value);
21823
+ prompt.skillPathOverride = resolve24(mapOverride.value);
21051
21824
  }
21052
21825
  if (input.existingEntitiesPath) {
21053
21826
  const entities = await readExistingContentfulEntitiesFromSession({ path: input.existingEntitiesPath });
@@ -26852,10 +27625,10 @@ function DoneStep({
26852
27625
  import { useState as useState27 } from "react";
26853
27626
  import { Box as Box41, Text as Text43 } from "ink";
26854
27627
  import { readdirSync as readdirSync3 } from "node:fs";
26855
- import { dirname as dirname15, basename as basename6, join as join20 } from "node:path";
27628
+ import { dirname as dirname16, basename as basename6, join as join20 } from "node:path";
26856
27629
 
26857
27630
  // packages/experience-design-system-cli/src/tui/import/steps/10-flow/support/path-utils.ts
26858
- import { resolve as resolve24 } from "node:path";
27631
+ import { resolve as resolve25 } from "node:path";
26859
27632
  import { homedir as homedir4 } from "node:os";
26860
27633
  function expandTilde(input) {
26861
27634
  if (input === "~" || input.startsWith("~/") || input.startsWith("~\\")) {
@@ -26869,7 +27642,7 @@ function normalizePath(input) {
26869
27642
  p = p.slice(1, -1);
26870
27643
  }
26871
27644
  p = expandTilde(p);
26872
- return resolve24(p);
27645
+ return resolve25(p);
26873
27646
  }
26874
27647
 
26875
27648
  // packages/experience-design-system-cli/src/tui/import/steps/10-flow/support/use-blinking-cursor.ts
@@ -26888,7 +27661,7 @@ import { jsx as jsx51, jsxs as jsxs41 } from "react/jsx-runtime";
26888
27661
  function autocomplete(partial) {
26889
27662
  if (!partial) return null;
26890
27663
  const normalized = normalizePath(partial);
26891
- const dir = dirname15(normalized);
27664
+ const dir = dirname16(normalized);
26892
27665
  const base = basename6(normalized);
26893
27666
  let entries;
26894
27667
  try {
@@ -27652,7 +28425,7 @@ import { useEffect as useEffect21, useRef as useRef14, useSyncExternalStore } fr
27652
28425
  import { appendFileSync, writeFileSync } from "node:fs";
27653
28426
  import { mkdir as mkdir8 } from "node:fs/promises";
27654
28427
  import { tmpdir } from "node:os";
27655
- import { join as join22, resolve as resolve25 } from "node:path";
28428
+ import { join as join22, resolve as resolve26 } from "node:path";
27656
28429
 
27657
28430
  // packages/experience-design-system-cli/src/tui/import/steps/10-flow/support/wizard-state-transitions.ts
27658
28431
  function shouldBypassPreview(state2) {
@@ -28026,7 +28799,7 @@ var realSaveDeps = () => ({
28026
28799
  writeFile: (path5, contents) => writeFile7(path5, contents),
28027
28800
  appendRun,
28028
28801
  buildSourceFingerprint,
28029
- sleep: (ms) => new Promise((resolve28) => setTimeout(resolve28, ms)),
28802
+ sleep: (ms) => new Promise((resolve29) => setTimeout(resolve29, ms)),
28030
28803
  warn: (message) => process.stderr.write(message)
28031
28804
  });
28032
28805
  async function runPrintFiles(input, deps, onPatch) {
@@ -28365,7 +29138,7 @@ function createFlowController(start, deps) {
28365
29138
  },
28366
29139
  async submitPath(submitted) {
28367
29140
  await deps.mkdir(submitted);
28368
- if (resolve25(submitted) !== resolve25(state2.outDir) && await deps.detectSaveConflict(submitted)) {
29141
+ if (resolve26(submitted) !== resolve26(state2.outDir) && await deps.detectSaveConflict(submitted)) {
28369
29142
  const subdir = deps.buildTimestampedSubdir(submitted);
28370
29143
  await deps.mkdir(subdir);
28371
29144
  await proceedToWrite(subdir);
@@ -28423,7 +29196,7 @@ init_debug_mode_store();
28423
29196
  init_version();
28424
29197
 
28425
29198
  // packages/experience-design-system-cli/src/tui/help/file-locations.ts
28426
- import { join as join25, resolve as resolve27 } from "node:path";
29199
+ import { join as join25, resolve as resolve28 } from "node:path";
28427
29200
  function describeFileLocations({
28428
29201
  contentfulBaseDir,
28429
29202
  debugModeEnabled,
@@ -28435,7 +29208,7 @@ function describeFileLocations({
28435
29208
  importFiles: `${join25("<project>", ".contentful")}/ (tokens.json, components.json)`
28436
29209
  };
28437
29210
  }
28438
- const base = contentfulBaseDir ? resolve27(contentfulBaseDir) : "<project>";
29211
+ const base = contentfulBaseDir ? resolve28(contentfulBaseDir) : "<project>";
28439
29212
  const session = currentSessionDir2 ?? join25(base, ".contentful", "<date>-session-<n>");
28440
29213
  return {
28441
29214
  debugLogs: join25(session, "debug"),
@@ -28656,20 +29429,20 @@ function resolveOnPath(binary) {
28656
29429
  () => null
28657
29430
  );
28658
29431
  }
28659
- return new Promise((resolve28) => {
29432
+ return new Promise((resolve29) => {
28660
29433
  execFile2(
28661
29434
  process.platform === "win32" ? "where" : "which",
28662
29435
  [binary],
28663
- (error, stdout) => resolve28(error ? null : stdout.split("\n")[0]?.trim() ?? null)
29436
+ (error, stdout) => resolve29(error ? null : stdout.split("\n")[0]?.trim() ?? null)
28664
29437
  );
28665
29438
  });
28666
29439
  }
28667
29440
  function readVersion(binary) {
28668
- return new Promise((resolve28) => {
29441
+ return new Promise((resolve29) => {
28669
29442
  execFile2(binary, ["--version"], { timeout: VERSION_TIMEOUT_MS }, (error, stdout) => {
28670
29443
  const line = stdout.split("\n")[0]?.trim() ?? "";
28671
- if (!error && line) resolve28(pass("version", line));
28672
- else resolve28(fail3("version", "runs, but did not report a version"));
29444
+ if (!error && line) resolve29(pass("version", line));
29445
+ else resolve29(fail3("version", "runs, but did not report a version"));
28673
29446
  });
28674
29447
  });
28675
29448
  }