@akanjs/cli 2.3.9-rc.6 → 2.3.9-rc.8

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.
@@ -2,7 +2,7 @@
2
2
  var __require = import.meta.require;
3
3
 
4
4
  // pkgs/@akanjs/devkit/incrementalBuilder/incrementalBuilder.proc.ts
5
- import path40 from "path";
5
+ import path42 from "path";
6
6
 
7
7
  // pkgs/@akanjs/devkit/aiEditor.ts
8
8
  import { input, select } from "@inquirer/prompts";
@@ -4777,8 +4777,8 @@ class AkanAppHost {
4777
4777
  }
4778
4778
  // pkgs/@akanjs/devkit/akanContext.ts
4779
4779
  import { readdir } from "fs/promises";
4780
- import path10 from "path";
4781
- import { capitalize as capitalize4 } from "akanjs/common";
4780
+ import path11 from "path";
4781
+ import { capitalize as capitalize3 } from "akanjs/common";
4782
4782
 
4783
4783
  // pkgs/@akanjs/devkit/workflow/utils.ts
4784
4784
  var jsonText = (value, { trailingNewline = true } = {}) => `${JSON.stringify(value, null, 2)}${trailingNewline ? `
@@ -4798,6 +4798,24 @@ var uniqueBy = (values, key) => {
4798
4798
  var compactDiagnostics = (diagnostics) => diagnostics.filter((diagnostic) => !!diagnostic);
4799
4799
 
4800
4800
  // pkgs/@akanjs/devkit/workflow/artifacts.ts
4801
+ var sourceChangeBlocked = (diagnostics) => diagnostics.some((diagnostic) => diagnostic.severity === "error" && (diagnostic.failureScope === "source-change" || !diagnostic.failureScope || diagnostic.failureScope === "unknown"));
4802
+ var inferNextActionCode = (action, diagnostics) => {
4803
+ if (action.action)
4804
+ return action.action;
4805
+ if (sourceChangeBlocked(diagnostics) && action.command.startsWith("akan workflow explain"))
4806
+ return "blocked";
4807
+ if (action.command.startsWith("akan workflow repair"))
4808
+ return "repair";
4809
+ if (action.command.startsWith("akan workflow explain"))
4810
+ return "manual-review";
4811
+ if (action.command.startsWith("akan "))
4812
+ return "validate";
4813
+ return "answer";
4814
+ };
4815
+ var nextActionPriority = (action, diagnostics) => {
4816
+ const priority = sourceChangeBlocked(diagnostics) ? { blocked: 0, repair: 1, "manual-review": 2, validate: 3, answer: 4 } : { "manual-review": 0, validate: 1, repair: 2, blocked: 3, answer: 4 };
4817
+ return priority[action.action ?? "answer"];
4818
+ };
4801
4819
  var createWorkflowApplyReport = ({
4802
4820
  workflow,
4803
4821
  mode,
@@ -4813,11 +4831,18 @@ var createWorkflowApplyReport = ({
4813
4831
  plan
4814
4832
  }) => {
4815
4833
  const validationCommands = recommendedValidationCommands ?? commands;
4816
- const orderedNextActions = uniqueBy(nextActions, (action) => action.command).sort((left, right) => {
4817
- const leftRepair = left.command.startsWith("akan workflow explain") ? 0 : 1;
4818
- const rightRepair = right.command.startsWith("akan workflow explain") ? 0 : 1;
4819
- return leftRepair - rightRepair;
4820
- });
4834
+ const nextActionsWithIntent = nextActions.map((action) => ({
4835
+ ...action,
4836
+ action: inferNextActionCode(action, diagnostics)
4837
+ }));
4838
+ if (sourceChangeBlocked(diagnostics) && !nextActionsWithIntent.some((action) => action.action === "blocked")) {
4839
+ nextActionsWithIntent.unshift({
4840
+ command: `akan workflow explain ${workflow}`,
4841
+ reason: "Review source-change blockers before running validation.",
4842
+ action: "blocked"
4843
+ });
4844
+ }
4845
+ const orderedNextActions = uniqueBy(nextActionsWithIntent, (action) => action.command).sort((left, right) => nextActionPriority(left, diagnostics) - nextActionPriority(right, diagnostics));
4821
4846
  return {
4822
4847
  schemaVersion: 1,
4823
4848
  workflow,
@@ -5054,7 +5079,14 @@ var createRepairReport = ({
5054
5079
  ...syncedAt ? { syncedAt } : {}
5055
5080
  });
5056
5081
  // pkgs/@akanjs/devkit/workflow/executor.ts
5057
- import { capitalize as capitalize2 } from "akanjs/common";
5082
+ import ts6 from "typescript";
5083
+
5084
+ // pkgs/@akanjs/devkit/workflow/moduleIndex.ts
5085
+ import { access } from "fs/promises";
5086
+ import path10 from "path";
5087
+ import ts5 from "typescript";
5088
+
5089
+ // pkgs/@akanjs/devkit/workflow/source.ts
5058
5090
  import ts4 from "typescript";
5059
5091
 
5060
5092
  // pkgs/@akanjs/devkit/workflow/primitive.ts
@@ -5107,7 +5139,7 @@ var sourceFile = (sys2, path10, action, reason) => ({
5107
5139
  action,
5108
5140
  reason
5109
5141
  });
5110
- var moduleComponentName = (moduleName) => `${moduleName.slice(0, 1).toUpperCase()}${moduleName.slice(1)}`;
5142
+ var moduleComponentName = (moduleName) => moduleName.replace(/[-_]+/g, " ").replace(/(?:^|\s+)([a-zA-Z0-9])/g, (_, char) => char.toUpperCase()).replace(/\s+/g, "");
5111
5143
  var moduleSourcePaths = (moduleName) => {
5112
5144
  const componentName = moduleComponentName(moduleName);
5113
5145
  return {
@@ -5210,12 +5242,13 @@ var normalizeFieldType = (typeName) => {
5210
5242
  var ensureBaseTypeImport = (content, typeName) => {
5211
5243
  if (typeName !== "Int" && typeName !== "Float")
5212
5244
  return content;
5213
- if (new RegExp(`import \\{[^}]*\\b${typeName}\\b[^}]*\\} from "akanjs/base";`).test(content))
5214
- return content;
5215
- const baseImport = /import \{ ([^}]+) \} from "akanjs\/base";/.exec(content);
5245
+ const source = sourceFileFor("constant.ts", content);
5246
+ const baseImport = findNamedImport(source, "akanjs/base");
5216
5247
  if (baseImport) {
5217
- const names = baseImport[1].split(",").map((name) => name.trim()).filter(Boolean);
5218
- return content.replace(baseImport[0], `import { ${[...names, typeName].sort().join(", ")} } from "akanjs/base";`);
5248
+ if (baseImport.names.includes(typeName))
5249
+ return content;
5250
+ const nextNames = [...baseImport.names, typeName].sort();
5251
+ return spliceText(content, baseImport.namedBindingsStart, baseImport.namedBindingsEnd, `{ ${nextNames.join(", ")} }`);
5219
5252
  }
5220
5253
  return `import { ${typeName} } from "akanjs/base";
5221
5254
  ${content}`;
@@ -5344,47 +5377,350 @@ var fieldExpression = (typeName, defaultValue, options = {}) => {
5344
5377
  const defaultOption = defaultExpression ? `, { default: ${defaultExpression} }` : "";
5345
5378
  return `${options.builderName ?? "field"}(${typeExpression}${defaultOption})`;
5346
5379
  };
5347
- var viaBuilderParameterName = (content, className) => {
5348
- const classIndex = content.indexOf(`export class ${className} extends via`);
5349
- if (classIndex < 0)
5380
+ var fieldOrderingPriority = [
5381
+ "id",
5382
+ "name",
5383
+ "title",
5384
+ "status",
5385
+ "category",
5386
+ "description",
5387
+ "content",
5388
+ "startAt",
5389
+ "dueAt",
5390
+ "endAt",
5391
+ "createdAt",
5392
+ "updatedAt"
5393
+ ];
5394
+ var sourceFileFor = (fileName, content, scriptKind = ts4.ScriptKind.TS) => ts4.createSourceFile(fileName, content, ts4.ScriptTarget.Latest, true, scriptKind);
5395
+ var hasParseDiagnostics = (source) => (source.parseDiagnostics ?? []).length > 0;
5396
+ var spliceText = (content, start, end, replacement) => `${content.slice(0, start)}${replacement}${content.slice(end)}`;
5397
+ var lineStartAt = (content, position) => content.lastIndexOf(`
5398
+ `, Math.max(0, position - 1)) + 1;
5399
+ var lineEndAt = (content, position) => {
5400
+ const end = content.indexOf(`
5401
+ `, position);
5402
+ return end < 0 ? content.length : end + 1;
5403
+ };
5404
+ var lineIndentAt = (content, position) => /^[ \t]*/.exec(content.slice(lineStartAt(content, position)))?.[0] ?? "";
5405
+ var nodeName = (node) => {
5406
+ if (!node)
5407
+ return null;
5408
+ if (ts4.isIdentifier(node) || ts4.isStringLiteral(node) || ts4.isNumericLiteral(node))
5409
+ return node.text;
5410
+ return null;
5411
+ };
5412
+ var propertyName = (node) => ts4.isPropertyAssignment(node) || ts4.isShorthandPropertyAssignment(node) || ts4.isMethodDeclaration(node) ? nodeName(node.name) : null;
5413
+ var expressionName = (expression) => {
5414
+ if (ts4.isIdentifier(expression))
5415
+ return expression.text;
5416
+ if (ts4.isPropertyAccessExpression(expression))
5417
+ return expression.name.text;
5418
+ if (ts4.isCallExpression(expression))
5419
+ return expressionName(expression.expression);
5420
+ if (ts4.isAsExpression(expression))
5421
+ return expressionName(expression.expression);
5422
+ return null;
5423
+ };
5424
+ var firstObjectReturnedByArrow = (node) => {
5425
+ if (!ts4.isArrowFunction(node) && !ts4.isFunctionExpression(node))
5426
+ return null;
5427
+ if (ts4.isObjectLiteralExpression(node.body))
5428
+ return node.body;
5429
+ if (ts4.isParenthesizedExpression(node.body) && ts4.isObjectLiteralExpression(node.body.expression)) {
5430
+ return node.body.expression;
5431
+ }
5432
+ if (!ts4.isBlock(node.body))
5433
+ return null;
5434
+ for (const statement of node.body.statements) {
5435
+ if (ts4.isReturnStatement(statement) && statement.expression && ts4.isObjectLiteralExpression(statement.expression)) {
5436
+ return statement.expression;
5437
+ }
5438
+ }
5439
+ return null;
5440
+ };
5441
+ var isViaCall = (expression) => ts4.isCallExpression(expression) && expressionName(expression.expression) === "via";
5442
+ var heritageCall = (node) => {
5443
+ const heritage = node.heritageClauses?.flatMap((clause) => [...clause.types]) ?? [];
5444
+ const expression = heritage.find((clause) => isViaCall(clause.expression))?.expression;
5445
+ return expression && ts4.isCallExpression(expression) ? expression : null;
5446
+ };
5447
+ var callExpressionName = (node) => ts4.isPropertyAccessExpression(node.expression) ? node.expression.name.text : expressionName(node.expression);
5448
+ var locatedObject = (source, objectLiteral) => ({
5449
+ objectStart: objectLiteral.getStart(source),
5450
+ objectEnd: objectLiteral.getEnd(),
5451
+ fields: objectLiteral.properties.map((property) => {
5452
+ const name = propertyName(property);
5453
+ if (!name)
5454
+ return null;
5455
+ return {
5456
+ name,
5457
+ start: property.getStart(source),
5458
+ fullStart: property.getFullStart(),
5459
+ end: property.getEnd()
5460
+ };
5461
+ }).filter((field) => field !== null)
5462
+ });
5463
+ var findConstantInputObject = (source, className) => {
5464
+ let locator = null;
5465
+ const visit = (node) => {
5466
+ if (locator)
5467
+ return;
5468
+ if (!ts4.isClassDeclaration(node) || node.name?.text !== className) {
5469
+ ts4.forEachChild(node, visit);
5470
+ return;
5471
+ }
5472
+ const viaCall = heritageCall(node);
5473
+ const callback = viaCall?.arguments.find((arg) => ts4.isArrowFunction(arg) || ts4.isFunctionExpression(arg));
5474
+ const objectLiteral = callback ? firstObjectReturnedByArrow(callback) : null;
5475
+ if (objectLiteral)
5476
+ locator = locatedObject(source, objectLiteral);
5477
+ };
5478
+ ts4.forEachChild(source, visit);
5479
+ return locator;
5480
+ };
5481
+ var chainMethodsForCall = (node) => {
5482
+ if (ts4.isAsExpression(node) || ts4.isParenthesizedExpression(node))
5483
+ return chainMethodsForCall(node.expression);
5484
+ if (!ts4.isCallExpression(node))
5485
+ return [];
5486
+ if (ts4.isPropertyAccessExpression(node.expression)) {
5487
+ return [...chainMethodsForCall(node.expression.expression), node.expression.name.text];
5488
+ }
5489
+ const name = expressionName(node.expression);
5490
+ return name ? [name] : [];
5491
+ };
5492
+ var outermostFluentCall = (node) => {
5493
+ let current = node;
5494
+ while (ts4.isPropertyAccessExpression(current.parent) && current.parent.expression === current && ts4.isCallExpression(current.parent.parent) && current.parent.parent.expression === current.parent) {
5495
+ current = current.parent.parent;
5496
+ }
5497
+ return current;
5498
+ };
5499
+ var protectedDictionaryChainOrder = ["model", "slice", "enum", "error", "translate"];
5500
+ var dictionaryChainOrderValid = (chainMethods) => {
5501
+ const protectedOrder = new Map(protectedDictionaryChainOrder.map((method, index) => [method, index]));
5502
+ let lastOrder = -1;
5503
+ for (const method of chainMethods) {
5504
+ const order = protectedOrder.get(method);
5505
+ if (order === undefined)
5506
+ continue;
5507
+ if (order < lastOrder)
5508
+ return false;
5509
+ lastOrder = order;
5510
+ }
5511
+ return true;
5512
+ };
5513
+ var findDictionaryModelObject = (source, moduleClassName) => {
5514
+ let locator = null;
5515
+ const visit = (node) => {
5516
+ if (locator)
5517
+ return;
5518
+ if (!ts4.isCallExpression(node) || callExpressionName(node) !== "model") {
5519
+ ts4.forEachChild(node, visit);
5520
+ return;
5521
+ }
5522
+ const typeArgument = node.typeArguments?.[0];
5523
+ if (!typeArgument || typeArgument.getText(source) !== moduleClassName) {
5524
+ ts4.forEachChild(node, visit);
5525
+ return;
5526
+ }
5527
+ const callback = node.arguments.find((arg) => ts4.isArrowFunction(arg) || ts4.isFunctionExpression(arg));
5528
+ const objectLiteral = callback ? firstObjectReturnedByArrow(callback) : null;
5529
+ if (objectLiteral) {
5530
+ locator = {
5531
+ ...locatedObject(source, objectLiteral),
5532
+ chainMethods: chainMethodsForCall(outermostFluentCall(node))
5533
+ };
5534
+ }
5535
+ };
5536
+ ts4.forEachChild(source, visit);
5537
+ return locator;
5538
+ };
5539
+ var findLightProjectionArray = (source, moduleClassName) => {
5540
+ let locator = null;
5541
+ const visit = (node) => {
5542
+ if (locator)
5543
+ return;
5544
+ if (!ts4.isClassDeclaration(node) || node.name?.text !== `Light${moduleClassName}`) {
5545
+ ts4.forEachChild(node, visit);
5546
+ return;
5547
+ }
5548
+ const viaCall = heritageCall(node);
5549
+ const projectionArg = viaCall?.arguments.find((arg) => {
5550
+ const expression = ts4.isAsExpression(arg) ? arg.expression : arg;
5551
+ return ts4.isArrayLiteralExpression(expression);
5552
+ });
5553
+ const arrayLiteral = projectionArg ? ts4.isAsExpression(projectionArg) ? projectionArg.expression : projectionArg : null;
5554
+ if (!projectionArg || !arrayLiteral || !ts4.isArrayLiteralExpression(arrayLiteral))
5555
+ return;
5556
+ locator = {
5557
+ projectionStart: projectionArg.getStart(source),
5558
+ projectionEnd: projectionArg.getEnd(),
5559
+ fields: arrayLiteral.elements.map((element) => ts4.isStringLiteralLike(element) ? element.text : null).filter((field) => field !== null)
5560
+ };
5561
+ };
5562
+ ts4.forEachChild(source, visit);
5563
+ return locator;
5564
+ };
5565
+ var findNamedImport = (source, moduleSpecifier) => {
5566
+ for (const statement of source.statements) {
5567
+ if (!ts4.isImportDeclaration(statement) || !ts4.isStringLiteral(statement.moduleSpecifier))
5568
+ continue;
5569
+ if (statement.moduleSpecifier.text !== moduleSpecifier)
5570
+ continue;
5571
+ const namedBindings = statement.importClause?.namedBindings;
5572
+ if (!namedBindings || !ts4.isNamedImports(namedBindings))
5573
+ continue;
5574
+ return {
5575
+ names: namedBindings.elements.map((element) => element.name.text),
5576
+ namedBindingsStart: namedBindings.getStart(source),
5577
+ namedBindingsEnd: namedBindings.getEnd()
5578
+ };
5579
+ }
5580
+ return null;
5581
+ };
5582
+ var fieldExpressionBuilder = (property) => {
5583
+ if (!ts4.isPropertyAssignment(property))
5584
+ return null;
5585
+ const initializer = ts4.isAsExpression(property.initializer) ? property.initializer.expression : property.initializer;
5586
+ if (!ts4.isCallExpression(initializer))
5350
5587
  return null;
5351
- const signature = content.slice(classIndex, content.indexOf("=>", classIndex));
5352
- return /via\(\(\s*([A-Za-z_$][\w$]*)\s*\)/.exec(signature)?.[1] ?? null;
5588
+ return expressionName(initializer.expression);
5589
+ };
5590
+ var priorityOf = (fieldName) => {
5591
+ const priority = fieldOrderingPriority.indexOf(fieldName);
5592
+ return priority < 0 ? null : priority;
5593
+ };
5594
+ var insertionIndexForFieldOrder = (fieldNames, newFieldName) => {
5595
+ const newPriority = priorityOf(newFieldName);
5596
+ if (newPriority !== null) {
5597
+ const greaterPriorityIndex = fieldNames.findIndex((name) => {
5598
+ const existingPriority = priorityOf(name);
5599
+ return existingPriority !== null && existingPriority > newPriority;
5600
+ });
5601
+ if (greaterPriorityIndex >= 0)
5602
+ return greaterPriorityIndex;
5603
+ const lastPriorityIndex = fieldNames.reduce((lastIndex, name, index) => {
5604
+ const existingPriority = priorityOf(name);
5605
+ return existingPriority !== null ? index : lastIndex;
5606
+ }, -1);
5607
+ return lastPriorityIndex + 1;
5608
+ }
5609
+ const lastNonPriorityIndex = fieldNames.reduce((lastIndex, name, index) => priorityOf(name) === null ? index : lastIndex, -1);
5610
+ return lastNonPriorityIndex >= 0 ? lastNonPriorityIndex + 1 : fieldNames.length;
5611
+ };
5612
+ var insertOrderedFieldLine = (content, locator, fieldName, line, options) => {
5613
+ if (locator.fields.some((field) => field.name === fieldName))
5614
+ return content;
5615
+ const insertIndex = insertionIndexForFieldOrder(locator.fields.map((field) => field.name), fieldName);
5616
+ const formattedLine = line.trim();
5617
+ if (locator.fields.length === 0) {
5618
+ return spliceText(content, locator.objectStart, locator.objectEnd, `{
5619
+ ${options.fieldIndent}${formattedLine}
5620
+ ${options.closingIndent}}`);
5621
+ }
5622
+ const beforeField = locator.fields[insertIndex];
5623
+ if (beforeField) {
5624
+ const leadingComments = ts4.getLeadingCommentRanges(content, beforeField.fullStart) ?? [];
5625
+ const insertAt2 = lineStartAt(content, leadingComments[0]?.pos ?? beforeField.start);
5626
+ const indent2 = lineIndentAt(content, beforeField.start) || options.fieldIndent;
5627
+ return spliceText(content, insertAt2, insertAt2, `${indent2}${formattedLine}
5628
+ `);
5629
+ }
5630
+ const afterField = locator.fields[locator.fields.length - 1];
5631
+ const insertAt = lineEndAt(content, afterField.end);
5632
+ const indent = lineIndentAt(content, afterField.start) || options.fieldIndent;
5633
+ return spliceText(content, insertAt, insertAt, `${indent}${formattedLine}
5634
+ `);
5635
+ };
5636
+ var viaBuilderParameterName = (content, className) => {
5637
+ const source = sourceFileFor("constant.ts", content);
5638
+ let builderName = null;
5639
+ const visit = (node) => {
5640
+ if (builderName !== null)
5641
+ return;
5642
+ if (!ts4.isClassDeclaration(node) || node.name?.text !== className) {
5643
+ ts4.forEachChild(node, visit);
5644
+ return;
5645
+ }
5646
+ const viaCall = heritageCall(node);
5647
+ const callback = viaCall?.arguments.find((arg) => ts4.isArrowFunction(arg) || ts4.isFunctionExpression(arg));
5648
+ if (callback && (ts4.isArrowFunction(callback) || ts4.isFunctionExpression(callback))) {
5649
+ builderName = nodeName(callback.parameters[0]?.name);
5650
+ }
5651
+ };
5652
+ ts4.forEachChild(source, visit);
5653
+ return builderName;
5654
+ };
5655
+ var inspectConstantStructure = (content, className, moduleClassName) => {
5656
+ const source = sourceFileFor("constant.ts", content);
5657
+ const inputObject = findConstantInputObject(source, className);
5658
+ const lightProjection = findLightProjectionArray(source, moduleClassName);
5659
+ const baseImport = findNamedImport(source, "akanjs/base");
5660
+ const fields = [];
5661
+ if (inputObject) {
5662
+ const visit = (node) => {
5663
+ if (!ts4.isClassDeclaration(node) || node.name?.text !== className) {
5664
+ ts4.forEachChild(node, visit);
5665
+ return;
5666
+ }
5667
+ const viaCall = heritageCall(node);
5668
+ const callback = viaCall?.arguments.find((arg) => ts4.isArrowFunction(arg) || ts4.isFunctionExpression(arg));
5669
+ const objectLiteral = callback ? firstObjectReturnedByArrow(callback) : null;
5670
+ if (!objectLiteral)
5671
+ return;
5672
+ fields.push(...objectLiteral.properties.map((property) => {
5673
+ const name = propertyName(property);
5674
+ if (!name)
5675
+ return null;
5676
+ return { name, expressionBuilder: fieldExpressionBuilder(property) };
5677
+ }).filter((field) => field !== null));
5678
+ };
5679
+ ts4.forEachChild(source, visit);
5680
+ }
5681
+ return {
5682
+ parseValid: !hasParseDiagnostics(source),
5683
+ inputObjectFound: inputObject !== null,
5684
+ builderName: viaBuilderParameterName(content, className),
5685
+ fields,
5686
+ lightProjectionFields: lightProjection?.fields ?? [],
5687
+ baseImports: baseImport?.names ?? []
5688
+ };
5689
+ };
5690
+ var inspectDictionaryStructure = (content, moduleClassName) => {
5691
+ const source = sourceFileFor("dictionary.ts", content);
5692
+ const modelObject = findDictionaryModelObject(source, moduleClassName);
5693
+ return {
5694
+ parseValid: !hasParseDiagnostics(source),
5695
+ modelObjectFound: modelObject !== null,
5696
+ chainOrderValid: modelObject ? dictionaryChainOrderValid(modelObject.chainMethods) : false,
5697
+ chainMethods: modelObject?.chainMethods ?? [],
5698
+ fields: modelObject?.fields.map((field) => field.name) ?? []
5699
+ };
5353
5700
  };
5354
5701
  var insertIntoObject = (content, className, line) => {
5355
- const classIndex = content.indexOf(`export class ${className} extends via`);
5356
- if (classIndex < 0)
5702
+ const fieldName = /^([A-Za-z_$][\w$]*)\s*:/.exec(line.trim())?.[1];
5703
+ if (!fieldName)
5357
5704
  return null;
5358
- const objectEndIndex = content.indexOf("}))", classIndex);
5359
- if (objectEndIndex < 0)
5705
+ const source = sourceFileFor("constant.ts", content);
5706
+ const locator = findConstantInputObject(source, className);
5707
+ if (!locator)
5360
5708
  return null;
5361
- const prefix = content.slice(0, objectEndIndex);
5362
- const suffix = content.slice(objectEndIndex);
5363
- const insertion = prefix.endsWith(`
5364
- `) ? ` ${line}
5365
- ` : `
5366
- ${line}
5367
- `;
5368
- return `${prefix}${insertion}${suffix}`;
5709
+ return insertOrderedFieldLine(content, locator, fieldName, line, { fieldIndent: " ", closingIndent: "" });
5369
5710
  };
5370
5711
  var insertLightProjectionField = (content, moduleClassName, fieldName) => {
5371
- const classIndex = content.indexOf(`export class Light${moduleClassName} extends via`);
5372
- if (classIndex < 0)
5712
+ const source = sourceFileFor("constant.ts", content);
5713
+ const locator = findLightProjectionArray(source, moduleClassName);
5714
+ if (!locator)
5373
5715
  return null;
5374
- const arrayMatch = /\[([\s\S]*?)\]\s+as const/.exec(content.slice(classIndex));
5375
- if (!arrayMatch || arrayMatch.index === undefined)
5376
- return null;
5377
- const arrayStart = classIndex + arrayMatch.index;
5378
- const arrayEnd = arrayStart + arrayMatch[0].length;
5379
- const fields = [...arrayMatch[1].matchAll(/"([^"]+)"/g)].map((match) => match[1]).filter(Boolean);
5380
- if (fields.includes(fieldName))
5716
+ if (locator.fields.includes(fieldName))
5381
5717
  return content;
5382
- const nextFields = [...fields, fieldName];
5718
+ const nextFields = [...locator.fields, fieldName];
5383
5719
  const nextArray = nextFields.length === 0 ? "[] as const" : `[
5384
5720
  ${nextFields.map((field) => ` ${JSON.stringify(field)},`).join(`
5385
5721
  `)}
5386
5722
  ] as const`;
5387
- return `${content.slice(0, arrayStart)}${nextArray}${content.slice(arrayEnd)}`;
5723
+ return spliceText(content, locator.projectionStart, locator.projectionEnd, nextArray);
5388
5724
  };
5389
5725
  var insertTemplateField = ({
5390
5726
  content,
@@ -5437,69 +5773,32 @@ ${values.map((value) => ` ${JSON.stringify(value)},`).join(`
5437
5773
  ${enumClass}`;
5438
5774
  return `${content.slice(0, firstClassIndex)}${enumClass}${content.slice(firstClassIndex)}`;
5439
5775
  };
5440
- var findMatchingBrace = (content, openIndex) => {
5441
- let depth = 0;
5442
- let quote = null;
5443
- let escaped = false;
5444
- for (let index = openIndex;index < content.length; index++) {
5445
- const char = content[index];
5446
- if (quote) {
5447
- if (escaped) {
5448
- escaped = false;
5449
- continue;
5450
- }
5451
- if (char === "\\") {
5452
- escaped = true;
5453
- continue;
5454
- }
5455
- if (char === quote)
5456
- quote = null;
5457
- continue;
5458
- }
5459
- if (char === '"' || char === "'" || char === "`") {
5460
- quote = char;
5461
- continue;
5462
- }
5463
- if (char === "{")
5464
- depth += 1;
5465
- if (char === "}") {
5466
- depth -= 1;
5467
- if (depth === 0)
5468
- return index;
5469
- }
5470
- }
5471
- return -1;
5472
- };
5473
5776
  var dictionaryModelFieldLine = (fieldName) => {
5474
5777
  const label = bilingualLabelForField(fieldName);
5475
5778
  const desc = bilingualDescriptionForField(fieldName);
5476
5779
  return `${fieldName}: t([${JSON.stringify(label.en)}, ${JSON.stringify(label.ko)}]).desc([${JSON.stringify(desc.en)}, ${JSON.stringify(desc.ko)}]),`;
5477
5780
  };
5478
5781
  var insertDictionaryModelField = (content, moduleClassName, fieldName) => {
5479
- if (new RegExp(`\\b${fieldName}\\s*:`).test(content))
5480
- return content;
5481
- const modelIndex = content.indexOf(`.model<${moduleClassName}>((t) => (`);
5482
- if (modelIndex < 0)
5483
- return null;
5484
- const objectStartIndex = content.indexOf("{", modelIndex);
5485
- if (objectStartIndex < 0)
5782
+ const source = sourceFileFor("dictionary.ts", content);
5783
+ const locator = findDictionaryModelObject(source, moduleClassName);
5784
+ if (!locator)
5486
5785
  return null;
5487
- const objectEndIndex = findMatchingBrace(content, objectStartIndex);
5488
- if (objectEndIndex < 0)
5489
- return null;
5490
- const fieldLine = dictionaryModelFieldLine(fieldName);
5491
- const body = content.slice(objectStartIndex + 1, objectEndIndex);
5492
- if (body.trim().length === 0) {
5493
- return `${content.slice(0, objectStartIndex + 1)}
5494
- ${fieldLine}
5495
- ${content.slice(objectEndIndex)}`;
5496
- }
5497
- const insertion = body.endsWith(`
5498
- `) ? ` ${fieldLine}
5499
- ` : `
5500
- ${fieldLine}
5501
- `;
5502
- return `${content.slice(0, objectEndIndex)}${insertion}${content.slice(objectEndIndex)}`;
5786
+ return insertOrderedFieldLine(content, locator, fieldName, dictionaryModelFieldLine(fieldName), {
5787
+ fieldIndent: " ",
5788
+ closingIndent: " "
5789
+ });
5790
+ };
5791
+ var hasConstantInputField = (content, className, fieldName) => {
5792
+ const source = sourceFileFor("constant.ts", content);
5793
+ if (hasParseDiagnostics(source))
5794
+ return false;
5795
+ return findConstantInputObject(source, className)?.fields.some((field) => field.name === fieldName) ?? false;
5796
+ };
5797
+ var hasDictionaryModelField = (content, moduleClassName, fieldName) => {
5798
+ const source = sourceFileFor("dictionary.ts", content);
5799
+ if (hasParseDiagnostics(source))
5800
+ return false;
5801
+ return findDictionaryModelObject(source, moduleClassName)?.fields.some((field) => field.name === fieldName) ?? false;
5503
5802
  };
5504
5803
  var ensureConstantTypeImport = (content, constantPath, typeName) => {
5505
5804
  if (new RegExp(`import type \\{[^}]*\\b${typeName}\\b[^}]*\\} from "${constantPath}";`).test(content))
@@ -5529,6 +5828,401 @@ ${values.map((value) => ` ${value}: t([${JSON.stringify(titleize(value))}, ${
5529
5828
  };
5530
5829
  var parseValues = (value) => value?.split(",").map((item) => item.trim()).filter(Boolean) ?? [];
5531
5830
 
5831
+ // pkgs/@akanjs/devkit/workflow/moduleIndex.ts
5832
+ var indexFileKinds = [
5833
+ "abstract",
5834
+ "constant",
5835
+ "dictionary",
5836
+ "service",
5837
+ "signal",
5838
+ "store",
5839
+ "template",
5840
+ "unit",
5841
+ "util",
5842
+ "view",
5843
+ "zone"
5844
+ ];
5845
+ var sourceText = async (filePath) => {
5846
+ try {
5847
+ return await Bun.file(filePath).text();
5848
+ } catch {
5849
+ return null;
5850
+ }
5851
+ };
5852
+ var fileExists = async (filePath) => {
5853
+ try {
5854
+ await access(filePath);
5855
+ return true;
5856
+ } catch {
5857
+ return false;
5858
+ }
5859
+ };
5860
+ var sourceFileFor2 = (filePath, content) => ts5.createSourceFile(filePath, content, ts5.ScriptTarget.Latest, true, ts5.ScriptKind.TS);
5861
+ var parseDiagnosticsFor = (source, filePath) => {
5862
+ const parseDiagnostics = source.parseDiagnostics ?? [];
5863
+ return parseDiagnostics.map((diagnostic) => ({
5864
+ severity: "error",
5865
+ code: "module-index-typescript-parse-error",
5866
+ message: `TypeScript parse diagnostic TS${diagnostic.code} in ${filePath}: ${ts5.flattenDiagnosticMessageText(diagnostic.messageText, `
5867
+ `)}`,
5868
+ context: { target: filePath, paths: [filePath] }
5869
+ }));
5870
+ };
5871
+ var spanFor = (source, file, node) => {
5872
+ const startOffset = node.getStart(source);
5873
+ const endOffset = node.getEnd();
5874
+ const start = source.getLineAndCharacterOfPosition(startOffset);
5875
+ const end = source.getLineAndCharacterOfPosition(endOffset);
5876
+ return {
5877
+ file,
5878
+ startLine: start.line + 1,
5879
+ endLine: end.line + 1,
5880
+ startOffset,
5881
+ endOffset
5882
+ };
5883
+ };
5884
+ var nodeName2 = (node) => {
5885
+ if (!node)
5886
+ return null;
5887
+ if (ts5.isIdentifier(node) || ts5.isStringLiteral(node) || ts5.isNumericLiteral(node))
5888
+ return node.text;
5889
+ return null;
5890
+ };
5891
+ var propertyName2 = (node) => ts5.isPropertyAssignment(node) || ts5.isShorthandPropertyAssignment(node) || ts5.isMethodDeclaration(node) ? nodeName2(node.name) : null;
5892
+ var expressionName2 = (expression) => {
5893
+ if (ts5.isIdentifier(expression))
5894
+ return expression.text;
5895
+ if (ts5.isPropertyAccessExpression(expression))
5896
+ return expression.name.text;
5897
+ if (ts5.isCallExpression(expression))
5898
+ return expressionName2(expression.expression);
5899
+ if (ts5.isAsExpression(expression))
5900
+ return expressionName2(expression.expression);
5901
+ return null;
5902
+ };
5903
+ var expressionSummary = (expression) => {
5904
+ if (ts5.isAsExpression(expression))
5905
+ return expressionSummary(expression.expression);
5906
+ if (ts5.isIdentifier(expression) || ts5.isPropertyAccessExpression(expression))
5907
+ return expressionName2(expression) ?? "expression";
5908
+ if (ts5.isArrayLiteralExpression(expression))
5909
+ return "array-literal";
5910
+ if (ts5.isObjectLiteralExpression(expression))
5911
+ return "object-literal";
5912
+ if (ts5.isStringLiteralLike(expression))
5913
+ return "string-literal";
5914
+ if (ts5.isNumericLiteral(expression))
5915
+ return "numeric-literal";
5916
+ if (expression.kind === ts5.SyntaxKind.TrueKeyword || expression.kind === ts5.SyntaxKind.FalseKeyword) {
5917
+ return "boolean-literal";
5918
+ }
5919
+ if (ts5.isCallExpression(expression)) {
5920
+ const callee = expressionName2(expression.expression);
5921
+ return callee ? `${callee}(...)` : "call-expression";
5922
+ }
5923
+ return ts5.SyntaxKind[expression.kind] ?? "expression";
5924
+ };
5925
+ var typeSummaryForInitializer = (initializer) => {
5926
+ if (!initializer)
5927
+ return;
5928
+ const expression = ts5.isAsExpression(initializer) ? initializer.expression : initializer;
5929
+ if (!ts5.isCallExpression(expression))
5930
+ return expressionSummary(expression);
5931
+ const callee = expressionName2(expression.expression);
5932
+ const firstArg = expression.arguments[0];
5933
+ const argSummary = firstArg ? expressionSummary(firstArg) : "";
5934
+ return [callee, argSummary ? `(${argSummary})` : ""].filter(Boolean).join("");
5935
+ };
5936
+ var fieldsFromObject = (source, file, objectLiteral, kind) => objectLiteral.properties.map((property, index) => {
5937
+ const name = propertyName2(property);
5938
+ if (!name)
5939
+ return null;
5940
+ const initializer = ts5.isPropertyAssignment(property) ? property.initializer : undefined;
5941
+ return {
5942
+ name,
5943
+ kind,
5944
+ order: index,
5945
+ ...initializer ? { typeSummary: typeSummaryForInitializer(initializer) } : {},
5946
+ sourceSpan: spanFor(source, file, property)
5947
+ };
5948
+ }).filter((field) => field !== null);
5949
+ var firstObjectReturnedByArrow2 = (node) => {
5950
+ if (!ts5.isArrowFunction(node) && !ts5.isFunctionExpression(node))
5951
+ return null;
5952
+ if (ts5.isObjectLiteralExpression(node.body))
5953
+ return node.body;
5954
+ if (ts5.isParenthesizedExpression(node.body) && ts5.isObjectLiteralExpression(node.body.expression)) {
5955
+ return node.body.expression;
5956
+ }
5957
+ if (!ts5.isBlock(node.body))
5958
+ return null;
5959
+ for (const statement of node.body.statements) {
5960
+ if (ts5.isReturnStatement(statement) && statement.expression && ts5.isObjectLiteralExpression(statement.expression)) {
5961
+ return statement.expression;
5962
+ }
5963
+ }
5964
+ return null;
5965
+ };
5966
+ var isViaCall2 = (expression) => ts5.isCallExpression(expression) && expressionName2(expression.expression) === "via";
5967
+ var heritageCall2 = (node) => {
5968
+ const heritage = node.heritageClauses?.flatMap((clause) => [...clause.types]) ?? [];
5969
+ const expression = heritage.find((clause) => isViaCall2(clause.expression))?.expression;
5970
+ return expression && ts5.isCallExpression(expression) ? expression : null;
5971
+ };
5972
+ var parseConstantIndex = (filePath, content, moduleClassName) => {
5973
+ const source = sourceFileFor2(filePath, content);
5974
+ const diagnostics = parseDiagnosticsFor(source, filePath);
5975
+ const inputClassName = `${moduleClassName}Input`;
5976
+ let inputClass = null;
5977
+ let inputViaFound = false;
5978
+ let inputBuilderFound = false;
5979
+ let inputBuilderObjectFound = false;
5980
+ let builderName = null;
5981
+ let fields = [];
5982
+ let lightProjection;
5983
+ const visit = (node) => {
5984
+ if (!ts5.isClassDeclaration(node) || !node.name) {
5985
+ ts5.forEachChild(node, visit);
5986
+ return;
5987
+ }
5988
+ const className = node.name.text;
5989
+ const viaCall = heritageCall2(node);
5990
+ if (className === inputClassName) {
5991
+ inputClass = node;
5992
+ if (!viaCall)
5993
+ return;
5994
+ inputViaFound = true;
5995
+ const callback = viaCall.arguments.find((arg) => ts5.isArrowFunction(arg) || ts5.isFunctionExpression(arg));
5996
+ if (callback && (ts5.isArrowFunction(callback) || ts5.isFunctionExpression(callback))) {
5997
+ inputBuilderFound = true;
5998
+ builderName = nodeName2(callback.parameters[0]?.name) ?? null;
5999
+ const objectLiteral = firstObjectReturnedByArrow2(callback);
6000
+ if (objectLiteral) {
6001
+ inputBuilderObjectFound = true;
6002
+ fields = fieldsFromObject(source, filePath, objectLiteral, "constant");
6003
+ }
6004
+ }
6005
+ }
6006
+ if (!viaCall)
6007
+ return;
6008
+ if (className === `Light${moduleClassName}`) {
6009
+ const projectionArg = viaCall.arguments.find((arg) => {
6010
+ const expression = ts5.isAsExpression(arg) ? arg.expression : arg;
6011
+ return ts5.isArrayLiteralExpression(expression);
6012
+ });
6013
+ const arrayLiteral = projectionArg ? ts5.isAsExpression(projectionArg) ? projectionArg.expression : projectionArg : null;
6014
+ if (arrayLiteral && ts5.isArrayLiteralExpression(arrayLiteral)) {
6015
+ lightProjection = {
6016
+ className,
6017
+ sourceSpan: spanFor(source, filePath, arrayLiteral),
6018
+ fields: arrayLiteral.elements.map((element, order) => ts5.isStringLiteralLike(element) ? {
6019
+ name: element.text,
6020
+ kind: "lightProjection",
6021
+ order,
6022
+ typeSummary: "string-literal",
6023
+ sourceSpan: spanFor(source, filePath, element)
6024
+ } : null).filter((field) => field !== null)
6025
+ };
6026
+ }
6027
+ }
6028
+ };
6029
+ ts5.forEachChild(source, visit);
6030
+ if (!inputClass) {
6031
+ diagnostics.push({
6032
+ severity: "error",
6033
+ code: "module-index-constant-input-missing",
6034
+ message: `Constant input class ${inputClassName} was not found in ${filePath}.`,
6035
+ context: { target: inputClassName, paths: [filePath] }
6036
+ });
6037
+ } else if (!inputViaFound) {
6038
+ diagnostics.push({
6039
+ severity: "error",
6040
+ code: "module-index-constant-via-missing",
6041
+ message: `Constant input class ${inputClassName} does not extend via(...) in ${filePath}.`,
6042
+ context: { target: inputClassName, paths: [filePath] }
6043
+ });
6044
+ } else if (!inputBuilderFound) {
6045
+ diagnostics.push({
6046
+ severity: "error",
6047
+ code: "module-index-constant-builder-missing",
6048
+ message: `Constant input class ${inputClassName} does not provide a via(...) builder callback in ${filePath}.`,
6049
+ context: { target: inputClassName, paths: [filePath] }
6050
+ });
6051
+ } else if (!inputBuilderObjectFound) {
6052
+ diagnostics.push({
6053
+ severity: "error",
6054
+ code: "module-index-constant-builder-object-missing",
6055
+ message: `Constant input class ${inputClassName} builder does not return an object literal in ${filePath}.`,
6056
+ context: { target: inputClassName, paths: [filePath] }
6057
+ });
6058
+ }
6059
+ return {
6060
+ index: {
6061
+ path: filePath,
6062
+ inputClassName,
6063
+ builderName,
6064
+ fields,
6065
+ ...lightProjection ? { lightProjection } : {},
6066
+ ...inputClass ? { sourceSpan: spanFor(source, filePath, inputClass) } : {}
6067
+ },
6068
+ diagnostics
6069
+ };
6070
+ };
6071
+ var callExpressionName2 = (node) => ts5.isPropertyAccessExpression(node.expression) ? node.expression.name.text : expressionName2(node.expression);
6072
+ var parseDictionaryIndex = (filePath, content, moduleClassName) => {
6073
+ const source = sourceFileFor2(filePath, content);
6074
+ const diagnostics = parseDiagnosticsFor(source, filePath);
6075
+ let index;
6076
+ let modelFound = false;
6077
+ const visit = (node) => {
6078
+ if (modelFound || !ts5.isCallExpression(node)) {
6079
+ ts5.forEachChild(node, visit);
6080
+ return;
6081
+ }
6082
+ if (callExpressionName2(node) !== "model") {
6083
+ ts5.forEachChild(node, visit);
6084
+ return;
6085
+ }
6086
+ const typeArgument = node.typeArguments?.[0];
6087
+ if (!typeArgument || typeArgument.getText(source) !== moduleClassName) {
6088
+ ts5.forEachChild(node, visit);
6089
+ return;
6090
+ }
6091
+ modelFound = true;
6092
+ const callback = node.arguments.find((arg) => ts5.isArrowFunction(arg) || ts5.isFunctionExpression(arg));
6093
+ if (!callback || !ts5.isArrowFunction(callback) && !ts5.isFunctionExpression(callback)) {
6094
+ diagnostics.push({
6095
+ severity: "error",
6096
+ code: "module-index-dictionary-builder-missing",
6097
+ message: `Dictionary .model<${moduleClassName}> branch does not provide a builder callback in ${filePath}.`,
6098
+ context: { target: moduleClassName, paths: [filePath] }
6099
+ });
6100
+ return;
6101
+ }
6102
+ const objectLiteral = firstObjectReturnedByArrow2(callback);
6103
+ if (!objectLiteral) {
6104
+ diagnostics.push({
6105
+ severity: "error",
6106
+ code: "module-index-dictionary-builder-object-missing",
6107
+ message: `Dictionary .model<${moduleClassName}> builder does not return an object literal in ${filePath}.`,
6108
+ context: { target: moduleClassName, paths: [filePath] }
6109
+ });
6110
+ }
6111
+ index = {
6112
+ path: filePath,
6113
+ modelClassName: moduleClassName,
6114
+ translatorName: nodeName2(callback.parameters[0]?.name),
6115
+ fields: objectLiteral ? fieldsFromObject(source, filePath, objectLiteral, "dictionary") : [],
6116
+ sourceSpan: spanFor(source, filePath, node)
6117
+ };
6118
+ };
6119
+ ts5.forEachChild(source, visit);
6120
+ return { index, diagnostics, modelFound };
6121
+ };
6122
+ var expectedFilesFor = (module) => {
6123
+ const paths = moduleSourcePaths(module.name);
6124
+ return indexFileKinds.map((kind) => {
6125
+ const expectedModulePath = paths[kind];
6126
+ const expectedFilename = path10.basename(expectedModulePath);
6127
+ const actualFilename = module.files.find((file) => file === expectedFilename) ?? module.files.find((file) => file.toLowerCase() === expectedFilename.toLowerCase());
6128
+ const present = actualFilename !== undefined;
6129
+ const casing = !present ? "missing" : actualFilename === expectedFilename ? "match" : "mismatch";
6130
+ return {
6131
+ kind,
6132
+ path: `${module.path}/${actualFilename ?? expectedFilename}`,
6133
+ expectedPath: `${module.path}/${expectedFilename}`,
6134
+ filename: actualFilename ?? expectedFilename,
6135
+ expectedFilename,
6136
+ present,
6137
+ casing
6138
+ };
6139
+ });
6140
+ };
6141
+ var diagnosticsForFiles = (files) => files.flatMap((file) => {
6142
+ if (file.kind !== "constant" && file.kind !== "dictionary")
6143
+ return [];
6144
+ if (file.casing === "match")
6145
+ return [];
6146
+ return [
6147
+ {
6148
+ severity: "error",
6149
+ code: file.casing === "missing" ? "module-index-file-missing" : "module-index-file-casing-mismatch",
6150
+ message: file.casing === "missing" ? `Expected ${file.kind} file is missing: ${file.expectedPath}.` : `Expected ${file.expectedPath}, but found ${file.path}.`,
6151
+ context: { target: file.expectedPath, paths: [file.path, file.expectedPath] }
6152
+ }
6153
+ ];
6154
+ });
6155
+ var fieldPresence = (requestedField, constantFields, dictionaryFields, lightFields) => {
6156
+ const names = new Set([
6157
+ ...constantFields.map((field) => field.name),
6158
+ ...dictionaryFields.map((field) => field.name),
6159
+ ...lightFields.map((field) => field.name),
6160
+ ...requestedField ? [requestedField] : []
6161
+ ]);
6162
+ return [...names].sort().map((name) => ({
6163
+ name,
6164
+ requested: requestedField === name,
6165
+ constant: constantFields.some((field) => field.name === name),
6166
+ dictionary: dictionaryFields.some((field) => field.name === name),
6167
+ lightProjection: lightFields.some((field) => field.name === name)
6168
+ }));
6169
+ };
6170
+ var partialPresenceDiagnostics = (presence, module) => presence.filter((field) => field.constant !== field.dictionary || field.lightProjection && (!field.constant || !field.dictionary)).map((field) => ({
6171
+ severity: "warning",
6172
+ code: "module-index-field-presence-partial",
6173
+ message: `${module.sysName}:${module.name}.${field.name} presence differs across constant, dictionary, and lightProjection.`,
6174
+ context: {
6175
+ target: `${module.sysName}:${module.name}.${field.name}`,
6176
+ paths: [`${module.path}/${module.name}.constant.ts`, `${module.path}/${module.name}.dictionary.ts`]
6177
+ }
6178
+ }));
6179
+ var buildAkanModuleContextIndex = async (workspace, module, options = {}) => {
6180
+ const files = expectedFilesFor(module);
6181
+ const diagnostics = diagnosticsForFiles(files);
6182
+ const moduleClassName = moduleComponentName(module.name);
6183
+ const constantFile = files.find((file) => file.kind === "constant");
6184
+ const dictionaryFile = files.find((file) => file.kind === "dictionary");
6185
+ const constantContent = constantFile?.present && constantFile.casing === "match" ? await sourceText(path10.join(workspace.workspaceRoot, constantFile.path)) : null;
6186
+ const dictionaryContent = dictionaryFile?.present && dictionaryFile.casing === "match" ? await sourceText(path10.join(workspace.workspaceRoot, dictionaryFile.path)) : null;
6187
+ const parsedConstant = constantFile && constantContent ? parseConstantIndex(constantFile.path, constantContent, moduleClassName) : undefined;
6188
+ const constant = parsedConstant?.index;
6189
+ const parsedDictionary = dictionaryFile && dictionaryContent ? parseDictionaryIndex(dictionaryFile.path, dictionaryContent, moduleClassName) : undefined;
6190
+ const dictionary = parsedDictionary?.index;
6191
+ const presence = fieldPresence(options.field, constant?.fields ?? [], dictionary?.fields ?? [], constant?.lightProjection?.fields ?? []);
6192
+ if (constantFile?.present && constantFile.casing === "match" && !await fileExists(path10.join(workspace.workspaceRoot, constantFile.path))) {
6193
+ diagnostics.push({
6194
+ severity: "error",
6195
+ code: "module-index-file-unreadable",
6196
+ message: `Expected constant file could not be read: ${constantFile.path}.`,
6197
+ context: { paths: [constantFile.path] }
6198
+ });
6199
+ }
6200
+ if (parsedConstant)
6201
+ diagnostics.push(...parsedConstant.diagnostics);
6202
+ if (parsedDictionary)
6203
+ diagnostics.push(...parsedDictionary.diagnostics);
6204
+ if (dictionaryFile?.present && dictionaryFile.casing === "match" && !parsedDictionary?.modelFound) {
6205
+ diagnostics.push({
6206
+ severity: "error",
6207
+ code: "module-index-dictionary-model-missing",
6208
+ message: `Dictionary .model<${moduleClassName}> branch was not found in ${dictionaryFile.path}.`,
6209
+ context: { paths: [dictionaryFile.path] }
6210
+ });
6211
+ }
6212
+ diagnostics.push(...partialPresenceDiagnostics(presence, module));
6213
+ return {
6214
+ schemaVersion: 1,
6215
+ app: module.sysName,
6216
+ module: module.name,
6217
+ moduleClassName,
6218
+ files,
6219
+ fieldPresence: presence,
6220
+ ...constant ? { constant } : {},
6221
+ ...dictionary ? { dictionary } : {},
6222
+ diagnostics
6223
+ };
6224
+ };
6225
+
5532
6226
  // pkgs/@akanjs/devkit/workflow/uiPolicy.ts
5533
6227
  var addFieldUiPolicyForType = (typeName) => {
5534
6228
  const normalizedType = typeName.toLowerCase() === "enum" ? "enum" : normalizeFieldType(typeName);
@@ -5593,11 +6287,18 @@ var postApplyDiagnostic = (code, message, target) => ({
5593
6287
  failureScope: "source-change",
5594
6288
  context: { target }
5595
6289
  });
6290
+ var postApplyWarning = (code, message, target) => ({
6291
+ severity: "warning",
6292
+ code,
6293
+ message,
6294
+ failureScope: "source-change",
6295
+ context: { target }
6296
+ });
5596
6297
  var sourceKindForPath = (filePath) => {
5597
6298
  if (filePath.endsWith(".tsx"))
5598
- return ts4.ScriptKind.TSX;
6299
+ return ts6.ScriptKind.TSX;
5599
6300
  if (filePath.endsWith(".ts"))
5600
- return ts4.ScriptKind.TS;
6301
+ return ts6.ScriptKind.TS;
5601
6302
  return null;
5602
6303
  };
5603
6304
  var checkPathCasing = async (workspace, filePath) => {
@@ -5625,7 +6326,7 @@ var checkTypeScriptSyntax = async (workspace, filePath) => {
5625
6326
  if (!scriptKind)
5626
6327
  return null;
5627
6328
  const content = await workspace.readFile(filePath);
5628
- const source = ts4.createSourceFile(filePath, content, ts4.ScriptTarget.Latest, true, scriptKind);
6329
+ const source = ts6.createSourceFile(filePath, content, ts6.ScriptTarget.Latest, true, scriptKind);
5629
6330
  const diagnostic = source.parseDiagnostics[0];
5630
6331
  if (!diagnostic)
5631
6332
  return null;
@@ -5633,7 +6334,7 @@ var checkTypeScriptSyntax = async (workspace, filePath) => {
5633
6334
  const location = position ? `:${position.line + 1}:${position.character + 1}` : "";
5634
6335
  return {
5635
6336
  code: "workflow-post-apply-syntax-error",
5636
- message: `Generated source has a TypeScript syntax error at ${filePath}${location}: ${ts4.flattenDiagnosticMessageText(diagnostic.messageText, " ")}`
6337
+ message: `Generated source has a TypeScript syntax error at ${filePath}${location}: ${ts6.flattenDiagnosticMessageText(diagnostic.messageText, " ")}`
5637
6338
  };
5638
6339
  };
5639
6340
  var checkChangedFile = async (workspace, file) => {
@@ -5675,6 +6376,111 @@ var checkRecommendationPath = async (workspace, recommendation) => {
5675
6376
  context: { target: recommendation.target }
5676
6377
  };
5677
6378
  };
6379
+ var sourceChangeError = (diagnostics) => diagnostics.some((diagnostic) => diagnostic.severity === "error" && (diagnostic.failureScope === "source-change" || !diagnostic.failureScope || diagnostic.failureScope === "unknown"));
6380
+ var fieldCount = (fields, fieldName) => fields.filter((field) => field === fieldName).length;
6381
+ var fieldOrderValid = (fields, fieldName) => {
6382
+ const actualIndex = fields.indexOf(fieldName);
6383
+ if (actualIndex < 0 || fields.lastIndexOf(fieldName) !== actualIndex)
6384
+ return false;
6385
+ const fieldsWithoutRequested = fields.filter((_, index) => index !== actualIndex);
6386
+ return insertionIndexForFieldOrder(fieldsWithoutRequested, fieldName) === actualIndex;
6387
+ };
6388
+ var workflowModuleContext = async (workspace, plan) => {
6389
+ const app = workflowStringInput(plan.inputs.app);
6390
+ const moduleName = workflowStringInput(plan.inputs.module);
6391
+ if (!app || !moduleName)
6392
+ return null;
6393
+ const [apps, libs] = await workspace.getSyss();
6394
+ const sysType = apps.includes(app) ? "app" : libs.includes(app) ? "lib" : null;
6395
+ if (!sysType)
6396
+ return null;
6397
+ const modulePath = `${sysType}s/${app}/lib/${moduleName}`;
6398
+ const files = await workspace.readdir(modulePath);
6399
+ const abstractPath = `${modulePath}/${moduleName}.abstract.md`;
6400
+ return {
6401
+ kind: "domain",
6402
+ name: moduleName,
6403
+ folderName: moduleName,
6404
+ sysName: app,
6405
+ sysType,
6406
+ path: modulePath,
6407
+ abstract: {
6408
+ path: abstractPath,
6409
+ exists: files.includes(`${moduleName}.abstract.md`),
6410
+ headings: []
6411
+ },
6412
+ files
6413
+ };
6414
+ };
6415
+ var structureCheck = (code, target, status, message) => ({
6416
+ code,
6417
+ target,
6418
+ status,
6419
+ message
6420
+ });
6421
+ var checkAddFieldStructure = async (workspace, plan) => {
6422
+ if (plan.workflow !== "add-field" && plan.workflow !== "add-enum-field")
6423
+ return {};
6424
+ const app = workflowStringInput(plan.inputs.app);
6425
+ const moduleName = workflowStringInput(plan.inputs.module);
6426
+ const fieldName = workflowStringInput(plan.inputs.field);
6427
+ const typeName = workflowStringInput(plan.inputs.type);
6428
+ if (!app || !moduleName || !fieldName || !typeName)
6429
+ return {};
6430
+ const moduleContext = await workflowModuleContext(workspace, plan);
6431
+ if (!moduleContext)
6432
+ return {};
6433
+ const paths = moduleSourcePaths(moduleName);
6434
+ const constantPath = `${moduleContext.path}/${paths.constant.replace(`lib/${moduleName}/`, "")}`;
6435
+ const dictionaryPath = `${moduleContext.path}/${paths.dictionary.replace(`lib/${moduleName}/`, "")}`;
6436
+ const moduleClassName = moduleComponentName(moduleName);
6437
+ const inputClassName = `${moduleClassName}Input`;
6438
+ const index = await buildAkanModuleContextIndex(workspace, moduleContext, { field: fieldName });
6439
+ const diagnostics = [];
6440
+ const postApplyChecks = [];
6441
+ const constantContent = await workspace.readFile(constantPath);
6442
+ const constantStructure = inspectConstantStructure(constantContent, inputClassName, moduleClassName);
6443
+ const constantNames = constantStructure.fields.map((field) => field.name);
6444
+ const requestedConstantFields = constantStructure.fields.filter((field) => field.name === fieldName);
6445
+ const normalizedType = typeName.toLowerCase() === "enum" ? typeName : normalizeFieldType(typeName);
6446
+ const constantFailures = [
6447
+ !constantStructure.parseValid ? "constant file does not parse" : null,
6448
+ !constantStructure.inputObjectFound ? `${inputClassName} via builder object was not found` : null,
6449
+ requestedConstantFields.length !== 1 ? `field "${fieldName}" appears ${requestedConstantFields.length} time(s) in ${inputClassName}` : null,
6450
+ constantStructure.builderName && requestedConstantFields[0]?.expressionBuilder && requestedConstantFields[0].expressionBuilder !== constantStructure.builderName ? `field "${fieldName}" uses builder "${requestedConstantFields[0].expressionBuilder}" instead of "${constantStructure.builderName}"` : null,
6451
+ !constantStructure.builderName ? `${inputClassName} via builder parameter was not found` : null,
6452
+ (normalizedType === "Int" || normalizedType === "Float") && !constantStructure.baseImports.includes(normalizedType) ? `missing ${normalizedType} import from "akanjs/base"` : null,
6453
+ workflowBooleanInput(plan.inputs.includeInLight) === true && fieldCount(constantStructure.lightProjectionFields, fieldName) !== 1 ? `field "${fieldName}" is not present exactly once in Light${moduleClassName}` : null,
6454
+ ...index.diagnostics.filter((diagnostic) => diagnostic.severity === "error" && diagnostic.context?.paths?.includes(constantPath)).map((diagnostic) => diagnostic.message)
6455
+ ].filter((failure) => failure !== null);
6456
+ const constantValid = constantFailures.length === 0;
6457
+ postApplyChecks.push(structureCheck(constantValid ? "workflow-post-apply-constant-shape-valid" : "workflow-post-apply-structure-invalid", constantPath, constantValid ? "passed" : "failed", constantValid ? `${inputClassName} keeps via structure, builder usage, imports, and requested field presence.` : constantFailures.join(" ")));
6458
+ if (!constantValid) {
6459
+ diagnostics.push(postApplyDiagnostic("workflow-post-apply-structure-invalid", constantFailures.join(" "), constantPath));
6460
+ }
6461
+ const dictionaryContent = await workspace.readFile(dictionaryPath);
6462
+ const dictionaryStructure = inspectDictionaryStructure(dictionaryContent, moduleClassName);
6463
+ const dictionaryFailures = [
6464
+ !dictionaryStructure.parseValid ? "dictionary file does not parse" : null,
6465
+ !dictionaryStructure.modelObjectFound ? `.model<${moduleClassName}> object was not found` : null,
6466
+ dictionaryStructure.modelObjectFound && !dictionaryStructure.chainOrderValid ? `.model(), .slice(), .enum(), .error(), and .translate() chain order is broken: ${dictionaryStructure.chainMethods.join(" -> ")}` : null,
6467
+ fieldCount(dictionaryStructure.fields, fieldName) !== 1 ? `field "${fieldName}" appears ${fieldCount(dictionaryStructure.fields, fieldName)} time(s) in .model<${moduleClassName}>` : null,
6468
+ ...index.diagnostics.filter((diagnostic) => diagnostic.severity === "error" && diagnostic.context?.paths?.includes(dictionaryPath)).map((diagnostic) => diagnostic.message)
6469
+ ].filter((failure) => failure !== null);
6470
+ const dictionaryValid = dictionaryFailures.length === 0;
6471
+ postApplyChecks.push(structureCheck(dictionaryValid ? "workflow-post-apply-dictionary-shape-valid" : "workflow-post-apply-structure-invalid", dictionaryPath, dictionaryValid ? "passed" : "failed", dictionaryValid ? `.model<${moduleClassName}> keeps the requested field inside the model object and preserves dictionary chain order.` : dictionaryFailures.join(" ")));
6472
+ if (!dictionaryValid) {
6473
+ diagnostics.push(postApplyDiagnostic("workflow-post-apply-structure-invalid", dictionaryFailures.join(" "), dictionaryPath));
6474
+ }
6475
+ const constantOrderValid = fieldOrderValid(constantNames, fieldName);
6476
+ const dictionaryOrderValid = fieldOrderValid(dictionaryStructure.fields, fieldName);
6477
+ const orderValid = constantOrderValid && dictionaryOrderValid;
6478
+ postApplyChecks.push(structureCheck("workflow-post-apply-field-order-valid", `${constantPath}, ${dictionaryPath}`, orderValid ? "passed" : "failed", orderValid ? `Field "${fieldName}" follows the shared priority ordering policy.` : `Field "${fieldName}" is present but does not match the shared priority ordering policy.`));
6479
+ if (!orderValid) {
6480
+ diagnostics.push(postApplyWarning("workflow-post-apply-field-order-mismatch", `Field "${fieldName}" is present but does not match the shared priority ordering policy.`, `${constantPath}, ${dictionaryPath}`));
6481
+ }
6482
+ return { diagnostics, postApplyChecks };
6483
+ };
5678
6484
  var resolveWorkflowSys = async (workspace, target) => {
5679
6485
  if (!target)
5680
6486
  return null;
@@ -5711,7 +6517,7 @@ var addFieldUiSurfaceInspection = (plan) => {
5711
6517
  const policy = addFieldUiPolicyForType(typeName ?? "String");
5712
6518
  const surfaces = workflowStringArrayInput(plan.inputs.surfaces);
5713
6519
  const templateRequested = surfaces?.includes("template") ?? false;
5714
- const moduleClassName = capitalize2(module);
6520
+ const moduleClassName = moduleComponentName(module);
5715
6521
  const target = `${app ? `apps/${app}` : "*"}/${moduleSourcePaths(module).template}`;
5716
6522
  return {
5717
6523
  recommendations: [
@@ -5880,6 +6686,11 @@ class WorkflowExecutor {
5880
6686
  postApplyChecks.push(...result.postApplyChecks ?? []);
5881
6687
  diagnostics.push(...result.diagnostics ?? []);
5882
6688
  }
6689
+ if (!sourceChangeError(diagnostics)) {
6690
+ const result = await checkAddFieldStructure(this.workspace, plan);
6691
+ postApplyChecks.push(...result.postApplyChecks ?? []);
6692
+ diagnostics.push(...result.diagnostics ?? []);
6693
+ }
5883
6694
  const recommendationDiagnostics = await Promise.all(recommendations.map((recommendation) => checkRecommendationPath(this.workspace, recommendation)));
5884
6695
  diagnostics.push(...recommendationDiagnostics.filter((diagnostic) => !!diagnostic));
5885
6696
  }
@@ -5898,7 +6709,7 @@ class WorkflowExecutor {
5898
6709
  }
5899
6710
  }
5900
6711
  // pkgs/@akanjs/devkit/workflow/plan.ts
5901
- import { capitalize as capitalize3 } from "akanjs/common";
6712
+ import { capitalize as capitalize2 } from "akanjs/common";
5902
6713
  var surfaceModes = new Set(["infer", "include", "skip"]);
5903
6714
  var parseStringList = (value) => {
5904
6715
  if (Array.isArray(value)) {
@@ -6003,7 +6814,7 @@ var createAddFieldRecommendations = (inputs) => {
6003
6814
  kind: "placement",
6004
6815
  target: paths.constant,
6005
6816
  confidence: "high",
6006
- message: `Insert ${field}: field(${normalizedType}) in ${capitalize3(module)}Input.`
6817
+ message: `Insert ${field}: field(${normalizedType}) in ${capitalize2(module)}Input.`
6007
6818
  },
6008
6819
  {
6009
6820
  code: "add-field-placement-dictionary",
@@ -6035,7 +6846,7 @@ var createAddFieldRecommendations = (inputs) => {
6035
6846
  code: "add-field-light-projection-choice",
6036
6847
  kind: "manual-action",
6037
6848
  target: paths.constant,
6038
- action: `Pass includeInLight=true when ${field} should appear in Light${capitalize3(module)} list/card projections.`,
6849
+ action: `Pass includeInLight=true when ${field} should appear in Light${capitalize2(module)} list/card projections.`,
6039
6850
  confidence: "medium",
6040
6851
  message: `Light projection exposure for ${module}.${field} is not selected yet.`
6041
6852
  }
@@ -6046,7 +6857,7 @@ var createAddFieldRecommendations = (inputs) => {
6046
6857
  kind: "placement",
6047
6858
  target: paths.constant,
6048
6859
  confidence: "high",
6049
- message: `Add ${field} to Light${capitalize3(module)} projection fields.`
6860
+ message: `Add ${field} to Light${capitalize2(module)} projection fields.`
6050
6861
  }
6051
6862
  ] : [],
6052
6863
  ...surfaces && !templateRequested ? [
@@ -6062,7 +6873,7 @@ var createAddFieldRecommendations = (inputs) => {
6062
6873
  code: "add-field-ui-manual-review",
6063
6874
  kind: "manual-action",
6064
6875
  target: paths.template,
6065
- action: `Review ${app}:${module} UI after apply. Template auto-edit requires a generated ${module}Form hook and Layout.Template field list; Unit/View are not auto-edited because list/card placement depends on local layout. Candidate positions: Layout.Template before the closing tag, Light${capitalize3(module)} projection array for list data, and Unit/View card sections for display.`,
6876
+ action: `Review ${app}:${module} UI after apply. Template auto-edit requires a generated ${module}Form hook and Layout.Template field list; Unit/View are not auto-edited because list/card placement depends on local layout. Candidate positions: Layout.Template before the closing tag, Light${capitalize2(module)} projection array for list data, and Unit/View card sections for display.`,
6066
6877
  confidence: "medium",
6067
6878
  message: "UI manual review includes the reason auto-edit may be skipped and candidate insertion positions."
6068
6879
  },
@@ -6280,6 +7091,7 @@ var renderRecommendation = (recommendation) => {
6280
7091
  return `- [${recommendation.kind}]${target} ${recommendation.message}${action}`;
6281
7092
  };
6282
7093
  var renderDiagnostic = (diagnostic) => `- [${diagnostic.severity}] ${diagnostic.code}: ${diagnostic.message}`;
7094
+ var renderNextAction = (action) => `- \`${action.command}\`: ${action.reason}`;
6283
7095
  var applySourceStatus = (report) => report.diagnostics.some((diagnostic) => diagnostic.severity === "error" && (diagnostic.failureScope === "source-change" || !diagnostic.failureScope || diagnostic.failureScope === "unknown")) ? "failed" : "passed";
6284
7096
  var renderWorkflowApplyReport = (report) => {
6285
7097
  const manualReviewItems = [
@@ -6328,7 +7140,7 @@ var renderWorkflowApplyReport = (report) => {
6328
7140
  ...report.recommendations.length ? report.recommendations.slice(0, 3).map(renderRecommendation) : ["- none"],
6329
7141
  "",
6330
7142
  "## Next Actions",
6331
- ...report.nextActions.length ? report.nextActions.map((action) => `- \`${action.command}\`: ${action.reason}`) : ["- none"],
7143
+ ...report.nextActions.length ? report.nextActions.slice(0, 3).map(renderNextAction) : ["- none"],
6332
7144
  ""
6333
7145
  ].join(`
6334
7146
  `);
@@ -6409,6 +7221,66 @@ var renderWorkflowRunArtifact = (artifact, format = "markdown") => {
6409
7221
  }
6410
7222
  return jsonText(artifact);
6411
7223
  };
7224
+ // pkgs/@akanjs/devkit/workflow/rolloutGate.ts
7225
+ var toolingRolloutCandidates = [
7226
+ {
7227
+ packageName: "typescript",
7228
+ status: "allowed",
7229
+ role: "Primary TypeScript Compiler API baseline for AST locator, text splice, and reparse checks.",
7230
+ adoptionGate: "Already present; keep using stable Bun-compatible package builds."
7231
+ },
7232
+ {
7233
+ packageName: "@ttsc/graph",
7234
+ status: "reference-only",
7235
+ role: "Source-free graph shape and lazy resident model reference.",
7236
+ adoptionGate: "Do not add as an Akan runtime dependency without a separate proposal or milestone update."
7237
+ },
7238
+ {
7239
+ packageName: "ts-morph",
7240
+ status: "experiment-only",
7241
+ role: "Prototype candidate for complex object literal insertion, import update, and class traversal.",
7242
+ adoptionGate: "Use only in isolated prototypes until package size and formatting churn are measured."
7243
+ },
7244
+ {
7245
+ packageName: "ast-grep",
7246
+ status: "experiment-only",
7247
+ role: "Prototype candidate for shape detection, CI rules, and migration rules.",
7248
+ adoptionGate: "Use as a local rule/check experiment, not as the edit engine."
7249
+ },
7250
+ {
7251
+ packageName: "recast",
7252
+ status: "experiment-only",
7253
+ role: "Prototype candidate for formatting preservation.",
7254
+ adoptionGate: "Low priority; require proof that formatting churn is lower than the baseline."
7255
+ },
7256
+ {
7257
+ packageName: "typescript-go",
7258
+ status: "blocked",
7259
+ role: "TypeScript-Go toolchain transition placeholder.",
7260
+ adoptionGate: "Out of scope for Season 2 rollout."
7261
+ },
7262
+ {
7263
+ packageName: "@typescript/native-preview",
7264
+ status: "blocked",
7265
+ role: "TypeScript-Go native preview package placeholder.",
7266
+ adoptionGate: "Out of scope for Season 2 rollout."
7267
+ }
7268
+ ];
7269
+ var toolingRolloutGate = {
7270
+ schemaVersion: 1,
7271
+ strategy: "reference-first-dependency-later",
7272
+ dependencyPolicy: "Season 2 keeps new AST and graph tooling as references or isolated experiments until a separate proposal or milestone update approves adoption.",
7273
+ gateConditions: [
7274
+ "Works in Bun runtime and published package artifacts.",
7275
+ "Does not break dist/pkgs package verification.",
7276
+ "Keeps generated source formatting churn limited.",
7277
+ "Reduces add-field regression fixture failures compared with the current TypeScript API baseline.",
7278
+ "Does not move MCP responses toward returning source bodies."
7279
+ ],
7280
+ candidates: toolingRolloutCandidates
7281
+ };
7282
+ var isRestrictedCandidate = (candidate) => candidate.status !== "allowed";
7283
+ var restrictedCandidates = new Map(toolingRolloutCandidates.filter(isRestrictedCandidate).map((candidate) => [candidate.packageName, candidate]));
6412
7284
  // pkgs/@akanjs/devkit/akanContext.ts
6413
7285
  var resourceList = [
6414
7286
  { uri: "akan://docs/framework", name: "Akan framework guide", mimeType: "text/markdown" },
@@ -6551,7 +7423,7 @@ var planInputString = (plan2, key) => {
6551
7423
  var expandWorkflowTarget = (target, plan2) => {
6552
7424
  const app = planInputString(plan2, "app");
6553
7425
  const module = planInputString(plan2, "module");
6554
- const moduleClass = module ? capitalize4(module) : "<Module>";
7426
+ const moduleClass = module ? capitalize3(module) : "<Module>";
6555
7427
  return target.replace(/^\*\//, app ? `apps/${app}/` : "").replaceAll("<module>", module || "<module>").replaceAll("<Module>", moduleClass);
6556
7428
  };
6557
7429
  var workflowPathsForPlan = (plan2) => plan2.predictedChanges.map((change) => expandWorkflowTarget(change.target, plan2));
@@ -6573,8 +7445,8 @@ var loadWorkflowContextPaths = async (workspace, runIdOrPlan, changedFiles) => {
6573
7445
  const paths = [...changedFiles];
6574
7446
  if (!runIdOrPlan)
6575
7447
  return paths;
6576
- const inputPath = path10.isAbsolute(runIdOrPlan) ? runIdOrPlan : path10.join(workspace.workspaceRoot, runIdOrPlan);
6577
- const artifact = await safeReadJson(inputPath) ?? await safeReadJson(path10.join(workspace.workspaceRoot, workflowRunArtifactPath(runIdOrPlan)));
7448
+ const inputPath = path11.isAbsolute(runIdOrPlan) ? runIdOrPlan : path11.join(workspace.workspaceRoot, runIdOrPlan);
7449
+ const artifact = await safeReadJson(inputPath) ?? await safeReadJson(path11.join(workspace.workspaceRoot, workflowRunArtifactPath(runIdOrPlan)));
6578
7450
  if (artifact && isWorkflowRunArtifact(artifact))
6579
7451
  paths.push(...workflowPathsForArtifact(artifact));
6580
7452
  return [...new Set(paths.filter(Boolean))];
@@ -6592,9 +7464,9 @@ var isWorkflowRelatedDiagnostic = (diagnostic, workflowPaths) => {
6592
7464
  });
6593
7465
  };
6594
7466
  var readGeneratedSyncStates = async (workspace) => {
6595
- const syncDir = path10.join(workspace.workspaceRoot, workflowSyncDir);
7467
+ const syncDir = path11.join(workspace.workspaceRoot, workflowSyncDir);
6596
7468
  const entries = await safeReadDir(syncDir);
6597
- const states = await Promise.all(entries.filter((entry) => entry.isFile() && entry.name.endsWith(".json")).map((entry) => safeReadJson(path10.join(syncDir, entry.name))));
7469
+ const states = await Promise.all(entries.filter((entry) => entry.isFile() && entry.name.endsWith(".json")).map((entry) => safeReadJson(path11.join(syncDir, entry.name))));
6598
7470
  return states.filter((state) => !!state && state.schemaVersion === 1 && typeof state.target === "string" && typeof state.syncedAt === "string");
6599
7471
  };
6600
7472
  var generatedFreshnessFromStates = async (workspace) => {
@@ -6631,12 +7503,12 @@ var parseAbstractSummary = (relativePath, content, includeContent) => {
6631
7503
  };
6632
7504
  };
6633
7505
  var readFiles = async (dirPath) => (await safeReadDir(dirPath)).filter((entry) => entry.isFile()).map((entry) => entry.name).sort();
6634
- var getRelative = (workspace, absolutePath) => path10.relative(workspace.workspaceRoot, absolutePath).replaceAll(path10.sep, "/");
7506
+ var getRelative = (workspace, absolutePath) => path11.relative(workspace.workspaceRoot, absolutePath).replaceAll(path11.sep, "/");
6635
7507
  var createModuleContext = async (workspace, sys2, kind, folderName, moduleName, includeAbstractContent) => {
6636
- const modulePath = kind === "scalar" ? path10.join(sys2.cwdPath, "lib", "__scalar", moduleName) : path10.join(sys2.cwdPath, "lib", folderName);
7508
+ const modulePath = kind === "scalar" ? path11.join(sys2.cwdPath, "lib", "__scalar", moduleName) : path11.join(sys2.cwdPath, "lib", folderName);
6637
7509
  const relativePath = getRelative(workspace, modulePath);
6638
7510
  const abstractPath = `${relativePath}/${moduleName}.abstract.md`;
6639
- const abstractContent = await safeReadText(path10.join(workspace.workspaceRoot, abstractPath));
7511
+ const abstractContent = await safeReadText(path11.join(workspace.workspaceRoot, abstractPath));
6640
7512
  return {
6641
7513
  kind,
6642
7514
  name: moduleName,
@@ -6652,7 +7524,7 @@ var getSysModules = async (workspace, sys2, {
6652
7524
  includeAbstractContent = false,
6653
7525
  module: moduleFilter
6654
7526
  } = {}) => {
6655
- const libPath = path10.join(sys2.cwdPath, "lib");
7527
+ const libPath = path11.join(sys2.cwdPath, "lib");
6656
7528
  const entries = await safeReadDir(libPath);
6657
7529
  const modules = [];
6658
7530
  for (const entry of entries) {
@@ -6666,24 +7538,24 @@ var getSysModules = async (workspace, sys2, {
6666
7538
  const serviceName = entry.name.replace(/^_+/, "");
6667
7539
  if (moduleFilter && moduleFilter !== serviceName && moduleFilter !== entry.name)
6668
7540
  continue;
6669
- if (!await FileSys.fileExists(path10.join(libPath, entry.name, `${serviceName}.service.ts`)))
7541
+ if (!await FileSys.fileExists(path11.join(libPath, entry.name, `${serviceName}.service.ts`)))
6670
7542
  continue;
6671
7543
  modules.push(await createModuleContext(workspace, sys2, "service", entry.name, serviceName, includeAbstractContent));
6672
7544
  } else {
6673
7545
  if (moduleFilter && moduleFilter !== entry.name)
6674
7546
  continue;
6675
- if (!await FileSys.fileExists(path10.join(libPath, entry.name, `${entry.name}.constant.ts`)))
7547
+ if (!await FileSys.fileExists(path11.join(libPath, entry.name, `${entry.name}.constant.ts`)))
6676
7548
  continue;
6677
7549
  modules.push(await createModuleContext(workspace, sys2, "domain", entry.name, entry.name, includeAbstractContent));
6678
7550
  }
6679
7551
  }
6680
- const scalarRoot = path10.join(libPath, "__scalar");
7552
+ const scalarRoot = path11.join(libPath, "__scalar");
6681
7553
  for (const entry of await safeReadDir(scalarRoot)) {
6682
7554
  if (!entry.isDirectory() || entry.name.startsWith("_"))
6683
7555
  continue;
6684
7556
  if (moduleFilter && moduleFilter !== entry.name)
6685
7557
  continue;
6686
- if (!await FileSys.fileExists(path10.join(scalarRoot, entry.name, `${entry.name}.constant.ts`)))
7558
+ if (!await FileSys.fileExists(path11.join(scalarRoot, entry.name, `${entry.name}.constant.ts`)))
6687
7559
  continue;
6688
7560
  modules.push(await createModuleContext(workspace, sys2, "scalar", entry.name, entry.name, includeAbstractContent));
6689
7561
  }
@@ -6695,7 +7567,7 @@ var getSysContext = async (workspace, type, name, options) => {
6695
7567
  type,
6696
7568
  name,
6697
7569
  path: `${type}s/${name}`,
6698
- hasConfig: await FileSys.fileExists(path10.join(sys2.cwdPath, "akan.config.ts")),
7570
+ hasConfig: await FileSys.fileExists(path11.join(sys2.cwdPath, "akan.config.ts")),
6699
7571
  modules: await getSysModules(workspace, sys2, {
6700
7572
  includeAbstractContent: options.includeAbstractContent,
6701
7573
  module: options.module
@@ -6706,13 +7578,13 @@ var getSysContext = async (workspace, type, name, options) => {
6706
7578
  class AkanContextAnalyzer {
6707
7579
  static async analyze(workspace, options = {}) {
6708
7580
  const [appNames, libNames, pkgNames] = await workspace.getExecs();
6709
- const rootPackageJson = await safeReadJson(path10.join(workspace.workspaceRoot, "package.json"));
7581
+ const rootPackageJson = await safeReadJson(path11.join(workspace.workspaceRoot, "package.json"));
6710
7582
  const filteredApps = options.app ? appNames.filter((name) => name === options.app) : appNames;
6711
7583
  const [apps, libs, pkgs] = await Promise.all([
6712
7584
  Promise.all(filteredApps.map((name) => getSysContext(workspace, "app", name, options))),
6713
7585
  Promise.all(libNames.map((name) => getSysContext(workspace, "lib", name, options))),
6714
7586
  Promise.all(pkgNames.map(async (name) => {
6715
- const packageJson = await safeReadJson(path10.join(workspace.workspaceRoot, "pkgs", name, "package.json"));
7587
+ const packageJson = await safeReadJson(path11.join(workspace.workspaceRoot, "pkgs", name, "package.json"));
6716
7588
  return {
6717
7589
  name,
6718
7590
  path: `pkgs/${name}`,
@@ -6745,7 +7617,7 @@ class AkanContextAnalyzer {
6745
7617
  repairAction("format", "akan repair format --target <app-or-lib-or-pkg>", "Run the formatter/linter repair path.", true)
6746
7618
  ];
6747
7619
  for (const app of context.apps) {
6748
- const appPath = path10.join(workspace.workspaceRoot, app.path);
7620
+ const appPath = path11.join(workspace.workspaceRoot, app.path);
6749
7621
  for (const entry of await safeReadDir(appPath)) {
6750
7622
  const allowed = entry.isDirectory() ? appRootAllowDirs.has(entry.name) : appRootAllowFiles.has(entry.name);
6751
7623
  if (!allowed) {
@@ -6769,7 +7641,7 @@ class AkanContextAnalyzer {
6769
7641
  severity: strict ? "error" : "warning",
6770
7642
  code: "module-abstract-missing",
6771
7643
  path: module.abstract.path,
6772
- message: `${capitalize4(module.kind)} module ${sys2.name}:${module.name} should include ${module.abstract.path}`,
7644
+ message: `${capitalize3(module.kind)} module ${sys2.name}:${module.name} should include ${module.abstract.path}`,
6773
7645
  repairActions: [action]
6774
7646
  });
6775
7647
  repairActions.push(action);
@@ -6781,14 +7653,14 @@ class AkanContextAnalyzer {
6781
7653
  severity: "error",
6782
7654
  code: "module-shape-invalid",
6783
7655
  path: module.path,
6784
- message: `${capitalize4(module.kind)} module ${sys2.name}:${module.name} is missing required files: ${missingFiles.join(", ")}`,
7656
+ message: `${capitalize3(module.kind)} module ${sys2.name}:${module.name} is missing required files: ${missingFiles.join(", ")}`,
6785
7657
  repairActions: [action]
6786
7658
  });
6787
7659
  repairActions.push(action);
6788
7660
  }
6789
7661
  if (module.kind !== "service" && module.files.includes(`${module.name}.dictionary.ts`)) {
6790
- const constantPath = path10.join(workspace.workspaceRoot, module.path, `${module.name}.constant.ts`);
6791
- const dictionaryPath = path10.join(workspace.workspaceRoot, module.path, `${module.name}.dictionary.ts`);
7662
+ const constantPath = path11.join(workspace.workspaceRoot, module.path, `${module.name}.constant.ts`);
7663
+ const dictionaryPath = path11.join(workspace.workspaceRoot, module.path, `${module.name}.dictionary.ts`);
6792
7664
  const [constantContent, dictionaryContent] = await Promise.all([
6793
7665
  safeReadText(constantPath),
6794
7666
  safeReadText(dictionaryPath)
@@ -6860,6 +7732,519 @@ class AkanContextAnalyzer {
6860
7732
  `;
6861
7733
  }
6862
7734
  }
7735
+ // pkgs/@akanjs/devkit/akanMcpContract.ts
7736
+ import path12 from "path";
7737
+ var emptySchema = { type: "object", properties: {} };
7738
+ var stringProperty = { type: "string" };
7739
+ var booleanProperty = { type: "boolean" };
7740
+ var objectProperty = { type: "object", additionalProperties: true };
7741
+ var stringArrayProperty = { type: "array", items: stringProperty };
7742
+ var inspectAkanContextRequestTypes = [
7743
+ "workspaceOverview",
7744
+ "moduleContext",
7745
+ "fieldInsertionContext",
7746
+ "workflowDiagnostics",
7747
+ "escape"
7748
+ ];
7749
+ var inspectAkanContextRequestTypeProperty = { type: "string", enum: inspectAkanContextRequestTypes };
7750
+ var inspectAkanContextRequestBranches = [
7751
+ {
7752
+ type: "object",
7753
+ properties: { type: { const: "workspaceOverview" } },
7754
+ required: ["type"]
7755
+ },
7756
+ {
7757
+ type: "object",
7758
+ properties: { type: { const: "moduleContext" }, app: stringProperty, module: stringProperty },
7759
+ required: ["type", "app", "module"]
7760
+ },
7761
+ {
7762
+ type: "object",
7763
+ properties: {
7764
+ type: { const: "fieldInsertionContext" },
7765
+ app: stringProperty,
7766
+ module: stringProperty,
7767
+ field: stringProperty,
7768
+ fieldType: stringProperty
7769
+ },
7770
+ required: ["type", "app", "module", "field", "fieldType"]
7771
+ },
7772
+ {
7773
+ type: "object",
7774
+ properties: { type: { const: "workflowDiagnostics" }, runIdOrPlan: stringProperty },
7775
+ required: ["type", "runIdOrPlan"]
7776
+ },
7777
+ {
7778
+ type: "object",
7779
+ properties: { type: { const: "escape" }, reason: stringProperty, nextStep: stringProperty },
7780
+ required: ["type", "reason"]
7781
+ }
7782
+ ];
7783
+ var inspectAkanContextInputSchema = {
7784
+ type: "object",
7785
+ properties: {
7786
+ question: {
7787
+ ...stringProperty,
7788
+ description: "The user-facing question the agent is trying to answer before reading source bodies."
7789
+ },
7790
+ draft: {
7791
+ type: "object",
7792
+ properties: {
7793
+ reason: stringProperty,
7794
+ type: inspectAkanContextRequestTypeProperty
7795
+ },
7796
+ required: ["reason", "type"]
7797
+ },
7798
+ review: {
7799
+ ...stringProperty,
7800
+ description: "A short self-review explaining why this minimal request is sufficient."
7801
+ },
7802
+ request: {
7803
+ type: "object",
7804
+ properties: {
7805
+ type: inspectAkanContextRequestTypeProperty,
7806
+ app: stringProperty,
7807
+ module: stringProperty,
7808
+ field: stringProperty,
7809
+ fieldType: stringProperty,
7810
+ runIdOrPlan: stringProperty,
7811
+ reason: stringProperty,
7812
+ nextStep: stringProperty
7813
+ },
7814
+ required: ["type"],
7815
+ oneOf: inspectAkanContextRequestBranches
7816
+ }
7817
+ },
7818
+ required: ["question", "draft", "review", "request"]
7819
+ };
7820
+ var isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
7821
+ var slugPart = (value) => typeof value === "string" ? value.trim().replace(/[^a-zA-Z0-9]+/g, "-").replace(/^-+|-+$/g, "").toLowerCase() : "";
7822
+ var optionalString = (args, key) => {
7823
+ const value = args[key];
7824
+ return typeof value === "string" && value ? value : undefined;
7825
+ };
7826
+ var nestedStringArg = (args, key) => {
7827
+ const value = args[key];
7828
+ if (typeof value !== "string" || !value)
7829
+ throw new Error(`MCP tool argument "${key}" is required.`);
7830
+ return value;
7831
+ };
7832
+ var isInspectAkanContextRequestType = (value) => typeof value === "string" && inspectAkanContextRequestTypes.includes(value);
7833
+ var parseJsonOutput = (output) => JSON.parse(output);
7834
+ var workspacePath = (workspace, filePath) => path12.isAbsolute(filePath) ? filePath : path12.join(workspace.workspaceRoot, filePath);
7835
+ var defaultWorkflowPlanPath = (workflow, inputs) => {
7836
+ const slug = [
7837
+ slugPart(workflow),
7838
+ slugPart(inputs.app),
7839
+ slugPart(inputs.module),
7840
+ slugPart(inputs.field),
7841
+ slugPart(inputs.scalar),
7842
+ slugPart(inputs.surface),
7843
+ slugPart(inputs.mutation),
7844
+ slugPart(inputs.slice)
7845
+ ].filter(Boolean).join("-");
7846
+ return `.akan/workflows/plans/${slug || "workflow-plan"}.json`;
7847
+ };
7848
+ var applyFirstPolicy = {
7849
+ mode: "apply-first",
7850
+ directSourceEdits: "fallback-only",
7851
+ applyRequiredWhen: ["plan_workflow returns planPath", "plan_workflow returns next.tool=apply_workflow"],
7852
+ validationRequiredAfterApply: ["validationTarget", "applyReportPath"],
7853
+ fallbackAllowedWhen: [
7854
+ "list_workflows and explain_workflow show no matching workflow",
7855
+ "apply_workflow reports unsupported/no-op/failed diagnostics that require manual action",
7856
+ "recommendations include manual-action follow-up after workflow apply and repairs"
7857
+ ],
7858
+ baselineDiagnosticsPolicy: "Do not fix unrelated baselineDiagnostics unless the user asks."
7859
+ };
7860
+ var stringArg = (args, key) => {
7861
+ const value = args[key];
7862
+ if (typeof value !== "string" || !value)
7863
+ throw new Error(`MCP tool argument "${key}" is required.`);
7864
+ return value;
7865
+ };
7866
+ var workflowInputsArg = (args) => {
7867
+ const value = args.inputs;
7868
+ if (!value || typeof value !== "object" || Array.isArray(value))
7869
+ return {};
7870
+ return value;
7871
+ };
7872
+ var inspectAkanContextPropsArg = (args) => {
7873
+ const question = stringArg(args, "question");
7874
+ const review = stringArg(args, "review");
7875
+ if (!isRecord(args.draft))
7876
+ throw new Error('MCP tool argument "draft" is required.');
7877
+ if (!isRecord(args.request))
7878
+ throw new Error('MCP tool argument "request" is required.');
7879
+ if (!isInspectAkanContextRequestType(args.draft.type)) {
7880
+ throw new Error('MCP tool argument "draft.type" must be a supported inspect_akan_context request type.');
7881
+ }
7882
+ if (!isInspectAkanContextRequestType(args.request.type)) {
7883
+ throw new Error('MCP tool argument "request.type" must be a supported inspect_akan_context request type.');
7884
+ }
7885
+ const draft = { reason: nestedStringArg(args.draft, "reason"), type: args.draft.type };
7886
+ const request = args.request;
7887
+ if (request.type === "workspaceOverview")
7888
+ return { question, draft, review, request: { type: request.type } };
7889
+ if (request.type === "moduleContext")
7890
+ return {
7891
+ question,
7892
+ draft,
7893
+ review,
7894
+ request: {
7895
+ type: request.type,
7896
+ app: nestedStringArg(request, "app"),
7897
+ module: nestedStringArg(request, "module")
7898
+ }
7899
+ };
7900
+ if (request.type === "fieldInsertionContext")
7901
+ return {
7902
+ question,
7903
+ draft,
7904
+ review,
7905
+ request: {
7906
+ type: request.type,
7907
+ app: nestedStringArg(request, "app"),
7908
+ module: nestedStringArg(request, "module"),
7909
+ field: nestedStringArg(request, "field"),
7910
+ fieldType: nestedStringArg(request, "fieldType")
7911
+ }
7912
+ };
7913
+ if (request.type === "workflowDiagnostics")
7914
+ return {
7915
+ question,
7916
+ draft,
7917
+ review,
7918
+ request: { type: request.type, runIdOrPlan: nestedStringArg(request, "runIdOrPlan") }
7919
+ };
7920
+ return {
7921
+ question,
7922
+ draft,
7923
+ review,
7924
+ request: {
7925
+ type: "escape",
7926
+ reason: nestedStringArg(request, "reason"),
7927
+ nextStep: optionalString(request, "nextStep")
7928
+ }
7929
+ };
7930
+ };
7931
+ var inspectDiagnostic = (severity, code, message) => ({ severity, code, message });
7932
+ var moduleEvidence = (module) => ({
7933
+ kind: "module",
7934
+ target: `${module.sysName}:${module.name}`,
7935
+ path: module.path,
7936
+ summary: `${module.kind} module at ${module.path} with ${module.files.length} source file(s).`
7937
+ });
7938
+ var moduleCandidate = (module) => ({
7939
+ app: module.sysName,
7940
+ sysType: module.sysType,
7941
+ module: module.name,
7942
+ kind: module.kind,
7943
+ path: module.path,
7944
+ files: module.files
7945
+ });
7946
+ var readonlyMcpTools = [
7947
+ {
7948
+ name: "inspect_akan_context",
7949
+ description: "Read-only typed context inspection. Use question -> draft -> review -> request before source body reads; choose fieldInsertionContext for add-field evidence and escape when source body or outside evidence is required.",
7950
+ inputSchema: inspectAkanContextInputSchema
7951
+ },
7952
+ {
7953
+ name: "get_workspace_summary",
7954
+ description: "Legacy broad workspace summary. Prefer inspect_akan_context.workspaceOverview for typed source-body-free evidence.",
7955
+ inputSchema: emptySchema
7956
+ },
7957
+ {
7958
+ name: "list_apps",
7959
+ description: "List Akan apps from the workspace context without reading source bodies.",
7960
+ inputSchema: emptySchema
7961
+ },
7962
+ {
7963
+ name: "list_modules",
7964
+ description: "List Akan modules across apps and libs; use inspect_akan_context.moduleContext for typed evidence.",
7965
+ inputSchema: emptySchema
7966
+ },
7967
+ {
7968
+ name: "get_module_context",
7969
+ description: "Legacy broad module context. Pass app in monorepos; prefer inspect_akan_context.moduleContext or fieldInsertionContext for typed add-field evidence.",
7970
+ inputSchema: { type: "object", properties: { app: stringProperty, module: stringProperty }, required: ["module"] }
7971
+ },
7972
+ {
7973
+ name: "get_guideline",
7974
+ description: "Return an Akan agent guideline resource by name.",
7975
+ inputSchema: { type: "object", properties: { name: stringProperty }, required: ["name"] }
7976
+ },
7977
+ {
7978
+ name: "explain_command",
7979
+ description: "Explain one Akan CLI command and its agent-facing workflow policy.",
7980
+ inputSchema: { type: "object", properties: { command: stringProperty }, required: ["command"] }
7981
+ },
7982
+ {
7983
+ name: "doctor_workspace",
7984
+ description: "Report workspace diagnostics, optionally split into baseline and workflow scopes.",
7985
+ inputSchema: {
7986
+ type: "object",
7987
+ properties: { strict: booleanProperty, runIdOrPlan: stringProperty, changedFiles: stringArrayProperty }
7988
+ }
7989
+ },
7990
+ {
7991
+ name: "get_validation_contract",
7992
+ description: "Return validation, artifact chain, and apply-first fallback policy.",
7993
+ inputSchema: emptySchema
7994
+ }
7995
+ ];
7996
+ var planMcpTools = [
7997
+ {
7998
+ name: "list_workflows",
7999
+ description: "List available read-only workflow specs before creating a plan.",
8000
+ inputSchema: emptySchema
8001
+ },
8002
+ {
8003
+ name: "explain_workflow",
8004
+ description: "Explain one workflow's inputs, predicted changes, validation, and completion criteria.",
8005
+ inputSchema: { type: "object", properties: { workflow: stringProperty }, required: ["workflow"] }
8006
+ },
8007
+ {
8008
+ name: "plan_workflow",
8009
+ description: "Create a read-only workflow plan after context inspection and return planPath plus next.tool=apply_workflow.",
8010
+ inputSchema: {
8011
+ type: "object",
8012
+ properties: { workflow: stringProperty, inputs: objectProperty, out: stringProperty },
8013
+ required: ["workflow"]
8014
+ }
8015
+ }
8016
+ ];
8017
+ var applyMcpTools = [
8018
+ {
8019
+ name: "apply_workflow",
8020
+ description: "Apply a stored workflow plan before direct edits and return validationTarget for run_validation.",
8021
+ inputSchema: {
8022
+ type: "object",
8023
+ properties: { planPath: stringProperty, dryRun: booleanProperty },
8024
+ required: ["planPath"]
8025
+ }
8026
+ },
8027
+ {
8028
+ name: "run_validation",
8029
+ description: "Validate a plan, apply report, validationTarget, or run artifact.",
8030
+ inputSchema: {
8031
+ type: "object",
8032
+ properties: { runIdOrPlan: stringProperty },
8033
+ required: ["runIdOrPlan"]
8034
+ }
8035
+ },
8036
+ {
8037
+ name: "repair_generated",
8038
+ description: "Refresh generated Akan files before direct generated-file edits.",
8039
+ inputSchema: { type: "object", properties: { app: stringProperty }, required: ["app"] }
8040
+ },
8041
+ {
8042
+ name: "repair_imports",
8043
+ description: "Run the import repair path before manual import edits.",
8044
+ inputSchema: { type: "object", properties: { target: stringProperty }, required: ["target"] }
8045
+ },
8046
+ {
8047
+ name: "repair_module_shape",
8048
+ description: "Report module-shape repair actions before direct module file fixes.",
8049
+ inputSchema: {
8050
+ type: "object",
8051
+ properties: { app: stringProperty, module: stringProperty },
8052
+ required: ["app", "module"]
8053
+ }
8054
+ }
8055
+ ];
8056
+ var listAkanMcpTools = (mode = "readonly") => {
8057
+ if (mode === "readonly")
8058
+ return readonlyMcpTools;
8059
+ if (mode === "plan")
8060
+ return [...readonlyMcpTools, ...planMcpTools];
8061
+ return [...readonlyMcpTools, ...planMcpTools, ...applyMcpTools];
8062
+ };
8063
+ var createAkanValidationContract = (listTools = listAkanMcpTools) => ({
8064
+ schemaVersion: 1,
8065
+ reports: ["WorkflowPlan", "WorkflowApplyReport", "WorkflowValidationRunReport", "RepairReport"],
8066
+ modes: {
8067
+ readonly: listTools("readonly").map((tool) => tool.name),
8068
+ plan: listTools("plan").map((tool) => tool.name),
8069
+ apply: listTools("apply").map((tool) => tool.name)
8070
+ },
8071
+ validationCommands: [
8072
+ "akan workflow validate <run-id-or-plan> --format json",
8073
+ "akan workflow report <run-id> --format json",
8074
+ "akan doctor --strict --format json"
8075
+ ],
8076
+ validationFailureScopes: ["workspace-config", "environment", "source-change", "unknown"],
8077
+ artifactChainFields: ["planPath", "applyReportPath", "repairReportPath", "runId", "validationTarget", "next"],
8078
+ diagnosticScopes: ["baseline", "workflow", "unknown"],
8079
+ validationStatuses: {
8080
+ sourceStatus: ["passed", "failed", "unknown"],
8081
+ workspaceStatus: ["passed", "failed", "unknown"],
8082
+ overallStatus: ["passed", "failed", "blocked-by-workspace-config", "blocked-by-environment"],
8083
+ knownBlockers: "Repeated workspace-config/environment failures are summarized before command output."
8084
+ },
8085
+ moduleContextInputs: {
8086
+ module: "required",
8087
+ app: "required"
8088
+ },
8089
+ generatedFreshnessStatuses: ["fresh", "stale", "missing", "unknown"],
8090
+ toolingRolloutGate,
8091
+ directEditFallbackPolicy: applyFirstPolicy,
8092
+ applyReportFields: [
8093
+ "appliedCommands",
8094
+ "recommendedValidationCommands",
8095
+ "commands",
8096
+ "recommendations",
8097
+ "validationTarget"
8098
+ ],
8099
+ repairCommands: [
8100
+ "akan repair generated --app <app-or-lib> --format json",
8101
+ "akan repair format --target <app-or-lib-or-pkg> --format json",
8102
+ "akan repair imports --target <app-or-lib-or-pkg> --format json",
8103
+ "akan repair dictionary --app <app-or-lib> --module <module> --format json",
8104
+ "akan repair module-shape --app <app-or-lib> --module <module> --format json"
8105
+ ]
8106
+ });
8107
+ var inspectAkanContext = async (workspace, args) => {
8108
+ const props = inspectAkanContextPropsArg(args);
8109
+ const diagnostics = [];
8110
+ if (props.draft.type !== props.request.type) {
8111
+ diagnostics.push(inspectDiagnostic("warning", "inspect-draft-request-mismatch", `Draft chose ${props.draft.type}, but request uses ${props.request.type}.`));
8112
+ }
8113
+ const baseResult = (type, evidence, next, data) => ({
8114
+ schemaVersion: 1,
8115
+ type,
8116
+ question: props.question,
8117
+ diagnostics,
8118
+ evidence,
8119
+ next,
8120
+ ...data ? { data } : {}
8121
+ });
8122
+ if (props.request.type === "escape") {
8123
+ return baseResult("escape", [{ kind: "escape", summary: props.request.reason }], {
8124
+ action: "escape",
8125
+ reason: props.request.reason,
8126
+ ...props.request.nextStep ? { args: { nextStep: props.request.nextStep } } : {}
8127
+ }, { reason: props.request.reason, nextStep: props.request.nextStep ?? null });
8128
+ }
8129
+ if (props.request.type === "workflowDiagnostics") {
8130
+ const doctor = await AkanContextAnalyzer.doctor(workspace, {
8131
+ strict: true,
8132
+ runIdOrPlan: workspacePath(workspace, props.request.runIdOrPlan)
8133
+ });
8134
+ diagnostics.push(...doctor.diagnostics.map((diagnostic) => ({
8135
+ severity: diagnostic.severity,
8136
+ code: diagnostic.code,
8137
+ message: diagnostic.message,
8138
+ scope: diagnostic.scope,
8139
+ context: {
8140
+ ...diagnostic.context,
8141
+ ...diagnostic.path ? { paths: [diagnostic.path] } : {}
8142
+ }
8143
+ })));
8144
+ return baseResult("workflowDiagnostics", [
8145
+ {
8146
+ kind: "workflow",
8147
+ target: props.request.runIdOrPlan,
8148
+ summary: `Workflow diagnostics status is ${doctor.status}.`
8149
+ }
8150
+ ], {
8151
+ action: doctor.status === "passed" ? "answer" : "validate",
8152
+ reason: doctor.status === "passed" ? "No strict workspace diagnostics were found for the workflow context." : "Review diagnostics before applying or manually editing source files."
8153
+ }, {
8154
+ status: doctor.status,
8155
+ baselineDiagnostics: doctor.baselineDiagnostics?.length ?? 0,
8156
+ workflowDiagnostics: doctor.workflowDiagnostics?.length ?? 0
8157
+ });
8158
+ }
8159
+ const context = await AkanContextAnalyzer.analyze(workspace, {
8160
+ app: props.request.type === "moduleContext" || props.request.type === "fieldInsertionContext" ? props.request.app : null,
8161
+ module: props.request.type === "moduleContext" || props.request.type === "fieldInsertionContext" ? props.request.module : null,
8162
+ includeAbstractContent: false
8163
+ });
8164
+ if (props.request.type === "workspaceOverview") {
8165
+ return baseResult("workspaceOverview", [
8166
+ {
8167
+ kind: "workspace",
8168
+ summary: `${context.repoName} has ${context.apps.length} app(s), ${context.libs.length} lib(s), and ${context.pkgs.length} package(s).`
8169
+ }
8170
+ ], {
8171
+ action: "inspect",
8172
+ reason: "Choose moduleContext or fieldInsertionContext for module-scoped evidence before planning a workflow.",
8173
+ tool: "inspect_akan_context"
8174
+ }, {
8175
+ repoName: context.repoName,
8176
+ apps: context.apps.map((app) => ({ name: app.name, path: app.path, modules: app.modules.length })),
8177
+ libs: context.libs.map((lib) => ({ name: lib.name, path: lib.path, modules: lib.modules.length })),
8178
+ pkgs: context.pkgs.map((pkg) => ({ name: pkg.name, path: pkg.path, version: pkg.version ?? null })),
8179
+ generatedFiles: context.generatedFiles,
8180
+ validationCommands: context.validationCommands
8181
+ });
8182
+ }
8183
+ const modules = AkanContextAnalyzer.findModules(context, props.request.module, {
8184
+ app: props.request.app ?? null
8185
+ });
8186
+ if (modules.length === 0) {
8187
+ diagnostics.push(inspectDiagnostic("error", "inspect-module-not-found", `No module matched ${props.request.app ? `${props.request.app}:` : ""}${props.request.module}.`));
8188
+ return baseResult(props.request.type, [], {
8189
+ action: "escape",
8190
+ reason: "The requested module was not found in the workspace index; inspect workspace files or clarify the target."
8191
+ }, { candidates: [] });
8192
+ }
8193
+ if (!props.request.app && modules.length > 1) {
8194
+ diagnostics.push(inspectDiagnostic("error", "inspect-module-ambiguous", `Multiple modules match "${props.request.module}". Re-run with app to disambiguate.`));
8195
+ return baseResult(props.request.type, modules.map(moduleEvidence), {
8196
+ action: "clarify",
8197
+ reason: "Multiple modules have the same name; choose an app before planning a workflow."
8198
+ }, { candidates: modules.map(moduleCandidate) });
8199
+ }
8200
+ const module = modules[0];
8201
+ if (props.request.type === "moduleContext") {
8202
+ return baseResult("moduleContext", [moduleEvidence(module)], {
8203
+ action: "inspect",
8204
+ reason: "Use fieldInsertionContext when preparing add-field or escape when source body details are required.",
8205
+ tool: "inspect_akan_context"
8206
+ }, { module: moduleCandidate(module) });
8207
+ }
8208
+ if (module.kind !== "domain") {
8209
+ diagnostics.push(inspectDiagnostic("error", "field-insertion-unsupported-module-kind", `fieldInsertionContext currently targets domain modules; ${module.sysName}:${module.name} is ${module.kind}.`));
8210
+ }
8211
+ const moduleIndex2 = await buildAkanModuleContextIndex(workspace, module, { field: props.request.field });
8212
+ diagnostics.push(...moduleIndex2.diagnostics);
8213
+ return baseResult("fieldInsertionContext", [
8214
+ moduleEvidence(module),
8215
+ {
8216
+ kind: "field-insertion",
8217
+ target: `${module.sysName}:${module.name}.${props.request.field}`,
8218
+ path: module.path,
8219
+ summary: "M2 returns source-body-free AST index evidence for constant fields, dictionary model labels, and light projection fields."
8220
+ }
8221
+ ], module.kind === "domain" ? {
8222
+ action: "plan_workflow",
8223
+ reason: "The module target is unambiguous; create an add-field workflow plan before source edits.",
8224
+ tool: "plan_workflow",
8225
+ args: {
8226
+ workflow: "add-field",
8227
+ inputs: {
8228
+ app: module.sysName,
8229
+ module: module.name,
8230
+ field: props.request.field,
8231
+ type: props.request.fieldType
8232
+ }
8233
+ }
8234
+ } : {
8235
+ action: "escape",
8236
+ reason: "This module kind is not a supported add-field target in the P1 context contract."
8237
+ }, {
8238
+ target: {
8239
+ app: module.sysName,
8240
+ module: module.name,
8241
+ field: props.request.field,
8242
+ fieldType: props.request.fieldType
8243
+ },
8244
+ files: moduleIndex2.files,
8245
+ moduleIndex: moduleIndex2
8246
+ });
8247
+ };
6863
8248
  // pkgs/@akanjs/devkit/applicationBuildReporter.ts
6864
8249
  import { Logger as Logger6 } from "akanjs/common";
6865
8250
 
@@ -6906,20 +8291,20 @@ Caused by: ${ApplicationBuildReporter.formatError(error.cause)}` : "";
6906
8291
  }
6907
8292
  // pkgs/@akanjs/devkit/applicationBuildRunner.ts
6908
8293
  import { mkdir as mkdir8, rm as rm3 } from "fs/promises";
6909
- import path35 from "path";
8294
+ import path37 from "path";
6910
8295
 
6911
8296
  // pkgs/@akanjs/devkit/frontendBuild/allRoutesBuilder.ts
6912
- import path20 from "path";
8297
+ import path22 from "path";
6913
8298
 
6914
8299
  // pkgs/@akanjs/devkit/artifact/implicitRootLayout.ts
6915
8300
  import { mkdir as mkdir3 } from "fs/promises";
6916
- import path11 from "path";
8301
+ import path13 from "path";
6917
8302
  var LAYOUT_KEY_RE = /^\.\/(.+\/)?_layout\.(tsx|ts|jsx|js)$/;
6918
8303
  async function appHasStModule(appCwdPath) {
6919
- return Bun.file(path11.join(appCwdPath, "lib", "st.ts")).exists();
8304
+ return Bun.file(path13.join(appCwdPath, "lib", "st.ts")).exists();
6920
8305
  }
6921
- var IMPLICIT_LAYOUT_DIR = path11.join(".akan", "generated", "root-layouts");
6922
- var IMPLICIT_DICT_DIR = path11.join(".akan", "generated", "dict");
8306
+ var IMPLICIT_LAYOUT_DIR = path13.join(".akan", "generated", "root-layouts");
8307
+ var IMPLICIT_DICT_DIR = path13.join(".akan", "generated", "dict");
6923
8308
  function getRootBoundarySegments(key) {
6924
8309
  const match = LAYOUT_KEY_RE.exec(key);
6925
8310
  if (!match)
@@ -6934,10 +8319,10 @@ function implicitRootLayoutKey(segments) {
6934
8319
  }
6935
8320
  function implicitRootLayoutAbsPath(appCwdPath, segments) {
6936
8321
  const filename = segments.length ? `${segments.join("__")}__root_layout.tsx` : "__root_layout.tsx";
6937
- return path11.join(path11.resolve(appCwdPath), IMPLICIT_LAYOUT_DIR, filename);
8322
+ return path13.join(path13.resolve(appCwdPath), IMPLICIT_LAYOUT_DIR, filename);
6938
8323
  }
6939
8324
  function implicitDictionaryMacroAbsPath(appCwdPath) {
6940
- return path11.join(path11.resolve(appCwdPath), IMPLICIT_DICT_DIR, "useDict.ts");
8325
+ return path13.join(path13.resolve(appCwdPath), IMPLICIT_DICT_DIR, "useDict.ts");
6941
8326
  }
6942
8327
  function isRootBoundarySegments(segments, basePaths) {
6943
8328
  const firstVisibleIndex = segments.findIndex((segment) => !/^\(.+\)$/.test(segment));
@@ -6960,7 +8345,7 @@ function findRootBoundaries(pageKeys, appCwdPath, basePaths) {
6960
8345
  const id = segments.join("/");
6961
8346
  boundaries.set(id, {
6962
8347
  sourceKey: key,
6963
- sourceAbsPath: path11.resolve(appCwdPath, "page", key.replace(/^\.\//, "")),
8348
+ sourceAbsPath: path13.resolve(appCwdPath, "page", key.replace(/^\.\//, "")),
6964
8349
  segments
6965
8350
  });
6966
8351
  }
@@ -6978,21 +8363,21 @@ function findExplicitRootLayoutAbsPath(pageKeys, appCwdPath) {
6978
8363
  const segments = getRootBoundarySegments(key);
6979
8364
  return segments !== null && segments.length === 0;
6980
8365
  });
6981
- return rootLayoutKey ? path11.resolve(appCwdPath, "page", rootLayoutKey.replace(/^\.\//, "")) : null;
8366
+ return rootLayoutKey ? path13.resolve(appCwdPath, "page", rootLayoutKey.replace(/^\.\//, "")) : null;
6982
8367
  }
6983
8368
  function routePrefixForSegments(segments) {
6984
8369
  const visible = segments.filter((segment) => !/^\(.+\)$/.test(segment));
6985
8370
  return visible[0] ?? null;
6986
8371
  }
6987
8372
  async function assertEnvClientConvention(appCwdPath, appName) {
6988
- const envPath = path11.join(appCwdPath, "env", "env.client.ts");
8373
+ const envPath = path13.join(appCwdPath, "env", "env.client.ts");
6989
8374
  if (!await Bun.file(envPath).exists()) {
6990
8375
  throw new Error(`[route-convention] app "${appName}" must provide env/env.client.ts exporting "env" for generated System.Provider`);
6991
8376
  }
6992
8377
  }
6993
8378
  async function writeGeneratedDictionaryMacroFile(appCwdPath, appName) {
6994
8379
  const absPath = implicitDictionaryMacroAbsPath(appCwdPath);
6995
- await mkdir3(path11.dirname(absPath), { recursive: true });
8380
+ await mkdir3(path13.dirname(absPath), { recursive: true });
6996
8381
  await Bun.write(absPath, `import { getAllDictionary } from "@apps/${appName}/lib/dict" with { type: "macro" };
6997
8382
 
6998
8383
  export const allDictionary = getAllDictionary();
@@ -7003,13 +8388,13 @@ async function writeGeneratedRootLayoutFile(opts) {
7003
8388
  await assertEnvClientConvention(opts.appCwdPath, opts.appName);
7004
8389
  const dictMacroAbsPath = opts.includeSystemProvider ? await writeGeneratedDictionaryMacroFile(opts.appCwdPath, opts.appName) : null;
7005
8390
  const absPath = implicitRootLayoutAbsPath(opts.appCwdPath, opts.boundary.segments);
7006
- await mkdir3(path11.dirname(absPath), { recursive: true });
7007
- const dictMacroRel = dictMacroAbsPath ? path11.relative(path11.dirname(absPath), dictMacroAbsPath).split(path11.sep).join("/") : null;
8391
+ await mkdir3(path13.dirname(absPath), { recursive: true });
8392
+ const dictMacroRel = dictMacroAbsPath ? path13.relative(path13.dirname(absPath), dictMacroAbsPath).split(path13.sep).join("/") : null;
7008
8393
  const dictMacroSpecifier = dictMacroRel ? dictMacroRel.startsWith(".") ? dictMacroRel : `./${dictMacroRel}` : null;
7009
- const sourceRel = opts.boundary.sourceAbsPath ? path11.relative(path11.dirname(absPath), opts.boundary.sourceAbsPath).split(path11.sep).join("/") : null;
8394
+ const sourceRel = opts.boundary.sourceAbsPath ? path13.relative(path13.dirname(absPath), opts.boundary.sourceAbsPath).split(path13.sep).join("/") : null;
7010
8395
  const sourceSpecifier = sourceRel ? sourceRel.startsWith(".") ? sourceRel : `./${sourceRel}` : null;
7011
8396
  const inheritedSourceAbsPath = opts.rootSourceAbsPath && opts.rootSourceAbsPath !== opts.boundary.sourceAbsPath ? opts.rootSourceAbsPath : null;
7012
- const inheritedSourceRel = inheritedSourceAbsPath ? path11.relative(path11.dirname(absPath), inheritedSourceAbsPath).split(path11.sep).join("/") : null;
8397
+ const inheritedSourceRel = inheritedSourceAbsPath ? path13.relative(path13.dirname(absPath), inheritedSourceAbsPath).split(path13.sep).join("/") : null;
7013
8398
  const inheritedSourceSpecifier = inheritedSourceRel ? inheritedSourceRel.startsWith(".") ? inheritedSourceRel : `./${inheritedSourceRel}` : null;
7014
8399
  const clientImport = opts.includeStInit ? `import { st } from "@apps/${opts.appName}/client";
7015
8400
  void st;
@@ -7103,7 +8488,7 @@ export default function GeneratedLayout({ children, params, searchParams }: Layo
7103
8488
  return absPath;
7104
8489
  }
7105
8490
  async function resolveSsrPageEntries(opts) {
7106
- const absPageDir = path11.resolve(opts.appCwdPath, "page");
8491
+ const absPageDir = path13.resolve(opts.appCwdPath, "page");
7107
8492
  const hasSt = await appHasStModule(opts.appCwdPath);
7108
8493
  const basePaths = opts.basePaths ?? [];
7109
8494
  const rootSourceAbsPath = findExplicitRootLayoutAbsPath(opts.pageKeys, opts.appCwdPath);
@@ -7114,7 +8499,7 @@ async function resolveSsrPageEntries(opts) {
7114
8499
  }));
7115
8500
  const base = opts.pageKeys.filter((key) => !rootLayoutKeys.has(key)).map((key) => ({
7116
8501
  key,
7117
- moduleAbsPath: path11.resolve(absPageDir, key)
8502
+ moduleAbsPath: path13.resolve(absPageDir, key)
7118
8503
  }));
7119
8504
  const generated = await Promise.all(rootBoundaries.map(async (boundary) => ({
7120
8505
  key: implicitRootLayoutKey(boundary.segments),
@@ -7138,14 +8523,14 @@ async function resolveSsrPageEntriesForApp(app, pageKeys) {
7138
8523
  }
7139
8524
 
7140
8525
  // pkgs/@akanjs/devkit/artifact/routeSeedIndex.ts
7141
- import path12 from "path";
8526
+ import path14 from "path";
7142
8527
  import { assertUniqueRoutePatterns, compareRouteSpecificity, parseRouteModuleKey as parseRouteModuleKey2 } from "akanjs/common";
7143
8528
  function computeRouteSeedIndex(pageEntries) {
7144
8529
  const layoutsByPrefix = new Map;
7145
8530
  const pagesBySegments = [];
7146
8531
  for (const { key, moduleAbsPath, seedAbsPaths } of pageEntries) {
7147
8532
  const parsed = parseRouteModuleKey2(key);
7148
- const files = [path12.resolve(moduleAbsPath), ...(seedAbsPaths ?? []).map((seed) => path12.resolve(seed))];
8533
+ const files = [path14.resolve(moduleAbsPath), ...(seedAbsPaths ?? []).map((seed) => path14.resolve(seed))];
7149
8534
  if (parsed.kind === "layout") {
7150
8535
  const prefix = parsed.routeSegments.join("/");
7151
8536
  const prev = layoutsByPrefix.get(prefix) ?? [];
@@ -7182,7 +8567,7 @@ function computeRouteSeedIndex(pageEntries) {
7182
8567
  }
7183
8568
  var ROUTE_SEED_INDEX_JSON = "route-seed-index.json";
7184
8569
  function serializeRouteSeedIndexForArtifact(index, artifactDir, options = {}) {
7185
- const normalizedArtifactDir = path12.resolve(artifactDir);
8570
+ const normalizedArtifactDir = path14.resolve(artifactDir);
7186
8571
  if (options.production) {
7187
8572
  return {
7188
8573
  entries: index.entries.map((entry) => ({ routeId: entry.routeId }))
@@ -7197,22 +8582,22 @@ function serializeRouteSeedIndexForArtifact(index, artifactDir, options = {}) {
7197
8582
  };
7198
8583
  }
7199
8584
  async function saveRouteSeedIndex(artifactDir, index, options = {}) {
7200
- const absPath = path12.join(path12.resolve(artifactDir), ROUTE_SEED_INDEX_JSON);
8585
+ const absPath = path14.join(path14.resolve(artifactDir), ROUTE_SEED_INDEX_JSON);
7201
8586
  await Bun.write(absPath, `${JSON.stringify(serializeRouteSeedIndexForArtifact(index, artifactDir, options), null, 2)}
7202
8587
  `);
7203
8588
  return absPath;
7204
8589
  }
7205
8590
  function serializeArtifactPath(artifactPath, artifactDir) {
7206
- if (!path12.isAbsolute(artifactPath))
8591
+ if (!path14.isAbsolute(artifactPath))
7207
8592
  return artifactPath;
7208
- return path12.relative(artifactDir, artifactPath).split(path12.sep).join("/");
8593
+ return path14.relative(artifactDir, artifactPath).split(path14.sep).join("/");
7209
8594
  }
7210
8595
 
7211
8596
  // pkgs/@akanjs/devkit/frontendBuild/clientEntryDiscovery.ts
7212
- import path15 from "path";
8597
+ import path17 from "path";
7213
8598
 
7214
8599
  // pkgs/@akanjs/devkit/transforms/barrelAnalyzer.ts
7215
- import path13 from "path";
8600
+ import path15 from "path";
7216
8601
  import { Logger as Logger7 } from "akanjs/common";
7217
8602
  var REEXPORT_RE = /(?:^|\n)\s*export\s+(?:type\s+)?(?:(\*)(?:\s+as\s+(\w+))?|\{\s*([^}]*?)\s*\})\s+from\s+(["'])([^"']+)\4;?/g;
7218
8603
  var LOCAL_NAMED_RE = /(?:^|\n)\s*export\s+\{\s*([^}]*?)\s*\}(?!\s*from)/g;
@@ -7335,7 +8720,7 @@ class BarrelAnalyzer {
7335
8720
  }
7336
8721
  #scanExports(source2, absFile) {
7337
8722
  try {
7338
- const transpiler = [".tsx", ".jsx"].includes(path13.extname(absFile)) ? this.#tsxTranspiler : this.#tsTranspiler;
8723
+ const transpiler = [".tsx", ".jsx"].includes(path15.extname(absFile)) ? this.#tsxTranspiler : this.#tsTranspiler;
7339
8724
  const { exports } = transpiler.scan(source2);
7340
8725
  return new Set(exports);
7341
8726
  } catch (err) {
@@ -7344,16 +8729,16 @@ class BarrelAnalyzer {
7344
8729
  }
7345
8730
  }
7346
8731
  #subpathFor(pkg, absFile) {
7347
- const rel = path13.relative(pkg.pkgDir, absFile);
7348
- if (!rel || rel.startsWith("..") || path13.isAbsolute(rel))
8732
+ const rel = path15.relative(pkg.pkgDir, absFile);
8733
+ if (!rel || rel.startsWith("..") || path15.isAbsolute(rel))
7349
8734
  return null;
7350
8735
  if (pkg.preserveFilePath)
7351
- return `${pkg.pkgName}/${rel.split(path13.sep).join("/")}`;
8736
+ return `${pkg.pkgName}/${rel.split(path15.sep).join("/")}`;
7352
8737
  const noExt = stripKnownExt(rel);
7353
8738
  const tail = collapseIndex(noExt);
7354
8739
  if (tail === "")
7355
8740
  return pkg.pkgName;
7356
- return `${pkg.pkgName}/${tail.split(path13.sep).join("/")}`;
8741
+ return `${pkg.pkgName}/${tail.split(path15.sep).join("/")}`;
7357
8742
  }
7358
8743
  async#resolveRel(fromFile, relSpec) {
7359
8744
  if (this.#opts.resolveRelative)
@@ -7394,9 +8779,9 @@ var readIfExists = async (absFile) => {
7394
8779
  return file.text();
7395
8780
  };
7396
8781
  var defaultResolveRelative = async (fromFile, relSpec) => {
7397
- const baseDir = path13.dirname(fromFile);
7398
- const joined = path13.resolve(baseDir, relSpec);
7399
- if (path13.extname(joined)) {
8782
+ const baseDir = path15.dirname(fromFile);
8783
+ const joined = path15.resolve(baseDir, relSpec);
8784
+ if (path15.extname(joined)) {
7400
8785
  if (await Bun.file(joined).exists())
7401
8786
  return joined;
7402
8787
  return null;
@@ -7407,7 +8792,7 @@ var defaultResolveRelative = async (fromFile, relSpec) => {
7407
8792
  return cand;
7408
8793
  }
7409
8794
  for (const ext of CANDIDATE_EXTS) {
7410
- const cand = path13.join(joined, `index${ext}`);
8795
+ const cand = path15.join(joined, `index${ext}`);
7411
8796
  if (await Bun.file(cand).exists())
7412
8797
  return cand;
7413
8798
  }
@@ -7421,15 +8806,15 @@ var stripKnownExt = (relPath) => {
7421
8806
  return relPath;
7422
8807
  };
7423
8808
  var collapseIndex = (relPathNoExt) => {
7424
- const parts = relPathNoExt.split(path13.sep);
8809
+ const parts = relPathNoExt.split(path15.sep);
7425
8810
  if (parts[parts.length - 1] === "index")
7426
8811
  parts.pop();
7427
- return parts.join(path13.sep);
8812
+ return parts.join(path15.sep);
7428
8813
  };
7429
8814
 
7430
8815
  // pkgs/@akanjs/devkit/transforms/barrelImportsPlugin.ts
7431
- import path14 from "path";
7432
- import ts5 from "typescript";
8816
+ import path16 from "path";
8817
+ import ts7 from "typescript";
7433
8818
  var createBarrelImportsPlugin = async (app, { skipPath = defaultSkipPath, pipeAfter } = {}) => {
7434
8819
  const akanConfig2 = await app.getConfig();
7435
8820
  const barrels = [...new Set(akanConfig2.barrelImports)].filter(Boolean);
@@ -7487,10 +8872,10 @@ var createTsconfigPackageResolver = async (app) => {
7487
8872
  const raw = exact[0];
7488
8873
  if (!raw)
7489
8874
  return null;
7490
- const entryFile = path14.resolve(app.workspace.workspaceRoot, raw);
8875
+ const entryFile = path16.resolve(app.workspace.workspaceRoot, raw);
7491
8876
  if (!await Bun.file(entryFile).exists())
7492
8877
  return null;
7493
- const parsed = path14.parse(entryFile);
8878
+ const parsed = path16.parse(entryFile);
7494
8879
  const lastSlash = pkgName.lastIndexOf("/");
7495
8880
  if (parsed.name !== "index" && lastSlash !== -1) {
7496
8881
  const facet = pkgName.slice(lastSlash + 1);
@@ -7499,7 +8884,7 @@ var createTsconfigPackageResolver = async (app) => {
7499
8884
  return { pkgName: parentSpec, entryFile, pkgDir: parsed.dir };
7500
8885
  }
7501
8886
  }
7502
- return { pkgName, entryFile, pkgDir: path14.dirname(entryFile) };
8887
+ return { pkgName, entryFile, pkgDir: path16.dirname(entryFile) };
7503
8888
  }
7504
8889
  for (const { prefix, replacements } of wildcardEntries) {
7505
8890
  if (!pkgName.startsWith(prefix))
@@ -7509,7 +8894,7 @@ var createTsconfigPackageResolver = async (app) => {
7509
8894
  if (!repl)
7510
8895
  continue;
7511
8896
  const replPath = repl.endsWith("/*") ? repl.slice(0, -1) : repl;
7512
- const candidate = path14.resolve(app.workspace.workspaceRoot, replPath + suffix);
8897
+ const candidate = path16.resolve(app.workspace.workspaceRoot, replPath + suffix);
7513
8898
  for (const ext of CANDIDATE_EXTS2) {
7514
8899
  const file = `${candidate}${ext}`;
7515
8900
  if (await Bun.file(file).exists()) {
@@ -7517,14 +8902,14 @@ var createTsconfigPackageResolver = async (app) => {
7517
8902
  if (lastSlash !== -1) {
7518
8903
  const parentSpec = pkgName.slice(0, lastSlash);
7519
8904
  if (parentSpec.length > 0) {
7520
- return { pkgName: parentSpec, entryFile: file, pkgDir: path14.dirname(file) };
8905
+ return { pkgName: parentSpec, entryFile: file, pkgDir: path16.dirname(file) };
7521
8906
  }
7522
8907
  }
7523
- return { pkgName, entryFile: file, pkgDir: path14.dirname(file) };
8908
+ return { pkgName, entryFile: file, pkgDir: path16.dirname(file) };
7524
8909
  }
7525
8910
  }
7526
8911
  for (const ext of CANDIDATE_EXTS2) {
7527
- const file = path14.join(candidate, `index${ext}`);
8912
+ const file = path16.join(candidate, `index${ext}`);
7528
8913
  if (await Bun.file(file).exists()) {
7529
8914
  return { pkgName, entryFile: file, pkgDir: candidate };
7530
8915
  }
@@ -7535,16 +8920,16 @@ var createTsconfigPackageResolver = async (app) => {
7535
8920
  const exported = await resolveNodePackageExport(app.workspace.workspaceRoot, pkgName);
7536
8921
  if (exported)
7537
8922
  return exported;
7538
- const pkgJsonPath = path14.join(app.workspace.workspaceRoot, "node_modules", pkgName, "package.json");
8923
+ const pkgJsonPath = path16.join(app.workspace.workspaceRoot, "node_modules", pkgName, "package.json");
7539
8924
  if (!await Bun.file(pkgJsonPath).exists())
7540
8925
  return null;
7541
8926
  try {
7542
8927
  const pkgJson = JSON.parse(await Bun.file(pkgJsonPath).text());
7543
8928
  const rel = pkgJson.module ?? pkgJson.main ?? "index.js";
7544
- const entryFile = path14.resolve(path14.dirname(pkgJsonPath), rel);
8929
+ const entryFile = path16.resolve(path16.dirname(pkgJsonPath), rel);
7545
8930
  if (!await Bun.file(entryFile).exists())
7546
8931
  return null;
7547
- return { pkgName, entryFile, pkgDir: path14.dirname(pkgJsonPath) };
8932
+ return { pkgName, entryFile, pkgDir: path16.dirname(pkgJsonPath) };
7548
8933
  } catch {
7549
8934
  return null;
7550
8935
  }
@@ -7558,22 +8943,22 @@ var resolveNodePackageExport = async (workspaceRoot, specifier) => {
7558
8943
  const packageName = getPackageName(specifier);
7559
8944
  if (!packageName)
7560
8945
  return null;
7561
- const pkgJsonPath = path14.join(workspaceRoot, "node_modules", packageName, "package.json");
8946
+ const pkgJsonPath = path16.join(workspaceRoot, "node_modules", packageName, "package.json");
7562
8947
  if (!await Bun.file(pkgJsonPath).exists())
7563
8948
  return null;
7564
8949
  try {
7565
- const pkgDir = path14.dirname(pkgJsonPath);
8950
+ const pkgDir = path16.dirname(pkgJsonPath);
7566
8951
  const pkgJson = JSON.parse(await Bun.file(pkgJsonPath).text());
7567
8952
  const subpath = specifier === packageName ? "." : `.${specifier.slice(packageName.length)}`;
7568
8953
  const exported = resolvePackageExport(pkgJson.exports, subpath);
7569
8954
  const rel = exported ?? (subpath === "." ? pkgJson.module ?? pkgJson.main ?? "index.js" : null);
7570
8955
  if (!rel || !rel.startsWith("."))
7571
8956
  return null;
7572
- const entryFile = await resolveFileCandidate(path14.resolve(pkgDir, rel));
8957
+ const entryFile = await resolveFileCandidate(path16.resolve(pkgDir, rel));
7573
8958
  if (!entryFile)
7574
8959
  return null;
7575
8960
  const pkgEntryName = specifier;
7576
- return { pkgName: pkgEntryName, entryFile, pkgDir: path14.dirname(entryFile), preserveFilePath: true };
8961
+ return { pkgName: pkgEntryName, entryFile, pkgDir: path16.dirname(entryFile), preserveFilePath: true };
7577
8962
  } catch {
7578
8963
  return null;
7579
8964
  }
@@ -7630,7 +9015,7 @@ var getPackageName = (specifier) => {
7630
9015
  var resolveFileCandidate = async (candidate) => {
7631
9016
  if (await Bun.file(candidate).exists())
7632
9017
  return candidate;
7633
- if (path14.extname(candidate))
9018
+ if (path16.extname(candidate))
7634
9019
  return null;
7635
9020
  for (const ext of CANDIDATE_EXTS2) {
7636
9021
  const file = `${candidate}${ext}`;
@@ -7638,7 +9023,7 @@ var resolveFileCandidate = async (candidate) => {
7638
9023
  return file;
7639
9024
  }
7640
9025
  for (const ext of CANDIDATE_EXTS2) {
7641
- const file = path14.join(candidate, `index${ext}`);
9026
+ const file = path16.join(candidate, `index${ext}`);
7642
9027
  if (await Bun.file(file).exists())
7643
9028
  return file;
7644
9029
  }
@@ -7670,11 +9055,11 @@ var rewriteBarrelImports = async (source2, barrels, analyzer) => {
7670
9055
  };
7671
9056
  var findImportStatements = (source2) => {
7672
9057
  const statements = [];
7673
- const sourceFile2 = ts5.createSourceFile("barrel-imports.tsx", source2, ts5.ScriptTarget.Latest, true, ts5.ScriptKind.TSX);
9058
+ const sourceFile2 = ts7.createSourceFile("barrel-imports.tsx", source2, ts7.ScriptTarget.Latest, true, ts7.ScriptKind.TSX);
7674
9059
  for (const statement of sourceFile2.statements) {
7675
- if (!ts5.isImportDeclaration(statement))
9060
+ if (!ts7.isImportDeclaration(statement))
7676
9061
  continue;
7677
- if (!ts5.isStringLiteral(statement.moduleSpecifier))
9062
+ if (!ts7.isStringLiteral(statement.moduleSpecifier))
7678
9063
  continue;
7679
9064
  const importClause = statement.importClause;
7680
9065
  if (!importClause)
@@ -7852,7 +9237,7 @@ class GraphClientEntryDiscovery {
7852
9237
  }
7853
9238
  invalidate(files) {
7854
9239
  for (const file of files) {
7855
- const absPath = path15.resolve(file);
9240
+ const absPath = path17.resolve(file);
7856
9241
  this.#readCache.delete(absPath);
7857
9242
  this.#rewriteCache.delete(absPath);
7858
9243
  this.#importCache.delete(absPath);
@@ -7862,7 +9247,7 @@ class GraphClientEntryDiscovery {
7862
9247
  this.#reachableEntriesCache.clear();
7863
9248
  }
7864
9249
  async#fileExists(p) {
7865
- const absPath = path15.resolve(p);
9250
+ const absPath = path17.resolve(p);
7866
9251
  let cached = this.#fileExistsCache.get(absPath);
7867
9252
  if (!cached) {
7868
9253
  cached = Bun.file(absPath).exists();
@@ -7871,7 +9256,7 @@ class GraphClientEntryDiscovery {
7871
9256
  return cached;
7872
9257
  }
7873
9258
  #readFile(file) {
7874
- const absPath = path15.resolve(file);
9259
+ const absPath = path17.resolve(file);
7875
9260
  let cached = this.#readCache.get(absPath);
7876
9261
  if (!cached) {
7877
9262
  cached = Bun.file(absPath).text().catch(() => null);
@@ -7880,7 +9265,7 @@ class GraphClientEntryDiscovery {
7880
9265
  return cached;
7881
9266
  }
7882
9267
  async#resolveFileCandidate(absPathNoExt) {
7883
- const cacheKey = path15.resolve(absPathNoExt);
9268
+ const cacheKey = path17.resolve(absPathNoExt);
7884
9269
  let cached = this.#resolvedFileCache.get(cacheKey);
7885
9270
  if (cached)
7886
9271
  return cached;
@@ -7893,7 +9278,7 @@ class GraphClientEntryDiscovery {
7893
9278
  return f;
7894
9279
  }
7895
9280
  for (const ext of SOURCE_EXTS2) {
7896
- const f = path15.join(cacheKey, `index${ext}`);
9281
+ const f = path17.join(cacheKey, `index${ext}`);
7897
9282
  if (await this.#fileExists(f))
7898
9283
  return f;
7899
9284
  }
@@ -7909,7 +9294,7 @@ class GraphClientEntryDiscovery {
7909
9294
  return cached;
7910
9295
  cached = (async () => {
7911
9296
  if (spec.startsWith(".") || spec.startsWith("/")) {
7912
- const abs = spec.startsWith("/") ? spec : path15.resolve(importerDir, spec);
9297
+ const abs = spec.startsWith("/") ? spec : path17.resolve(importerDir, spec);
7913
9298
  return this.#resolveFileCandidate(abs);
7914
9299
  }
7915
9300
  const pkg = await this.#resolvePackage(spec);
@@ -7921,7 +9306,7 @@ class GraphClientEntryDiscovery {
7921
9306
  return cached;
7922
9307
  }
7923
9308
  async#getRewrittenSource(file, content) {
7924
- const absPath = path15.resolve(file);
9309
+ const absPath = path17.resolve(file);
7925
9310
  let cached = this.#rewriteCache.get(absPath);
7926
9311
  if (!cached) {
7927
9312
  cached = (async () => {
@@ -7938,7 +9323,7 @@ class GraphClientEntryDiscovery {
7938
9323
  return cached;
7939
9324
  }
7940
9325
  async#getImports(file, source2) {
7941
- const absPath = path15.resolve(file);
9326
+ const absPath = path17.resolve(file);
7942
9327
  let cached = this.#importCache.get(absPath);
7943
9328
  if (!cached) {
7944
9329
  cached = Promise.resolve().then(() => {
@@ -7953,7 +9338,7 @@ class GraphClientEntryDiscovery {
7953
9338
  return cached;
7954
9339
  }
7955
9340
  async#discoverFromFile(file, visiting) {
7956
- const absPath = path15.resolve(file);
9341
+ const absPath = path17.resolve(file);
7957
9342
  const cached = this.#reachableEntriesCache.get(absPath);
7958
9343
  if (cached)
7959
9344
  return new Set(cached);
@@ -7970,7 +9355,7 @@ class GraphClientEntryDiscovery {
7970
9355
  }
7971
9356
  const source2 = await this.#getRewrittenSource(absPath, content);
7972
9357
  const imports = await this.#getImports(absPath, source2);
7973
- const importerDir = path15.dirname(absPath);
9358
+ const importerDir = path17.dirname(absPath);
7974
9359
  for (const imp of imports) {
7975
9360
  const spec = imp.path;
7976
9361
  if (!spec)
@@ -7996,14 +9381,14 @@ class GraphClientEntryDiscovery {
7996
9381
 
7997
9382
  // pkgs/@akanjs/devkit/frontendBuild/routeClientBuilder.ts
7998
9383
  import { mkdir as mkdir4 } from "fs/promises";
7999
- import path18 from "path";
9384
+ import path20 from "path";
8000
9385
 
8001
9386
  // pkgs/@akanjs/devkit/transforms/rscUseClientTransform.ts
8002
- import path16 from "path";
9387
+ import path18 from "path";
8003
9388
  var USE_CLIENT_RE2 = /^\s*(?:\/\*[\s\S]*?\*\/\s*|\/\/[^\n]*\n\s*)*["']use client["']/;
8004
9389
  var IMPLICIT_ROOT_LAYOUT_RE = /[/\\]\.akan[/\\]generated[/\\](?:implicit-root-layout|root-layouts[/\\].*__root_layout)\.(tsx|ts|jsx|js)$/;
8005
9390
  function toClientReferencePath(absPath, workspaceRoot) {
8006
- return path16.relative(path16.resolve(workspaceRoot), path16.resolve(absPath)).split(path16.sep).join("/");
9391
+ return path18.relative(path18.resolve(workspaceRoot), path18.resolve(absPath)).split(path18.sep).join("/");
8007
9392
  }
8008
9393
  function transformUseClient(source2, args) {
8009
9394
  if (!USE_CLIENT_RE2.test(source2))
@@ -8039,7 +9424,7 @@ function loaderFor2(absPath) {
8039
9424
 
8040
9425
  // pkgs/@akanjs/devkit/frontendBuild/clientEntriesBundler.ts
8041
9426
  import fs2 from "fs";
8042
- import path17 from "path";
9427
+ import path19 from "path";
8043
9428
 
8044
9429
  // pkgs/@akanjs/devkit/frontendBuild/clientBuildTypes.ts
8045
9430
  var CLIENT_BUNDLE_NAMING = {
@@ -8128,23 +9513,23 @@ class ClientEntriesBundler {
8128
9513
  };
8129
9514
  }
8130
9515
  async#createOpaqueEntryAliases() {
8131
- const aliasDir = path17.join(this.#app.cwdPath, ".akan", "generated", "client-entry-alias", this.#outputSubdir);
9516
+ const aliasDir = path19.join(this.#app.cwdPath, ".akan", "generated", "client-entry-alias", this.#outputSubdir);
8132
9517
  fs2.mkdirSync(aliasDir, { recursive: true });
8133
9518
  const originalByAlias = new Map;
8134
9519
  const aliasedEntries = await Promise.all(this.#entries.map(async (entry) => {
8135
- const absEntry = path17.resolve(entry);
9520
+ const absEntry = path19.resolve(entry);
8136
9521
  const hash = Bun.hash(`${this.#app.name}
8137
9522
  ${this.#outputSubdir}
8138
9523
  ${absEntry}`).toString(36);
8139
- const aliasPath = path17.join(aliasDir, `${hash}.tsx`);
9524
+ const aliasPath = path19.join(aliasDir, `${hash}.tsx`);
8140
9525
  await Bun.write(aliasPath, this.#createOpaqueEntryAliasSource(absEntry, await this.#scanEntryExportNames(absEntry)));
8141
- originalByAlias.set(path17.resolve(aliasPath), absEntry);
9526
+ originalByAlias.set(path19.resolve(aliasPath), absEntry);
8142
9527
  return aliasPath;
8143
9528
  }));
8144
9529
  return { entries: aliasedEntries, originalByAlias, aliasDir };
8145
9530
  }
8146
9531
  #createOpaqueEntryAliasSource(absEntry, exportNames) {
8147
- const entryLit = JSON.stringify(path17.resolve(absEntry));
9532
+ const entryLit = JSON.stringify(path19.resolve(absEntry));
8148
9533
  if (exportNames.length === 0)
8149
9534
  return `export * from ${entryLit};
8150
9535
  `;
@@ -8227,16 +9612,16 @@ ${absEntry}`).toString(36);
8227
9612
  return rewritten;
8228
9613
  }
8229
9614
  #toServeUrl(absOutPath) {
8230
- const rel = path17.relative(this.#outdir, absOutPath).split(path17.sep).join("/");
9615
+ const rel = path19.relative(this.#outdir, absOutPath).split(path19.sep).join("/");
8231
9616
  return `${this.#servePrefix}/${rel}`;
8232
9617
  }
8233
9618
  #absFromOutdir(p) {
8234
- return path17.isAbsolute(p) ? p : path17.resolve(this.#outdir, p);
9619
+ return path19.isAbsolute(p) ? p : path19.resolve(this.#outdir, p);
8235
9620
  }
8236
9621
  #absFromEntryPoint(p) {
8237
- if (path17.isAbsolute(p))
8238
- return path17.resolve(p);
8239
- const candidates = [path17.resolve(process.cwd(), p), path17.resolve(this.#app.cwdPath, p)];
9622
+ if (path19.isAbsolute(p))
9623
+ return path19.resolve(p);
9624
+ const candidates = [path19.resolve(process.cwd(), p), path19.resolve(this.#app.cwdPath, p)];
8240
9625
  return candidates.find((candidate) => fs2.existsSync(candidate)) ?? candidates[0];
8241
9626
  }
8242
9627
  #collectChunkUrls(absOutPath, visited = new Set) {
@@ -8386,13 +9771,13 @@ class RouteClientBuilder {
8386
9771
  ssrModuleMap[row.id][row.name] = { id: ssrOutput, chunks: [ssrOutput, ssrOutput], name: row.name, async: true };
8387
9772
  }
8388
9773
  for (const entry of bootstrapEntries.buildEntries) {
8389
- const buildEntry = path18.resolve(entry);
8390
- const originalEntry = path18.resolve(bootstrapEntries.originalByBuildEntry.get(buildEntry) ?? buildEntry);
9774
+ const buildEntry = path20.resolve(entry);
9775
+ const originalEntry = path20.resolve(bootstrapEntries.originalByBuildEntry.get(buildEntry) ?? buildEntry);
8391
9776
  if (!acceptedEntries.has(originalEntry))
8392
9777
  continue;
8393
9778
  const deps = new Set([originalEntry]);
8394
9779
  for (const dep of browserBundle.entryDepsByAbsPath.get(buildEntry) ?? [])
8395
- deps.add(path18.resolve(dep));
9780
+ deps.add(path20.resolve(dep));
8396
9781
  const sortedDeps = [...deps].sort();
8397
9782
  clientDepsByEntry[originalEntry] = sortedDeps;
8398
9783
  for (const dep of sortedDeps)
@@ -8444,25 +9829,25 @@ class RouteClientBuilder {
8444
9829
  }).bundle();
8445
9830
  }
8446
9831
  async#createBootstrapEntries(entries) {
8447
- if (!await Bun.file(path18.join(this.#app.cwdPath, "lib", "st.ts")).exists()) {
9832
+ if (!await Bun.file(path20.join(this.#app.cwdPath, "lib", "st.ts")).exists()) {
8448
9833
  return { buildEntries: entries, originalByBuildEntry: new Map };
8449
9834
  }
8450
- const outdir = path18.join(this.#app.cwdPath, ".akan", "generated", "client-entry-bootstrap");
9835
+ const outdir = path20.join(this.#app.cwdPath, ".akan", "generated", "client-entry-bootstrap");
8451
9836
  await mkdir4(outdir, { recursive: true });
8452
9837
  const originalByBuildEntry = new Map;
8453
9838
  const buildEntries = await Promise.all(entries.map(async (entry) => {
8454
- const absEntry = path18.resolve(entry);
9839
+ const absEntry = path20.resolve(entry);
8455
9840
  const hash = Bun.hash(`${this.#app.name}
8456
9841
  ${absEntry}`).toString(36);
8457
- const base = path18.basename(absEntry).replace(/[^A-Za-z0-9._-]/g, "_");
8458
- const wrapperEntry = path18.join(outdir, `${base}-${hash}.tsx`);
9842
+ const base = path20.basename(absEntry).replace(/[^A-Za-z0-9._-]/g, "_");
9843
+ const wrapperEntry = path20.join(outdir, `${base}-${hash}.tsx`);
8459
9844
  const exportNames = await this.#scanExportNames(absEntry);
8460
9845
  await Bun.write(wrapperEntry, RouteClientBuilder.createStoreBootstrapEntrySource({
8461
9846
  appName: this.#app.name,
8462
9847
  originalEntry: absEntry,
8463
9848
  exportNames
8464
9849
  }));
8465
- originalByBuildEntry.set(path18.resolve(wrapperEntry), absEntry);
9850
+ originalByBuildEntry.set(path20.resolve(wrapperEntry), absEntry);
8466
9851
  return wrapperEntry;
8467
9852
  }));
8468
9853
  return { buildEntries, originalByBuildEntry };
@@ -8514,11 +9899,11 @@ ${defaultNames.map((name) => `export default ${name};`).join(`
8514
9899
  try {
8515
9900
  return Bun.resolveSync("akanjs/server", import.meta.dir);
8516
9901
  } catch {
8517
- return path18.resolve(import.meta.dir, "../../../server/index.ts");
9902
+ return path20.resolve(import.meta.dir, "../../../server/index.ts");
8518
9903
  }
8519
9904
  }
8520
9905
  static createStoreBootstrapEntrySource(args) {
8521
- const originalEntry = JSON.stringify(path18.resolve(args.originalEntry));
9906
+ const originalEntry = JSON.stringify(path20.resolve(args.originalEntry));
8522
9907
  const namedExports = args.exportNames.filter((name) => name !== "default");
8523
9908
  const lines = [
8524
9909
  `import ${JSON.stringify(`@apps/${args.appName}/client`)};`,
@@ -8544,7 +9929,7 @@ ${defaultNames.map((name) => `export default ${name};`).join(`
8544
9929
  }
8545
9930
 
8546
9931
  // pkgs/@akanjs/devkit/frontendBuild/routesManifestArtifactSerializer.ts
8547
- import path19 from "path";
9932
+ import path21 from "path";
8548
9933
 
8549
9934
  class RoutesManifestArtifactSerializer {
8550
9935
  #manifest;
@@ -8552,7 +9937,7 @@ class RoutesManifestArtifactSerializer {
8552
9937
  #production;
8553
9938
  constructor(manifest, artifactDir, options = {}) {
8554
9939
  this.#manifest = manifest;
8555
- this.#artifactDir = path19.resolve(artifactDir);
9940
+ this.#artifactDir = path21.resolve(artifactDir);
8556
9941
  this.#production = options.production ?? false;
8557
9942
  }
8558
9943
  static serialize(manifest, artifactDir, options = {}) {
@@ -8585,9 +9970,9 @@ class RoutesManifestArtifactSerializer {
8585
9970
  };
8586
9971
  }
8587
9972
  #serializeArtifactPath(artifactPath) {
8588
- if (!path19.isAbsolute(artifactPath))
9973
+ if (!path21.isAbsolute(artifactPath))
8589
9974
  return artifactPath;
8590
- return path19.relative(this.#artifactDir, artifactPath).split(path19.sep).join("/");
9975
+ return path21.relative(this.#artifactDir, artifactPath).split(path21.sep).join("/");
8591
9976
  }
8592
9977
  }
8593
9978
 
@@ -8627,7 +10012,7 @@ class AllRoutesBuilder {
8627
10012
  routeIds: this.#routeIds,
8628
10013
  ...this.#merged
8629
10014
  };
8630
- const manifestPath = path20.join(path20.resolve(this.#artifactDir), "routes-manifest.json");
10015
+ const manifestPath = path22.join(path22.resolve(this.#artifactDir), "routes-manifest.json");
8631
10016
  await Bun.write(manifestPath, `${JSON.stringify(RoutesManifestArtifactSerializer.serialize(manifest, this.#artifactDir, {
8632
10017
  production: this.#command === "build"
8633
10018
  }), null, 2)}
@@ -8664,12 +10049,12 @@ class AllRoutesBuilder {
8664
10049
  }
8665
10050
  // pkgs/@akanjs/devkit/frontendBuild/csrArtifactBuilder.ts
8666
10051
  import { mkdir as mkdir5, rm, unlink } from "fs/promises";
8667
- import path22 from "path";
10052
+ import path24 from "path";
8668
10053
 
8669
10054
  // pkgs/@akanjs/devkit/frontendBuild/pagesEntrySourceGenerator.ts
8670
10055
  import fs3 from "fs";
8671
- import path21 from "path";
8672
- import ts6 from "typescript";
10056
+ import path23 from "path";
10057
+ import ts8 from "typescript";
8673
10058
 
8674
10059
  class PagesEntrySourceGenerator {
8675
10060
  #pageEntries;
@@ -8681,7 +10066,7 @@ class PagesEntrySourceGenerator {
8681
10066
  }
8682
10067
  generate() {
8683
10068
  const lines = this.#pageEntries.map(({ key, moduleAbsPath }) => {
8684
- const absPath = path21.resolve(moduleAbsPath);
10069
+ const absPath = path23.resolve(moduleAbsPath);
8685
10070
  return ` ${JSON.stringify(key)}: () => import(${JSON.stringify(absPath)}),`;
8686
10071
  });
8687
10072
  return `export const pages = {
@@ -8695,7 +10080,7 @@ ${lines.join(`
8695
10080
  }
8696
10081
  generateStatic() {
8697
10082
  const imports = this.#pageEntries.map(({ moduleAbsPath }, index) => {
8698
- const absPath = path21.resolve(moduleAbsPath);
10083
+ const absPath = path23.resolve(moduleAbsPath);
8699
10084
  return `import * as page${index} from ${JSON.stringify(absPath)};`;
8700
10085
  });
8701
10086
  const entries = this.#pageEntries.map(({ key, moduleAbsPath }, index) => {
@@ -8712,8 +10097,8 @@ ${entries.join(`
8712
10097
  }
8713
10098
  static #hasAsyncDefaultExport(moduleAbsPath) {
8714
10099
  try {
8715
- const source2 = fs3.readFileSync(path21.resolve(moduleAbsPath), "utf8");
8716
- const sourceFile2 = ts6.createSourceFile(moduleAbsPath, source2, ts6.ScriptTarget.Latest, true, PagesEntrySourceGenerator.#scriptKind(moduleAbsPath));
10100
+ const source2 = fs3.readFileSync(path23.resolve(moduleAbsPath), "utf8");
10101
+ const sourceFile2 = ts8.createSourceFile(moduleAbsPath, source2, ts8.ScriptTarget.Latest, true, PagesEntrySourceGenerator.#scriptKind(moduleAbsPath));
8717
10102
  return PagesEntrySourceGenerator.#sourceFileHasAsyncDefaultExport(sourceFile2);
8718
10103
  } catch {
8719
10104
  return false;
@@ -8723,31 +10108,31 @@ ${entries.join(`
8723
10108
  const asyncBindings = new Map;
8724
10109
  let defaultIdentifier = null;
8725
10110
  for (const statement of sourceFile2.statements) {
8726
- if (ts6.isFunctionDeclaration(statement)) {
8727
- if (PagesEntrySourceGenerator.#hasModifier(statement, ts6.SyntaxKind.DefaultKeyword)) {
8728
- return PagesEntrySourceGenerator.#hasModifier(statement, ts6.SyntaxKind.AsyncKeyword);
10111
+ if (ts8.isFunctionDeclaration(statement)) {
10112
+ if (PagesEntrySourceGenerator.#hasModifier(statement, ts8.SyntaxKind.DefaultKeyword)) {
10113
+ return PagesEntrySourceGenerator.#hasModifier(statement, ts8.SyntaxKind.AsyncKeyword);
8729
10114
  }
8730
10115
  if (statement.name) {
8731
- asyncBindings.set(statement.name.text, PagesEntrySourceGenerator.#hasModifier(statement, ts6.SyntaxKind.AsyncKeyword));
10116
+ asyncBindings.set(statement.name.text, PagesEntrySourceGenerator.#hasModifier(statement, ts8.SyntaxKind.AsyncKeyword));
8732
10117
  }
8733
10118
  continue;
8734
10119
  }
8735
- if (ts6.isVariableStatement(statement)) {
10120
+ if (ts8.isVariableStatement(statement)) {
8736
10121
  for (const declaration of statement.declarationList.declarations) {
8737
- if (!ts6.isIdentifier(declaration.name))
10122
+ if (!ts8.isIdentifier(declaration.name))
8738
10123
  continue;
8739
10124
  asyncBindings.set(declaration.name.text, PagesEntrySourceGenerator.#isAsyncFunctionExpression(declaration.initializer));
8740
10125
  }
8741
10126
  continue;
8742
10127
  }
8743
- if (ts6.isExportAssignment(statement)) {
10128
+ if (ts8.isExportAssignment(statement)) {
8744
10129
  if (PagesEntrySourceGenerator.#isAsyncFunctionExpression(statement.expression))
8745
10130
  return true;
8746
- if (ts6.isIdentifier(statement.expression))
10131
+ if (ts8.isIdentifier(statement.expression))
8747
10132
  defaultIdentifier = statement.expression.text;
8748
10133
  continue;
8749
10134
  }
8750
- if (ts6.isExportDeclaration(statement) && statement.exportClause && ts6.isNamedExports(statement.exportClause)) {
10135
+ if (ts8.isExportDeclaration(statement) && statement.exportClause && ts8.isNamedExports(statement.exportClause)) {
8751
10136
  const exportClause = statement.exportClause;
8752
10137
  for (const specifier of exportClause.elements) {
8753
10138
  if (specifier.name.text !== "default")
@@ -8759,13 +10144,13 @@ ${entries.join(`
8759
10144
  return defaultIdentifier ? asyncBindings.get(defaultIdentifier) === true : false;
8760
10145
  }
8761
10146
  static #hasModifier(node, kind) {
8762
- return ts6.canHaveModifiers(node) && (ts6.getModifiers(node)?.some((modifier) => modifier.kind === kind) ?? false);
10147
+ return ts8.canHaveModifiers(node) && (ts8.getModifiers(node)?.some((modifier) => modifier.kind === kind) ?? false);
8763
10148
  }
8764
10149
  static #isAsyncFunctionExpression(node) {
8765
- return Boolean(node && (ts6.isArrowFunction(node) || ts6.isFunctionExpression(node)) && PagesEntrySourceGenerator.#hasModifier(node, ts6.SyntaxKind.AsyncKeyword));
10150
+ return Boolean(node && (ts8.isArrowFunction(node) || ts8.isFunctionExpression(node)) && PagesEntrySourceGenerator.#hasModifier(node, ts8.SyntaxKind.AsyncKeyword));
8766
10151
  }
8767
10152
  static #scriptKind(moduleAbsPath) {
8768
- return moduleAbsPath.endsWith(".tsx") || moduleAbsPath.endsWith(".jsx") ? ts6.ScriptKind.TSX : ts6.ScriptKind.TS;
10153
+ return moduleAbsPath.endsWith(".tsx") || moduleAbsPath.endsWith(".jsx") ? ts8.ScriptKind.TSX : ts8.ScriptKind.TS;
8769
10154
  }
8770
10155
  }
8771
10156
 
@@ -8791,7 +10176,7 @@ class CsrArtifactBuilder {
8791
10176
  const csrBasePaths = [...akanConfig2.basePaths];
8792
10177
  const htmlEntries = csrBasePaths.length > 0 ? csrBasePaths : ["index"];
8793
10178
  await rm(this.#outputDir, { recursive: true, force: true });
8794
- await mkdir5(path22.join(this.#app.cwdPath, ".akan/generated/csr"), { recursive: true });
10179
+ await mkdir5(path24.join(this.#app.cwdPath, ".akan/generated/csr"), { recursive: true });
8795
10180
  const generatedHtmlFiles = Object.fromEntries(htmlEntries.map((basePath2) => this.#createHtmlFile(basePath2)));
8796
10181
  const result = await Bun.build({
8797
10182
  target: "browser",
@@ -8823,7 +10208,7 @@ ${logs}` : ""}`);
8823
10208
  return { outputDir: this.#outputDir };
8824
10209
  }
8825
10210
  get #outputDir() {
8826
- return path22.join(this.#command === "build" ? this.#app.dist.cwdPath : this.#app.cwdPath, this.#command === "build" ? "csr" : ".akan/artifact/csr");
10211
+ return path24.join(this.#command === "build" ? this.#app.dist.cwdPath : this.#app.cwdPath, this.#command === "build" ? "csr" : ".akan/artifact/csr");
8827
10212
  }
8828
10213
  #define() {
8829
10214
  const nodeEnv = this.#command === "build" ? "production" : "development";
@@ -8854,8 +10239,8 @@ ${logs}` : ""}`);
8854
10239
  ];
8855
10240
  }
8856
10241
  async#loadCsrArtifact() {
8857
- const artifactDir = path22.join(this.#command === "build" ? this.#app.dist.cwdPath : this.#app.cwdPath, ".akan/artifact");
8858
- const artifactFile = Bun.file(path22.join(artifactDir, "base-artifact.json"));
10242
+ const artifactDir = path24.join(this.#command === "build" ? this.#app.dist.cwdPath : this.#app.cwdPath, ".akan/artifact");
10243
+ const artifactFile = Bun.file(path24.join(artifactDir, "base-artifact.json"));
8859
10244
  if (!await artifactFile.exists())
8860
10245
  return { cssAssets: {} };
8861
10246
  const artifact = await artifactFile.json();
@@ -8868,7 +10253,7 @@ ${logs}` : ""}`);
8868
10253
  const htmlFile = Bun.file(htmlPath);
8869
10254
  if (!await htmlFile.exists())
8870
10255
  continue;
8871
- const basePath2 = path22.basename(htmlPath, ".html") === "index" ? "" : path22.basename(htmlPath, ".html");
10256
+ const basePath2 = path24.basename(htmlPath, ".html") === "index" ? "" : path24.basename(htmlPath, ".html");
8872
10257
  const inlined = await this.#inlineHtmlAssets(await htmlFile.text(), htmlPath, cssAssets[basePath2]);
8873
10258
  for (const filePath of inlined.jsFiles)
8874
10259
  jsFiles.add(filePath);
@@ -8910,7 +10295,7 @@ ${remainingAssets.join(`
8910
10295
  next = CsrArtifactBuilder.injectBeforeHeadEnd(next, style);
8911
10296
  }
8912
10297
  if (cssAsset) {
8913
- const cssPath = path22.join(this.#command === "build" ? this.#app.dist.cwdPath : this.#app.cwdPath, ".akan/artifact", cssAsset.cssRelPath);
10298
+ const cssPath = path24.join(this.#command === "build" ? this.#app.dist.cwdPath : this.#app.cwdPath, ".akan/artifact", cssAsset.cssRelPath);
8914
10299
  const css = await Bun.file(cssPath).text();
8915
10300
  const style = CsrArtifactBuilder.createInlineStyle(css);
8916
10301
  if (!next.includes(style))
@@ -8981,16 +10366,16 @@ ${CsrArtifactBuilder.escapeInlineScript(await loadScript(src))}
8981
10366
  throw new Error(`[csr-build] cannot inline external script: ${src}`);
8982
10367
  }
8983
10368
  const normalized = src.startsWith("/") ? src.slice(1) : src;
8984
- return path22.resolve(path22.dirname(htmlPath), normalized);
10369
+ return path24.resolve(path24.dirname(htmlPath), normalized);
8985
10370
  }
8986
10371
  }
8987
10372
  // pkgs/@akanjs/devkit/frontendBuild/cssCompiler.ts
8988
- import path24 from "path";
10373
+ import path26 from "path";
8989
10374
  import { Logger as Logger8 } from "akanjs/common";
8990
10375
  import { compile } from "tailwindcss";
8991
10376
 
8992
10377
  // pkgs/@akanjs/devkit/frontendBuild/cssImportResolver.ts
8993
- import path23 from "path";
10378
+ import path25 from "path";
8994
10379
  var CSS_IMPORT_EXTS = ["", ".css", "/styles.css", "/index.css"];
8995
10380
 
8996
10381
  class CssImportResolver {
@@ -9043,7 +10428,7 @@ class CssImportResolver {
9043
10428
  const exact = this.#paths[id];
9044
10429
  if (exact) {
9045
10430
  for (const repl of exact) {
9046
- const resolved = await this.#firstExisting(path23.resolve(this.#workspaceRoot, repl));
10431
+ const resolved = await this.#firstExisting(path25.resolve(this.#workspaceRoot, repl));
9047
10432
  if (resolved)
9048
10433
  return resolved;
9049
10434
  }
@@ -9054,7 +10439,7 @@ class CssImportResolver {
9054
10439
  const suffix = id.slice(prefix.length);
9055
10440
  for (const repl of replacements) {
9056
10441
  const replPath = repl.endsWith("/*") ? repl.slice(0, -1) : repl;
9057
- const resolved = await this.#firstExisting(path23.resolve(this.#workspaceRoot, replPath + suffix));
10442
+ const resolved = await this.#firstExisting(path25.resolve(this.#workspaceRoot, replPath + suffix));
9058
10443
  if (resolved)
9059
10444
  return resolved;
9060
10445
  }
@@ -9084,25 +10469,25 @@ class CssImportResolver {
9084
10469
  try {
9085
10470
  if (!await Bun.file(pkgPath).exists())
9086
10471
  return null;
9087
- const pkgDir = path23.dirname(pkgPath);
10472
+ const pkgDir = path25.dirname(pkgPath);
9088
10473
  const pkg = await Bun.file(pkgPath).json();
9089
10474
  const subpath = id === pkgName ? "." : `.${id.slice(pkgName.length)}`;
9090
10475
  const exportValue = pkg.exports?.[subpath];
9091
10476
  const styleEntry = (typeof exportValue === "string" ? exportValue : exportValue?.style || exportValue?.import || exportValue?.default) || pkg.exports?.["."]?.style || pkg.style || "index.css";
9092
- return await this.#firstExisting(path23.resolve(pkgDir, styleEntry));
10477
+ return await this.#firstExisting(path25.resolve(pkgDir, styleEntry));
9093
10478
  } catch {
9094
10479
  return null;
9095
10480
  }
9096
10481
  }
9097
10482
  #resolutionBases(fromBase) {
9098
- return [fromBase, this.#workspaceRoot, path23.dirname(Bun.main), path23.resolve(path23.dirname(Bun.main), "../..")];
10483
+ return [fromBase, this.#workspaceRoot, path25.dirname(Bun.main), path25.resolve(path25.dirname(Bun.main), "../..")];
9099
10484
  }
9100
10485
  #packageJsonCandidates(pkgName) {
9101
10486
  return [
9102
- path23.join(this.#workspaceRoot, "pkgs", pkgName, "package.json"),
9103
- path23.join(this.#workspaceRoot, "node_modules", pkgName, "package.json"),
9104
- path23.join(path23.dirname(Bun.main), "node_modules", pkgName, "package.json"),
9105
- path23.join(path23.dirname(Bun.main), "../../", pkgName, "package.json")
10487
+ path25.join(this.#workspaceRoot, "pkgs", pkgName, "package.json"),
10488
+ path25.join(this.#workspaceRoot, "node_modules", pkgName, "package.json"),
10489
+ path25.join(path25.dirname(Bun.main), "node_modules", pkgName, "package.json"),
10490
+ path25.join(path25.dirname(Bun.main), "../../", pkgName, "package.json")
9106
10491
  ];
9107
10492
  }
9108
10493
  async#firstExisting(basePath2) {
@@ -9120,7 +10505,7 @@ class CssImportResolver {
9120
10505
  return parts[0] ?? null;
9121
10506
  }
9122
10507
  static isCssFile(filePath) {
9123
- return path23.extname(filePath) === ".css";
10508
+ return path25.extname(filePath) === ".css";
9124
10509
  }
9125
10510
  }
9126
10511
 
@@ -9187,7 +10572,7 @@ class CssCompiler {
9187
10572
  pageKeys
9188
10573
  } = {}) {
9189
10574
  pageKeys ??= await this.#app.getPageKeys({ refresh });
9190
- const seeds = pageKeys.map((key) => path24.resolve(this.#app.cwdPath, "page", key));
10575
+ const seeds = pageKeys.map((key) => path26.resolve(this.#app.cwdPath, "page", key));
9191
10576
  const cssFiles = new Set;
9192
10577
  const sourceFiles = new Set;
9193
10578
  const queue = [...seeds];
@@ -9219,7 +10604,7 @@ class CssCompiler {
9219
10604
  } catch {
9220
10605
  continue;
9221
10606
  }
9222
- const importerDir = path24.dirname(filePath);
10607
+ const importerDir = path26.dirname(filePath);
9223
10608
  for (const imp of imports) {
9224
10609
  const spec = imp.path;
9225
10610
  if (!spec)
@@ -9245,7 +10630,7 @@ class CssCompiler {
9245
10630
  const compileStarted = Date.now();
9246
10631
  const compilers = await Promise.all(cssPaths.map(async (cssPath) => {
9247
10632
  const css = await Bun.file(cssPath).text();
9248
- const base = path24.dirname(cssPath);
10633
+ const base = path26.dirname(cssPath);
9249
10634
  const compiler = await compile(css, {
9250
10635
  base,
9251
10636
  loadStylesheet: (id, fromBase) => this.#loadStylesheet(id, fromBase),
@@ -9276,11 +10661,11 @@ class CssCompiler {
9276
10661
  async#loadStylesheet(id, fromBase) {
9277
10662
  const p = await this.#resolveCssImport(id, fromBase);
9278
10663
  const content = await Bun.file(p).text();
9279
- return { path: p, base: path24.dirname(p), content };
10664
+ return { path: p, base: path26.dirname(p), content };
9280
10665
  }
9281
10666
  async#resolveCssImport(id, fromBase) {
9282
10667
  if (id.startsWith(".") || id.startsWith("/"))
9283
- return path24.resolve(fromBase, id);
10668
+ return path26.resolve(fromBase, id);
9284
10669
  const resolver = await this.#getCssImportResolver();
9285
10670
  const resolved = await resolver.resolve(id, fromBase);
9286
10671
  if (resolved)
@@ -9296,11 +10681,11 @@ class CssCompiler {
9296
10681
  async#loadModule(id, fromBase) {
9297
10682
  const p = __require.resolve(id, { paths: [fromBase] });
9298
10683
  const mod = await import(p);
9299
- return { path: p, base: path24.dirname(p), module: mod.default ?? mod };
10684
+ return { path: p, base: path26.dirname(p), module: mod.default ?? mod };
9300
10685
  }
9301
10686
  async#resolveSourceImport(id, fromBase, resolvePackage) {
9302
10687
  if (id.startsWith(".") || id.startsWith("/")) {
9303
- const abs = id.startsWith("/") ? id : path24.resolve(fromBase, id);
10688
+ const abs = id.startsWith("/") ? id : path26.resolve(fromBase, id);
9304
10689
  return resolveSourceFileCandidate(abs);
9305
10690
  }
9306
10691
  const pkg = await resolvePackage(id);
@@ -9342,7 +10727,7 @@ async function resolveSourceFileCandidate(absPathNoExt) {
9342
10727
  return filePath;
9343
10728
  }
9344
10729
  for (const ext of SOURCE_EXTS3) {
9345
- const filePath = path24.join(absPathNoExt, `index${ext}`);
10730
+ const filePath = path26.join(absPathNoExt, `index${ext}`);
9346
10731
  if (await Bun.file(filePath).exists())
9347
10732
  return filePath;
9348
10733
  }
@@ -9365,19 +10750,19 @@ function resolveSourceWithRequire(id, fromBase) {
9365
10750
  }
9366
10751
  }
9367
10752
  function isSourceFile(filePath) {
9368
- return SOURCE_EXTS3.includes(path24.extname(filePath));
10753
+ return SOURCE_EXTS3.includes(path26.extname(filePath));
9369
10754
  }
9370
10755
  function isIgnoredNodeModuleSource(filePath) {
9371
10756
  return NODE_MODULES_RE3.test(filePath) && !AKANJS_NODE_MODULE_RE3.test(filePath);
9372
10757
  }
9373
10758
  function getPageKeyBasePath(pageKey, basePaths) {
9374
- const normalized = pageKey.split(path24.sep).join("/").replace(/^\.\//, "");
10759
+ const normalized = pageKey.split(path26.sep).join("/").replace(/^\.\//, "");
9375
10760
  const segments = normalized.split("/");
9376
10761
  const firstPublicSegment = segments.find((segment) => segment !== "[lang]" && !/^\(.+\)$/.test(segment));
9377
10762
  return firstPublicSegment && basePaths.includes(firstPublicSegment) ? firstPublicSegment : null;
9378
10763
  }
9379
10764
  // pkgs/@akanjs/devkit/frontendBuild/devChangePlanner.ts
9380
- import path25 from "path";
10765
+ import path27 from "path";
9381
10766
  var SOURCE_EXTS4 = new Set([".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs"]);
9382
10767
  var CONFIG_BASENAMES = new Set(["akan.config.ts", "bunfig.toml", "tsconfig.json", "package.json"]);
9383
10768
  var BARREL_FACETS = new Set(["common", "srvkit", "ui", "webkit"]);
@@ -9389,11 +10774,11 @@ var RUNTIME_METADATA_BASENAMES2 = new Set(["dict.ts", "sig.ts", "useClient.ts",
9389
10774
  class DevChangePlanner {
9390
10775
  #workspaceRoot;
9391
10776
  constructor({ workspaceRoot }) {
9392
- this.#workspaceRoot = path25.resolve(workspaceRoot);
10777
+ this.#workspaceRoot = path27.resolve(workspaceRoot);
9393
10778
  }
9394
10779
  plan({ generation, files, kinds, generatedFiles: generatedFiles2 = [] }) {
9395
10780
  const fileList = uniqueResolved([...files, ...generatedFiles2]);
9396
- const generatedSet = new Set(generatedFiles2.map((file) => path25.resolve(file)));
10781
+ const generatedSet = new Set(generatedFiles2.map((file) => path27.resolve(file)));
9397
10782
  const kindSet = new Set(kinds);
9398
10783
  const roles = new Set;
9399
10784
  const actions = new Set;
@@ -9410,13 +10795,13 @@ class DevChangePlanner {
9410
10795
  }
9411
10796
  for (const file of fileList) {
9412
10797
  const reasons = new Set;
9413
- const fileRoles = this.#rolesForFile(file, { isGenerated: generatedSet.has(path25.resolve(file)), reasons });
10798
+ const fileRoles = this.#rolesForFile(file, { isGenerated: generatedSet.has(path27.resolve(file)), reasons });
9414
10799
  for (const role of fileRoles)
9415
10800
  roles.add(role);
9416
10801
  if (reasons.has("runtime-metadata"))
9417
10802
  actions.add("restart-builder");
9418
10803
  if (reasons.size > 0)
9419
- reasonByFile[path25.resolve(file)] = [...reasons].sort();
10804
+ reasonByFile[path27.resolve(file)] = [...reasons].sort();
9420
10805
  }
9421
10806
  if (roles.has("barrel"))
9422
10807
  actions.add("sync-generated");
@@ -9437,12 +10822,12 @@ class DevChangePlanner {
9437
10822
  }
9438
10823
  #rolesForFile(file, { isGenerated, reasons }) {
9439
10824
  const roles = new Set;
9440
- const abs = path25.resolve(file);
9441
- const base = path25.basename(abs);
9442
- const ext = path25.extname(abs).toLowerCase();
10825
+ const abs = path27.resolve(file);
10826
+ const base = path27.basename(abs);
10827
+ const ext = path27.extname(abs).toLowerCase();
9443
10828
  const isSource = SOURCE_EXTS4.has(ext);
9444
- const rel = path25.relative(this.#workspaceRoot, abs);
9445
- const parts = rel.split(path25.sep).filter(Boolean);
10829
+ const rel = path27.relative(this.#workspaceRoot, abs);
10830
+ const parts = rel.split(path27.sep).filter(Boolean);
9446
10831
  if (CONFIG_BASENAMES.has(base)) {
9447
10832
  roles.add("config");
9448
10833
  reasons.add("config-file");
@@ -9483,15 +10868,15 @@ class DevChangePlanner {
9483
10868
  return roles;
9484
10869
  }
9485
10870
  #isServerBiased(abs, parts) {
9486
- const base = path25.basename(abs);
10871
+ const base = path27.basename(abs);
9487
10872
  return parts.includes("srvkit") || SERVER_SUFFIXES2.some((suffix) => base.endsWith(suffix)) || base === "main.ts" || base === "server.ts";
9488
10873
  }
9489
10874
  #isClientBiased(abs, parts) {
9490
- const base = path25.basename(abs);
10875
+ const base = path27.basename(abs);
9491
10876
  return parts.includes("ui") || parts.includes("webkit") || parts.includes("page") || CLIENT_SUFFIXES.some((suffix) => base.endsWith(suffix));
9492
10877
  }
9493
10878
  #isSharedBiased(abs, parts) {
9494
- const base = path25.basename(abs);
10879
+ const base = path27.basename(abs);
9495
10880
  return parts.includes("common") || SHARED_SUFFIXES2.some((suffix) => base.endsWith(suffix)) || RUNTIME_METADATA_BASENAMES2.has(base);
9496
10881
  }
9497
10882
  #isRuntimeMetadataFile(parts, base) {
@@ -9516,16 +10901,16 @@ class DevChangePlanner {
9516
10901
  return true;
9517
10902
  }
9518
10903
  #isWorkspaceSource(rel) {
9519
- if (!rel || rel.startsWith("..") || path25.isAbsolute(rel))
10904
+ if (!rel || rel.startsWith("..") || path27.isAbsolute(rel))
9520
10905
  return false;
9521
- const [scope] = rel.split(path25.sep);
10906
+ const [scope] = rel.split(path27.sep);
9522
10907
  return scope === "apps" || scope === "libs" || scope === "pkgs";
9523
10908
  }
9524
10909
  }
9525
- var uniqueResolved = (files) => [...new Set(files.map((file) => path25.resolve(file)))].sort();
10910
+ var uniqueResolved = (files) => [...new Set(files.map((file) => path27.resolve(file)))].sort();
9526
10911
  // pkgs/@akanjs/devkit/frontendBuild/devGeneratedIndexSync.ts
9527
10912
  import { mkdir as mkdir6, readdir as readdir2, readFile, rm as rm2, stat as stat3, writeFile } from "fs/promises";
9528
- import path26 from "path";
10913
+ import path28 from "path";
9529
10914
  var BARREL_FACETS2 = new Set(["common", "srvkit", "ui", "webkit"]);
9530
10915
  var FACET_SOURCE_FILE_RE = /\.(ts|tsx)$/;
9531
10916
  var FACET_EXCLUDED_FILE_RE = /(^index\.tsx?$|\.d\.ts$|\.(test|spec)\.(ts|tsx)$|\.css$|\.scss$|\.sass$)/;
@@ -9536,7 +10921,7 @@ var SCALAR_UI_TYPES = ["Template", "Unit"];
9536
10921
  class DevGeneratedIndexSync {
9537
10922
  #workspaceRoot;
9538
10923
  constructor({ workspaceRoot }) {
9539
- this.#workspaceRoot = path26.resolve(workspaceRoot);
10924
+ this.#workspaceRoot = path28.resolve(workspaceRoot);
9540
10925
  }
9541
10926
  async syncForBatch(files) {
9542
10927
  const indexPaths = new Set;
@@ -9545,12 +10930,12 @@ class DevGeneratedIndexSync {
9545
10930
  const facetIndex = this.#facetIndexFor(file);
9546
10931
  if (facetIndex)
9547
10932
  indexPaths.add(facetIndex);
9548
- const moduleIndex = await this.#moduleIndexForDirectoryEvent(file).catch((err) => {
10933
+ const moduleIndex2 = await this.#moduleIndexForDirectoryEvent(file).catch((err) => {
9549
10934
  errors.push(`[generated-index] module detection failed for ${file}: ${formatError(err)}`);
9550
10935
  return null;
9551
10936
  });
9552
- if (moduleIndex)
9553
- indexPaths.add(moduleIndex);
10937
+ if (moduleIndex2)
10938
+ indexPaths.add(moduleIndex2);
9554
10939
  }
9555
10940
  const changedFiles = [];
9556
10941
  for (const indexPath of [...indexPaths].sort()) {
@@ -9565,11 +10950,11 @@ class DevGeneratedIndexSync {
9565
10950
  return { changedFiles, errors };
9566
10951
  }
9567
10952
  #facetIndexFor(file) {
9568
- const abs = path26.resolve(file);
9569
- const rel = path26.relative(this.#workspaceRoot, abs);
9570
- if (rel.startsWith("..") || path26.isAbsolute(rel))
10953
+ const abs = path28.resolve(file);
10954
+ const rel = path28.relative(this.#workspaceRoot, abs);
10955
+ if (rel.startsWith("..") || path28.isAbsolute(rel))
9571
10956
  return null;
9572
- const parts = rel.split(path26.sep).filter(Boolean);
10957
+ const parts = rel.split(path28.sep).filter(Boolean);
9573
10958
  if (parts.length < 4)
9574
10959
  return null;
9575
10960
  const [scope, project, facet, child] = parts;
@@ -9577,32 +10962,32 @@ class DevGeneratedIndexSync {
9577
10962
  return null;
9578
10963
  if (!child || child.startsWith(".") || child === "index.ts" || child === "index.tsx")
9579
10964
  return null;
9580
- return path26.join(this.#workspaceRoot, scope, project, facet, "index.ts");
10965
+ return path28.join(this.#workspaceRoot, scope, project, facet, "index.ts");
9581
10966
  }
9582
10967
  async#moduleIndexForDirectoryEvent(file) {
9583
- const abs = path26.resolve(file);
9584
- const rel = path26.relative(this.#workspaceRoot, abs);
9585
- if (rel.startsWith("..") || path26.isAbsolute(rel))
10968
+ const abs = path28.resolve(file);
10969
+ const rel = path28.relative(this.#workspaceRoot, abs);
10970
+ if (rel.startsWith("..") || path28.isAbsolute(rel))
9586
10971
  return null;
9587
- const parts = rel.split(path26.sep).filter(Boolean);
10972
+ const parts = rel.split(path28.sep).filter(Boolean);
9588
10973
  if (parts.length !== 4 && parts.length !== 5)
9589
10974
  return null;
9590
10975
  const [scope, project, libSegment, moduleSegment, scalarSegment] = parts;
9591
10976
  if (scope !== "apps" && scope !== "libs" || !project || libSegment !== "lib")
9592
10977
  return null;
9593
10978
  const isExistingDirectory = await stat3(abs).then((s) => s.isDirectory()).catch(() => false);
9594
- const looksLikeDeletedDirectory = !path26.extname(abs);
10979
+ const looksLikeDeletedDirectory = !path28.extname(abs);
9595
10980
  if (!isExistingDirectory && !looksLikeDeletedDirectory)
9596
10981
  return null;
9597
10982
  if (moduleSegment === "__scalar" && scalarSegment) {
9598
- return path26.join(this.#workspaceRoot, scope, project, "lib", "__scalar", scalarSegment, "index.ts");
10983
+ return path28.join(this.#workspaceRoot, scope, project, "lib", "__scalar", scalarSegment, "index.ts");
9599
10984
  }
9600
10985
  if (!moduleSegment || moduleSegment === "__scalar")
9601
10986
  return null;
9602
- return path26.join(this.#workspaceRoot, scope, project, "lib", moduleSegment, "index.ts");
10987
+ return path28.join(this.#workspaceRoot, scope, project, "lib", moduleSegment, "index.ts");
9603
10988
  }
9604
10989
  async#syncIndex(indexPath) {
9605
- const dir = path26.dirname(indexPath);
10990
+ const dir = path28.dirname(indexPath);
9606
10991
  const content = await this.#contentForIndex(indexPath);
9607
10992
  if (content === null) {
9608
10993
  if (!await exists(indexPath))
@@ -9618,11 +11003,11 @@ class DevGeneratedIndexSync {
9618
11003
  return true;
9619
11004
  }
9620
11005
  async#contentForIndex(indexPath) {
9621
- const parts = path26.relative(this.#workspaceRoot, indexPath).split(path26.sep).filter(Boolean);
11006
+ const parts = path28.relative(this.#workspaceRoot, indexPath).split(path28.sep).filter(Boolean);
9622
11007
  const facet = parts.at(-2);
9623
11008
  if (facet && BARREL_FACETS2.has(facet))
9624
- return this.#facetContent(path26.dirname(indexPath));
9625
- return this.#moduleContent(path26.dirname(indexPath));
11009
+ return this.#facetContent(path28.dirname(indexPath));
11010
+ return this.#moduleContent(path28.dirname(indexPath));
9626
11011
  }
9627
11012
  async#facetContent(dir) {
9628
11013
  const entries = await readdir2(dir, { withFileTypes: true }).catch(() => []);
@@ -9645,8 +11030,8 @@ class DevGeneratedIndexSync {
9645
11030
  `;
9646
11031
  }
9647
11032
  async#moduleContent(dir) {
9648
- const rel = path26.relative(this.#workspaceRoot, dir);
9649
- const parts = rel.split(path26.sep).filter(Boolean);
11033
+ const rel = path28.relative(this.#workspaceRoot, dir);
11034
+ const parts = rel.split(path28.sep).filter(Boolean);
9650
11035
  const moduleSegment = parts.at(-1);
9651
11036
  if (!moduleSegment)
9652
11037
  return null;
@@ -9654,11 +11039,11 @@ class DevGeneratedIndexSync {
9654
11039
  const rawModel = moduleSegment.startsWith("_") ? moduleSegment.slice(1) : moduleSegment;
9655
11040
  if (!rawModel)
9656
11041
  return null;
9657
- const modelName = capitalize5(rawModel);
11042
+ const modelName = capitalize4(rawModel);
9658
11043
  const allowedTypes = isScalar ? SCALAR_UI_TYPES : moduleSegment.startsWith("_") ? SERVICE_UI_TYPES : MODULE_UI_TYPES;
9659
11044
  const fileTypes = [];
9660
11045
  for (const type of allowedTypes) {
9661
- if (await exists(path26.join(dir, `${modelName}.${type}.tsx`)))
11046
+ if (await exists(path28.join(dir, `${modelName}.${type}.tsx`)))
9662
11047
  fileTypes.push(type);
9663
11048
  }
9664
11049
  if (fileTypes.length === 0)
@@ -9671,11 +11056,11 @@ export const ${modelName} = { ${fileTypes.join(", ")} };`;
9671
11056
  }
9672
11057
  }
9673
11058
  var exists = async (file) => stat3(file).then(() => true).catch(() => false);
9674
- var capitalize5 = (value) => `${value.charAt(0).toUpperCase()}${value.slice(1)}`;
11059
+ var capitalize4 = (value) => `${value.charAt(0).toUpperCase()}${value.slice(1)}`;
9675
11060
  var formatError = (err) => err instanceof Error ? err.message : String(err);
9676
11061
  // pkgs/@akanjs/devkit/frontendBuild/fontOptimizer.ts
9677
11062
  import { mkdir as mkdir7 } from "fs/promises";
9678
- import path27 from "path";
11063
+ import path29 from "path";
9679
11064
  import {
9680
11065
  generateFontFace,
9681
11066
  getMetricsForFamily,
@@ -9684,7 +11069,7 @@ import {
9684
11069
  } from "fontaine";
9685
11070
  import { createFont, woff2 } from "fonteditor-core";
9686
11071
  import subsetFont from "subset-font";
9687
- import ts7 from "typescript";
11072
+ import ts9 from "typescript";
9688
11073
  var FONT_URL_PREFIX = "/_akan/fonts";
9689
11074
  var DEFAULT_FONT_SUBSETS = ["latin"];
9690
11075
 
@@ -9699,7 +11084,7 @@ class FontOptimizer {
9699
11084
  constructor(app, command = "start") {
9700
11085
  this.#app = app;
9701
11086
  this.#command = command;
9702
- this.#artifactRoot = path27.join(command === "build" ? app.dist.cwdPath : app.cwdPath, ".akan/artifact");
11087
+ this.#artifactRoot = path29.join(command === "build" ? app.dist.cwdPath : app.cwdPath, ".akan/artifact");
9703
11088
  }
9704
11089
  async optimize() {
9705
11090
  const fonts = await this.discoverFonts();
@@ -9718,7 +11103,7 @@ class FontOptimizer {
9718
11103
  const pageKeys = await this.#app.getPageKeys();
9719
11104
  const fonts = [];
9720
11105
  await Promise.all(pageKeys.map(async (key) => {
9721
- const filePath = path27.resolve(this.#app.cwdPath, "page", key);
11106
+ const filePath = path29.resolve(this.#app.cwdPath, "page", key);
9722
11107
  const file = Bun.file(filePath);
9723
11108
  if (!await file.exists())
9724
11109
  return;
@@ -9734,8 +11119,8 @@ class FontOptimizer {
9734
11119
  this.#app.logger.warn(`[font] source not found: ${face.src}`);
9735
11120
  continue;
9736
11121
  }
9737
- const outputPath = path27.join(this.#artifactRoot, face.optimizedSrc.replace(/^\/_akan\//, ""));
9738
- await mkdir7(path27.dirname(outputPath), { recursive: true });
11122
+ const outputPath = path29.join(this.#artifactRoot, face.optimizedSrc.replace(/^\/_akan\//, ""));
11123
+ await mkdir7(path29.dirname(outputPath), { recursive: true });
9739
11124
  const sourceBuffer = Buffer.from(await Bun.file(sourcePath).arrayBuffer());
9740
11125
  const outputBuffer = font.subset === false ? await this.#convertToWoff2(sourceBuffer, sourcePath) : await subsetFont(sourceBuffer, await this.#getSubsetText(font), { targetFormat: "woff2" });
9741
11126
  await Bun.write(outputPath, outputBuffer);
@@ -9749,17 +11134,17 @@ class FontOptimizer {
9749
11134
  this.#cssParts.push(...faceCss, this.#buildRootVariableRule(font));
9750
11135
  }
9751
11136
  #extractFontsExport(source2, filePath) {
9752
- const sourceFile2 = ts7.createSourceFile(filePath, source2, ts7.ScriptTarget.Latest, true, ts7.ScriptKind.TSX);
11137
+ const sourceFile2 = ts9.createSourceFile(filePath, source2, ts9.ScriptTarget.Latest, true, ts9.ScriptKind.TSX);
9753
11138
  const fonts = [];
9754
11139
  for (const statement of sourceFile2.statements) {
9755
- if (!ts7.isVariableStatement(statement))
11140
+ if (!ts9.isVariableStatement(statement))
9756
11141
  continue;
9757
- const modifiers = ts7.canHaveModifiers(statement) ? ts7.getModifiers(statement) : undefined;
9758
- const isExported = modifiers?.some((modifier) => modifier.kind === ts7.SyntaxKind.ExportKeyword) ?? false;
11142
+ const modifiers = ts9.canHaveModifiers(statement) ? ts9.getModifiers(statement) : undefined;
11143
+ const isExported = modifiers?.some((modifier) => modifier.kind === ts9.SyntaxKind.ExportKeyword) ?? false;
9759
11144
  if (!isExported)
9760
11145
  continue;
9761
11146
  for (const declaration of statement.declarationList.declarations) {
9762
- if (!ts7.isIdentifier(declaration.name) || declaration.name.text !== "fonts")
11147
+ if (!ts9.isIdentifier(declaration.name) || declaration.name.text !== "fonts")
9763
11148
  continue;
9764
11149
  const value = declaration.initializer ? this.#literalToValue(declaration.initializer) : null;
9765
11150
  if (Array.isArray(value)) {
@@ -9770,20 +11155,20 @@ class FontOptimizer {
9770
11155
  return fonts;
9771
11156
  }
9772
11157
  #literalToValue(node) {
9773
- if (ts7.isStringLiteralLike(node))
11158
+ if (ts9.isStringLiteralLike(node))
9774
11159
  return node.text;
9775
- if (ts7.isNumericLiteral(node))
11160
+ if (ts9.isNumericLiteral(node))
9776
11161
  return Number(node.text);
9777
- if (node.kind === ts7.SyntaxKind.TrueKeyword)
11162
+ if (node.kind === ts9.SyntaxKind.TrueKeyword)
9778
11163
  return true;
9779
- if (node.kind === ts7.SyntaxKind.FalseKeyword)
11164
+ if (node.kind === ts9.SyntaxKind.FalseKeyword)
9780
11165
  return false;
9781
- if (ts7.isArrayLiteralExpression(node))
11166
+ if (ts9.isArrayLiteralExpression(node))
9782
11167
  return node.elements.map((element) => this.#literalToValue(element));
9783
- if (ts7.isObjectLiteralExpression(node)) {
11168
+ if (ts9.isObjectLiteralExpression(node)) {
9784
11169
  const obj = {};
9785
11170
  for (const prop of node.properties) {
9786
- if (!ts7.isPropertyAssignment(prop))
11171
+ if (!ts9.isPropertyAssignment(prop))
9787
11172
  continue;
9788
11173
  const name = this.#getPropertyName(prop.name);
9789
11174
  if (!name)
@@ -9792,13 +11177,13 @@ class FontOptimizer {
9792
11177
  }
9793
11178
  return obj;
9794
11179
  }
9795
- if (ts7.isAsExpression(node) || ts7.isSatisfiesExpression(node) || ts7.isParenthesizedExpression(node)) {
11180
+ if (ts9.isAsExpression(node) || ts9.isSatisfiesExpression(node) || ts9.isParenthesizedExpression(node)) {
9796
11181
  return this.#literalToValue(node.expression);
9797
11182
  }
9798
11183
  return;
9799
11184
  }
9800
11185
  #getPropertyName(name) {
9801
- if (ts7.isIdentifier(name) || ts7.isStringLiteral(name) || ts7.isNumericLiteral(name))
11186
+ if (ts9.isIdentifier(name) || ts9.isStringLiteral(name) || ts9.isNumericLiteral(name))
9802
11187
  return name.text;
9803
11188
  return null;
9804
11189
  }
@@ -9882,8 +11267,8 @@ class FontOptimizer {
9882
11267
  return null;
9883
11268
  const rel = src.replace(/^\//, "");
9884
11269
  const candidates = [
9885
- this.#command === "build" ? path27.join(this.#app.dist.cwdPath, "public", rel) : null,
9886
- path27.join(this.#app.cwdPath, "public", rel),
11270
+ this.#command === "build" ? path29.join(this.#app.dist.cwdPath, "public", rel) : null,
11271
+ path29.join(this.#app.cwdPath, "public", rel),
9887
11272
  this.#resolveWorkspacePublicPath(rel)
9888
11273
  ].filter(Boolean);
9889
11274
  for (const candidate of candidates) {
@@ -9911,7 +11296,7 @@ class FontOptimizer {
9911
11296
  return "woff2";
9912
11297
  if (signature === "OTTO")
9913
11298
  return "otf";
9914
- const ext = path27.extname(sourcePath).slice(1).toLowerCase();
11299
+ const ext = path29.extname(sourcePath).slice(1).toLowerCase();
9915
11300
  if (ext === "otf" || ext === "woff" || ext === "woff2")
9916
11301
  return ext;
9917
11302
  return "ttf";
@@ -9920,7 +11305,7 @@ class FontOptimizer {
9920
11305
  const [root, dep, ...rest] = rel.split("/");
9921
11306
  if (root !== "libs" || !dep || rest.length === 0)
9922
11307
  return null;
9923
- return path27.join(this.#app.workspace.workspaceRoot, "libs", dep, "public", ...rest);
11308
+ return path29.join(this.#app.workspace.workspaceRoot, "libs", dep, "public", ...rest);
9924
11309
  }
9925
11310
  async#getSubsetText(font) {
9926
11311
  const parts = new Set;
@@ -9930,7 +11315,7 @@ class FontOptimizer {
9930
11315
  if (font.subsetText)
9931
11316
  parts.add(font.subsetText);
9932
11317
  for (const filePath of font.subsetFiles ?? []) {
9933
- const abs = path27.isAbsolute(filePath) ? filePath : path27.join(this.#app.cwdPath, filePath);
11318
+ const abs = path29.isAbsolute(filePath) ? filePath : path29.join(this.#app.cwdPath, filePath);
9934
11319
  const file = Bun.file(abs);
9935
11320
  if (await file.exists())
9936
11321
  parts.add(await file.text());
@@ -9949,7 +11334,7 @@ class FontOptimizer {
9949
11334
  return "";
9950
11335
  }
9951
11336
  async#collectAutoSubsetText() {
9952
- const roots = ["page", "ui"].map((dir) => path27.join(this.#app.cwdPath, dir));
11337
+ const roots = ["page", "ui"].map((dir) => path29.join(this.#app.cwdPath, dir));
9953
11338
  const glob = new Bun.Glob("**/*.{ts,tsx,js,jsx,html,md}");
9954
11339
  const parts = [];
9955
11340
  await Promise.all(roots.map(async (root) => {
@@ -10063,7 +11448,7 @@ ${declarations.map(([prop, value]) => ` ${prop}: ${value};`).join(`
10063
11448
  }
10064
11449
  }
10065
11450
  // pkgs/@akanjs/devkit/frontendBuild/hmrChangeClassifier.ts
10066
- import path28 from "path";
11451
+ import path30 from "path";
10067
11452
  var SOURCE_EXTS5 = new Set([".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs"]);
10068
11453
  var CSS_EXTS = new Set([".css"]);
10069
11454
  var CONFIG_BASENAMES2 = new Set(["akan.config.ts", "bunfig.toml", "tsconfig.json", "package.json"]);
@@ -10072,10 +11457,10 @@ class HmrChangeClassifier {
10072
11457
  classify(abs) {
10073
11458
  if (this.#isUninteresting(abs))
10074
11459
  return "ignore";
10075
- const base = path28.basename(abs);
11460
+ const base = path30.basename(abs);
10076
11461
  if (CONFIG_BASENAMES2.has(base))
10077
11462
  return "config";
10078
- const ext = path28.extname(abs).toLowerCase();
11463
+ const ext = path30.extname(abs).toLowerCase();
10079
11464
  if (CSS_EXTS.has(ext))
10080
11465
  return "css";
10081
11466
  if (SOURCE_EXTS5.has(ext))
@@ -10083,23 +11468,23 @@ class HmrChangeClassifier {
10083
11468
  return "ignore";
10084
11469
  }
10085
11470
  #isUninteresting(abs) {
10086
- const base = path28.basename(abs);
11471
+ const base = path30.basename(abs);
10087
11472
  if (!base)
10088
11473
  return true;
10089
11474
  if (base.startsWith("."))
10090
11475
  return true;
10091
11476
  if (base.endsWith("~") || base.endsWith(".swp") || base.endsWith(".swx") || base.endsWith(".tmp"))
10092
11477
  return true;
10093
- if (abs.includes(`${path28.sep}node_modules${path28.sep}`))
11478
+ if (abs.includes(`${path30.sep}node_modules${path30.sep}`))
10094
11479
  return true;
10095
- if (abs.includes(`${path28.sep}.akan${path28.sep}`))
11480
+ if (abs.includes(`${path30.sep}.akan${path30.sep}`))
10096
11481
  return true;
10097
11482
  return false;
10098
11483
  }
10099
11484
  }
10100
11485
  // pkgs/@akanjs/devkit/frontendBuild/hmrWatcher.ts
10101
11486
  import fs4 from "fs";
10102
- import path29 from "path";
11487
+ import path31 from "path";
10103
11488
  class HmrWatcher {
10104
11489
  #roots;
10105
11490
  #debounceMs;
@@ -10112,7 +11497,7 @@ class HmrWatcher {
10112
11497
  #stopped = false;
10113
11498
  #flushing = false;
10114
11499
  constructor(opts) {
10115
- this.#roots = [...new Set(opts.roots.map((r) => path29.resolve(r)))];
11500
+ this.#roots = [...new Set(opts.roots.map((r) => path31.resolve(r)))];
10116
11501
  this.#debounceMs = opts.debounceMs ?? 80;
10117
11502
  this.#onBatch = opts.onBatch;
10118
11503
  this.#logger = opts.logger;
@@ -10123,7 +11508,7 @@ class HmrWatcher {
10123
11508
  const w = fs4.watch(root, { recursive: true, persistent: false }, (_event, filename) => {
10124
11509
  if (!filename)
10125
11510
  return;
10126
- const abs = path29.resolve(root, filename.toString());
11511
+ const abs = path31.resolve(root, filename.toString());
10127
11512
  this.#queue(abs);
10128
11513
  });
10129
11514
  this.#watchers.push(w);
@@ -10181,10 +11566,10 @@ class HmrWatcher {
10181
11566
  }
10182
11567
  }
10183
11568
  // pkgs/@akanjs/devkit/frontendBuild/pagesBundleBuilder.ts
10184
- import path31 from "path";
11569
+ import path33 from "path";
10185
11570
 
10186
11571
  // pkgs/@akanjs/devkit/transforms/externalizeFrameworkPlugin.ts
10187
- import path30 from "path";
11572
+ import path32 from "path";
10188
11573
  var DEFAULT_INCLUDE = ["akanjs/", "@apps/", "@libs/"];
10189
11574
  var DEFAULT_EXCLUDE_EXACT = new Set(["akanjs/webkit", "@akanjs/cli", "@akanjs/devkit"]);
10190
11575
  var DEFAULT_EXCLUDE_PREFIX = ["@akanjs/cli/", "@akanjs/devkit/"];
@@ -10227,7 +11612,7 @@ async function createExternalizeFrameworkPlugin(options) {
10227
11612
  const replPath = repl?.endsWith("/*") ? repl.slice(0, -1) : repl ?? "";
10228
11613
  if (!replPath)
10229
11614
  continue;
10230
- const candidate = path30.resolve(workspaceRoot, replPath + suffix);
11615
+ const candidate = path32.resolve(workspaceRoot, replPath + suffix);
10231
11616
  const hit = await firstExisting(candidate);
10232
11617
  if (hit)
10233
11618
  return hit;
@@ -10239,8 +11624,8 @@ async function createExternalizeFrameworkPlugin(options) {
10239
11624
  if (spec === pkg)
10240
11625
  continue;
10241
11626
  const suffix = spec.slice(pkg.length + 1);
10242
- const pkgDir = path30.dirname(path30.resolve(workspaceRoot, entryFile));
10243
- const candidate = path30.join(pkgDir, suffix);
11627
+ const pkgDir = path32.dirname(path32.resolve(workspaceRoot, entryFile));
11628
+ const candidate = path32.join(pkgDir, suffix);
10244
11629
  const hit = await firstExisting(candidate);
10245
11630
  if (hit)
10246
11631
  return hit;
@@ -10290,7 +11675,7 @@ async function firstExisting(basePath2) {
10290
11675
  return candidate;
10291
11676
  }
10292
11677
  for (const ext of CANDIDATE_EXTS3) {
10293
- const candidate = path30.join(basePath2, `index${ext}`);
11678
+ const candidate = path32.join(basePath2, `index${ext}`);
10294
11679
  if (await Bun.file(candidate).exists())
10295
11680
  return candidate;
10296
11681
  }
@@ -10381,11 +11766,11 @@ class PagesBundleBuilder {
10381
11766
  const entryArtifact = result.outputs.find((a) => a.kind === "entry-point");
10382
11767
  if (!entryArtifact)
10383
11768
  throw new Error("[PagesBundleBuilder] Bun.build emitted no entry-point artifact");
10384
- const bundlePath = path31.resolve(entryArtifact.path);
11769
+ const bundlePath = path33.resolve(entryArtifact.path);
10385
11770
  const buildId = Date.now();
10386
11771
  const outputBytes = result.outputs.reduce((sum, output) => sum + output.size, 0);
10387
11772
  const chunkCount = result.outputs.filter((output) => output.kind === "chunk").length;
10388
- this.#app.verbose(`[PagesBundleBuilder] ${path31.basename(bundlePath)} emitted in ${Date.now() - this.#started}ms splitting=${this.#splitting} entry=${entryArtifact.size} bytes outputs=${result.outputs.length} chunks=${chunkCount} total=${outputBytes} bytes`);
11773
+ this.#app.verbose(`[PagesBundleBuilder] ${path33.basename(bundlePath)} emitted in ${Date.now() - this.#started}ms splitting=${this.#splitting} entry=${entryArtifact.size} bytes outputs=${result.outputs.length} chunks=${chunkCount} total=${outputBytes} bytes`);
10389
11774
  return {
10390
11775
  bundlePath,
10391
11776
  buildId,
@@ -10467,11 +11852,11 @@ function loaderFor4(absPath) {
10467
11852
  }
10468
11853
  // pkgs/@akanjs/devkit/frontendBuild/precompressArtifacts.ts
10469
11854
  import fs5 from "fs";
10470
- import path32 from "path";
11855
+ import path34 from "path";
10471
11856
  var COMPRESSIBLE_EXTS = new Set([".css", ".html", ".js", ".json", ".svg"]);
10472
11857
  var MIN_COMPRESS_BYTES = 1024;
10473
11858
  async function precompressArtifacts(app) {
10474
- const roots = [path32.join(app.dist.cwdPath, ".akan/artifact/client")];
11859
+ const roots = [path34.join(app.dist.cwdPath, ".akan/artifact/client")];
10475
11860
  const result = { files: 0, inputBytes: 0, outputBytes: 0 };
10476
11861
  await Promise.all(roots.map((root) => precompressRoot(root, result)));
10477
11862
  if (result.files > 0) {
@@ -10497,7 +11882,7 @@ async function precompressRoot(root, result) {
10497
11882
  async function shouldPrecompress(filePath) {
10498
11883
  if (filePath.endsWith(".gz"))
10499
11884
  return false;
10500
- if (!COMPRESSIBLE_EXTS.has(path32.extname(filePath).toLowerCase()))
11885
+ if (!COMPRESSIBLE_EXTS.has(path34.extname(filePath).toLowerCase()))
10501
11886
  return false;
10502
11887
  const file = Bun.file(filePath);
10503
11888
  if (!await file.exists())
@@ -10515,7 +11900,7 @@ function formatBytes(bytes) {
10515
11900
  return `${(bytes / 1024 / 1024).toFixed(1)}MB`;
10516
11901
  }
10517
11902
  // pkgs/@akanjs/devkit/frontendBuild/ssrBaseArtifactBuilder.ts
10518
- import path33 from "path";
11903
+ import path35 from "path";
10519
11904
  import { optimize } from "@tailwindcss/node";
10520
11905
  function prepareCssAsset(command, basePath2, cssText) {
10521
11906
  return optimize(cssText, { file: `${basePath2 || "root"}.css`, minify: command === "build" }).code;
@@ -10531,7 +11916,7 @@ class SsrBaseArtifactBuilder {
10531
11916
  this.#app = app;
10532
11917
  this.#command = command;
10533
11918
  this.#artifactDir = `${command === "build" ? app.dist.cwdPath : app.cwdPath}/.akan/artifact`;
10534
- this.#absArtifactDir = path33.resolve(this.#artifactDir);
11919
+ this.#absArtifactDir = path35.resolve(this.#artifactDir);
10535
11920
  }
10536
11921
  async build() {
10537
11922
  const akanConfig2 = await this.#app.getConfig();
@@ -10553,7 +11938,7 @@ class SsrBaseArtifactBuilder {
10553
11938
  rscRuntimeSsrManifest,
10554
11939
  vendorMap,
10555
11940
  cssAssets,
10556
- pagesBundlePath: this.#command === "build" ? path33.relative(this.#absArtifactDir, pagesBundle.bundlePath) : pagesBundle.bundlePath,
11941
+ pagesBundlePath: this.#command === "build" ? path35.relative(this.#absArtifactDir, pagesBundle.bundlePath) : pagesBundle.bundlePath,
10557
11942
  pagesBundleBuildId: pagesBundle.buildId,
10558
11943
  domains: [...akanConfig2.domains],
10559
11944
  subRoutes: Object.fromEntries(Array.from(akanConfig2.subRoutes.entries()).map(([basePath2, domains]) => [basePath2, [...domains]])),
@@ -10562,7 +11947,7 @@ class SsrBaseArtifactBuilder {
10562
11947
  i18n: akanConfig2.i18n,
10563
11948
  imageConfig: akanConfig2.images
10564
11949
  };
10565
- await Bun.write(path33.join(this.#absArtifactDir, "base-artifact.json"), `${JSON.stringify(artifact, null, 2)}
11950
+ await Bun.write(path35.join(this.#absArtifactDir, "base-artifact.json"), `${JSON.stringify(artifact, null, 2)}
10566
11951
  `);
10567
11952
  this.#app.verbose(`[base-artifact] complete in ${Date.now() - this.#started}ms`);
10568
11953
  return { artifact, seedIndex, cssCompiler, optimizedFonts };
@@ -10610,15 +11995,15 @@ class SsrBaseArtifactBuilder {
10610
11995
  async#resolveAkanServerPath() {
10611
11996
  const candidates = [];
10612
11997
  try {
10613
- candidates.push(path33.dirname(Bun.resolveSync("akanjs/server", this.#app.workspace.workspaceRoot)));
11998
+ candidates.push(path35.dirname(Bun.resolveSync("akanjs/server", this.#app.workspace.workspaceRoot)));
10614
11999
  } catch {}
10615
- candidates.push(path33.join(this.#app.workspace.workspaceRoot, "pkgs/akanjs/server"), path33.join(this.#app.workspace.workspaceRoot, "node_modules/akanjs/server"));
12000
+ candidates.push(path35.join(this.#app.workspace.workspaceRoot, "pkgs/akanjs/server"), path35.join(this.#app.workspace.workspaceRoot, "node_modules/akanjs/server"));
10616
12001
  try {
10617
- candidates.push(path33.dirname(Bun.resolveSync("akanjs/server", path33.dirname(Bun.main))));
12002
+ candidates.push(path35.dirname(Bun.resolveSync("akanjs/server", path35.dirname(Bun.main))));
10618
12003
  } catch {}
10619
- candidates.push(path33.join(path33.dirname(Bun.main), "node_modules/akanjs/server"), path33.join(path33.dirname(Bun.main), "../../akanjs/server"), path33.resolve(import.meta.dir, "../../server"), path33.resolve(import.meta.dir, "../server"));
12004
+ candidates.push(path35.join(path35.dirname(Bun.main), "node_modules/akanjs/server"), path35.join(path35.dirname(Bun.main), "../../akanjs/server"), path35.resolve(import.meta.dir, "../../server"), path35.resolve(import.meta.dir, "../server"));
10620
12005
  for (const candidate of candidates) {
10621
- if (await Bun.file(path33.join(candidate, "rscClient.tsx")).exists())
12006
+ if (await Bun.file(path35.join(candidate, "rscClient.tsx")).exists())
10622
12007
  return candidate;
10623
12008
  }
10624
12009
  throw new Error(`[base-artifact] failed to locate akanjs/server; looked in: ${candidates.join(", ")}`);
@@ -10647,14 +12032,14 @@ ${preparedCssText}`).toString(36);
10647
12032
  `styles/${cssAssetName}-${cssHash}.css`,
10648
12033
  `/_akan/styles/${cssAssetName}-${cssHash}.css`
10649
12034
  ];
10650
- await Bun.write(path33.join(this.#absArtifactDir, cssRelPath), preparedCssText);
12035
+ await Bun.write(path35.join(this.#absArtifactDir, cssRelPath), preparedCssText);
10651
12036
  this.#app.verbose(`[base-artifact] wrote ${preparedCssText.length} bytes of CSS for ${basePath2} -> ${cssRelPath}`);
10652
12037
  return [basePath2, { cssUrl, cssRelPath }];
10653
12038
  }
10654
12039
  }
10655
12040
  // pkgs/@akanjs/devkit/frontendBuild/watchRootResolver.ts
10656
12041
  import fs6 from "fs";
10657
- import path34 from "path";
12042
+ import path36 from "path";
10658
12043
 
10659
12044
  class WatchRootResolver {
10660
12045
  #app;
@@ -10664,15 +12049,15 @@ class WatchRootResolver {
10664
12049
  async resolve() {
10665
12050
  const tsconfig = await this.#app.getTsConfig();
10666
12051
  const set = new Set;
10667
- set.add(path34.resolve(`${this.#app.cwdPath}/page`));
12052
+ set.add(path36.resolve(`${this.#app.cwdPath}/page`));
10668
12053
  for (const targets of Object.values(tsconfig.compilerOptions.paths ?? {})) {
10669
12054
  for (const target of targets) {
10670
12055
  if (!target)
10671
12056
  continue;
10672
- if (path34.isAbsolute(target))
12057
+ if (path36.isAbsolute(target))
10673
12058
  continue;
10674
12059
  const cleaned = target.replace(/\/?\*+.*$/, "").replace(/\/[^/]+\.[^/]+$/, "");
10675
- const resolved = path34.resolve(this.#app.workspace.workspaceRoot, cleaned);
12060
+ const resolved = path36.resolve(this.#app.workspace.workspaceRoot, cleaned);
10676
12061
  if (fs6.existsSync(resolved))
10677
12062
  set.add(resolved);
10678
12063
  }
@@ -10739,7 +12124,7 @@ class ApplicationBuildRunner {
10739
12124
  phases: this.#phases,
10740
12125
  durationMs: Date.now() - this.#startedAt,
10741
12126
  outputDir: this.#app.dist.cwdPath,
10742
- artifactDir: path35.join(this.#app.dist.cwdPath, ".akan/artifact")
12127
+ artifactDir: path37.join(this.#app.dist.cwdPath, ".akan/artifact")
10743
12128
  };
10744
12129
  }
10745
12130
  async typecheck(options = {}) {
@@ -10747,7 +12132,7 @@ class ApplicationBuildRunner {
10747
12132
  await this.#app.getPageKeys({ refresh: true });
10748
12133
  const { typecheckDir, tsconfigPath } = await this.#writeTypecheckTsconfig({ incremental });
10749
12134
  if (clean)
10750
- await rm3(path35.join(typecheckDir, "tsconfig.tsbuildinfo"), { force: true });
12135
+ await rm3(path37.join(typecheckDir, "tsconfig.tsbuildinfo"), { force: true });
10751
12136
  await this.#checkProjectInChildProcess(tsconfigPath);
10752
12137
  }
10753
12138
  async#runPhase(id, label, task, summarize, options = {}) {
@@ -10819,7 +12204,7 @@ class ApplicationBuildRunner {
10819
12204
  };
10820
12205
  }
10821
12206
  async#writeConsoleShim() {
10822
- await Bun.write(path35.join(this.#app.dist.cwdPath, "console.js"), `import { cnst, db, dict, option, server, sig, srv } from "./server.js";
12207
+ await Bun.write(path37.join(this.#app.dist.cwdPath, "console.js"), `import { cnst, db, dict, option, server, sig, srv } from "./server.js";
10823
12208
  import { assertAkanConsoleAllowed, startAkanConsole } from "./console-runtime.js";
10824
12209
 
10825
12210
  const run = async () => {
@@ -10842,14 +12227,14 @@ void run().catch((error) => {
10842
12227
  try {
10843
12228
  return Bun.resolveSync("akanjs/server/rsc-worker", import.meta.dir);
10844
12229
  } catch {
10845
- return path35.join(this.#app.workspace.workspaceRoot, "pkgs/akanjs/server/rscWorker.tsx");
12230
+ return path37.join(this.#app.workspace.workspaceRoot, "pkgs/akanjs/server/rscWorker.tsx");
10846
12231
  }
10847
12232
  }
10848
12233
  #resolveConsoleRuntimeBuildEntry() {
10849
12234
  try {
10850
- return path35.join(path35.dirname(Bun.resolveSync("akanjs/server", import.meta.dir)), "console.ts");
12235
+ return path37.join(path37.dirname(Bun.resolveSync("akanjs/server", import.meta.dir)), "console.ts");
10851
12236
  } catch {
10852
- return path35.join(this.#app.workspace.workspaceRoot, "pkgs/akanjs/server/console.ts");
12237
+ return path37.join(this.#app.workspace.workspaceRoot, "pkgs/akanjs/server/console.ts");
10853
12238
  }
10854
12239
  }
10855
12240
  async#buildCsr() {
@@ -10866,7 +12251,7 @@ void run().catch((error) => {
10866
12251
  return { base, allRoutes };
10867
12252
  }
10868
12253
  async#writeTypecheckTsconfig({ incremental = true } = {}) {
10869
- const typecheckDir = path35.join(this.#app.cwdPath, ".akan", "typecheck");
12254
+ const typecheckDir = path37.join(this.#app.cwdPath, ".akan", "typecheck");
10870
12255
  await mkdir8(typecheckDir, { recursive: true });
10871
12256
  const tsconfig = {
10872
12257
  extends: "../../tsconfig.json",
@@ -10885,7 +12270,7 @@ void run().catch((error) => {
10885
12270
  ],
10886
12271
  references: []
10887
12272
  };
10888
- const tsconfigPath = path35.join(typecheckDir, "tsconfig.json");
12273
+ const tsconfigPath = path37.join(typecheckDir, "tsconfig.json");
10889
12274
  await Bun.write(tsconfigPath, `${JSON.stringify(tsconfig, null, 2)}
10890
12275
  `);
10891
12276
  return { typecheckDir, tsconfigPath };
@@ -10911,10 +12296,10 @@ void run().catch((error) => {
10911
12296
  }
10912
12297
  async#resolveTypecheckWorkerEntry() {
10913
12298
  const candidates = [
10914
- path35.join(this.#app.workspace.workspaceRoot, "pkgs/@akanjs/devkit/typecheck/typecheck.proc.ts"),
10915
- path35.join(this.#app.workspace.workspaceRoot, "node_modules/@akanjs/devkit/typecheck/typecheck.proc.ts"),
10916
- path35.join(import.meta.dir, "typecheck.proc.js"),
10917
- path35.join(import.meta.dir, "typecheck.proc.ts")
12299
+ path37.join(this.#app.workspace.workspaceRoot, "pkgs/@akanjs/devkit/typecheck/typecheck.proc.ts"),
12300
+ path37.join(this.#app.workspace.workspaceRoot, "node_modules/@akanjs/devkit/typecheck/typecheck.proc.ts"),
12301
+ path37.join(import.meta.dir, "typecheck.proc.js"),
12302
+ path37.join(import.meta.dir, "typecheck.proc.ts")
10918
12303
  ];
10919
12304
  for (const candidate of candidates)
10920
12305
  if (await Bun.file(candidate).exists())
@@ -11090,13 +12475,13 @@ class ApplicationReleasePackager {
11090
12475
  await cp(this.#app.dist.cwdPath, `${sourceRoot}/apps/${this.#app.name}`, { recursive: true });
11091
12476
  const libDeps = ["social", "shared", "platform", "util"];
11092
12477
  await Promise.all(libDeps.map((lib) => cp(`${this.#app.workspace.cwdPath}/libs/${lib}`, `${sourceRoot}/libs/${lib}`, { recursive: true })));
11093
- await Promise.all([".next", "ios", "android", "public/libs"].map(async (path36) => {
11094
- const targetPath = `${sourceRoot}/apps/${this.#app.name}/${path36}`;
12478
+ await Promise.all([".next", "ios", "android", "public/libs"].map(async (path38) => {
12479
+ const targetPath = `${sourceRoot}/apps/${this.#app.name}/${path38}`;
11095
12480
  if (await FileSys.dirExists(targetPath))
11096
12481
  await rm4(targetPath, { recursive: true, force: true });
11097
12482
  }));
11098
12483
  const syncPaths = [".husky", ".gitignore", "package.json"];
11099
- await Promise.all(syncPaths.map((path36) => cp(`${this.#app.workspace.cwdPath}/${path36}`, `${sourceRoot}/${path36}`, { recursive: true })));
12484
+ await Promise.all(syncPaths.map((path38) => cp(`${this.#app.workspace.cwdPath}/${path38}`, `${sourceRoot}/${path38}`, { recursive: true })));
11100
12485
  await this.#writeSourceTsconfig(sourceRoot, libDeps);
11101
12486
  await Bun.write(`${sourceRoot}/README.md`, readme);
11102
12487
  await this.#app.workspace.spawn("tar", [
@@ -11187,20 +12572,20 @@ class ApplicationReleasePackager {
11187
12572
  }
11188
12573
  }
11189
12574
  // pkgs/@akanjs/devkit/applicationTestPreload.ts
11190
- import path36 from "path";
12575
+ import path38 from "path";
11191
12576
  var SIGNAL_TEST_PRELOAD_PATH = "test/signalTest.preload.ts";
11192
12577
  async function resolveSignalTestPreloadPath(target) {
11193
12578
  const candidates = [];
11194
12579
  const addResolvedPackageCandidate = (basePath2) => {
11195
12580
  try {
11196
- candidates.push(path36.join(path36.dirname(Bun.resolveSync("akanjs/package.json", basePath2)), SIGNAL_TEST_PRELOAD_PATH));
12581
+ candidates.push(path38.join(path38.dirname(Bun.resolveSync("akanjs/package.json", basePath2)), SIGNAL_TEST_PRELOAD_PATH));
11197
12582
  } catch {}
11198
12583
  };
11199
12584
  addResolvedPackageCandidate(target.cwdPath);
11200
12585
  addResolvedPackageCandidate(process.cwd());
11201
- addResolvedPackageCandidate(path36.dirname(Bun.main));
12586
+ addResolvedPackageCandidate(path38.dirname(Bun.main));
11202
12587
  addResolvedPackageCandidate(import.meta.dir);
11203
- candidates.push(path36.join(target.cwdPath, "../../node_modules/akanjs", SIGNAL_TEST_PRELOAD_PATH), path36.join(target.cwdPath, "../../pkgs/akanjs", SIGNAL_TEST_PRELOAD_PATH), path36.join(process.cwd(), "node_modules/akanjs", SIGNAL_TEST_PRELOAD_PATH), path36.join(process.cwd(), "pkgs/akanjs", SIGNAL_TEST_PRELOAD_PATH), path36.join(path36.dirname(Bun.main), "../../akanjs", SIGNAL_TEST_PRELOAD_PATH), path36.resolve(import.meta.dir, "../../akanjs", SIGNAL_TEST_PRELOAD_PATH));
12588
+ candidates.push(path38.join(target.cwdPath, "../../node_modules/akanjs", SIGNAL_TEST_PRELOAD_PATH), path38.join(target.cwdPath, "../../pkgs/akanjs", SIGNAL_TEST_PRELOAD_PATH), path38.join(process.cwd(), "node_modules/akanjs", SIGNAL_TEST_PRELOAD_PATH), path38.join(process.cwd(), "pkgs/akanjs", SIGNAL_TEST_PRELOAD_PATH), path38.join(path38.dirname(Bun.main), "../../akanjs", SIGNAL_TEST_PRELOAD_PATH), path38.resolve(import.meta.dir, "../../akanjs", SIGNAL_TEST_PRELOAD_PATH));
11204
12589
  for (const candidate of [...new Set(candidates)]) {
11205
12590
  if (await Bun.file(candidate).exists())
11206
12591
  return candidate;
@@ -11210,7 +12595,7 @@ async function resolveSignalTestPreloadPath(target) {
11210
12595
  // pkgs/@akanjs/devkit/builder.ts
11211
12596
  import { existsSync as existsSync2 } from "fs";
11212
12597
  import { mkdir as mkdir10 } from "fs/promises";
11213
- import path37 from "path";
12598
+ import path39 from "path";
11214
12599
  var SKIP_ENTRY_DIR_SET = new Set(["node_modules", "dist", "build", ".git", ".next"]);
11215
12600
  var assetExtensions = [".css", ".md", ".js", ".png", ".ico", ".svg", ".json", ".template"];
11216
12601
  var assetLoader = Object.fromEntries(assetExtensions.map((ext) => [ext, "file"]));
@@ -11227,14 +12612,14 @@ class Builder {
11227
12612
  #globEntrypoints(cwd, pattern) {
11228
12613
  const glob = new Bun.Glob(pattern);
11229
12614
  return Array.from(glob.scanSync({ cwd, onlyFiles: true })).filter((relativePath) => {
11230
- const segments = relativePath.split(path37.sep);
12615
+ const segments = relativePath.split(path39.sep);
11231
12616
  return !segments.some((segment) => SKIP_ENTRY_DIR_SET.has(segment));
11232
- }).map((rel) => path37.join(cwd, rel));
12617
+ }).map((rel) => path39.join(cwd, rel));
11233
12618
  }
11234
12619
  #globFiles(cwd, pattern = "**/*.*") {
11235
12620
  const glob = new Bun.Glob(pattern);
11236
12621
  return Array.from(glob.scanSync({ cwd, onlyFiles: true })).filter((relativePath) => {
11237
- const segments = relativePath.split(path37.sep);
12622
+ const segments = relativePath.split(path39.sep);
11238
12623
  return !segments.some((segment) => SKIP_ENTRY_DIR_SET.has(segment));
11239
12624
  });
11240
12625
  }
@@ -11242,17 +12627,17 @@ class Builder {
11242
12627
  const out = [];
11243
12628
  for (const p of additionalEntryPoints) {
11244
12629
  if (p.includes("*")) {
11245
- const rel = p.startsWith(`${cwd}/`) || p.startsWith(`${cwd}${path37.sep}`) ? p.slice(cwd.length + 1) : p;
12630
+ const rel = p.startsWith(`${cwd}/`) || p.startsWith(`${cwd}${path39.sep}`) ? p.slice(cwd.length + 1) : p;
11246
12631
  out.push(...this.#globEntrypoints(cwd, rel));
11247
12632
  } else
11248
- out.push(path37.isAbsolute(p) ? p : path37.join(cwd, p));
12633
+ out.push(path39.isAbsolute(p) ? p : path39.join(cwd, p));
11249
12634
  }
11250
12635
  return out;
11251
12636
  }
11252
12637
  #getBuildOptions({ bundle = false, additionalEntryPoints = [] } = {}) {
11253
12638
  const cwd = this.#executor.cwdPath;
11254
12639
  const entrypoints = [
11255
- ...bundle ? [path37.join(cwd, "index.ts")] : this.#globEntrypoints(cwd, "**/*.{ts,tsx}"),
12640
+ ...bundle ? [path39.join(cwd, "index.ts")] : this.#globEntrypoints(cwd, "**/*.{ts,tsx}"),
11256
12641
  ...this.#resolveAdditionalEntrypoints(cwd, additionalEntryPoints)
11257
12642
  ];
11258
12643
  return {
@@ -11273,9 +12658,9 @@ class Builder {
11273
12658
  for (const relativePath of this.#globFiles(cwd)) {
11274
12659
  if (relativePath === "package.json")
11275
12660
  continue;
11276
- const sourcePath = path37.join(cwd, relativePath);
11277
- const targetPath = path37.join(this.#distExecutor.cwdPath, relativePath);
11278
- await mkdir10(path37.dirname(targetPath), { recursive: true });
12661
+ const sourcePath = path39.join(cwd, relativePath);
12662
+ const targetPath = path39.join(this.#distExecutor.cwdPath, relativePath);
12663
+ await mkdir10(path39.dirname(targetPath), { recursive: true });
11279
12664
  await Bun.write(targetPath, Bun.file(sourcePath));
11280
12665
  }
11281
12666
  }
@@ -11286,13 +12671,13 @@ class Builder {
11286
12671
  return withoutFormatDir;
11287
12672
  if (!hasDotSlash && withoutFormatDir === publishedPath)
11288
12673
  return publishedPath;
11289
- const parsed = path37.posix.parse(withoutFormatDir);
12674
+ const parsed = path39.posix.parse(withoutFormatDir);
11290
12675
  if (![".js", ".mjs", ".cjs"].includes(parsed.ext))
11291
12676
  return withoutFormatDir;
11292
- const withoutExt = path37.posix.join(parsed.dir, parsed.name);
12677
+ const withoutExt = path39.posix.join(parsed.dir, parsed.name);
11293
12678
  const sourcePath = withoutExt.startsWith("./") ? withoutExt.slice(2) : withoutExt;
11294
12679
  const sourceCandidates = [`${sourcePath}.ts`, `${sourcePath}.tsx`];
11295
- const matchedSource = sourceCandidates.find((candidate) => existsSync2(path37.join(this.#executor.cwdPath, candidate)));
12680
+ const matchedSource = sourceCandidates.find((candidate) => existsSync2(path39.join(this.#executor.cwdPath, candidate)));
11296
12681
  if (!matchedSource)
11297
12682
  return withoutFormatDir;
11298
12683
  return hasDotSlash ? `./${matchedSource}` : matchedSource;
@@ -11343,10 +12728,10 @@ class Builder {
11343
12728
  // pkgs/@akanjs/devkit/capacitorApp.ts
11344
12729
  import { cp as cp2, mkdir as mkdir11, rm as rm5 } from "fs/promises";
11345
12730
  import os from "os";
11346
- import path38 from "path";
12731
+ import path40 from "path";
11347
12732
  import { select as select2 } from "@inquirer/prompts";
11348
12733
  import { MobileProject } from "@trapezedev/project";
11349
- import { capitalize as capitalize6 } from "akanjs/common";
12734
+ import { capitalize as capitalize5 } from "akanjs/common";
11350
12735
 
11351
12736
  // pkgs/@akanjs/devkit/fileEditor.ts
11352
12737
  class FileEditor {
@@ -11550,13 +12935,13 @@ var rootCapacitorConfigFilenames = [
11550
12935
  "capacitor.config.js",
11551
12936
  "capacitor.config.json"
11552
12937
  ];
11553
- var rootCapacitorConfigPaths = (appRoot) => rootCapacitorConfigFilenames.map((file) => path38.join(appRoot, file));
12938
+ var rootCapacitorConfigPaths = (appRoot) => rootCapacitorConfigFilenames.map((file) => path40.join(appRoot, file));
11554
12939
  async function clearRootCapacitorConfigs(appRoot) {
11555
12940
  await Promise.all(rootCapacitorConfigPaths(appRoot).map((file) => rm5(file, { force: true })));
11556
12941
  }
11557
12942
  async function writeRootCapacitorConfig(appRoot, content) {
11558
12943
  await clearRootCapacitorConfigs(appRoot);
11559
- await Bun.write(path38.join(appRoot, "capacitor.config.json"), content);
12944
+ await Bun.write(path40.join(appRoot, "capacitor.config.json"), content);
11560
12945
  }
11561
12946
  var getLocalIP = () => {
11562
12947
  const interfaces = os.networkInterfaces();
@@ -11570,7 +12955,7 @@ var getLocalIP = () => {
11570
12955
  }
11571
12956
  return "127.0.0.1";
11572
12957
  };
11573
- var isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
12958
+ var isRecord2 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
11574
12959
  var asString = (value) => typeof value === "string" ? value : undefined;
11575
12960
  var firstString = (...values) => values.find((value) => typeof value === "string");
11576
12961
  var scoreIosDeviceTarget = (target) => {
@@ -11594,7 +12979,7 @@ function walkRecords(value, visit) {
11594
12979
  walkRecords(item, visit);
11595
12980
  return;
11596
12981
  }
11597
- if (!isRecord(value))
12982
+ if (!isRecord2(value))
11598
12983
  return;
11599
12984
  visit(value);
11600
12985
  for (const item of Object.values(value))
@@ -11605,9 +12990,9 @@ function parseDevicectlDevices(output) {
11605
12990
  const json = JSON.parse(output);
11606
12991
  const targets = new Map;
11607
12992
  walkRecords(json, (record) => {
11608
- const deviceProperties = isRecord(record.deviceProperties) ? record.deviceProperties : {};
11609
- const hardwareProperties = isRecord(record.hardwareProperties) ? record.hardwareProperties : {};
11610
- const connectionProperties = isRecord(record.connectionProperties) ? record.connectionProperties : {};
12993
+ const deviceProperties = isRecord2(record.deviceProperties) ? record.deviceProperties : {};
12994
+ const hardwareProperties = isRecord2(record.hardwareProperties) ? record.hardwareProperties : {};
12995
+ const connectionProperties = isRecord2(record.connectionProperties) ? record.connectionProperties : {};
11611
12996
  const devicectlId = firstString(record.identifier, record.deviceIdentifier);
11612
12997
  const potentialHostnames = Array.isArray(connectionProperties.potentialHostnames) ? connectionProperties.potentialHostnames.filter((value) => typeof value === "string") : [];
11613
12998
  const hostnameUdid = potentialHostnames.map((hostname) => hostname.match(/([0-9A-Fa-f]{8}-[0-9A-Fa-f]{16})\.coredevice\.local/)?.[1]).find((value) => Boolean(value));
@@ -11640,7 +13025,7 @@ function parseSimctlDevices(output) {
11640
13025
  try {
11641
13026
  const json = JSON.parse(output);
11642
13027
  const devices = json.devices ?? {};
11643
- return Object.values(devices).flatMap((runtimeDevices) => runtimeDevices).filter(isRecord).flatMap((device) => {
13028
+ return Object.values(devices).flatMap((runtimeDevices) => runtimeDevices).filter(isRecord2).flatMap((device) => {
11644
13029
  const id = firstString(device.udid, device.UDID, device.identifier);
11645
13030
  const name = firstString(device.name, device.displayName);
11646
13031
  const isAvailable = device.isAvailable !== false && device.availabilityError === undefined;
@@ -11665,13 +13050,13 @@ function buildIosNativeRunCommand({
11665
13050
  scheme = "App",
11666
13051
  configuration = "Debug"
11667
13052
  }) {
11668
- const derivedDataPath = path38.join(appRoot, "ios/DerivedData", device.id);
13053
+ const derivedDataPath = path40.join(appRoot, "ios/DerivedData", device.id);
11669
13054
  const productPlatform = device.kind === "device" ? "iphoneos" : "iphonesimulator";
11670
13055
  const destination = device.kind === "device" ? `id=${device.xcodebuildId ?? device.id}` : `platform=iOS Simulator,id=${device.id}`;
11671
13056
  return {
11672
13057
  configuration,
11673
13058
  derivedDataPath,
11674
- appPath: path38.join(derivedDataPath, "Build/Products", `${configuration}-${productPlatform}`, "App.app"),
13059
+ appPath: path40.join(derivedDataPath, "Build/Products", `${configuration}-${productPlatform}`, "App.app"),
11675
13060
  xcodebuildArgs: [
11676
13061
  "-project",
11677
13062
  "App.xcodeproj",
@@ -11872,16 +13257,16 @@ function materializeCapacitorConfig(target, { operation, localServerUrl, localIp
11872
13257
  experimental,
11873
13258
  ...capacitorConfig
11874
13259
  } = target;
11875
- const serverConfig = isRecord(server) ? server : undefined;
11876
- const cordovaConfig = isRecord(cordova) ? cordova : undefined;
11877
- const experimentalConfig = isRecord(experimental) ? experimental : undefined;
11878
- const pluginsConfig = isRecord(plugins) ? plugins : {};
11879
- const keyboardPluginConfig = isRecord(pluginsConfig.Keyboard) ? pluginsConfig.Keyboard : {};
13260
+ const serverConfig = isRecord2(server) ? server : undefined;
13261
+ const cordovaConfig = isRecord2(cordova) ? cordova : undefined;
13262
+ const experimentalConfig = isRecord2(experimental) ? experimental : undefined;
13263
+ const pluginsConfig = isRecord2(plugins) ? plugins : {};
13264
+ const keyboardPluginConfig = isRecord2(pluginsConfig.Keyboard) ? pluginsConfig.Keyboard : {};
11880
13265
  const config = {
11881
13266
  ...capacitorConfig,
11882
13267
  appId,
11883
13268
  appName,
11884
- webDir: path38.posix.join(".akan", "mobile", name, "www"),
13269
+ webDir: path40.posix.join(".akan", "mobile", name, "www"),
11885
13270
  plugins: {
11886
13271
  CapacitorCookies: { enabled: true },
11887
13272
  ...pluginsConfig,
@@ -11891,11 +13276,11 @@ function materializeCapacitorConfig(target, { operation, localServerUrl, localIp
11891
13276
  }
11892
13277
  },
11893
13278
  android: {
11894
- ...isRecord(android) ? android : {},
13279
+ ...isRecord2(android) ? android : {},
11895
13280
  path: "android"
11896
13281
  },
11897
13282
  ios: {
11898
- ...isRecord(ios) ? ios : {},
13283
+ ...isRecord2(ios) ? ios : {},
11899
13284
  path: "ios"
11900
13285
  }
11901
13286
  };
@@ -11938,10 +13323,10 @@ class CapacitorApp {
11938
13323
  constructor(app, target) {
11939
13324
  this.app = app;
11940
13325
  this.target = target;
11941
- this.targetRootPath = path38.posix.join(".akan", "mobile", this.target.name);
11942
- this.targetRoot = path38.join(this.app.cwdPath, this.targetRootPath);
11943
- this.targetWebRoot = path38.join(this.targetRoot, "www");
11944
- this.targetAssetRoot = path38.join(this.targetRoot, "assets");
13326
+ this.targetRootPath = path40.posix.join(".akan", "mobile", this.target.name);
13327
+ this.targetRoot = path40.join(this.app.cwdPath, this.targetRootPath);
13328
+ this.targetWebRoot = path40.join(this.targetRoot, "www");
13329
+ this.targetAssetRoot = path40.join(this.targetRoot, "assets");
11945
13330
  this.project = new MobileProject(this.app.cwdPath, {
11946
13331
  android: { path: this.androidRootPath },
11947
13332
  ios: { path: this.iosProjectPath }
@@ -11956,9 +13341,9 @@ class CapacitorApp {
11956
13341
  await mkdir11(this.targetRoot, { recursive: true });
11957
13342
  if (regenerate) {
11958
13343
  if (!platform || platform === "ios")
11959
- await rm5(path38.join(this.app.cwdPath, this.iosRootPath), { recursive: true, force: true });
13344
+ await rm5(path40.join(this.app.cwdPath, this.iosRootPath), { recursive: true, force: true });
11960
13345
  if (!platform || platform === "android")
11961
- await rm5(path38.join(this.app.cwdPath, this.androidRootPath), { recursive: true, force: true });
13346
+ await rm5(path40.join(this.app.cwdPath, this.androidRootPath), { recursive: true, force: true });
11962
13347
  }
11963
13348
  const project = this.project;
11964
13349
  await this.project.load();
@@ -12081,7 +13466,7 @@ ${textError instanceof Error ? textError.message : ""}`);
12081
13466
  const xcodebuildArgs = noAllowProvisioningUpdates ? command.xcodebuildArgs : [...command.xcodebuildArgs.slice(0, -1), "-allowProvisioningUpdates", ...command.xcodebuildArgs.slice(-1)];
12082
13467
  try {
12083
13468
  await this.#spawn("xcodebuild", xcodebuildArgs, {
12084
- cwd: path38.join(this.app.cwdPath, this.iosProjectPath),
13469
+ cwd: path40.join(this.app.cwdPath, this.iosProjectPath),
12085
13470
  env: mobileEnv
12086
13471
  });
12087
13472
  const devicectlId = runTarget.devicectlId ?? runTarget.id;
@@ -12103,10 +13488,10 @@ ${textError instanceof Error ? textError.message : ""}`);
12103
13488
  }
12104
13489
  }
12105
13490
  #iosScheme() {
12106
- return isRecord(this.target.ios) && typeof this.target.ios.scheme === "string" ? this.target.ios.scheme : "App";
13491
+ return isRecord2(this.target.ios) && typeof this.target.ios.scheme === "string" ? this.target.ios.scheme : "App";
12107
13492
  }
12108
13493
  async#getIosDevelopmentTeam() {
12109
- const pbxprojPath = path38.join(this.app.cwdPath, this.iosProjectPath, "App.xcodeproj/project.pbxproj");
13494
+ const pbxprojPath = path40.join(this.app.cwdPath, this.iosProjectPath, "App.xcodeproj/project.pbxproj");
12110
13495
  if (!await Bun.file(pbxprojPath).exists())
12111
13496
  return;
12112
13497
  return (await Bun.file(pbxprojPath).text()).match(/DEVELOPMENT_TEAM = ([^;]+);/)?.[1]?.trim();
@@ -12132,7 +13517,7 @@ ${error.message}`;
12132
13517
  await this.#spawnMobile("npx", ["cap", "sync", "android"], { operation, env });
12133
13518
  }
12134
13519
  async#updateAndroidBuildTypes() {
12135
- const appGradle = await FileEditor.create(path38.join(this.app.cwdPath, this.androidRootPath, "app/build.gradle"));
13520
+ const appGradle = await FileEditor.create(path40.join(this.app.cwdPath, this.androidRootPath, "app/build.gradle"));
12136
13521
  const buildTypesBlock = `
12137
13522
  debug {
12138
13523
  applicationIdSuffix ".debug"
@@ -12176,7 +13561,7 @@ ${error.message}`;
12176
13561
  const gradleCommand = isWindows ? "gradlew.bat" : "./gradlew";
12177
13562
  await this.app.spawn(gradleCommand, [assembleType === "apk" ? "assembleRelease" : "bundleRelease"], {
12178
13563
  stdio: "inherit",
12179
- cwd: path38.join(this.app.cwdPath, this.androidRootPath),
13564
+ cwd: path40.join(this.app.cwdPath, this.androidRootPath),
12180
13565
  env: await this.#commandEnv("release", env)
12181
13566
  });
12182
13567
  }
@@ -12184,10 +13569,10 @@ ${error.message}`;
12184
13569
  await this.#spawnMobile("npx", ["cap", "open", "android"], { operation: "local", env: "local" });
12185
13570
  }
12186
13571
  async#ensureAndroidAssetsDir() {
12187
- await mkdir11(path38.join(this.app.cwdPath, this.androidAssetsPath), { recursive: true });
13572
+ await mkdir11(path40.join(this.app.cwdPath, this.androidAssetsPath), { recursive: true });
12188
13573
  }
12189
13574
  async#ensureAndroidDebugKeystore() {
12190
- const keystorePath = path38.join(this.app.cwdPath, this.androidRootPath, "app/debug.keystore");
13575
+ const keystorePath = path40.join(this.app.cwdPath, this.androidRootPath, "app/debug.keystore");
12191
13576
  if (await Bun.file(keystorePath).exists())
12192
13577
  return;
12193
13578
  await this.#spawn("keytool", [
@@ -12226,7 +13611,7 @@ ${error.message}`;
12226
13611
  await this.#spawnMobile("npx", args, { operation, env }, { stdio: "inherit" });
12227
13612
  }
12228
13613
  async#assertAndroidReleaseSigningConfig() {
12229
- const gradlePropertiesPath = path38.join(this.app.cwdPath, this.androidRootPath, "gradle.properties");
13614
+ const gradlePropertiesPath = path40.join(this.app.cwdPath, this.androidRootPath, "gradle.properties");
12230
13615
  const gradleProperties = await Bun.file(gradlePropertiesPath).exists() ? await Bun.file(gradlePropertiesPath).text() : "";
12231
13616
  const missingKeys = getMissingAndroidReleaseSigningKeys({ gradleProperties });
12232
13617
  if (missingKeys.length > 0)
@@ -12253,12 +13638,12 @@ ${error.message}`;
12253
13638
  await this.#prepareAndroid({ operation: "release", env: "main" });
12254
13639
  }
12255
13640
  async prepareWww() {
12256
- const htmlSource = path38.join(this.app.dist.cwdPath, "csr", targetHtmlFilename(this.target));
13641
+ const htmlSource = path40.join(this.app.dist.cwdPath, "csr", targetHtmlFilename(this.target));
12257
13642
  if (!await Bun.file(htmlSource).exists())
12258
13643
  throw new Error(`CSR html for mobile target '${this.target.name}' not found: ${htmlSource}`);
12259
13644
  await rm5(this.targetWebRoot, { recursive: true, force: true });
12260
13645
  await mkdir11(this.targetWebRoot, { recursive: true });
12261
- await Bun.write(path38.join(this.targetWebRoot, "index.html"), this.#injectMobileTargetMeta(await Bun.file(htmlSource).text()));
13646
+ await Bun.write(path40.join(this.targetWebRoot, "index.html"), this.#injectMobileTargetMeta(await Bun.file(htmlSource).text()));
12262
13647
  }
12263
13648
  #injectMobileTargetMeta(html) {
12264
13649
  const basePath2 = this.target.basePath?.replace(/^\/+|\/+$/g, "") ?? "";
@@ -12278,7 +13663,7 @@ ${error.message}`;
12278
13663
  });
12279
13664
  const content = `${JSON.stringify(config, null, 2)}
12280
13665
  `;
12281
- await Bun.write(path38.join(this.targetRoot, "capacitor.config.json"), content);
13666
+ await Bun.write(path40.join(this.targetRoot, "capacitor.config.json"), content);
12282
13667
  return content;
12283
13668
  }
12284
13669
  async#prepareTargetAssets() {
@@ -12286,11 +13671,11 @@ ${error.message}`;
12286
13671
  return;
12287
13672
  await mkdir11(this.targetAssetRoot, { recursive: true });
12288
13673
  if (this.target.assets.icon)
12289
- await cp2(path38.join(this.app.cwdPath, this.target.assets.icon), path38.join(this.targetAssetRoot, "icon.png"), {
13674
+ await cp2(path40.join(this.app.cwdPath, this.target.assets.icon), path40.join(this.targetAssetRoot, "icon.png"), {
12290
13675
  force: true
12291
13676
  });
12292
13677
  if (this.target.assets.splash)
12293
- await cp2(path38.join(this.app.cwdPath, this.target.assets.splash), path38.join(this.targetAssetRoot, "splash.png"), {
13678
+ await cp2(path40.join(this.app.cwdPath, this.target.assets.splash), path40.join(this.targetAssetRoot, "splash.png"), {
12294
13679
  force: true
12295
13680
  });
12296
13681
  }
@@ -12298,11 +13683,11 @@ ${error.message}`;
12298
13683
  const files = this.target.files?.[platform];
12299
13684
  if (!files)
12300
13685
  return;
12301
- const platformRoot = path38.join(this.app.cwdPath, platform === "ios" ? this.iosRootPath : this.androidRootPath);
13686
+ const platformRoot = path40.join(this.app.cwdPath, platform === "ios" ? this.iosRootPath : this.androidRootPath);
12302
13687
  await Promise.all(Object.entries(files).map(async ([to, from]) => {
12303
- const targetPath = path38.join(platformRoot, to);
12304
- await mkdir11(path38.dirname(targetPath), { recursive: true });
12305
- await cp2(path38.join(this.app.cwdPath, from), targetPath, { force: true });
13688
+ const targetPath = path40.join(platformRoot, to);
13689
+ await mkdir11(path40.dirname(targetPath), { recursive: true });
13690
+ await cp2(path40.join(this.app.cwdPath, from), targetPath, { force: true });
12306
13691
  }));
12307
13692
  }
12308
13693
  async#generateAssets({ operation, env }) {
@@ -12312,7 +13697,7 @@ ${error.message}`;
12312
13697
  "@capacitor/assets",
12313
13698
  "generate",
12314
13699
  "--assetPath",
12315
- path38.posix.join(this.targetRootPath, "assets"),
13700
+ path40.posix.join(this.targetRootPath, "assets"),
12316
13701
  "--iosProject",
12317
13702
  this.iosProjectPath,
12318
13703
  "--androidProject",
@@ -12437,7 +13822,7 @@ ${error.message}`;
12437
13822
  this.#setPermissionsInAndroid(["POST_NOTIFICATIONS"]);
12438
13823
  }
12439
13824
  async#setPermissionInIos(permissions) {
12440
- const updateNs = Object.fromEntries(Object.entries(permissions).map(([key, value]) => [`NS${capitalize6(key)}`, value]));
13825
+ const updateNs = Object.fromEntries(Object.entries(permissions).map(([key, value]) => [`NS${capitalize5(key)}`, value]));
12441
13826
  await Promise.all([
12442
13827
  this.project.ios.updateInfoPlist(this.iosTargetName, "Debug", updateNs),
12443
13828
  this.project.ios.updateInfoPlist(this.iosTargetName, "Release", updateNs)
@@ -12522,15 +13907,15 @@ var Pkg = createInternalArgToken("Pkg");
12522
13907
  var Module = createInternalArgToken("Module");
12523
13908
  var Workspace = createInternalArgToken("Workspace");
12524
13909
  // pkgs/@akanjs/devkit/commandDecorators/command.ts
12525
- import path39 from "path";
13910
+ import path41 from "path";
12526
13911
  import { confirm, input as input2, select as select3 } from "@inquirer/prompts";
12527
13912
  import { Logger as Logger10 } from "akanjs/common";
12528
13913
  import chalk6 from "chalk";
12529
13914
  import { program } from "commander";
12530
13915
 
12531
13916
  // pkgs/@akanjs/devkit/commandDecorators/dependencyBuilder.ts
12532
- var capitalize7 = (value) => value.slice(0, 1).toUpperCase() + value.slice(1);
12533
- var createDependencyKey = (refName, kind) => `${refName}${capitalize7(kind)}`;
13917
+ var capitalize6 = (value) => value.slice(0, 1).toUpperCase() + value.slice(1);
13918
+ var createDependencyKey = (refName, kind) => `${refName}${capitalize6(kind)}`;
12534
13919
 
12535
13920
  class CommandContainer {
12536
13921
  static #instances = new Map;
@@ -13026,7 +14411,7 @@ var runCommands = async (...commands) => {
13026
14411
  process.exit(1);
13027
14412
  });
13028
14413
  const __dirname2 = getDirname(import.meta.url);
13029
- const packageJsonCandidates = [`${path39.dirname(Bun.main)}/package.json`, `${__dirname2}/../package.json`];
14414
+ const packageJsonCandidates = [`${path41.dirname(Bun.main)}/package.json`, `${__dirname2}/../package.json`];
13030
14415
  let cliPackageJson = null;
13031
14416
  for (const packageJsonPath of packageJsonCandidates) {
13032
14417
  if (!await FileSys.fileExists(packageJsonPath))
@@ -13269,11 +14654,11 @@ var NODE_NATIVE_MODULE_SET = new Set([
13269
14654
  // pkgs/@akanjs/devkit/getCredentials.ts
13270
14655
  import yaml from "js-yaml";
13271
14656
  // pkgs/@akanjs/devkit/getModelFileData.ts
13272
- import { capitalize as capitalize8 } from "akanjs/common";
14657
+ import { capitalize as capitalize7 } from "akanjs/common";
13273
14658
  // pkgs/@akanjs/devkit/getRelatedCnsts.ts
13274
14659
  import { readFileSync as readFileSync4, realpathSync } from "fs";
13275
14660
  import ora2 from "ora";
13276
- import * as ts8 from "typescript";
14661
+ import * as ts10 from "typescript";
13277
14662
  var tsTranspiler = new Bun.Transpiler({ loader: "ts" });
13278
14663
  var tsxTranspiler = new Bun.Transpiler({ loader: "tsx" });
13279
14664
  var getTranspiler = (filePath) => filePath.endsWith(".tsx") ? tsxTranspiler : tsTranspiler;
@@ -13306,10 +14691,10 @@ var scanModuleSpecifiers = (source2, filePath, includeExports) => {
13306
14691
  return importSpecifiers;
13307
14692
  };
13308
14693
  var parseTsConfig = (tsConfigPath = "./tsconfig.json") => {
13309
- const configFile = ts8.readConfigFile(tsConfigPath, (path40) => {
13310
- return ts8.sys.readFile(path40);
14694
+ const configFile = ts10.readConfigFile(tsConfigPath, (path42) => {
14695
+ return ts10.sys.readFile(path42);
13311
14696
  });
13312
- return ts8.parseJsonConfigFileContent(configFile.config, ts8.sys, realpathSync(tsConfigPath).replace(/[^/\\]+$/, ""));
14697
+ return ts10.parseJsonConfigFileContent(configFile.config, ts10.sys, realpathSync(tsConfigPath).replace(/[^/\\]+$/, ""));
13313
14698
  };
13314
14699
  var collectImportedFiles = (constantFilePath, parsedConfig) => {
13315
14700
  const allFilesToAnalyze = new Set([constantFilePath]);
@@ -13324,7 +14709,7 @@ var collectImportedFiles = (constantFilePath, parsedConfig) => {
13324
14709
  for (const importPath of scanModuleSpecifiers(source2, filePath, false)) {
13325
14710
  if (!importPath.startsWith("."))
13326
14711
  continue;
13327
- const resolved = ts8.resolveModuleName(importPath, filePath, parsedConfig.options, ts8.sys).resolvedModule?.resolvedFileName;
14712
+ const resolved = ts10.resolveModuleName(importPath, filePath, parsedConfig.options, ts10.sys).resolvedModule?.resolvedFileName;
13328
14713
  if (resolved && !allFilesToAnalyze.has(resolved)) {
13329
14714
  allFilesToAnalyze.add(resolved);
13330
14715
  collectImported(resolved);
@@ -13341,7 +14726,7 @@ var collectImportedFiles = (constantFilePath, parsedConfig) => {
13341
14726
  var createTsProgram = (filePaths, options) => {
13342
14727
  const spinner = ora2("Creating TypeScript program for all files...");
13343
14728
  spinner.start();
13344
- const program2 = ts8.createProgram(Array.from(filePaths), options);
14729
+ const program2 = ts10.createProgram(Array.from(filePaths), options);
13345
14730
  const checker = program2.getTypeChecker();
13346
14731
  spinner.succeed("TypeScript program created.");
13347
14732
  return {
@@ -13381,17 +14766,17 @@ var analyzeProperties = (filesToAnalyze, program2, checker) => {
13381
14766
  function visit(node) {
13382
14767
  if (!source2)
13383
14768
  return;
13384
- if (ts8.isPropertyAccessExpression(node)) {
14769
+ if (ts10.isPropertyAccessExpression(node)) {
13385
14770
  const left = node.expression;
13386
14771
  const right = node.name;
13387
- const { line } = ts8.getLineAndCharacterOfPosition(source2, node.getStart());
13388
- if (ts8.isIdentifier(left) && sourceLines && sourceLines.length > line && sourceLines[line] && (sourceLines[line]?.includes(`@Field.Prop(() => ${left.text}.${right.text}`) || sourceLines[line].includes(`base.Filter(${left.text}.${right.text},`))) {
14772
+ const { line } = ts10.getLineAndCharacterOfPosition(source2, node.getStart());
14773
+ if (ts10.isIdentifier(left) && sourceLines && sourceLines.length > line && sourceLines[line] && (sourceLines[line]?.includes(`@Field.Prop(() => ${left.text}.${right.text}`) || sourceLines[line].includes(`base.Filter(${left.text}.${right.text},`))) {
13389
14774
  const symbol = getCachedSymbol(right);
13390
14775
  if (symbol?.declarations && symbol.declarations.length > 0) {
13391
14776
  const key = symbol.declarations[0]?.getSourceFile().fileName.split("/").pop()?.split(".")[0] ?? "";
13392
14777
  const property = propertyMap.get(key);
13393
14778
  const isScalar = symbol.declarations[0]?.getSourceFile().fileName.includes("_") ?? false;
13394
- const symbolFilePath = symbol.declarations[0]?.getSourceFile().fileName.replace(`${ts8.sys.getCurrentDirectory()}/`, "");
14779
+ const symbolFilePath = symbol.declarations[0]?.getSourceFile().fileName.replace(`${ts10.sys.getCurrentDirectory()}/`, "");
13395
14780
  if (!symbolFilePath)
13396
14781
  throw new Error(`No symbol file path found for ${left.text}.${right.text}`);
13397
14782
  if (property) {
@@ -13415,10 +14800,10 @@ var analyzeProperties = (filesToAnalyze, program2, checker) => {
13415
14800
  }
13416
14801
  }
13417
14802
  }
13418
- } else if (ts8.isImportDeclaration(node) && ts8.isStringLiteral(node.moduleSpecifier)) {
14803
+ } else if (ts10.isImportDeclaration(node) && ts10.isStringLiteral(node.moduleSpecifier)) {
13419
14804
  const importPath = node.moduleSpecifier.text;
13420
14805
  if (importPath.startsWith(".")) {
13421
- const resolved = ts8.resolveModuleName(importPath, filePath, program2.getCompilerOptions(), ts8.sys).resolvedModule?.resolvedFileName;
14806
+ const resolved = ts10.resolveModuleName(importPath, filePath, program2.getCompilerOptions(), ts10.sys).resolvedModule?.resolvedFileName;
13422
14807
  const moduleName = importPath.split("/").pop()?.split(".")[0] ?? "";
13423
14808
  const property = propertyMap.get(moduleName);
13424
14809
  const isScalar = importPath.includes("_");
@@ -13433,7 +14818,7 @@ var analyzeProperties = (filesToAnalyze, program2, checker) => {
13433
14818
  }
13434
14819
  }
13435
14820
  }
13436
- ts8.forEachChild(node, visit);
14821
+ ts10.forEachChild(node, visit);
13437
14822
  }
13438
14823
  visit(source2);
13439
14824
  }
@@ -13640,10 +15025,10 @@ class IncrementalBuilder {
13640
15025
  }
13641
15026
  }
13642
15027
  batchTouchesPagesTree(appDir, batch) {
13643
- const absAppDir = path40.resolve(appDir);
15028
+ const absAppDir = path42.resolve(appDir);
13644
15029
  for (const f of batch.files) {
13645
- const abs = path40.resolve(f);
13646
- if (!abs.startsWith(`${absAppDir}${path40.sep}`) && abs !== absAppDir)
15030
+ const abs = path42.resolve(f);
15031
+ if (!abs.startsWith(`${absAppDir}${path42.sep}`) && abs !== absAppDir)
13647
15032
  continue;
13648
15033
  if (/\.(tsx|ts|jsx|js)$/.test(abs))
13649
15034
  return true;
@@ -13651,15 +15036,15 @@ class IncrementalBuilder {
13651
15036
  return false;
13652
15037
  }
13653
15038
  async batchMayChangePageKeys(appDir, batch) {
13654
- const absAppDir = path40.resolve(appDir);
13655
- const pageKeys = new Set((await this.#app.getPageKeys()).map((key) => path40.normalize(key)));
15039
+ const absAppDir = path42.resolve(appDir);
15040
+ const pageKeys = new Set((await this.#app.getPageKeys()).map((key) => path42.normalize(key)));
13656
15041
  for (const f of batch.files) {
13657
- const abs = path40.resolve(f);
13658
- if (!abs.startsWith(`${absAppDir}${path40.sep}`) && abs !== absAppDir)
15042
+ const abs = path42.resolve(f);
15043
+ if (!abs.startsWith(`${absAppDir}${path42.sep}`) && abs !== absAppDir)
13659
15044
  continue;
13660
15045
  if (!/\.(tsx|ts|jsx|js)$/.test(abs))
13661
15046
  continue;
13662
- const rel = path40.normalize(path40.relative(absAppDir, abs));
15047
+ const rel = path42.normalize(path42.relative(absAppDir, abs));
13663
15048
  if (!await Bun.file(abs).exists() || !pageKeys.has(rel))
13664
15049
  return true;
13665
15050
  }
@@ -13687,7 +15072,7 @@ class IncrementalBuilder {
13687
15072
  ${cssText}`).toString(36);
13688
15073
  const cssRelPath = `styles/${cssAssetName}-${cssHash}.css`;
13689
15074
  const cssUrl = `/_akan/styles/${cssAssetName}-${cssHash}.css`;
13690
- await Bun.write(path40.join(artifactDir, cssRelPath), cssText);
15075
+ await Bun.write(path42.join(artifactDir, cssRelPath), cssText);
13691
15076
  cssAssetEntries.push([basePath2, { cssUrl, cssRelPath }]);
13692
15077
  cssBase64ByUrl[cssUrl] = Buffer.from(new TextEncoder().encode(cssText)).toString("base64");
13693
15078
  })()
@@ -13755,10 +15140,10 @@ ${cssText}`).toString(36);
13755
15140
  if (changedFiles.length === 0)
13756
15141
  return false;
13757
15142
  return changedFiles.some((file) => {
13758
- const normalized = path40.resolve(file);
15143
+ const normalized = path42.resolve(file);
13759
15144
  if (/\.(woff2?|ttf|otf)$/i.test(normalized))
13760
15145
  return true;
13761
- return this.#optimizedFonts.files.some((fontFile) => path40.resolve(fontFile) === normalized);
15146
+ return this.#optimizedFonts.files.some((fontFile) => path42.resolve(fontFile) === normalized);
13762
15147
  });
13763
15148
  }
13764
15149
  async installWatcher() {