@akanjs/cli 2.3.9-rc.5 → 2.3.9-rc.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/incrementalBuilder.proc.js +244 -60
- package/index.js +247 -62
- package/package.json +2 -2
- package/templates/module/__model__.constant.ts +1 -1
|
@@ -4807,11 +4807,17 @@ var createWorkflowApplyReport = ({
|
|
|
4807
4807
|
recommendedValidationCommands,
|
|
4808
4808
|
commands = [],
|
|
4809
4809
|
diagnostics = [],
|
|
4810
|
+
postApplyChecks = [],
|
|
4810
4811
|
recommendations = [],
|
|
4811
4812
|
nextActions = [],
|
|
4812
4813
|
plan
|
|
4813
4814
|
}) => {
|
|
4814
4815
|
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
|
+
});
|
|
4815
4821
|
return {
|
|
4816
4822
|
schemaVersion: 1,
|
|
4817
4823
|
workflow,
|
|
@@ -4823,8 +4829,9 @@ var createWorkflowApplyReport = ({
|
|
|
4823
4829
|
recommendedValidationCommands: uniqueBy(validationCommands, (command) => command.command),
|
|
4824
4830
|
commands: uniqueBy(validationCommands, (command) => command.command),
|
|
4825
4831
|
diagnostics,
|
|
4832
|
+
postApplyChecks,
|
|
4826
4833
|
recommendations: uniqueBy(recommendations, (recommendation) => `${recommendation.kind}:${recommendation.code}`),
|
|
4827
|
-
nextActions:
|
|
4834
|
+
nextActions: orderedNextActions.slice(0, 3),
|
|
4828
4835
|
plan
|
|
4829
4836
|
};
|
|
4830
4837
|
};
|
|
@@ -5048,6 +5055,7 @@ var createRepairReport = ({
|
|
|
5048
5055
|
});
|
|
5049
5056
|
// pkgs/@akanjs/devkit/workflow/executor.ts
|
|
5050
5057
|
import { capitalize as capitalize2 } from "akanjs/common";
|
|
5058
|
+
import ts4 from "typescript";
|
|
5051
5059
|
|
|
5052
5060
|
// pkgs/@akanjs/devkit/workflow/primitive.ts
|
|
5053
5061
|
var createPrimitiveWriteReport = ({
|
|
@@ -5334,7 +5342,14 @@ var fieldExpression = (typeName, defaultValue, options = {}) => {
|
|
|
5334
5342
|
const typeExpression = normalizeFieldType(typeName);
|
|
5335
5343
|
const defaultExpression = coerceFieldDefault(options.enumValues ? "enum" : typeExpression, defaultValue, options).expression;
|
|
5336
5344
|
const defaultOption = defaultExpression ? `, { default: ${defaultExpression} }` : "";
|
|
5337
|
-
return
|
|
5345
|
+
return `${options.builderName ?? "field"}(${typeExpression}${defaultOption})`;
|
|
5346
|
+
};
|
|
5347
|
+
var viaBuilderParameterName = (content, className) => {
|
|
5348
|
+
const classIndex = content.indexOf(`export class ${className} extends via`);
|
|
5349
|
+
if (classIndex < 0)
|
|
5350
|
+
return null;
|
|
5351
|
+
const signature = content.slice(classIndex, content.indexOf("=>", classIndex));
|
|
5352
|
+
return /via\(\(\s*([A-Za-z_$][\w$]*)\s*\)/.exec(signature)?.[1] ?? null;
|
|
5338
5353
|
};
|
|
5339
5354
|
var insertIntoObject = (content, className, line) => {
|
|
5340
5355
|
const classIndex = content.indexOf(`export class ${className} extends via`);
|
|
@@ -5422,19 +5437,69 @@ ${values.map((value) => ` ${JSON.stringify(value)},`).join(`
|
|
|
5422
5437
|
${enumClass}`;
|
|
5423
5438
|
return `${content.slice(0, firstClassIndex)}${enumClass}${content.slice(firstClassIndex)}`;
|
|
5424
5439
|
};
|
|
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
|
+
var dictionaryModelFieldLine = (fieldName) => {
|
|
5474
|
+
const label = bilingualLabelForField(fieldName);
|
|
5475
|
+
const desc = bilingualDescriptionForField(fieldName);
|
|
5476
|
+
return `${fieldName}: t([${JSON.stringify(label.en)}, ${JSON.stringify(label.ko)}]).desc([${JSON.stringify(desc.en)}, ${JSON.stringify(desc.ko)}]),`;
|
|
5477
|
+
};
|
|
5425
5478
|
var insertDictionaryModelField = (content, moduleClassName, fieldName) => {
|
|
5426
5479
|
if (new RegExp(`\\b${fieldName}\\s*:`).test(content))
|
|
5427
5480
|
return content;
|
|
5428
|
-
const
|
|
5429
|
-
const desc = bilingualDescriptionForField(fieldName);
|
|
5430
|
-
const modelIndex = content.indexOf(`.model<${moduleClassName}>((t) => ({`);
|
|
5481
|
+
const modelIndex = content.indexOf(`.model<${moduleClassName}>((t) => (`);
|
|
5431
5482
|
if (modelIndex < 0)
|
|
5432
5483
|
return null;
|
|
5433
|
-
const
|
|
5484
|
+
const objectStartIndex = content.indexOf("{", modelIndex);
|
|
5485
|
+
if (objectStartIndex < 0)
|
|
5486
|
+
return null;
|
|
5487
|
+
const objectEndIndex = findMatchingBrace(content, objectStartIndex);
|
|
5434
5488
|
if (objectEndIndex < 0)
|
|
5435
5489
|
return null;
|
|
5436
|
-
|
|
5437
|
-
|
|
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)}`;
|
|
5438
5503
|
};
|
|
5439
5504
|
var ensureConstantTypeImport = (content, constantPath, typeName) => {
|
|
5440
5505
|
if (new RegExp(`import type \\{[^}]*\\b${typeName}\\b[^}]*\\} from "${constantPath}";`).test(content))
|
|
@@ -5521,6 +5586,95 @@ var workflowStringInput = (value) => typeof value === "string" ? value : null;
|
|
|
5521
5586
|
var workflowStringListInput = (value) => Array.isArray(value) ? value.join(",") : null;
|
|
5522
5587
|
var workflowStringArrayInput = (value) => Array.isArray(value) ? value : null;
|
|
5523
5588
|
var workflowBooleanInput = (value) => typeof value === "boolean" ? value : null;
|
|
5589
|
+
var postApplyDiagnostic = (code, message, target) => ({
|
|
5590
|
+
severity: "error",
|
|
5591
|
+
code,
|
|
5592
|
+
message,
|
|
5593
|
+
failureScope: "source-change",
|
|
5594
|
+
context: { target }
|
|
5595
|
+
});
|
|
5596
|
+
var sourceKindForPath = (filePath) => {
|
|
5597
|
+
if (filePath.endsWith(".tsx"))
|
|
5598
|
+
return ts4.ScriptKind.TSX;
|
|
5599
|
+
if (filePath.endsWith(".ts"))
|
|
5600
|
+
return ts4.ScriptKind.TS;
|
|
5601
|
+
return null;
|
|
5602
|
+
};
|
|
5603
|
+
var checkPathCasing = async (workspace, filePath) => {
|
|
5604
|
+
const segments = filePath.split("/").filter(Boolean);
|
|
5605
|
+
let current = ".";
|
|
5606
|
+
for (const segment of segments) {
|
|
5607
|
+
const entries = await workspace.readdir(current);
|
|
5608
|
+
if (entries.includes(segment)) {
|
|
5609
|
+
current = current === "." ? segment : `${current}/${segment}`;
|
|
5610
|
+
continue;
|
|
5611
|
+
}
|
|
5612
|
+
const caseInsensitiveMatch = entries.find((entry) => entry.toLowerCase() === segment.toLowerCase());
|
|
5613
|
+
return caseInsensitiveMatch ? {
|
|
5614
|
+
code: "workflow-path-casing-mismatch",
|
|
5615
|
+
message: `Reported path segment "${segment}" does not match actual casing "${caseInsensitiveMatch}" in ${filePath}.`
|
|
5616
|
+
} : {
|
|
5617
|
+
code: "workflow-path-missing",
|
|
5618
|
+
message: `Reported path does not exist: ${filePath}.`
|
|
5619
|
+
};
|
|
5620
|
+
}
|
|
5621
|
+
return null;
|
|
5622
|
+
};
|
|
5623
|
+
var checkTypeScriptSyntax = async (workspace, filePath) => {
|
|
5624
|
+
const scriptKind = sourceKindForPath(filePath);
|
|
5625
|
+
if (!scriptKind)
|
|
5626
|
+
return null;
|
|
5627
|
+
const content = await workspace.readFile(filePath);
|
|
5628
|
+
const source = ts4.createSourceFile(filePath, content, ts4.ScriptTarget.Latest, true, scriptKind);
|
|
5629
|
+
const diagnostic = source.parseDiagnostics[0];
|
|
5630
|
+
if (!diagnostic)
|
|
5631
|
+
return null;
|
|
5632
|
+
const position = diagnostic.file?.getLineAndCharacterOfPosition(diagnostic.start ?? 0);
|
|
5633
|
+
const location = position ? `:${position.line + 1}:${position.character + 1}` : "";
|
|
5634
|
+
return {
|
|
5635
|
+
code: "workflow-post-apply-syntax-error",
|
|
5636
|
+
message: `Generated source has a TypeScript syntax error at ${filePath}${location}: ${ts4.flattenDiagnosticMessageText(diagnostic.messageText, " ")}`
|
|
5637
|
+
};
|
|
5638
|
+
};
|
|
5639
|
+
var checkChangedFile = async (workspace, file) => {
|
|
5640
|
+
if (file.action === "remove")
|
|
5641
|
+
return { postApplyChecks: [] };
|
|
5642
|
+
const diagnostics = [];
|
|
5643
|
+
const checks = [];
|
|
5644
|
+
const pathIssue = await checkPathCasing(workspace, file.path);
|
|
5645
|
+
if (pathIssue) {
|
|
5646
|
+
diagnostics.push(postApplyDiagnostic(pathIssue.code, pathIssue.message, file.path));
|
|
5647
|
+
checks.push({ ...pathIssue, target: file.path, status: "failed" });
|
|
5648
|
+
return { diagnostics, postApplyChecks: checks };
|
|
5649
|
+
}
|
|
5650
|
+
const syntaxIssue = await checkTypeScriptSyntax(workspace, file.path);
|
|
5651
|
+
if (syntaxIssue) {
|
|
5652
|
+
diagnostics.push(postApplyDiagnostic(syntaxIssue.code, syntaxIssue.message, file.path));
|
|
5653
|
+
checks.push({ ...syntaxIssue, target: file.path, status: "failed" });
|
|
5654
|
+
return { diagnostics, postApplyChecks: checks };
|
|
5655
|
+
}
|
|
5656
|
+
checks.push({
|
|
5657
|
+
code: "workflow-post-apply-file-valid",
|
|
5658
|
+
target: file.path,
|
|
5659
|
+
status: "passed",
|
|
5660
|
+
message: "Changed file exists with exact casing and parses as source when applicable."
|
|
5661
|
+
});
|
|
5662
|
+
return { postApplyChecks: checks };
|
|
5663
|
+
};
|
|
5664
|
+
var checkRecommendationPath = async (workspace, recommendation) => {
|
|
5665
|
+
if (!recommendation.target || recommendation.target.includes("*") || recommendation.target.startsWith("<"))
|
|
5666
|
+
return null;
|
|
5667
|
+
const pathIssue = await checkPathCasing(workspace, recommendation.target);
|
|
5668
|
+
if (!pathIssue)
|
|
5669
|
+
return null;
|
|
5670
|
+
return {
|
|
5671
|
+
severity: "warning",
|
|
5672
|
+
code: "workflow-recommendation-path-unverified",
|
|
5673
|
+
message: `${pathIssue.message} Recommendation "${recommendation.code}" should not be treated as an exact file target until the path is corrected.`,
|
|
5674
|
+
failureScope: "source-change",
|
|
5675
|
+
context: { target: recommendation.target }
|
|
5676
|
+
};
|
|
5677
|
+
};
|
|
5524
5678
|
var resolveWorkflowSys = async (workspace, target) => {
|
|
5525
5679
|
if (!target)
|
|
5526
5680
|
return null;
|
|
@@ -5665,14 +5819,17 @@ var createWorkflowStepRegistry = ({
|
|
|
5665
5819
|
};
|
|
5666
5820
|
class WorkflowExecutor {
|
|
5667
5821
|
registry;
|
|
5668
|
-
|
|
5822
|
+
workspace;
|
|
5823
|
+
constructor(registry, workspace) {
|
|
5669
5824
|
this.registry = registry;
|
|
5825
|
+
this.workspace = workspace;
|
|
5670
5826
|
}
|
|
5671
5827
|
async apply(plan) {
|
|
5672
5828
|
const changedFiles = [];
|
|
5673
5829
|
const generatedFiles = [];
|
|
5674
5830
|
const recommendedValidationCommands = [];
|
|
5675
5831
|
const diagnostics = [...plan.diagnostics];
|
|
5832
|
+
const postApplyChecks = [];
|
|
5676
5833
|
const recommendations = [...plan.recommendations];
|
|
5677
5834
|
const nextActions = [];
|
|
5678
5835
|
if (diagnostics.some((diagnostic) => diagnostic.severity === "error")) {
|
|
@@ -5683,6 +5840,7 @@ class WorkflowExecutor {
|
|
|
5683
5840
|
generatedFiles,
|
|
5684
5841
|
recommendedValidationCommands,
|
|
5685
5842
|
diagnostics,
|
|
5843
|
+
postApplyChecks,
|
|
5686
5844
|
recommendations,
|
|
5687
5845
|
nextActions,
|
|
5688
5846
|
plan
|
|
@@ -5716,6 +5874,15 @@ class WorkflowExecutor {
|
|
|
5716
5874
|
if (diagnostics.some((diagnostic) => diagnostic.severity === "error"))
|
|
5717
5875
|
break;
|
|
5718
5876
|
}
|
|
5877
|
+
if (this.workspace && !diagnostics.some((diagnostic) => diagnostic.severity === "error")) {
|
|
5878
|
+
for (const file of changedFiles) {
|
|
5879
|
+
const result = await checkChangedFile(this.workspace, file);
|
|
5880
|
+
postApplyChecks.push(...result.postApplyChecks ?? []);
|
|
5881
|
+
diagnostics.push(...result.diagnostics ?? []);
|
|
5882
|
+
}
|
|
5883
|
+
const recommendationDiagnostics = await Promise.all(recommendations.map((recommendation) => checkRecommendationPath(this.workspace, recommendation)));
|
|
5884
|
+
diagnostics.push(...recommendationDiagnostics.filter((diagnostic) => !!diagnostic));
|
|
5885
|
+
}
|
|
5719
5886
|
return createWorkflowApplyReport({
|
|
5720
5887
|
workflow: plan.workflow,
|
|
5721
5888
|
mode: "apply",
|
|
@@ -5723,6 +5890,7 @@ class WorkflowExecutor {
|
|
|
5723
5890
|
generatedFiles,
|
|
5724
5891
|
recommendedValidationCommands,
|
|
5725
5892
|
diagnostics,
|
|
5893
|
+
postApplyChecks,
|
|
5726
5894
|
recommendations,
|
|
5727
5895
|
nextActions,
|
|
5728
5896
|
plan
|
|
@@ -6112,19 +6280,29 @@ var renderRecommendation = (recommendation) => {
|
|
|
6112
6280
|
return `- [${recommendation.kind}]${target} ${recommendation.message}${action}`;
|
|
6113
6281
|
};
|
|
6114
6282
|
var renderDiagnostic = (diagnostic) => `- [${diagnostic.severity}] ${diagnostic.code}: ${diagnostic.message}`;
|
|
6283
|
+
var applySourceStatus = (report) => report.diagnostics.some((diagnostic) => diagnostic.severity === "error" && (diagnostic.failureScope === "source-change" || !diagnostic.failureScope || diagnostic.failureScope === "unknown")) ? "failed" : "passed";
|
|
6115
6284
|
var renderWorkflowApplyReport = (report) => {
|
|
6116
6285
|
const manualReviewItems = [
|
|
6117
6286
|
...report.diagnostics.filter((diagnostic) => diagnostic.severity === "warning").map(renderDiagnostic),
|
|
6118
6287
|
...report.recommendations.filter((recommendation) => recommendation.kind === "manual-action").map(renderRecommendation)
|
|
6119
6288
|
];
|
|
6120
6289
|
const validationBlockers = report.diagnostics.filter((diagnostic) => diagnostic.severity === "error" && (diagnostic.failureScope === "workspace-config" || diagnostic.failureScope === "environment")).map(renderDiagnostic);
|
|
6290
|
+
const sourceBlockers = report.diagnostics.filter((diagnostic) => diagnostic.severity === "error" && (diagnostic.failureScope === "source-change" || !diagnostic.failureScope || diagnostic.failureScope === "unknown")).map(renderDiagnostic);
|
|
6121
6291
|
return [
|
|
6122
6292
|
`# Workflow Apply: ${report.workflow}`,
|
|
6123
6293
|
"",
|
|
6124
6294
|
`- Mode: ${report.mode}`,
|
|
6125
6295
|
`- Status: ${report.status}`,
|
|
6296
|
+
`- Source-change status: ${applySourceStatus(report)}`,
|
|
6297
|
+
`- Workspace status: ${validationBlockers.length ? "blocked" : "not blocked during apply"}`,
|
|
6126
6298
|
...report.validationTarget ? [`- Validation target: ${report.validationTarget}`] : [],
|
|
6127
6299
|
"",
|
|
6300
|
+
"## Apply Checks",
|
|
6301
|
+
...report.postApplyChecks?.length ? report.postApplyChecks.map((check) => `- [${check.status}] ${check.code} ${check.target}: ${check.message}`) : ["- not run"],
|
|
6302
|
+
"",
|
|
6303
|
+
"## Source Change Blockers",
|
|
6304
|
+
...sourceBlockers.length ? sourceBlockers : ["- none"],
|
|
6305
|
+
"",
|
|
6128
6306
|
"## Automatically Modified",
|
|
6129
6307
|
...report.changedFiles.length ? report.changedFiles.map((file) => `- \`${file.action}\` ${file.path}: ${file.reason}`) : ["- none"],
|
|
6130
6308
|
"",
|
|
@@ -6147,7 +6325,7 @@ var renderWorkflowApplyReport = (report) => {
|
|
|
6147
6325
|
...report.diagnostics.length ? report.diagnostics.map(renderDiagnostic) : ["- none"],
|
|
6148
6326
|
"",
|
|
6149
6327
|
"## Recommendations",
|
|
6150
|
-
...report.recommendations.length ? report.recommendations.map(renderRecommendation) : ["- none"],
|
|
6328
|
+
...report.recommendations.length ? report.recommendations.slice(0, 3).map(renderRecommendation) : ["- none"],
|
|
6151
6329
|
"",
|
|
6152
6330
|
"## Next Actions",
|
|
6153
6331
|
...report.nextActions.length ? report.nextActions.map((action) => `- \`${action.command}\`: ${action.reason}`) : ["- none"],
|
|
@@ -6166,10 +6344,16 @@ var renderWorkflowValidationRunReport = (report) => [
|
|
|
6166
6344
|
`- Overall status: ${report.overallStatus}`,
|
|
6167
6345
|
"",
|
|
6168
6346
|
"## Status Summary",
|
|
6169
|
-
`-
|
|
6170
|
-
`- Generated sync
|
|
6171
|
-
`- Workspace
|
|
6172
|
-
`- Environment
|
|
6347
|
+
`- Source-change: ${report.summary.sourceChange}`,
|
|
6348
|
+
`- Generated sync: ${report.summary.generatedSync}`,
|
|
6349
|
+
`- Workspace config: ${report.summary.workspaceConfig}`,
|
|
6350
|
+
`- Environment: ${report.summary.environment}`,
|
|
6351
|
+
"",
|
|
6352
|
+
"## Source Change Diagnostics",
|
|
6353
|
+
...report.workflowDiagnostics?.length ? report.workflowDiagnostics.map((diagnostic) => `- [${diagnostic.severity}] ${diagnostic.code}: ${diagnostic.message}`) : ["- none"],
|
|
6354
|
+
"",
|
|
6355
|
+
"## Existing Workspace Blockers",
|
|
6356
|
+
...report.baselineDiagnostics?.length ? report.baselineDiagnostics.map((diagnostic) => `- [${diagnostic.severity}] ${diagnostic.code}: ${diagnostic.message}`) : ["- none"],
|
|
6173
6357
|
"",
|
|
6174
6358
|
"## Known Blockers",
|
|
6175
6359
|
...report.knownBlockers.length ? report.knownBlockers.map((blocker) => {
|
|
@@ -7245,7 +7429,7 @@ var collapseIndex = (relPathNoExt) => {
|
|
|
7245
7429
|
|
|
7246
7430
|
// pkgs/@akanjs/devkit/transforms/barrelImportsPlugin.ts
|
|
7247
7431
|
import path14 from "path";
|
|
7248
|
-
import
|
|
7432
|
+
import ts5 from "typescript";
|
|
7249
7433
|
var createBarrelImportsPlugin = async (app, { skipPath = defaultSkipPath, pipeAfter } = {}) => {
|
|
7250
7434
|
const akanConfig2 = await app.getConfig();
|
|
7251
7435
|
const barrels = [...new Set(akanConfig2.barrelImports)].filter(Boolean);
|
|
@@ -7486,11 +7670,11 @@ var rewriteBarrelImports = async (source2, barrels, analyzer) => {
|
|
|
7486
7670
|
};
|
|
7487
7671
|
var findImportStatements = (source2) => {
|
|
7488
7672
|
const statements = [];
|
|
7489
|
-
const sourceFile2 =
|
|
7673
|
+
const sourceFile2 = ts5.createSourceFile("barrel-imports.tsx", source2, ts5.ScriptTarget.Latest, true, ts5.ScriptKind.TSX);
|
|
7490
7674
|
for (const statement of sourceFile2.statements) {
|
|
7491
|
-
if (!
|
|
7675
|
+
if (!ts5.isImportDeclaration(statement))
|
|
7492
7676
|
continue;
|
|
7493
|
-
if (!
|
|
7677
|
+
if (!ts5.isStringLiteral(statement.moduleSpecifier))
|
|
7494
7678
|
continue;
|
|
7495
7679
|
const importClause = statement.importClause;
|
|
7496
7680
|
if (!importClause)
|
|
@@ -8485,7 +8669,7 @@ import path22 from "path";
|
|
|
8485
8669
|
// pkgs/@akanjs/devkit/frontendBuild/pagesEntrySourceGenerator.ts
|
|
8486
8670
|
import fs3 from "fs";
|
|
8487
8671
|
import path21 from "path";
|
|
8488
|
-
import
|
|
8672
|
+
import ts6 from "typescript";
|
|
8489
8673
|
|
|
8490
8674
|
class PagesEntrySourceGenerator {
|
|
8491
8675
|
#pageEntries;
|
|
@@ -8529,7 +8713,7 @@ ${entries.join(`
|
|
|
8529
8713
|
static #hasAsyncDefaultExport(moduleAbsPath) {
|
|
8530
8714
|
try {
|
|
8531
8715
|
const source2 = fs3.readFileSync(path21.resolve(moduleAbsPath), "utf8");
|
|
8532
|
-
const sourceFile2 =
|
|
8716
|
+
const sourceFile2 = ts6.createSourceFile(moduleAbsPath, source2, ts6.ScriptTarget.Latest, true, PagesEntrySourceGenerator.#scriptKind(moduleAbsPath));
|
|
8533
8717
|
return PagesEntrySourceGenerator.#sourceFileHasAsyncDefaultExport(sourceFile2);
|
|
8534
8718
|
} catch {
|
|
8535
8719
|
return false;
|
|
@@ -8539,31 +8723,31 @@ ${entries.join(`
|
|
|
8539
8723
|
const asyncBindings = new Map;
|
|
8540
8724
|
let defaultIdentifier = null;
|
|
8541
8725
|
for (const statement of sourceFile2.statements) {
|
|
8542
|
-
if (
|
|
8543
|
-
if (PagesEntrySourceGenerator.#hasModifier(statement,
|
|
8544
|
-
return PagesEntrySourceGenerator.#hasModifier(statement,
|
|
8726
|
+
if (ts6.isFunctionDeclaration(statement)) {
|
|
8727
|
+
if (PagesEntrySourceGenerator.#hasModifier(statement, ts6.SyntaxKind.DefaultKeyword)) {
|
|
8728
|
+
return PagesEntrySourceGenerator.#hasModifier(statement, ts6.SyntaxKind.AsyncKeyword);
|
|
8545
8729
|
}
|
|
8546
8730
|
if (statement.name) {
|
|
8547
|
-
asyncBindings.set(statement.name.text, PagesEntrySourceGenerator.#hasModifier(statement,
|
|
8731
|
+
asyncBindings.set(statement.name.text, PagesEntrySourceGenerator.#hasModifier(statement, ts6.SyntaxKind.AsyncKeyword));
|
|
8548
8732
|
}
|
|
8549
8733
|
continue;
|
|
8550
8734
|
}
|
|
8551
|
-
if (
|
|
8735
|
+
if (ts6.isVariableStatement(statement)) {
|
|
8552
8736
|
for (const declaration of statement.declarationList.declarations) {
|
|
8553
|
-
if (!
|
|
8737
|
+
if (!ts6.isIdentifier(declaration.name))
|
|
8554
8738
|
continue;
|
|
8555
8739
|
asyncBindings.set(declaration.name.text, PagesEntrySourceGenerator.#isAsyncFunctionExpression(declaration.initializer));
|
|
8556
8740
|
}
|
|
8557
8741
|
continue;
|
|
8558
8742
|
}
|
|
8559
|
-
if (
|
|
8743
|
+
if (ts6.isExportAssignment(statement)) {
|
|
8560
8744
|
if (PagesEntrySourceGenerator.#isAsyncFunctionExpression(statement.expression))
|
|
8561
8745
|
return true;
|
|
8562
|
-
if (
|
|
8746
|
+
if (ts6.isIdentifier(statement.expression))
|
|
8563
8747
|
defaultIdentifier = statement.expression.text;
|
|
8564
8748
|
continue;
|
|
8565
8749
|
}
|
|
8566
|
-
if (
|
|
8750
|
+
if (ts6.isExportDeclaration(statement) && statement.exportClause && ts6.isNamedExports(statement.exportClause)) {
|
|
8567
8751
|
const exportClause = statement.exportClause;
|
|
8568
8752
|
for (const specifier of exportClause.elements) {
|
|
8569
8753
|
if (specifier.name.text !== "default")
|
|
@@ -8575,13 +8759,13 @@ ${entries.join(`
|
|
|
8575
8759
|
return defaultIdentifier ? asyncBindings.get(defaultIdentifier) === true : false;
|
|
8576
8760
|
}
|
|
8577
8761
|
static #hasModifier(node, kind) {
|
|
8578
|
-
return
|
|
8762
|
+
return ts6.canHaveModifiers(node) && (ts6.getModifiers(node)?.some((modifier) => modifier.kind === kind) ?? false);
|
|
8579
8763
|
}
|
|
8580
8764
|
static #isAsyncFunctionExpression(node) {
|
|
8581
|
-
return Boolean(node && (
|
|
8765
|
+
return Boolean(node && (ts6.isArrowFunction(node) || ts6.isFunctionExpression(node)) && PagesEntrySourceGenerator.#hasModifier(node, ts6.SyntaxKind.AsyncKeyword));
|
|
8582
8766
|
}
|
|
8583
8767
|
static #scriptKind(moduleAbsPath) {
|
|
8584
|
-
return moduleAbsPath.endsWith(".tsx") || moduleAbsPath.endsWith(".jsx") ?
|
|
8768
|
+
return moduleAbsPath.endsWith(".tsx") || moduleAbsPath.endsWith(".jsx") ? ts6.ScriptKind.TSX : ts6.ScriptKind.TS;
|
|
8585
8769
|
}
|
|
8586
8770
|
}
|
|
8587
8771
|
|
|
@@ -9500,7 +9684,7 @@ import {
|
|
|
9500
9684
|
} from "fontaine";
|
|
9501
9685
|
import { createFont, woff2 } from "fonteditor-core";
|
|
9502
9686
|
import subsetFont from "subset-font";
|
|
9503
|
-
import
|
|
9687
|
+
import ts7 from "typescript";
|
|
9504
9688
|
var FONT_URL_PREFIX = "/_akan/fonts";
|
|
9505
9689
|
var DEFAULT_FONT_SUBSETS = ["latin"];
|
|
9506
9690
|
|
|
@@ -9565,17 +9749,17 @@ class FontOptimizer {
|
|
|
9565
9749
|
this.#cssParts.push(...faceCss, this.#buildRootVariableRule(font));
|
|
9566
9750
|
}
|
|
9567
9751
|
#extractFontsExport(source2, filePath) {
|
|
9568
|
-
const sourceFile2 =
|
|
9752
|
+
const sourceFile2 = ts7.createSourceFile(filePath, source2, ts7.ScriptTarget.Latest, true, ts7.ScriptKind.TSX);
|
|
9569
9753
|
const fonts = [];
|
|
9570
9754
|
for (const statement of sourceFile2.statements) {
|
|
9571
|
-
if (!
|
|
9755
|
+
if (!ts7.isVariableStatement(statement))
|
|
9572
9756
|
continue;
|
|
9573
|
-
const modifiers =
|
|
9574
|
-
const isExported = modifiers?.some((modifier) => modifier.kind ===
|
|
9757
|
+
const modifiers = ts7.canHaveModifiers(statement) ? ts7.getModifiers(statement) : undefined;
|
|
9758
|
+
const isExported = modifiers?.some((modifier) => modifier.kind === ts7.SyntaxKind.ExportKeyword) ?? false;
|
|
9575
9759
|
if (!isExported)
|
|
9576
9760
|
continue;
|
|
9577
9761
|
for (const declaration of statement.declarationList.declarations) {
|
|
9578
|
-
if (!
|
|
9762
|
+
if (!ts7.isIdentifier(declaration.name) || declaration.name.text !== "fonts")
|
|
9579
9763
|
continue;
|
|
9580
9764
|
const value = declaration.initializer ? this.#literalToValue(declaration.initializer) : null;
|
|
9581
9765
|
if (Array.isArray(value)) {
|
|
@@ -9586,20 +9770,20 @@ class FontOptimizer {
|
|
|
9586
9770
|
return fonts;
|
|
9587
9771
|
}
|
|
9588
9772
|
#literalToValue(node) {
|
|
9589
|
-
if (
|
|
9773
|
+
if (ts7.isStringLiteralLike(node))
|
|
9590
9774
|
return node.text;
|
|
9591
|
-
if (
|
|
9775
|
+
if (ts7.isNumericLiteral(node))
|
|
9592
9776
|
return Number(node.text);
|
|
9593
|
-
if (node.kind ===
|
|
9777
|
+
if (node.kind === ts7.SyntaxKind.TrueKeyword)
|
|
9594
9778
|
return true;
|
|
9595
|
-
if (node.kind ===
|
|
9779
|
+
if (node.kind === ts7.SyntaxKind.FalseKeyword)
|
|
9596
9780
|
return false;
|
|
9597
|
-
if (
|
|
9781
|
+
if (ts7.isArrayLiteralExpression(node))
|
|
9598
9782
|
return node.elements.map((element) => this.#literalToValue(element));
|
|
9599
|
-
if (
|
|
9783
|
+
if (ts7.isObjectLiteralExpression(node)) {
|
|
9600
9784
|
const obj = {};
|
|
9601
9785
|
for (const prop of node.properties) {
|
|
9602
|
-
if (!
|
|
9786
|
+
if (!ts7.isPropertyAssignment(prop))
|
|
9603
9787
|
continue;
|
|
9604
9788
|
const name = this.#getPropertyName(prop.name);
|
|
9605
9789
|
if (!name)
|
|
@@ -9608,13 +9792,13 @@ class FontOptimizer {
|
|
|
9608
9792
|
}
|
|
9609
9793
|
return obj;
|
|
9610
9794
|
}
|
|
9611
|
-
if (
|
|
9795
|
+
if (ts7.isAsExpression(node) || ts7.isSatisfiesExpression(node) || ts7.isParenthesizedExpression(node)) {
|
|
9612
9796
|
return this.#literalToValue(node.expression);
|
|
9613
9797
|
}
|
|
9614
9798
|
return;
|
|
9615
9799
|
}
|
|
9616
9800
|
#getPropertyName(name) {
|
|
9617
|
-
if (
|
|
9801
|
+
if (ts7.isIdentifier(name) || ts7.isStringLiteral(name) || ts7.isNumericLiteral(name))
|
|
9618
9802
|
return name.text;
|
|
9619
9803
|
return null;
|
|
9620
9804
|
}
|
|
@@ -13089,7 +13273,7 @@ import { capitalize as capitalize8 } from "akanjs/common";
|
|
|
13089
13273
|
// pkgs/@akanjs/devkit/getRelatedCnsts.ts
|
|
13090
13274
|
import { readFileSync as readFileSync4, realpathSync } from "fs";
|
|
13091
13275
|
import ora2 from "ora";
|
|
13092
|
-
import * as
|
|
13276
|
+
import * as ts8 from "typescript";
|
|
13093
13277
|
var tsTranspiler = new Bun.Transpiler({ loader: "ts" });
|
|
13094
13278
|
var tsxTranspiler = new Bun.Transpiler({ loader: "tsx" });
|
|
13095
13279
|
var getTranspiler = (filePath) => filePath.endsWith(".tsx") ? tsxTranspiler : tsTranspiler;
|
|
@@ -13122,10 +13306,10 @@ var scanModuleSpecifiers = (source2, filePath, includeExports) => {
|
|
|
13122
13306
|
return importSpecifiers;
|
|
13123
13307
|
};
|
|
13124
13308
|
var parseTsConfig = (tsConfigPath = "./tsconfig.json") => {
|
|
13125
|
-
const configFile =
|
|
13126
|
-
return
|
|
13309
|
+
const configFile = ts8.readConfigFile(tsConfigPath, (path40) => {
|
|
13310
|
+
return ts8.sys.readFile(path40);
|
|
13127
13311
|
});
|
|
13128
|
-
return
|
|
13312
|
+
return ts8.parseJsonConfigFileContent(configFile.config, ts8.sys, realpathSync(tsConfigPath).replace(/[^/\\]+$/, ""));
|
|
13129
13313
|
};
|
|
13130
13314
|
var collectImportedFiles = (constantFilePath, parsedConfig) => {
|
|
13131
13315
|
const allFilesToAnalyze = new Set([constantFilePath]);
|
|
@@ -13140,7 +13324,7 @@ var collectImportedFiles = (constantFilePath, parsedConfig) => {
|
|
|
13140
13324
|
for (const importPath of scanModuleSpecifiers(source2, filePath, false)) {
|
|
13141
13325
|
if (!importPath.startsWith("."))
|
|
13142
13326
|
continue;
|
|
13143
|
-
const resolved =
|
|
13327
|
+
const resolved = ts8.resolveModuleName(importPath, filePath, parsedConfig.options, ts8.sys).resolvedModule?.resolvedFileName;
|
|
13144
13328
|
if (resolved && !allFilesToAnalyze.has(resolved)) {
|
|
13145
13329
|
allFilesToAnalyze.add(resolved);
|
|
13146
13330
|
collectImported(resolved);
|
|
@@ -13157,7 +13341,7 @@ var collectImportedFiles = (constantFilePath, parsedConfig) => {
|
|
|
13157
13341
|
var createTsProgram = (filePaths, options) => {
|
|
13158
13342
|
const spinner = ora2("Creating TypeScript program for all files...");
|
|
13159
13343
|
spinner.start();
|
|
13160
|
-
const program2 =
|
|
13344
|
+
const program2 = ts8.createProgram(Array.from(filePaths), options);
|
|
13161
13345
|
const checker = program2.getTypeChecker();
|
|
13162
13346
|
spinner.succeed("TypeScript program created.");
|
|
13163
13347
|
return {
|
|
@@ -13197,17 +13381,17 @@ var analyzeProperties = (filesToAnalyze, program2, checker) => {
|
|
|
13197
13381
|
function visit(node) {
|
|
13198
13382
|
if (!source2)
|
|
13199
13383
|
return;
|
|
13200
|
-
if (
|
|
13384
|
+
if (ts8.isPropertyAccessExpression(node)) {
|
|
13201
13385
|
const left = node.expression;
|
|
13202
13386
|
const right = node.name;
|
|
13203
|
-
const { line } =
|
|
13204
|
-
if (
|
|
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},`))) {
|
|
13205
13389
|
const symbol = getCachedSymbol(right);
|
|
13206
13390
|
if (symbol?.declarations && symbol.declarations.length > 0) {
|
|
13207
13391
|
const key = symbol.declarations[0]?.getSourceFile().fileName.split("/").pop()?.split(".")[0] ?? "";
|
|
13208
13392
|
const property = propertyMap.get(key);
|
|
13209
13393
|
const isScalar = symbol.declarations[0]?.getSourceFile().fileName.includes("_") ?? false;
|
|
13210
|
-
const symbolFilePath = symbol.declarations[0]?.getSourceFile().fileName.replace(`${
|
|
13394
|
+
const symbolFilePath = symbol.declarations[0]?.getSourceFile().fileName.replace(`${ts8.sys.getCurrentDirectory()}/`, "");
|
|
13211
13395
|
if (!symbolFilePath)
|
|
13212
13396
|
throw new Error(`No symbol file path found for ${left.text}.${right.text}`);
|
|
13213
13397
|
if (property) {
|
|
@@ -13231,10 +13415,10 @@ var analyzeProperties = (filesToAnalyze, program2, checker) => {
|
|
|
13231
13415
|
}
|
|
13232
13416
|
}
|
|
13233
13417
|
}
|
|
13234
|
-
} else if (
|
|
13418
|
+
} else if (ts8.isImportDeclaration(node) && ts8.isStringLiteral(node.moduleSpecifier)) {
|
|
13235
13419
|
const importPath = node.moduleSpecifier.text;
|
|
13236
13420
|
if (importPath.startsWith(".")) {
|
|
13237
|
-
const resolved =
|
|
13421
|
+
const resolved = ts8.resolveModuleName(importPath, filePath, program2.getCompilerOptions(), ts8.sys).resolvedModule?.resolvedFileName;
|
|
13238
13422
|
const moduleName = importPath.split("/").pop()?.split(".")[0] ?? "";
|
|
13239
13423
|
const property = propertyMap.get(moduleName);
|
|
13240
13424
|
const isScalar = importPath.includes("_");
|
|
@@ -13249,7 +13433,7 @@ var analyzeProperties = (filesToAnalyze, program2, checker) => {
|
|
|
13249
13433
|
}
|
|
13250
13434
|
}
|
|
13251
13435
|
}
|
|
13252
|
-
|
|
13436
|
+
ts8.forEachChild(node, visit);
|
|
13253
13437
|
}
|
|
13254
13438
|
visit(source2);
|
|
13255
13439
|
}
|
package/index.js
CHANGED
|
@@ -4805,11 +4805,17 @@ var createWorkflowApplyReport = ({
|
|
|
4805
4805
|
recommendedValidationCommands,
|
|
4806
4806
|
commands = [],
|
|
4807
4807
|
diagnostics = [],
|
|
4808
|
+
postApplyChecks = [],
|
|
4808
4809
|
recommendations = [],
|
|
4809
4810
|
nextActions = [],
|
|
4810
4811
|
plan
|
|
4811
4812
|
}) => {
|
|
4812
4813
|
const validationCommands = recommendedValidationCommands ?? commands;
|
|
4814
|
+
const orderedNextActions = uniqueBy(nextActions, (action) => action.command).sort((left, right) => {
|
|
4815
|
+
const leftRepair = left.command.startsWith("akan workflow explain") ? 0 : 1;
|
|
4816
|
+
const rightRepair = right.command.startsWith("akan workflow explain") ? 0 : 1;
|
|
4817
|
+
return leftRepair - rightRepair;
|
|
4818
|
+
});
|
|
4813
4819
|
return {
|
|
4814
4820
|
schemaVersion: 1,
|
|
4815
4821
|
workflow,
|
|
@@ -4821,8 +4827,9 @@ var createWorkflowApplyReport = ({
|
|
|
4821
4827
|
recommendedValidationCommands: uniqueBy(validationCommands, (command) => command.command),
|
|
4822
4828
|
commands: uniqueBy(validationCommands, (command) => command.command),
|
|
4823
4829
|
diagnostics,
|
|
4830
|
+
postApplyChecks,
|
|
4824
4831
|
recommendations: uniqueBy(recommendations, (recommendation) => `${recommendation.kind}:${recommendation.code}`),
|
|
4825
|
-
nextActions:
|
|
4832
|
+
nextActions: orderedNextActions.slice(0, 3),
|
|
4826
4833
|
plan
|
|
4827
4834
|
};
|
|
4828
4835
|
};
|
|
@@ -5046,6 +5053,7 @@ var createRepairReport = ({
|
|
|
5046
5053
|
});
|
|
5047
5054
|
// pkgs/@akanjs/devkit/workflow/executor.ts
|
|
5048
5055
|
import { capitalize as capitalize2 } from "akanjs/common";
|
|
5056
|
+
import ts4 from "typescript";
|
|
5049
5057
|
|
|
5050
5058
|
// pkgs/@akanjs/devkit/workflow/primitive.ts
|
|
5051
5059
|
var createPrimitiveWriteReport = ({
|
|
@@ -5332,7 +5340,14 @@ var fieldExpression = (typeName, defaultValue, options = {}) => {
|
|
|
5332
5340
|
const typeExpression = normalizeFieldType(typeName);
|
|
5333
5341
|
const defaultExpression = coerceFieldDefault(options.enumValues ? "enum" : typeExpression, defaultValue, options).expression;
|
|
5334
5342
|
const defaultOption = defaultExpression ? `, { default: ${defaultExpression} }` : "";
|
|
5335
|
-
return
|
|
5343
|
+
return `${options.builderName ?? "field"}(${typeExpression}${defaultOption})`;
|
|
5344
|
+
};
|
|
5345
|
+
var viaBuilderParameterName = (content, className) => {
|
|
5346
|
+
const classIndex = content.indexOf(`export class ${className} extends via`);
|
|
5347
|
+
if (classIndex < 0)
|
|
5348
|
+
return null;
|
|
5349
|
+
const signature = content.slice(classIndex, content.indexOf("=>", classIndex));
|
|
5350
|
+
return /via\(\(\s*([A-Za-z_$][\w$]*)\s*\)/.exec(signature)?.[1] ?? null;
|
|
5336
5351
|
};
|
|
5337
5352
|
var insertIntoObject = (content, className, line) => {
|
|
5338
5353
|
const classIndex = content.indexOf(`export class ${className} extends via`);
|
|
@@ -5420,19 +5435,69 @@ ${values.map((value) => ` ${JSON.stringify(value)},`).join(`
|
|
|
5420
5435
|
${enumClass}`;
|
|
5421
5436
|
return `${content.slice(0, firstClassIndex)}${enumClass}${content.slice(firstClassIndex)}`;
|
|
5422
5437
|
};
|
|
5438
|
+
var findMatchingBrace = (content, openIndex) => {
|
|
5439
|
+
let depth = 0;
|
|
5440
|
+
let quote = null;
|
|
5441
|
+
let escaped = false;
|
|
5442
|
+
for (let index = openIndex;index < content.length; index++) {
|
|
5443
|
+
const char = content[index];
|
|
5444
|
+
if (quote) {
|
|
5445
|
+
if (escaped) {
|
|
5446
|
+
escaped = false;
|
|
5447
|
+
continue;
|
|
5448
|
+
}
|
|
5449
|
+
if (char === "\\") {
|
|
5450
|
+
escaped = true;
|
|
5451
|
+
continue;
|
|
5452
|
+
}
|
|
5453
|
+
if (char === quote)
|
|
5454
|
+
quote = null;
|
|
5455
|
+
continue;
|
|
5456
|
+
}
|
|
5457
|
+
if (char === '"' || char === "'" || char === "`") {
|
|
5458
|
+
quote = char;
|
|
5459
|
+
continue;
|
|
5460
|
+
}
|
|
5461
|
+
if (char === "{")
|
|
5462
|
+
depth += 1;
|
|
5463
|
+
if (char === "}") {
|
|
5464
|
+
depth -= 1;
|
|
5465
|
+
if (depth === 0)
|
|
5466
|
+
return index;
|
|
5467
|
+
}
|
|
5468
|
+
}
|
|
5469
|
+
return -1;
|
|
5470
|
+
};
|
|
5471
|
+
var dictionaryModelFieldLine = (fieldName) => {
|
|
5472
|
+
const label = bilingualLabelForField(fieldName);
|
|
5473
|
+
const desc = bilingualDescriptionForField(fieldName);
|
|
5474
|
+
return `${fieldName}: t([${JSON.stringify(label.en)}, ${JSON.stringify(label.ko)}]).desc([${JSON.stringify(desc.en)}, ${JSON.stringify(desc.ko)}]),`;
|
|
5475
|
+
};
|
|
5423
5476
|
var insertDictionaryModelField = (content, moduleClassName, fieldName) => {
|
|
5424
5477
|
if (new RegExp(`\\b${fieldName}\\s*:`).test(content))
|
|
5425
5478
|
return content;
|
|
5426
|
-
const
|
|
5427
|
-
const desc = bilingualDescriptionForField(fieldName);
|
|
5428
|
-
const modelIndex = content.indexOf(`.model<${moduleClassName}>((t) => ({`);
|
|
5479
|
+
const modelIndex = content.indexOf(`.model<${moduleClassName}>((t) => (`);
|
|
5429
5480
|
if (modelIndex < 0)
|
|
5430
5481
|
return null;
|
|
5431
|
-
const
|
|
5482
|
+
const objectStartIndex = content.indexOf("{", modelIndex);
|
|
5483
|
+
if (objectStartIndex < 0)
|
|
5484
|
+
return null;
|
|
5485
|
+
const objectEndIndex = findMatchingBrace(content, objectStartIndex);
|
|
5432
5486
|
if (objectEndIndex < 0)
|
|
5433
5487
|
return null;
|
|
5434
|
-
|
|
5435
|
-
|
|
5488
|
+
const fieldLine = dictionaryModelFieldLine(fieldName);
|
|
5489
|
+
const body = content.slice(objectStartIndex + 1, objectEndIndex);
|
|
5490
|
+
if (body.trim().length === 0) {
|
|
5491
|
+
return `${content.slice(0, objectStartIndex + 1)}
|
|
5492
|
+
${fieldLine}
|
|
5493
|
+
${content.slice(objectEndIndex)}`;
|
|
5494
|
+
}
|
|
5495
|
+
const insertion = body.endsWith(`
|
|
5496
|
+
`) ? ` ${fieldLine}
|
|
5497
|
+
` : `
|
|
5498
|
+
${fieldLine}
|
|
5499
|
+
`;
|
|
5500
|
+
return `${content.slice(0, objectEndIndex)}${insertion}${content.slice(objectEndIndex)}`;
|
|
5436
5501
|
};
|
|
5437
5502
|
var ensureConstantTypeImport = (content, constantPath, typeName) => {
|
|
5438
5503
|
if (new RegExp(`import type \\{[^}]*\\b${typeName}\\b[^}]*\\} from "${constantPath}";`).test(content))
|
|
@@ -5519,6 +5584,95 @@ var workflowStringInput = (value) => typeof value === "string" ? value : null;
|
|
|
5519
5584
|
var workflowStringListInput = (value) => Array.isArray(value) ? value.join(",") : null;
|
|
5520
5585
|
var workflowStringArrayInput = (value) => Array.isArray(value) ? value : null;
|
|
5521
5586
|
var workflowBooleanInput = (value) => typeof value === "boolean" ? value : null;
|
|
5587
|
+
var postApplyDiagnostic = (code, message, target) => ({
|
|
5588
|
+
severity: "error",
|
|
5589
|
+
code,
|
|
5590
|
+
message,
|
|
5591
|
+
failureScope: "source-change",
|
|
5592
|
+
context: { target }
|
|
5593
|
+
});
|
|
5594
|
+
var sourceKindForPath = (filePath) => {
|
|
5595
|
+
if (filePath.endsWith(".tsx"))
|
|
5596
|
+
return ts4.ScriptKind.TSX;
|
|
5597
|
+
if (filePath.endsWith(".ts"))
|
|
5598
|
+
return ts4.ScriptKind.TS;
|
|
5599
|
+
return null;
|
|
5600
|
+
};
|
|
5601
|
+
var checkPathCasing = async (workspace, filePath) => {
|
|
5602
|
+
const segments = filePath.split("/").filter(Boolean);
|
|
5603
|
+
let current = ".";
|
|
5604
|
+
for (const segment of segments) {
|
|
5605
|
+
const entries = await workspace.readdir(current);
|
|
5606
|
+
if (entries.includes(segment)) {
|
|
5607
|
+
current = current === "." ? segment : `${current}/${segment}`;
|
|
5608
|
+
continue;
|
|
5609
|
+
}
|
|
5610
|
+
const caseInsensitiveMatch = entries.find((entry) => entry.toLowerCase() === segment.toLowerCase());
|
|
5611
|
+
return caseInsensitiveMatch ? {
|
|
5612
|
+
code: "workflow-path-casing-mismatch",
|
|
5613
|
+
message: `Reported path segment "${segment}" does not match actual casing "${caseInsensitiveMatch}" in ${filePath}.`
|
|
5614
|
+
} : {
|
|
5615
|
+
code: "workflow-path-missing",
|
|
5616
|
+
message: `Reported path does not exist: ${filePath}.`
|
|
5617
|
+
};
|
|
5618
|
+
}
|
|
5619
|
+
return null;
|
|
5620
|
+
};
|
|
5621
|
+
var checkTypeScriptSyntax = async (workspace, filePath) => {
|
|
5622
|
+
const scriptKind = sourceKindForPath(filePath);
|
|
5623
|
+
if (!scriptKind)
|
|
5624
|
+
return null;
|
|
5625
|
+
const content = await workspace.readFile(filePath);
|
|
5626
|
+
const source = ts4.createSourceFile(filePath, content, ts4.ScriptTarget.Latest, true, scriptKind);
|
|
5627
|
+
const diagnostic = source.parseDiagnostics[0];
|
|
5628
|
+
if (!diagnostic)
|
|
5629
|
+
return null;
|
|
5630
|
+
const position = diagnostic.file?.getLineAndCharacterOfPosition(diagnostic.start ?? 0);
|
|
5631
|
+
const location = position ? `:${position.line + 1}:${position.character + 1}` : "";
|
|
5632
|
+
return {
|
|
5633
|
+
code: "workflow-post-apply-syntax-error",
|
|
5634
|
+
message: `Generated source has a TypeScript syntax error at ${filePath}${location}: ${ts4.flattenDiagnosticMessageText(diagnostic.messageText, " ")}`
|
|
5635
|
+
};
|
|
5636
|
+
};
|
|
5637
|
+
var checkChangedFile = async (workspace, file) => {
|
|
5638
|
+
if (file.action === "remove")
|
|
5639
|
+
return { postApplyChecks: [] };
|
|
5640
|
+
const diagnostics = [];
|
|
5641
|
+
const checks = [];
|
|
5642
|
+
const pathIssue = await checkPathCasing(workspace, file.path);
|
|
5643
|
+
if (pathIssue) {
|
|
5644
|
+
diagnostics.push(postApplyDiagnostic(pathIssue.code, pathIssue.message, file.path));
|
|
5645
|
+
checks.push({ ...pathIssue, target: file.path, status: "failed" });
|
|
5646
|
+
return { diagnostics, postApplyChecks: checks };
|
|
5647
|
+
}
|
|
5648
|
+
const syntaxIssue = await checkTypeScriptSyntax(workspace, file.path);
|
|
5649
|
+
if (syntaxIssue) {
|
|
5650
|
+
diagnostics.push(postApplyDiagnostic(syntaxIssue.code, syntaxIssue.message, file.path));
|
|
5651
|
+
checks.push({ ...syntaxIssue, target: file.path, status: "failed" });
|
|
5652
|
+
return { diagnostics, postApplyChecks: checks };
|
|
5653
|
+
}
|
|
5654
|
+
checks.push({
|
|
5655
|
+
code: "workflow-post-apply-file-valid",
|
|
5656
|
+
target: file.path,
|
|
5657
|
+
status: "passed",
|
|
5658
|
+
message: "Changed file exists with exact casing and parses as source when applicable."
|
|
5659
|
+
});
|
|
5660
|
+
return { postApplyChecks: checks };
|
|
5661
|
+
};
|
|
5662
|
+
var checkRecommendationPath = async (workspace, recommendation) => {
|
|
5663
|
+
if (!recommendation.target || recommendation.target.includes("*") || recommendation.target.startsWith("<"))
|
|
5664
|
+
return null;
|
|
5665
|
+
const pathIssue = await checkPathCasing(workspace, recommendation.target);
|
|
5666
|
+
if (!pathIssue)
|
|
5667
|
+
return null;
|
|
5668
|
+
return {
|
|
5669
|
+
severity: "warning",
|
|
5670
|
+
code: "workflow-recommendation-path-unverified",
|
|
5671
|
+
message: `${pathIssue.message} Recommendation "${recommendation.code}" should not be treated as an exact file target until the path is corrected.`,
|
|
5672
|
+
failureScope: "source-change",
|
|
5673
|
+
context: { target: recommendation.target }
|
|
5674
|
+
};
|
|
5675
|
+
};
|
|
5522
5676
|
var resolveWorkflowSys = async (workspace, target) => {
|
|
5523
5677
|
if (!target)
|
|
5524
5678
|
return null;
|
|
@@ -5663,14 +5817,17 @@ var createWorkflowStepRegistry = ({
|
|
|
5663
5817
|
};
|
|
5664
5818
|
class WorkflowExecutor {
|
|
5665
5819
|
registry;
|
|
5666
|
-
|
|
5820
|
+
workspace;
|
|
5821
|
+
constructor(registry, workspace) {
|
|
5667
5822
|
this.registry = registry;
|
|
5823
|
+
this.workspace = workspace;
|
|
5668
5824
|
}
|
|
5669
5825
|
async apply(plan) {
|
|
5670
5826
|
const changedFiles = [];
|
|
5671
5827
|
const generatedFiles = [];
|
|
5672
5828
|
const recommendedValidationCommands = [];
|
|
5673
5829
|
const diagnostics = [...plan.diagnostics];
|
|
5830
|
+
const postApplyChecks = [];
|
|
5674
5831
|
const recommendations = [...plan.recommendations];
|
|
5675
5832
|
const nextActions = [];
|
|
5676
5833
|
if (diagnostics.some((diagnostic) => diagnostic.severity === "error")) {
|
|
@@ -5681,6 +5838,7 @@ class WorkflowExecutor {
|
|
|
5681
5838
|
generatedFiles,
|
|
5682
5839
|
recommendedValidationCommands,
|
|
5683
5840
|
diagnostics,
|
|
5841
|
+
postApplyChecks,
|
|
5684
5842
|
recommendations,
|
|
5685
5843
|
nextActions,
|
|
5686
5844
|
plan
|
|
@@ -5714,6 +5872,15 @@ class WorkflowExecutor {
|
|
|
5714
5872
|
if (diagnostics.some((diagnostic) => diagnostic.severity === "error"))
|
|
5715
5873
|
break;
|
|
5716
5874
|
}
|
|
5875
|
+
if (this.workspace && !diagnostics.some((diagnostic) => diagnostic.severity === "error")) {
|
|
5876
|
+
for (const file of changedFiles) {
|
|
5877
|
+
const result = await checkChangedFile(this.workspace, file);
|
|
5878
|
+
postApplyChecks.push(...result.postApplyChecks ?? []);
|
|
5879
|
+
diagnostics.push(...result.diagnostics ?? []);
|
|
5880
|
+
}
|
|
5881
|
+
const recommendationDiagnostics = await Promise.all(recommendations.map((recommendation) => checkRecommendationPath(this.workspace, recommendation)));
|
|
5882
|
+
diagnostics.push(...recommendationDiagnostics.filter((diagnostic) => !!diagnostic));
|
|
5883
|
+
}
|
|
5717
5884
|
return createWorkflowApplyReport({
|
|
5718
5885
|
workflow: plan.workflow,
|
|
5719
5886
|
mode: "apply",
|
|
@@ -5721,6 +5888,7 @@ class WorkflowExecutor {
|
|
|
5721
5888
|
generatedFiles,
|
|
5722
5889
|
recommendedValidationCommands,
|
|
5723
5890
|
diagnostics,
|
|
5891
|
+
postApplyChecks,
|
|
5724
5892
|
recommendations,
|
|
5725
5893
|
nextActions,
|
|
5726
5894
|
plan
|
|
@@ -6110,19 +6278,29 @@ var renderRecommendation = (recommendation) => {
|
|
|
6110
6278
|
return `- [${recommendation.kind}]${target} ${recommendation.message}${action}`;
|
|
6111
6279
|
};
|
|
6112
6280
|
var renderDiagnostic = (diagnostic) => `- [${diagnostic.severity}] ${diagnostic.code}: ${diagnostic.message}`;
|
|
6281
|
+
var applySourceStatus = (report) => report.diagnostics.some((diagnostic) => diagnostic.severity === "error" && (diagnostic.failureScope === "source-change" || !diagnostic.failureScope || diagnostic.failureScope === "unknown")) ? "failed" : "passed";
|
|
6113
6282
|
var renderWorkflowApplyReport = (report) => {
|
|
6114
6283
|
const manualReviewItems = [
|
|
6115
6284
|
...report.diagnostics.filter((diagnostic) => diagnostic.severity === "warning").map(renderDiagnostic),
|
|
6116
6285
|
...report.recommendations.filter((recommendation) => recommendation.kind === "manual-action").map(renderRecommendation)
|
|
6117
6286
|
];
|
|
6118
6287
|
const validationBlockers = report.diagnostics.filter((diagnostic) => diagnostic.severity === "error" && (diagnostic.failureScope === "workspace-config" || diagnostic.failureScope === "environment")).map(renderDiagnostic);
|
|
6288
|
+
const sourceBlockers = report.diagnostics.filter((diagnostic) => diagnostic.severity === "error" && (diagnostic.failureScope === "source-change" || !diagnostic.failureScope || diagnostic.failureScope === "unknown")).map(renderDiagnostic);
|
|
6119
6289
|
return [
|
|
6120
6290
|
`# Workflow Apply: ${report.workflow}`,
|
|
6121
6291
|
"",
|
|
6122
6292
|
`- Mode: ${report.mode}`,
|
|
6123
6293
|
`- Status: ${report.status}`,
|
|
6294
|
+
`- Source-change status: ${applySourceStatus(report)}`,
|
|
6295
|
+
`- Workspace status: ${validationBlockers.length ? "blocked" : "not blocked during apply"}`,
|
|
6124
6296
|
...report.validationTarget ? [`- Validation target: ${report.validationTarget}`] : [],
|
|
6125
6297
|
"",
|
|
6298
|
+
"## Apply Checks",
|
|
6299
|
+
...report.postApplyChecks?.length ? report.postApplyChecks.map((check) => `- [${check.status}] ${check.code} ${check.target}: ${check.message}`) : ["- not run"],
|
|
6300
|
+
"",
|
|
6301
|
+
"## Source Change Blockers",
|
|
6302
|
+
...sourceBlockers.length ? sourceBlockers : ["- none"],
|
|
6303
|
+
"",
|
|
6126
6304
|
"## Automatically Modified",
|
|
6127
6305
|
...report.changedFiles.length ? report.changedFiles.map((file) => `- \`${file.action}\` ${file.path}: ${file.reason}`) : ["- none"],
|
|
6128
6306
|
"",
|
|
@@ -6145,7 +6323,7 @@ var renderWorkflowApplyReport = (report) => {
|
|
|
6145
6323
|
...report.diagnostics.length ? report.diagnostics.map(renderDiagnostic) : ["- none"],
|
|
6146
6324
|
"",
|
|
6147
6325
|
"## Recommendations",
|
|
6148
|
-
...report.recommendations.length ? report.recommendations.map(renderRecommendation) : ["- none"],
|
|
6326
|
+
...report.recommendations.length ? report.recommendations.slice(0, 3).map(renderRecommendation) : ["- none"],
|
|
6149
6327
|
"",
|
|
6150
6328
|
"## Next Actions",
|
|
6151
6329
|
...report.nextActions.length ? report.nextActions.map((action) => `- \`${action.command}\`: ${action.reason}`) : ["- none"],
|
|
@@ -6164,10 +6342,16 @@ var renderWorkflowValidationRunReport = (report) => [
|
|
|
6164
6342
|
`- Overall status: ${report.overallStatus}`,
|
|
6165
6343
|
"",
|
|
6166
6344
|
"## Status Summary",
|
|
6167
|
-
`-
|
|
6168
|
-
`- Generated sync
|
|
6169
|
-
`- Workspace
|
|
6170
|
-
`- Environment
|
|
6345
|
+
`- Source-change: ${report.summary.sourceChange}`,
|
|
6346
|
+
`- Generated sync: ${report.summary.generatedSync}`,
|
|
6347
|
+
`- Workspace config: ${report.summary.workspaceConfig}`,
|
|
6348
|
+
`- Environment: ${report.summary.environment}`,
|
|
6349
|
+
"",
|
|
6350
|
+
"## Source Change Diagnostics",
|
|
6351
|
+
...report.workflowDiagnostics?.length ? report.workflowDiagnostics.map((diagnostic) => `- [${diagnostic.severity}] ${diagnostic.code}: ${diagnostic.message}`) : ["- none"],
|
|
6352
|
+
"",
|
|
6353
|
+
"## Existing Workspace Blockers",
|
|
6354
|
+
...report.baselineDiagnostics?.length ? report.baselineDiagnostics.map((diagnostic) => `- [${diagnostic.severity}] ${diagnostic.code}: ${diagnostic.message}`) : ["- none"],
|
|
6171
6355
|
"",
|
|
6172
6356
|
"## Known Blockers",
|
|
6173
6357
|
...report.knownBlockers.length ? report.knownBlockers.map((blocker) => {
|
|
@@ -7243,7 +7427,7 @@ var collapseIndex = (relPathNoExt) => {
|
|
|
7243
7427
|
|
|
7244
7428
|
// pkgs/@akanjs/devkit/transforms/barrelImportsPlugin.ts
|
|
7245
7429
|
import path14 from "path";
|
|
7246
|
-
import
|
|
7430
|
+
import ts5 from "typescript";
|
|
7247
7431
|
var createBarrelImportsPlugin = async (app, { skipPath = defaultSkipPath, pipeAfter } = {}) => {
|
|
7248
7432
|
const akanConfig2 = await app.getConfig();
|
|
7249
7433
|
const barrels = [...new Set(akanConfig2.barrelImports)].filter(Boolean);
|
|
@@ -7484,11 +7668,11 @@ var rewriteBarrelImports = async (source2, barrels, analyzer) => {
|
|
|
7484
7668
|
};
|
|
7485
7669
|
var findImportStatements = (source2) => {
|
|
7486
7670
|
const statements = [];
|
|
7487
|
-
const sourceFile2 =
|
|
7671
|
+
const sourceFile2 = ts5.createSourceFile("barrel-imports.tsx", source2, ts5.ScriptTarget.Latest, true, ts5.ScriptKind.TSX);
|
|
7488
7672
|
for (const statement of sourceFile2.statements) {
|
|
7489
|
-
if (!
|
|
7673
|
+
if (!ts5.isImportDeclaration(statement))
|
|
7490
7674
|
continue;
|
|
7491
|
-
if (!
|
|
7675
|
+
if (!ts5.isStringLiteral(statement.moduleSpecifier))
|
|
7492
7676
|
continue;
|
|
7493
7677
|
const importClause = statement.importClause;
|
|
7494
7678
|
if (!importClause)
|
|
@@ -8483,7 +8667,7 @@ import path22 from "path";
|
|
|
8483
8667
|
// pkgs/@akanjs/devkit/frontendBuild/pagesEntrySourceGenerator.ts
|
|
8484
8668
|
import fs3 from "fs";
|
|
8485
8669
|
import path21 from "path";
|
|
8486
|
-
import
|
|
8670
|
+
import ts6 from "typescript";
|
|
8487
8671
|
|
|
8488
8672
|
class PagesEntrySourceGenerator {
|
|
8489
8673
|
#pageEntries;
|
|
@@ -8527,7 +8711,7 @@ ${entries.join(`
|
|
|
8527
8711
|
static #hasAsyncDefaultExport(moduleAbsPath) {
|
|
8528
8712
|
try {
|
|
8529
8713
|
const source2 = fs3.readFileSync(path21.resolve(moduleAbsPath), "utf8");
|
|
8530
|
-
const sourceFile2 =
|
|
8714
|
+
const sourceFile2 = ts6.createSourceFile(moduleAbsPath, source2, ts6.ScriptTarget.Latest, true, PagesEntrySourceGenerator.#scriptKind(moduleAbsPath));
|
|
8531
8715
|
return PagesEntrySourceGenerator.#sourceFileHasAsyncDefaultExport(sourceFile2);
|
|
8532
8716
|
} catch {
|
|
8533
8717
|
return false;
|
|
@@ -8537,31 +8721,31 @@ ${entries.join(`
|
|
|
8537
8721
|
const asyncBindings = new Map;
|
|
8538
8722
|
let defaultIdentifier = null;
|
|
8539
8723
|
for (const statement of sourceFile2.statements) {
|
|
8540
|
-
if (
|
|
8541
|
-
if (PagesEntrySourceGenerator.#hasModifier(statement,
|
|
8542
|
-
return PagesEntrySourceGenerator.#hasModifier(statement,
|
|
8724
|
+
if (ts6.isFunctionDeclaration(statement)) {
|
|
8725
|
+
if (PagesEntrySourceGenerator.#hasModifier(statement, ts6.SyntaxKind.DefaultKeyword)) {
|
|
8726
|
+
return PagesEntrySourceGenerator.#hasModifier(statement, ts6.SyntaxKind.AsyncKeyword);
|
|
8543
8727
|
}
|
|
8544
8728
|
if (statement.name) {
|
|
8545
|
-
asyncBindings.set(statement.name.text, PagesEntrySourceGenerator.#hasModifier(statement,
|
|
8729
|
+
asyncBindings.set(statement.name.text, PagesEntrySourceGenerator.#hasModifier(statement, ts6.SyntaxKind.AsyncKeyword));
|
|
8546
8730
|
}
|
|
8547
8731
|
continue;
|
|
8548
8732
|
}
|
|
8549
|
-
if (
|
|
8733
|
+
if (ts6.isVariableStatement(statement)) {
|
|
8550
8734
|
for (const declaration of statement.declarationList.declarations) {
|
|
8551
|
-
if (!
|
|
8735
|
+
if (!ts6.isIdentifier(declaration.name))
|
|
8552
8736
|
continue;
|
|
8553
8737
|
asyncBindings.set(declaration.name.text, PagesEntrySourceGenerator.#isAsyncFunctionExpression(declaration.initializer));
|
|
8554
8738
|
}
|
|
8555
8739
|
continue;
|
|
8556
8740
|
}
|
|
8557
|
-
if (
|
|
8741
|
+
if (ts6.isExportAssignment(statement)) {
|
|
8558
8742
|
if (PagesEntrySourceGenerator.#isAsyncFunctionExpression(statement.expression))
|
|
8559
8743
|
return true;
|
|
8560
|
-
if (
|
|
8744
|
+
if (ts6.isIdentifier(statement.expression))
|
|
8561
8745
|
defaultIdentifier = statement.expression.text;
|
|
8562
8746
|
continue;
|
|
8563
8747
|
}
|
|
8564
|
-
if (
|
|
8748
|
+
if (ts6.isExportDeclaration(statement) && statement.exportClause && ts6.isNamedExports(statement.exportClause)) {
|
|
8565
8749
|
const exportClause = statement.exportClause;
|
|
8566
8750
|
for (const specifier of exportClause.elements) {
|
|
8567
8751
|
if (specifier.name.text !== "default")
|
|
@@ -8573,13 +8757,13 @@ ${entries.join(`
|
|
|
8573
8757
|
return defaultIdentifier ? asyncBindings.get(defaultIdentifier) === true : false;
|
|
8574
8758
|
}
|
|
8575
8759
|
static #hasModifier(node, kind) {
|
|
8576
|
-
return
|
|
8760
|
+
return ts6.canHaveModifiers(node) && (ts6.getModifiers(node)?.some((modifier) => modifier.kind === kind) ?? false);
|
|
8577
8761
|
}
|
|
8578
8762
|
static #isAsyncFunctionExpression(node) {
|
|
8579
|
-
return Boolean(node && (
|
|
8763
|
+
return Boolean(node && (ts6.isArrowFunction(node) || ts6.isFunctionExpression(node)) && PagesEntrySourceGenerator.#hasModifier(node, ts6.SyntaxKind.AsyncKeyword));
|
|
8580
8764
|
}
|
|
8581
8765
|
static #scriptKind(moduleAbsPath) {
|
|
8582
|
-
return moduleAbsPath.endsWith(".tsx") || moduleAbsPath.endsWith(".jsx") ?
|
|
8766
|
+
return moduleAbsPath.endsWith(".tsx") || moduleAbsPath.endsWith(".jsx") ? ts6.ScriptKind.TSX : ts6.ScriptKind.TS;
|
|
8583
8767
|
}
|
|
8584
8768
|
}
|
|
8585
8769
|
|
|
@@ -9498,7 +9682,7 @@ import {
|
|
|
9498
9682
|
} from "fontaine";
|
|
9499
9683
|
import { createFont, woff2 } from "fonteditor-core";
|
|
9500
9684
|
import subsetFont from "subset-font";
|
|
9501
|
-
import
|
|
9685
|
+
import ts7 from "typescript";
|
|
9502
9686
|
var FONT_URL_PREFIX = "/_akan/fonts";
|
|
9503
9687
|
var DEFAULT_FONT_SUBSETS = ["latin"];
|
|
9504
9688
|
|
|
@@ -9563,17 +9747,17 @@ class FontOptimizer {
|
|
|
9563
9747
|
this.#cssParts.push(...faceCss, this.#buildRootVariableRule(font));
|
|
9564
9748
|
}
|
|
9565
9749
|
#extractFontsExport(source2, filePath) {
|
|
9566
|
-
const sourceFile2 =
|
|
9750
|
+
const sourceFile2 = ts7.createSourceFile(filePath, source2, ts7.ScriptTarget.Latest, true, ts7.ScriptKind.TSX);
|
|
9567
9751
|
const fonts = [];
|
|
9568
9752
|
for (const statement of sourceFile2.statements) {
|
|
9569
|
-
if (!
|
|
9753
|
+
if (!ts7.isVariableStatement(statement))
|
|
9570
9754
|
continue;
|
|
9571
|
-
const modifiers =
|
|
9572
|
-
const isExported = modifiers?.some((modifier) => modifier.kind ===
|
|
9755
|
+
const modifiers = ts7.canHaveModifiers(statement) ? ts7.getModifiers(statement) : undefined;
|
|
9756
|
+
const isExported = modifiers?.some((modifier) => modifier.kind === ts7.SyntaxKind.ExportKeyword) ?? false;
|
|
9573
9757
|
if (!isExported)
|
|
9574
9758
|
continue;
|
|
9575
9759
|
for (const declaration of statement.declarationList.declarations) {
|
|
9576
|
-
if (!
|
|
9760
|
+
if (!ts7.isIdentifier(declaration.name) || declaration.name.text !== "fonts")
|
|
9577
9761
|
continue;
|
|
9578
9762
|
const value = declaration.initializer ? this.#literalToValue(declaration.initializer) : null;
|
|
9579
9763
|
if (Array.isArray(value)) {
|
|
@@ -9584,20 +9768,20 @@ class FontOptimizer {
|
|
|
9584
9768
|
return fonts;
|
|
9585
9769
|
}
|
|
9586
9770
|
#literalToValue(node) {
|
|
9587
|
-
if (
|
|
9771
|
+
if (ts7.isStringLiteralLike(node))
|
|
9588
9772
|
return node.text;
|
|
9589
|
-
if (
|
|
9773
|
+
if (ts7.isNumericLiteral(node))
|
|
9590
9774
|
return Number(node.text);
|
|
9591
|
-
if (node.kind ===
|
|
9775
|
+
if (node.kind === ts7.SyntaxKind.TrueKeyword)
|
|
9592
9776
|
return true;
|
|
9593
|
-
if (node.kind ===
|
|
9777
|
+
if (node.kind === ts7.SyntaxKind.FalseKeyword)
|
|
9594
9778
|
return false;
|
|
9595
|
-
if (
|
|
9779
|
+
if (ts7.isArrayLiteralExpression(node))
|
|
9596
9780
|
return node.elements.map((element) => this.#literalToValue(element));
|
|
9597
|
-
if (
|
|
9781
|
+
if (ts7.isObjectLiteralExpression(node)) {
|
|
9598
9782
|
const obj = {};
|
|
9599
9783
|
for (const prop of node.properties) {
|
|
9600
|
-
if (!
|
|
9784
|
+
if (!ts7.isPropertyAssignment(prop))
|
|
9601
9785
|
continue;
|
|
9602
9786
|
const name = this.#getPropertyName(prop.name);
|
|
9603
9787
|
if (!name)
|
|
@@ -9606,13 +9790,13 @@ class FontOptimizer {
|
|
|
9606
9790
|
}
|
|
9607
9791
|
return obj;
|
|
9608
9792
|
}
|
|
9609
|
-
if (
|
|
9793
|
+
if (ts7.isAsExpression(node) || ts7.isSatisfiesExpression(node) || ts7.isParenthesizedExpression(node)) {
|
|
9610
9794
|
return this.#literalToValue(node.expression);
|
|
9611
9795
|
}
|
|
9612
9796
|
return;
|
|
9613
9797
|
}
|
|
9614
9798
|
#getPropertyName(name) {
|
|
9615
|
-
if (
|
|
9799
|
+
if (ts7.isIdentifier(name) || ts7.isStringLiteral(name) || ts7.isNumericLiteral(name))
|
|
9616
9800
|
return name.text;
|
|
9617
9801
|
return null;
|
|
9618
9802
|
}
|
|
@@ -13087,7 +13271,7 @@ import { capitalize as capitalize8 } from "akanjs/common";
|
|
|
13087
13271
|
// pkgs/@akanjs/devkit/getRelatedCnsts.ts
|
|
13088
13272
|
import { readFileSync as readFileSync4, realpathSync } from "fs";
|
|
13089
13273
|
import ora2 from "ora";
|
|
13090
|
-
import * as
|
|
13274
|
+
import * as ts8 from "typescript";
|
|
13091
13275
|
var tsTranspiler = new Bun.Transpiler({ loader: "ts" });
|
|
13092
13276
|
var tsxTranspiler = new Bun.Transpiler({ loader: "tsx" });
|
|
13093
13277
|
var getTranspiler = (filePath) => filePath.endsWith(".tsx") ? tsxTranspiler : tsTranspiler;
|
|
@@ -13120,10 +13304,10 @@ var scanModuleSpecifiers = (source2, filePath, includeExports) => {
|
|
|
13120
13304
|
return importSpecifiers;
|
|
13121
13305
|
};
|
|
13122
13306
|
var parseTsConfig = (tsConfigPath = "./tsconfig.json") => {
|
|
13123
|
-
const configFile =
|
|
13124
|
-
return
|
|
13307
|
+
const configFile = ts8.readConfigFile(tsConfigPath, (path40) => {
|
|
13308
|
+
return ts8.sys.readFile(path40);
|
|
13125
13309
|
});
|
|
13126
|
-
return
|
|
13310
|
+
return ts8.parseJsonConfigFileContent(configFile.config, ts8.sys, realpathSync(tsConfigPath).replace(/[^/\\]+$/, ""));
|
|
13127
13311
|
};
|
|
13128
13312
|
var collectImportedFiles = (constantFilePath, parsedConfig) => {
|
|
13129
13313
|
const allFilesToAnalyze = new Set([constantFilePath]);
|
|
@@ -13138,7 +13322,7 @@ var collectImportedFiles = (constantFilePath, parsedConfig) => {
|
|
|
13138
13322
|
for (const importPath of scanModuleSpecifiers(source2, filePath, false)) {
|
|
13139
13323
|
if (!importPath.startsWith("."))
|
|
13140
13324
|
continue;
|
|
13141
|
-
const resolved =
|
|
13325
|
+
const resolved = ts8.resolveModuleName(importPath, filePath, parsedConfig.options, ts8.sys).resolvedModule?.resolvedFileName;
|
|
13142
13326
|
if (resolved && !allFilesToAnalyze.has(resolved)) {
|
|
13143
13327
|
allFilesToAnalyze.add(resolved);
|
|
13144
13328
|
collectImported(resolved);
|
|
@@ -13155,7 +13339,7 @@ var collectImportedFiles = (constantFilePath, parsedConfig) => {
|
|
|
13155
13339
|
var createTsProgram = (filePaths, options) => {
|
|
13156
13340
|
const spinner = ora2("Creating TypeScript program for all files...");
|
|
13157
13341
|
spinner.start();
|
|
13158
|
-
const program2 =
|
|
13342
|
+
const program2 = ts8.createProgram(Array.from(filePaths), options);
|
|
13159
13343
|
const checker = program2.getTypeChecker();
|
|
13160
13344
|
spinner.succeed("TypeScript program created.");
|
|
13161
13345
|
return {
|
|
@@ -13195,17 +13379,17 @@ var analyzeProperties = (filesToAnalyze, program2, checker) => {
|
|
|
13195
13379
|
function visit(node) {
|
|
13196
13380
|
if (!source2)
|
|
13197
13381
|
return;
|
|
13198
|
-
if (
|
|
13382
|
+
if (ts8.isPropertyAccessExpression(node)) {
|
|
13199
13383
|
const left = node.expression;
|
|
13200
13384
|
const right = node.name;
|
|
13201
|
-
const { line } =
|
|
13202
|
-
if (
|
|
13385
|
+
const { line } = ts8.getLineAndCharacterOfPosition(source2, node.getStart());
|
|
13386
|
+
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},`))) {
|
|
13203
13387
|
const symbol = getCachedSymbol(right);
|
|
13204
13388
|
if (symbol?.declarations && symbol.declarations.length > 0) {
|
|
13205
13389
|
const key = symbol.declarations[0]?.getSourceFile().fileName.split("/").pop()?.split(".")[0] ?? "";
|
|
13206
13390
|
const property = propertyMap.get(key);
|
|
13207
13391
|
const isScalar = symbol.declarations[0]?.getSourceFile().fileName.includes("_") ?? false;
|
|
13208
|
-
const symbolFilePath = symbol.declarations[0]?.getSourceFile().fileName.replace(`${
|
|
13392
|
+
const symbolFilePath = symbol.declarations[0]?.getSourceFile().fileName.replace(`${ts8.sys.getCurrentDirectory()}/`, "");
|
|
13209
13393
|
if (!symbolFilePath)
|
|
13210
13394
|
throw new Error(`No symbol file path found for ${left.text}.${right.text}`);
|
|
13211
13395
|
if (property) {
|
|
@@ -13229,10 +13413,10 @@ var analyzeProperties = (filesToAnalyze, program2, checker) => {
|
|
|
13229
13413
|
}
|
|
13230
13414
|
}
|
|
13231
13415
|
}
|
|
13232
|
-
} else if (
|
|
13416
|
+
} else if (ts8.isImportDeclaration(node) && ts8.isStringLiteral(node.moduleSpecifier)) {
|
|
13233
13417
|
const importPath = node.moduleSpecifier.text;
|
|
13234
13418
|
if (importPath.startsWith(".")) {
|
|
13235
|
-
const resolved =
|
|
13419
|
+
const resolved = ts8.resolveModuleName(importPath, filePath, program2.getCompilerOptions(), ts8.sys).resolvedModule?.resolvedFileName;
|
|
13236
13420
|
const moduleName = importPath.split("/").pop()?.split(".")[0] ?? "";
|
|
13237
13421
|
const property = propertyMap.get(moduleName);
|
|
13238
13422
|
const isScalar = importPath.includes("_");
|
|
@@ -13247,7 +13431,7 @@ var analyzeProperties = (filesToAnalyze, program2, checker) => {
|
|
|
13247
13431
|
}
|
|
13248
13432
|
}
|
|
13249
13433
|
}
|
|
13250
|
-
|
|
13434
|
+
ts8.forEachChild(node, visit);
|
|
13251
13435
|
}
|
|
13252
13436
|
visit(source2);
|
|
13253
13437
|
}
|
|
@@ -15813,6 +15997,7 @@ class PrimitiveScript extends script("primitive", [ModuleScript]) {
|
|
|
15813
15997
|
}
|
|
15814
15998
|
let constantContent = await sys3.readFile(constantPath);
|
|
15815
15999
|
let dictionaryContent = await sys3.readFile(dictionaryPath);
|
|
16000
|
+
const fieldBuilderName = viaBuilderParameterName(constantContent, inputClassName) ?? "field";
|
|
15816
16001
|
if (new RegExp(`\\b${input7.field}\\s*:`).test(constantContent)) {
|
|
15817
16002
|
diagnostics.push({
|
|
15818
16003
|
severity: "error",
|
|
@@ -15850,7 +16035,7 @@ class PrimitiveScript extends script("primitive", [ModuleScript]) {
|
|
|
15850
16035
|
if (defaultCoercion.diagnostic)
|
|
15851
16036
|
diagnostics.push(defaultCoercion.diagnostic);
|
|
15852
16037
|
}
|
|
15853
|
-
const nextConstantContent = insertIntoObject(constantContent, inputClassName, `${input7.field}: ${fieldExpression(input7.type, input7.defaultValue, { enumValues })},`);
|
|
16038
|
+
const nextConstantContent = insertIntoObject(constantContent, inputClassName, `${input7.field}: ${fieldExpression(input7.type, input7.defaultValue, { enumValues, builderName: fieldBuilderName })},`);
|
|
15854
16039
|
const nextConstantContentWithLight = nextConstantContent && input7.includeInLight ? insertLightProjectionField(nextConstantContent, moduleClassName, input7.field) : nextConstantContent;
|
|
15855
16040
|
const nextDictionaryContent = insertDictionaryModelField(dictionaryContent, moduleClassName, input7.field);
|
|
15856
16041
|
if (nextConstantContentWithLight && (input7.type === "Int" || input7.type === "Float") && new RegExp(`\\b${input7.field}\\s*:\\s*field\\(${input7.type}, \\{ default: "`, "m").test(nextConstantContentWithLight)) {
|
|
@@ -17088,7 +17273,7 @@ class WorkflowRunner extends runner("workflow") {
|
|
|
17088
17273
|
], plan2);
|
|
17089
17274
|
return await renderApplyReport(report);
|
|
17090
17275
|
}
|
|
17091
|
-
return await renderApplyReport(await new WorkflowExecutor(registry).apply(plan2));
|
|
17276
|
+
return await renderApplyReport(await new WorkflowExecutor(registry, workspace).apply(plan2));
|
|
17092
17277
|
}
|
|
17093
17278
|
async validate(runIdOrPlan, {
|
|
17094
17279
|
format = "markdown",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@akanjs/cli",
|
|
3
|
-
"version": "2.3.9-rc.
|
|
3
|
+
"version": "2.3.9-rc.7",
|
|
4
4
|
"sourceType": "module",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"publishConfig": {
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"@langchain/openai": "^1.4.6",
|
|
35
35
|
"@tailwindcss/node": "^4.3.0",
|
|
36
36
|
"@trapezedev/project": "^7.1.4",
|
|
37
|
-
"akanjs": "2.3.9-rc.
|
|
37
|
+
"akanjs": "2.3.9-rc.7",
|
|
38
38
|
"chalk": "^5.6.2",
|
|
39
39
|
"commander": "^14.0.3",
|
|
40
40
|
"daisyui": "5.5.23",
|
|
@@ -9,7 +9,7 @@ export default function getContent(scanInfo: AppInfo | LibInfo | null, dict: Dic
|
|
|
9
9
|
return `
|
|
10
10
|
import { via } from "akanjs/constant";
|
|
11
11
|
|
|
12
|
-
export class ${dict.Model}Input extends via((
|
|
12
|
+
export class ${dict.Model}Input extends via((field) => ({
|
|
13
13
|
})) {}
|
|
14
14
|
|
|
15
15
|
export class ${dict.Model}Object extends via(${dict.Model}Input, (field) => ({})) {}
|