@akanjs/devkit 3.2.0-rc.1 → 3.2.0-rc.10
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/CHANGELOG.md +233 -11
- package/agentAssets.ts +1 -1
- package/akanApp/akanApp.host.test.ts +127 -0
- package/akanApp/akanApp.host.ts +50 -57
- package/akanApp/devHostPolicy.test.ts +11 -11
- package/akanApp/devHostPolicy.ts +2 -4
- package/akanContext.ts +2 -5
- package/akanMcpContract.ts +21 -10
- package/akanMcpToolError.ts +16 -0
- package/apiReport/apiDeclarationPrinter.ts +120 -0
- package/apiReport/apiReport.test.ts +497 -0
- package/apiReport/apiReport.ts +232 -0
- package/apiReport/apiReportDiff.ts +126 -0
- package/apiReport/apiReportPolicy.ts +65 -0
- package/apiReport/apiTargets.ts +311 -0
- package/apiReport/changesetBump.ts +19 -0
- package/applicationBuildReporter.test.ts +21 -0
- package/applicationBuildReporter.ts +8 -0
- package/applicationBuildRunner.test.ts +67 -0
- package/applicationBuildRunner.ts +6 -1
- package/artifact/implicitRootLayout.test.ts +4 -0
- package/artifact/implicitRootLayout.ts +13 -1
- package/artifact/storeBootstrap.ts +3 -2
- package/bareErrorScanner.ts +126 -0
- package/biome.base.json +2 -1
- package/codeAgent/skills/akan-debug/SKILL.md +7 -3
- package/codeAgent/skills/akan-err/SKILL.md +7 -0
- package/codeAgent/skills/akan-mcp/SKILL.md +7 -1
- package/codeAgent/skills/akan-scaffold/SKILL.md +3 -2
- package/codeAgent/skills/akan-transport/SKILL.md +2 -0
- package/codeAgent/skills/akan-validate/SKILL.md +1 -0
- package/codeAgent/tools/McpClient.ts +28 -6
- package/codeAgent/tools/McpToolPack.ts +1 -1
- package/codeAgent/tools/akanCodePlugins.test.ts +13 -1
- package/commandDecorators/argMeta.ts +4 -0
- package/commandDecorators/cliError.ts +72 -0
- package/commandDecorators/command.ts +186 -96
- package/commandDecorators/commandDecorators.test.ts +240 -17
- package/commandDecorators/exitCodeError.ts +6 -7
- package/commandDecorators/index.ts +1 -0
- package/commandDecorators/targetMeta.ts +3 -0
- package/conventionSet.test.ts +5 -2
- package/csrE2e/csrE2eHarness.fixture.ts +1 -1
- package/errorCodeReference.test.ts +282 -0
- package/errorCodeReference.ts +71 -0
- package/errorCodeScan.ts +551 -0
- package/frontendBuild/allRoutesBuilder.test.ts +16 -4
- package/frontendBuild/allRoutesBuilder.ts +24 -6
- package/frontendBuild/buildRouteClient.test.ts +43 -0
- package/frontendBuild/bundleDefine.ts +2 -0
- package/frontendBuild/clientBuildTypes.ts +5 -2
- package/frontendBuild/clientEntryDiscovery.test.ts +80 -0
- package/frontendBuild/clientEntryDiscovery.ts +53 -9
- package/frontendBuild/csrArtifactBuilder.test.ts +48 -0
- package/frontendBuild/csrArtifactBuilder.ts +9 -3
- package/frontendBuild/csrDevBundler.ts +12 -2
- package/frontendBuild/csrDevModuleCompiler.test.ts +97 -0
- package/frontendBuild/csrDevModuleCompiler.ts +37 -8
- package/frontendBuild/csrDevPatcher.test.ts +89 -2
- package/frontendBuild/csrDevPatcher.ts +47 -7
- package/frontendBuild/csrDevTypes.ts +16 -0
- package/frontendBuild/cssCompiler.test.ts +63 -1
- package/frontendBuild/devBarrelImports.ts +132 -0
- package/frontendBuild/devRegistryBundler.ts +19 -4
- package/frontendBuild/mcpAppViewBuilder.test.ts +67 -0
- package/frontendBuild/nativeCore.test.ts +148 -0
- package/frontendBuild/precompressArtifacts.ts +1 -1
- package/frontendBuild/ssrBaseArtifactBuilder.test.ts +26 -0
- package/frontendBuild/ssrBaseArtifactBuilder.ts +23 -19
- package/frontendBuild/ssrDevBundler.ts +13 -2
- package/frontendBuild/vendorImportScanner.test.ts +24 -3
- package/frontendBuild/vendorImportScanner.ts +25 -10
- package/incrementalBuilder/incrementalBuilder.host.test.ts +30 -1
- package/incrementalBuilder/incrementalBuilder.host.ts +10 -22
- package/lint/__fixtures__/no-import-common-err/bad.tsx +13 -0
- package/lint/__fixtures__/no-import-common-err/good.tsx +12 -0
- package/lint/no-import-common-err.grit +31 -0
- package/lint/no-init-fetch-in-client.grit +1 -1
- package/lint/no-web-only-api-outside-webkit.grit +3 -3
- package/maintainabilityBaseline.test.ts +49 -0
- package/maintainabilityBaseline.ts +73 -8
- package/maintainabilityContract.test.ts +302 -1
- package/maintainabilityContract.ts +87 -22
- package/maintainabilityExceptionScanner.test.ts +14 -0
- package/maintainabilityExceptionScanner.ts +5 -1
- package/maintainabilityLimits.ts +12 -0
- package/maintainabilityReport.ts +20 -3
- package/moduleFieldNames.test.ts +56 -0
- package/moduleFieldNames.ts +25 -0
- package/package.json +3 -3
- package/preview/PreviewView.ts +32 -11
- package/preview/previewView.test.ts +76 -9
- package/routeJsBudget.test.ts +47 -11
- package/routeJsBudget.ts +88 -25
- package/transforms/barrelAnalyzer.ts +46 -1
- package/transforms/barrelImportsPlugin.ts +61 -45
- package/transforms/transforms.test.ts +67 -1
- package/typecheck/projectTypecheck.ts +5 -1
- package/typecheck/typecheck.proc.ts +3 -2
- package/typecheck/typecheckFailure.ts +6 -1
- package/workflow/artifacts.ts +25 -7
- package/workflow/fieldType.ts +92 -0
- package/workflow/index.ts +2 -0
- package/workflow/plainName.ts +28 -0
- package/workflow/plan.ts +67 -22
- package/workflow/source.ts +0 -5
- package/workspaceGraph.test.ts +200 -3
- package/workspaceGraph.ts +46 -8
package/workspaceGraph.ts
CHANGED
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
import { readFile } from "node:fs/promises";
|
|
2
2
|
import path from "node:path";
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
type AkanChangeMap,
|
|
5
|
+
type AkanGraph,
|
|
6
|
+
AkanGraphDiff,
|
|
7
|
+
type AkanGraphEdge,
|
|
8
|
+
type AkanGraphNode,
|
|
9
|
+
AkanIndex,
|
|
10
|
+
} from "@akanjs/language";
|
|
4
11
|
import ts from "typescript";
|
|
5
12
|
import type { Workspace } from "./commandDecorators";
|
|
6
13
|
import { GitRevision } from "./gitRevision";
|
|
@@ -64,12 +71,14 @@ export class WorkspaceGraph {
|
|
|
64
71
|
.filter((node) => node.change)
|
|
65
72
|
.flatMap((node) => [
|
|
66
73
|
node.at?.file,
|
|
74
|
+
...(node.sources ?? []),
|
|
67
75
|
...(node.fields ?? []).filter((field) => field.change).map(({ at }) => at.file),
|
|
68
76
|
]),
|
|
69
77
|
...changes.edges.filter((edge) => edge.change).map((edge) => edge.at?.file),
|
|
70
78
|
]);
|
|
71
79
|
const unmapped = files.filter(({ file }) => !mapped.has(file) && !hiddenPath.test(file));
|
|
72
|
-
|
|
80
|
+
const nodes = changes.nodes.map(({ sources: _sources, ...node }) => node);
|
|
81
|
+
return { ...changes, nodes, since: sha.slice(0, 12), unmapped };
|
|
73
82
|
}
|
|
74
83
|
|
|
75
84
|
static #baseAt(root: string, sha: string) {
|
|
@@ -107,9 +116,30 @@ export class WorkspaceGraph {
|
|
|
107
116
|
//? A lib's guard is linked from every app's endpoints; through it, a scope would reach all of them.
|
|
108
117
|
const guards = new Set(graph.nodes.filter((node) => node.kind === "guard").map((node) => node.id));
|
|
109
118
|
const reaches = (id: string) => seeds.has(id) && !guards.has(id);
|
|
110
|
-
const edges = graph.edges.filter((edge) => reaches(edge.from) || reaches(edge.to));
|
|
111
|
-
const
|
|
112
|
-
|
|
119
|
+
const edges = graph.edges.filter((edge) => edge.kind !== "binds" && (reaches(edge.from) || reaches(edge.to)));
|
|
120
|
+
const kept = new Set([...seeds, ...edges.flatMap((edge) => [edge.from, edge.to])]);
|
|
121
|
+
const isLib =
|
|
122
|
+
!!app &&
|
|
123
|
+
graph.nodes.some((node) => node.owner === `libs/${app}`) &&
|
|
124
|
+
!graph.nodes.some((node) => node.owner === `apps/${app}`);
|
|
125
|
+
const applicable = WorkspaceGraph.#bindingsOf(graph, app && !isLib ? `apps/${app}` : null);
|
|
126
|
+
const isOwn = (edge: AkanGraphEdge) => !module && !!owners?.has(edge.label ?? "");
|
|
127
|
+
const roles = new Set(
|
|
128
|
+
applicable.filter((edge) => isOwn(edge) || kept.has(edge.from) || reaches(edge.to)).map((edge) => edge.from),
|
|
129
|
+
);
|
|
130
|
+
const bindings = applicable.filter((edge) => roles.has(edge.from));
|
|
131
|
+
const ids = new Set([...kept, ...bindings.flatMap((edge) => [edge.from, edge.to])]);
|
|
132
|
+
return { version: 1, nodes: graph.nodes.filter((node) => ids.has(node.id)), edges: [...edges, ...bindings] };
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
//? An app runs a role as its own `applyAdaptor` binds it, else as a lib's does; a lib's code runs under every app's.
|
|
136
|
+
static #bindingsOf(graph: AkanGraph, appOwner: string | null) {
|
|
137
|
+
const binds = graph.edges.filter((edge) => edge.kind === "binds");
|
|
138
|
+
if (!appOwner) return binds;
|
|
139
|
+
const own = new Set(
|
|
140
|
+
binds.filter((edge) => edge.label === appOwner && edge.change !== "removed").map((edge) => edge.from),
|
|
141
|
+
);
|
|
142
|
+
return binds.filter((edge) => edge.label === appOwner || (!edge.label?.startsWith("apps/") && !own.has(edge.from)));
|
|
113
143
|
}
|
|
114
144
|
|
|
115
145
|
//? Pages are many and most only wrap one another, so a graph too large to answer whole drops the pages that neither
|
|
@@ -139,7 +169,14 @@ export class WorkspaceGraph {
|
|
|
139
169
|
const isVisible = ({ owner }: AkanGraphNode) => !owner || owner === appOwner || owner.startsWith("libs/");
|
|
140
170
|
const nodes = graph.nodes.filter(isVisible);
|
|
141
171
|
const ids = new Set(nodes.map((node) => node.id));
|
|
142
|
-
|
|
172
|
+
const bindings = new Set(WorkspaceGraph.#bindingsOf(graph, appOwner));
|
|
173
|
+
return {
|
|
174
|
+
version: 1,
|
|
175
|
+
nodes,
|
|
176
|
+
edges: graph.edges.filter(
|
|
177
|
+
(edge) => ids.has(edge.from) && ids.has(edge.to) && (edge.kind !== "binds" || bindings.has(edge)),
|
|
178
|
+
),
|
|
179
|
+
};
|
|
143
180
|
}
|
|
144
181
|
|
|
145
182
|
static changesVisibleTo(changes: AkanChangeMap, app: string): AkanChangeMap {
|
|
@@ -188,15 +225,16 @@ export class WorkspaceGraph {
|
|
|
188
225
|
if (scope.app || scope.module || graph.nodes.length <= unscopedNodeLimit) return WorkspaceGraph.scope(graph, scope);
|
|
189
226
|
const unscoped = WorkspaceGraph.#withoutPages(graph);
|
|
190
227
|
if (unscoped.nodes.length <= unscopedNodeLimit) return unscoped;
|
|
228
|
+
const kept = new Set(unscoped.nodes.map((node) => node.id));
|
|
191
229
|
const owners = new Map<string, number>();
|
|
192
230
|
for (const node of counted)
|
|
193
|
-
if (node.owner &&
|
|
231
|
+
if (node.owner && kept.has(node.id)) owners.set(node.owner, (owners.get(node.owner) ?? 0) + 1);
|
|
194
232
|
return {
|
|
195
233
|
diagnostics: [
|
|
196
234
|
{
|
|
197
235
|
severity: "error",
|
|
198
236
|
code: "graph-scope-required",
|
|
199
|
-
message: `The graph has ${unscoped.nodes.length} nodes
|
|
237
|
+
message: `The graph has ${unscoped.nodes.length} nodes once unchanged pages are set aside. Pass app, module or both to scope it.`,
|
|
200
238
|
input: "app",
|
|
201
239
|
},
|
|
202
240
|
],
|