@akanjs/cli 3.0.0-alpha.10 → 3.0.0-alpha.100
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/.build-stamp +1 -1
- package/README.ko.md +1 -1
- package/README.md +1 -1
- package/{abstractCompactor-e5yq60qz.js → abstractCompactor-byytxs22.js} +3 -5
- package/{agent.command-f0gqkfgz.js → agent.command-v1a4746v.js} +11 -13
- package/{application.command-x903m2qq.js → application.command-fzdcnzhg.js} +65 -38
- package/{applicationBuildRunner-ha3y8ew8.js → applicationBuildRunner-s4gsk728.js} +27 -23
- package/{applicationReleasePackager-gg8ccbeh.js → applicationReleasePackager-28v9vbzk.js} +8 -9
- package/buildBatch.proc.js +12 -14
- package/capacitorApp-8d6d4zkm.js +12 -0
- package/{cloud.command-zs6kyf83.js → cloud.command-wygy2z05.js} +15 -18
- package/commandManifest.json +1 -1
- package/{context.command-fmepgjzg.js → context.command-4vdt1aqq.js} +19 -23
- package/dependencyScanner-shs82ynp.js +8 -0
- package/devTui-qnf1txdz.js +553 -0
- package/devTuiView-yzct2cq6.js +9 -0
- package/getDirname-dr3jz1xg.js +7 -0
- package/{guideline.command-n6sw0a0c.js → guideline.command-p92dq6ts.js} +16 -18
- package/guidelines/agentRule/agentRule.generate.json +31 -0
- package/guidelines/agentRule/agentRule.instruction.md +533 -0
- package/guidelines/conventions/conventions.instruction.md +437 -197
- package/guidelines/cssRule/cssRule.instruction.md +7 -0
- package/guidelines/framework/framework.generate.json +3 -2
- package/guidelines/framework/framework.instruction.md +1 -9
- package/guidelines/mcpRule/mcpRule.generate.json +25 -0
- package/guidelines/mcpRule/mcpRule.instruction.md +217 -0
- package/guidelines/modelStore/modelStore.instruction.md +12 -0
- package/guidelines/modelTemplate/modelTemplate.instruction.md +5 -0
- package/guidelines/queryRule/queryRule.generate.json +31 -0
- package/guidelines/queryRule/queryRule.instruction.md +175 -0
- package/guidelines/runtimeRule/runtimeRule.generate.json +25 -0
- package/guidelines/runtimeRule/runtimeRule.instruction.md +220 -0
- package/guidelines/ssrRule/ssrRule.instruction.md +49 -5
- package/guidelines/transportRule/transportRule.generate.json +31 -0
- package/guidelines/transportRule/transportRule.instruction.md +60 -0
- package/guidelines/workspaceOnboarding/workspaceOnboarding.instruction.md +51 -760
- package/guidelines/workspaceRecipes/workspaceRecipes.generate.json +33 -0
- package/guidelines/workspaceRecipes/workspaceRecipes.instruction.md +402 -0
- package/incrementalBuilder.proc.js +26 -25
- package/{index-jf2ya7r2.js → index-0amdxycf.js} +8 -8
- package/{index-779ske1y.js → index-1yxtbmbj.js} +27 -27
- package/{index-eyyf2149.js → index-29sxqfaw.js} +36 -37
- package/index-3d9y066c.js +76 -0
- package/{index-76rn3g2c.js → index-47pj3aee.js} +4 -4
- package/index-5svjba73.js +159 -0
- package/{index-1577bej2.js → index-6wwzs1bc.js} +2 -2
- package/{index-gcv8ncfh.js → index-7d6vny25.js} +16 -12
- package/{index-y4vkyhvv.js → index-8p8p0cf8.js} +14 -14
- package/{index-wnp7hwq7.js → index-92zztqy1.js} +7 -7
- package/{index-fgc8r6dj.js → index-a5vmm6x4.js} +3 -1
- package/{index-xys926f2.js → index-by5gpp8x.js} +4 -4
- package/{index-0cj2zxbm.js → index-c69j78kk.js} +12 -11
- package/{index-rxkpk7n4.js → index-fc1bh0a7.js} +4 -4
- package/{index-d43t8af2.js → index-gq44bqjt.js} +58 -25
- package/{index-774gcx29.js → index-gtmz74tj.js} +41 -34
- package/{index-j37qq1f2.js → index-h7yw2z9n.js} +7 -7
- package/{index-bjpxzr6s.js → index-hwkygn9s.js} +51 -3
- package/{index-xmmzf150.js → index-hyywke0f.js} +1 -1
- package/{index-46tjzh6s.js → index-kcxmv48c.js} +29 -29
- package/{index-xjd3rqzj.js → index-n68jx79w.js} +6 -15
- package/{index-qb61h0k7.js → index-p5neav9b.js} +1098 -1360
- package/{index-67546d0j.js → index-q0y2jq9j.js} +14 -2
- package/{index-3vta1tqa.js → index-qkk27bk6.js} +32 -32
- package/{index-z8ptfkzv.js → index-qsq3q8fy.js} +975 -242
- package/{index-qzdjd4ct.js → index-srdssqj7.js} +18 -18
- package/{index-j9cxndc0.js → index-w8kmx1b6.js} +20 -11
- package/{index-82jrh4hj.js → index-yks023mb.js} +13 -13
- package/{index-5sn5w2mt.js → index-yza7zkpt.js} +94 -61
- package/{index-jhpa13zj.js → index-zmjppp25.js} +57 -57
- package/{index-kdh76j26.js → index-znynzt5w.js} +100 -32
- package/{index-4m0bphac.js → index-zxgr3s8s.js} +31 -30
- package/{index-62955kn5.js → index-zz5jyd94.js} +1002 -128
- package/index.js +22 -25
- package/{library.command-cv9gdbmg.js → library.command-s4fszngs.js} +11 -10
- package/{localRegistry.command-d8fg36zc.js → localRegistry.command-gyw4da9z.js} +20 -23
- package/{module.command-qyr1s9cn.js → module.command-6n7dwvav.js} +13 -16
- package/{package.command-wsjx0k47.js → package.command-gr82ypnr.js} +8 -10
- package/package.json +5 -7
- package/{page.command-rdzg65rm.js → page.command-7gvgb3jb.js} +7 -9
- package/{primitive.command-89g38b53.js → primitive.command-tk5ckw38.js} +13 -16
- package/{quality.command-0cs2z92d.js → quality.command-38v81baf.js} +226 -105
- package/recipeScanner-fpagtgc1.js +11 -0
- package/{repair.command-6fphxfwj.js → repair.command-5xbwvsxp.js} +12 -14
- package/{routeSourceValidator-e4jmbfcx.js → routeSourceValidator-ze6x894c.js} +0 -2
- package/{scalar.command-xfer69s6.js → scalar.command-0epwcr5k.js} +11 -14
- package/subspace.command-e2t36xb2.js +755 -0
- package/templates/app/env/env.client.debug.ts.template +1 -5
- package/templates/app/env/env.client.develop.ts.template +1 -5
- package/templates/app/env/env.client.local.ts.template +1 -5
- package/templates/app/env/env.client.main.ts.template +1 -5
- package/templates/app/env/env.client.testing.ts.template +1 -5
- package/templates/app/env/env.client.type.ts +2 -6
- package/templates/app/env/env.server.debug.ts.template +1 -5
- package/templates/app/env/env.server.develop.ts.template +1 -5
- package/templates/app/env/env.server.local.ts.template +1 -5
- package/templates/app/env/env.server.main.ts.template +1 -5
- package/templates/app/main.ts +3 -1
- package/templates/appSample/lib/task/task.signal.ts +11 -6
- package/templates/appSample/srvkit/AuthGuard.ts +9 -5
- package/templates/appSample/srvkit/SessionInternalArg.ts +4 -3
- package/templates/crudPages/[__model__Id]/edit/page.tsx +5 -5
- package/templates/crudPages/[__model__Id]/page.tsx +10 -13
- package/templates/crudPages/new/page.tsx +5 -5
- package/templates/crudPages/page.tsx +9 -9
- package/templates/crudSinglePage/page.tsx +11 -7
- package/templates/env/_env.server.type.ts +7 -5
- package/templates/lib/db.ts +1 -1
- package/templates/lib/dict.ts +1 -1
- package/templates/lib/sig.ts +5 -1
- package/templates/lib/srv.ts +6 -2
- package/templates/module/__model__.dictionary.ts +4 -1
- package/templates/module/__model__.signal.ts +2 -3
- package/templates/module/__model__.store.ts +1 -2
- package/templates/workspaceRoot/.gitignore.template +0 -1
- package/templates/workspaceRoot/.husky/pre-commit.template +16 -0
- package/templates/workspaceRoot/.vscode/settings.json.template +1 -1
- package/templates/workspaceRoot/AGENTS.md.template +4 -0
- package/templates/workspaceRoot/CLAUDE.md.template +19 -0
- package/templates/workspaceRoot/biome.json.template +2 -1
- package/templates/workspaceRoot/docs/AI-DEVELOPMENT.md.template +10 -14
- package/templates/workspaceRoot/docs/GENERATED.md.template +12 -10
- package/templates/workspaceRoot/package.json.template +2 -4
- package/typeChecker-3xgrzc2v.js +7 -0
- package/typecheck.proc.js +4 -5
- package/{workflow.command-2ygfqt4f.js → workflow.command-kphbr7eh.js} +22 -25
- package/{workspace.command-vbgpjkf9.js → workspace.command-j1gatz3d.js} +96 -81
- package/capacitorApp-9xswcgx7.js +0 -61
- package/dependencyScanner-f6grrep3.js +0 -9
- package/getDirname-m9s0cmhq.js +0 -8
- package/index-mxvakhsm.js +0 -66
- package/index-r24hmh0q.js +0 -4
- package/recipeScanner-tghkzrrt.js +0 -12
- package/typeChecker-kravn7ns.js +0 -8
- /package/{index-0wae5ebk.js → index-meh558jy.js} +0 -0
- /package/{index-ss469dec.js → index-nz8prx9g.js} +0 -0
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
// @bun
|
|
2
|
+
import {
|
|
3
|
+
CommandExecutionError
|
|
4
|
+
} from "./index-qsq3q8fy.js";
|
|
2
5
|
import {
|
|
3
6
|
resolveMobilePath,
|
|
4
7
|
targetHtmlFilename
|
|
5
|
-
} from "./index-
|
|
6
|
-
import {
|
|
7
|
-
CommandExecutionError
|
|
8
|
-
} from "./index-z8ptfkzv.js";
|
|
8
|
+
} from "./index-47pj3aee.js";
|
|
9
9
|
|
|
10
10
|
// pkgs/@akanjs/devkit/capacitorApp.ts
|
|
11
11
|
import { cp, mkdir, readFile, rm, writeFile } from "fs/promises";
|
|
@@ -17,22 +17,22 @@ import { capitalize } from "akanjs/common";
|
|
|
17
17
|
|
|
18
18
|
// pkgs/@akanjs/devkit/fileEditor.ts
|
|
19
19
|
class FileEditor {
|
|
20
|
-
filePath;
|
|
21
|
-
content;
|
|
20
|
+
#filePath;
|
|
21
|
+
#content;
|
|
22
22
|
constructor(filePath, content) {
|
|
23
|
-
this
|
|
24
|
-
this
|
|
23
|
+
this.#filePath = filePath;
|
|
24
|
+
this.#content = content;
|
|
25
25
|
}
|
|
26
26
|
static async create(filePath) {
|
|
27
27
|
try {
|
|
28
28
|
const content = await Bun.file(filePath).text();
|
|
29
29
|
return new FileEditor(filePath, content);
|
|
30
|
-
} catch (
|
|
30
|
+
} catch (_error) {
|
|
31
31
|
throw new Error(`Failed to read file: ${filePath}`);
|
|
32
32
|
}
|
|
33
33
|
}
|
|
34
34
|
find(pattern) {
|
|
35
|
-
const lines = this
|
|
35
|
+
const lines = this.#content.split(`
|
|
36
36
|
`);
|
|
37
37
|
const regex = typeof pattern === "string" ? new RegExp(pattern) : pattern;
|
|
38
38
|
for (let i = 0;i < lines.length; i++) {
|
|
@@ -45,7 +45,7 @@ class FileEditor {
|
|
|
45
45
|
return -1;
|
|
46
46
|
}
|
|
47
47
|
findAll(pattern) {
|
|
48
|
-
const lines = this
|
|
48
|
+
const lines = this.#content.split(`
|
|
49
49
|
`);
|
|
50
50
|
const regex = typeof pattern === "string" ? new RegExp(pattern) : pattern;
|
|
51
51
|
const matches = [];
|
|
@@ -63,10 +63,10 @@ class FileEditor {
|
|
|
63
63
|
if (lineIndex === -1) {
|
|
64
64
|
throw new Error(`Pattern not found: ${pattern}`);
|
|
65
65
|
}
|
|
66
|
-
const lines = this
|
|
66
|
+
const lines = this.#content.split(`
|
|
67
67
|
`);
|
|
68
68
|
lines.splice(lineIndex + 1, 0, data);
|
|
69
|
-
this
|
|
69
|
+
this.#content = lines.join(`
|
|
70
70
|
`);
|
|
71
71
|
return this;
|
|
72
72
|
}
|
|
@@ -75,40 +75,40 @@ class FileEditor {
|
|
|
75
75
|
if (lineIndex === -1) {
|
|
76
76
|
throw new Error(`Pattern not found: ${pattern}`);
|
|
77
77
|
}
|
|
78
|
-
const lines = this
|
|
78
|
+
const lines = this.#content.split(`
|
|
79
79
|
`);
|
|
80
80
|
lines.splice(lineIndex, 0, data);
|
|
81
|
-
this
|
|
81
|
+
this.#content = lines.join(`
|
|
82
82
|
`);
|
|
83
83
|
return this;
|
|
84
84
|
}
|
|
85
85
|
replace(pattern, replacement) {
|
|
86
86
|
const regex = typeof pattern === "string" ? new RegExp(pattern, "g") : pattern;
|
|
87
|
-
this
|
|
87
|
+
this.#content = this.#content.replace(regex, replacement);
|
|
88
88
|
return this;
|
|
89
89
|
}
|
|
90
90
|
append(data) {
|
|
91
|
-
this
|
|
91
|
+
this.#content += `
|
|
92
92
|
${data}`;
|
|
93
93
|
return this;
|
|
94
94
|
}
|
|
95
95
|
prepend(data) {
|
|
96
|
-
this
|
|
97
|
-
${this
|
|
96
|
+
this.#content = `${data}
|
|
97
|
+
${this.#content}`;
|
|
98
98
|
return this;
|
|
99
99
|
}
|
|
100
100
|
async save() {
|
|
101
101
|
try {
|
|
102
|
-
await Bun.write(this
|
|
103
|
-
} catch (
|
|
104
|
-
throw new Error(`Failed to save file: ${this
|
|
102
|
+
await Bun.write(this.#filePath, this.#content);
|
|
103
|
+
} catch (_error) {
|
|
104
|
+
throw new Error(`Failed to save file: ${this.#filePath}`);
|
|
105
105
|
}
|
|
106
106
|
}
|
|
107
107
|
getContent() {
|
|
108
|
-
return this
|
|
108
|
+
return this.#content;
|
|
109
109
|
}
|
|
110
110
|
setContent(content) {
|
|
111
|
-
this
|
|
111
|
+
this.#content = content;
|
|
112
112
|
return this;
|
|
113
113
|
}
|
|
114
114
|
}
|
|
@@ -474,7 +474,7 @@ var PLACEHOLDER_APP_IDS = [
|
|
|
474
474
|
"com.example.myapp"
|
|
475
475
|
];
|
|
476
476
|
var placeholderAppIdSegment = /^(example|examples|myorg|myapp|mycompany|myorganization|changeme|todo|sample|test)$/;
|
|
477
|
-
var
|
|
477
|
+
var isPlaceholderAppId2 = (appId) => {
|
|
478
478
|
const normalized = appId?.trim().toLowerCase() ?? "";
|
|
479
479
|
if (!normalized)
|
|
480
480
|
return true;
|
|
@@ -641,7 +641,7 @@ function materializeCapacitorConfig(target, { operation, localServerUrl, localIp
|
|
|
641
641
|
return config;
|
|
642
642
|
}
|
|
643
643
|
|
|
644
|
-
class
|
|
644
|
+
class CapacitorApp2 {
|
|
645
645
|
app;
|
|
646
646
|
target;
|
|
647
647
|
project;
|
|
@@ -1513,4 +1513,4 @@ ${filter}$1`);
|
|
|
1513
1513
|
}
|
|
1514
1514
|
}
|
|
1515
1515
|
|
|
1516
|
-
export {
|
|
1516
|
+
export { isPlaceholderAppId2, CapacitorApp2 };
|
|
@@ -1,28 +1,29 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import {
|
|
3
|
-
AkanContextAnalyzer
|
|
4
|
-
} from "./index-774gcx29.js";
|
|
5
|
-
import {
|
|
6
|
-
Prompter
|
|
7
|
-
} from "./index-j37qq1f2.js";
|
|
8
2
|
import {
|
|
9
3
|
runner,
|
|
10
4
|
script
|
|
11
|
-
} from "./index-
|
|
5
|
+
} from "./index-znynzt5w.js";
|
|
12
6
|
import {
|
|
13
|
-
AGENT_BLOCK_END,
|
|
14
7
|
AGENT_BLOCK_START,
|
|
15
|
-
|
|
16
|
-
|
|
8
|
+
AGENT_BLOCK_END,
|
|
9
|
+
stampBlockVersion,
|
|
17
10
|
readDevkitVersion,
|
|
11
|
+
upsertAgentBlock,
|
|
18
12
|
renderRecipeEntries,
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
13
|
+
CLAUDE_COMMENT_RULE,
|
|
14
|
+
AppExecutor,
|
|
15
|
+
LibExecutor
|
|
16
|
+
} from "./index-qsq3q8fy.js";
|
|
22
17
|
import {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
} from "./index-
|
|
18
|
+
collectRecipeSources2,
|
|
19
|
+
scanRecipes2
|
|
20
|
+
} from "./index-by5gpp8x.js";
|
|
21
|
+
import {
|
|
22
|
+
AkanContextAnalyzer
|
|
23
|
+
} from "./index-gtmz74tj.js";
|
|
24
|
+
import {
|
|
25
|
+
Prompter
|
|
26
|
+
} from "./index-h7yw2z9n.js";
|
|
26
27
|
|
|
27
28
|
// pkgs/@akanjs/cli/agent/agent.script.ts
|
|
28
29
|
import { Logger as Logger2 } from "akanjs/common";
|
|
@@ -76,8 +77,8 @@ Keep a sample only while you are still learning its pattern; delete it once your
|
|
|
76
77
|
`;
|
|
77
78
|
};
|
|
78
79
|
var renderRecipeIndex = async (workspace) => {
|
|
79
|
-
const sources = await
|
|
80
|
-
const recipes =
|
|
80
|
+
const sources = await collectRecipeSources2(`${workspace.workspaceRoot}/pkgs/akanjs/ui`, "akanjs/ui", "recipe");
|
|
81
|
+
const recipes = scanRecipes2(sources);
|
|
81
82
|
const scopeIndexPointer = `App and lib recipes are **not** listed here. Each app/lib carries its own generated index \u2014
|
|
82
83
|
\`apps/<app>/AGENTS.md\` / \`libs/<lib>/AGENTS.md\` (\`## Recipes In Scope\`) \u2014 regenerated by \`akan sync\` and
|
|
83
84
|
verified by \`akan lint\`. When working inside an app or lib, consult that file before consuming or authoring a look.`;
|
|
@@ -89,15 +90,14 @@ ${scopeIndexPointer}
|
|
|
89
90
|
`;
|
|
90
91
|
return `## Recipes
|
|
91
92
|
|
|
92
|
-
Framework UI recipes (Tailwind-variant look factories), importable from every app and lib
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
the
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
near-duplicate.** Full authoring/consumption policy: the \`recipeRule\` guideline.
|
|
93
|
+
Framework UI recipes (Tailwind-variant look factories), importable from every app and lib: \`import { <name> } from
|
|
94
|
+
"akanjs/ui"\`, then \`<name>(variants?, className?)\`. The second arg merges internally and takes **an array too**, so
|
|
95
|
+
never wrap it in \`cn()\`: \`<name>({}, ["h-full", isWide && "w-full", className])\`. The list below is the full
|
|
96
|
+
contract (\`*\` marks the default, \`key?\` is a boolean flag) \u2014 do not guess a name, path, or variant value, and do
|
|
97
|
+
not open the recipe file to consume one. **Before inlining a repeated surface (card, box, tile, \u2026): reuse a recipe,
|
|
98
|
+
or add one as \`apps/<app>/ui/Recipe/<name>.ts\`, one per file, re-exported from that folder's \`index.ts\` \u2014 never
|
|
99
|
+
re-implement the same look inline in several places, and never author a near-duplicate.** Full policy: the
|
|
100
|
+
\`recipeRule\` guideline.
|
|
101
101
|
|
|
102
102
|
${renderRecipeEntries(recipes)}
|
|
103
103
|
|
|
@@ -147,15 +147,12 @@ If generated output is stale or broken, update the owning source file and run \`
|
|
|
147
147
|
|
|
148
148
|
${recipeIndex}## MCP Workflow Policy
|
|
149
149
|
|
|
150
|
-
- Prefer Akan
|
|
151
|
-
-
|
|
152
|
-
-
|
|
153
|
-
-
|
|
154
|
-
-
|
|
155
|
-
-
|
|
156
|
-
- If no workflow exists, or apply reports unsupported/no-op/failed diagnostics that require manual action, keep edits scoped to owning source files and never patch generated files directly.
|
|
157
|
-
- For compound requests, split the request into workflows and apply each \`planPath\` in order, such as \`create-module\` followed by \`add-field\`.
|
|
158
|
-
- **CLI-only fallback (MCP not connected):** \`akan mcp\` starts a stdio MCP server, so the \`list_workflows\`/\`plan_workflow\`/\`apply_workflow\` tools exist only when your agent is wired to it as an MCP client. When they are unavailable, the CLI is a first-class equivalent: \`akan workflow list\` / \`explain <name>\` / \`plan <name> ... --format json --out <planPath>\` / \`apply <planPath> --format json\`, \`akan doctor --strict --format json\` for validation, and \`akan repair generated|imports|module-shape --app <app> --format json\` for repairs. Scaffolding primitives (\`create-module\`/\`create-scalar\`/\`create-service\` take the target app/lib as a POSITIONAL arg; \`add-field\`/\`add-enum-field\` use \`--app\`/\`--module\` flags) call the same code the workflows do.
|
|
150
|
+
- **Prefer an Akan workflow to a direct source edit.** A direct edit is denied when an allowlisted workflow or repair tool can make the change.
|
|
151
|
+
- Inspect with \`akan mcp --mode plan\` (\`list_workflows\`, \`explain_workflow\`, \`plan_workflow\`); apply with \`akan mcp --mode apply\`, which allowlists \`apply_workflow\`, \`run_validation\`, and the repair tools.
|
|
152
|
+
- If \`plan_workflow\` returns \`planPath\` or \`next.tool=apply_workflow\`, call \`apply_workflow({ planPath })\` before editing source. Then run \`run_validation\` with \`validationTarget\` when present, otherwise \`applyReportPath\`.
|
|
153
|
+
- Split a compound request into workflows and apply each \`planPath\` in order, such as \`create-module\` followed by \`add-field\`.
|
|
154
|
+
- When no workflow exists, or apply reports unsupported/no-op/failed diagnostics needing manual action, keep edits scoped to owning source files and never patch generated files directly.
|
|
155
|
+
- **MCP not connected?** The CLI is a first-class equivalent \u2014 \`akan workflow list\` / \`explain\` / \`plan\` / \`apply\`, \`akan doctor\`, \`akan repair\`. See the onboarding guide's CLI-only fallback for the exact flags.
|
|
159
156
|
|
|
160
157
|
## Validation
|
|
161
158
|
|
|
@@ -199,6 +196,8 @@ var renderClaudeMd = async (workspace) => {
|
|
|
199
196
|
return `# ${context.repoName} \u2014 Claude Code Guide
|
|
200
197
|
|
|
201
198
|
@AGENTS.md
|
|
199
|
+
|
|
200
|
+
${CLAUDE_COMMENT_RULE}
|
|
202
201
|
`;
|
|
203
202
|
};
|
|
204
203
|
var renderCursorRule = () => `---
|
|
@@ -246,7 +245,7 @@ class AgentRunner extends runner("agent") {
|
|
|
246
245
|
written.push(`${exec.type}s/${exec.name}/AGENTS.md`);
|
|
247
246
|
} catch (error) {
|
|
248
247
|
const message = error instanceof Error ? error.message : String(error);
|
|
249
|
-
Logger.rawLog(`Skipped ${exec.type}s/${exec.name}/AGENTS.md (${message})`, undefined, "
|
|
248
|
+
Logger.rawLog(`Skipped ${exec.type}s/${exec.name}/AGENTS.md (${message})`, undefined, "error");
|
|
250
249
|
}
|
|
251
250
|
};
|
|
252
251
|
for (const name of libNames)
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
// pkgs/@akanjs/devkit/libSource.ts
|
|
3
|
+
class LibSource {
|
|
4
|
+
static manifestKey = "akan";
|
|
5
|
+
static unhashedDirs = ["env"];
|
|
6
|
+
#lib;
|
|
7
|
+
constructor(lib) {
|
|
8
|
+
this.#lib = lib;
|
|
9
|
+
}
|
|
10
|
+
get #prefix() {
|
|
11
|
+
return `libs/${this.#lib.name}/`;
|
|
12
|
+
}
|
|
13
|
+
#isHashed(file) {
|
|
14
|
+
const relative = file.slice(this.#prefix.length);
|
|
15
|
+
return !LibSource.unhashedDirs.includes(relative.split("/")[0] ?? "");
|
|
16
|
+
}
|
|
17
|
+
async#hashableContent(file) {
|
|
18
|
+
const content = await this.#lib.workspace.readFile(file);
|
|
19
|
+
if (file !== `${this.#prefix}package.json`)
|
|
20
|
+
return content;
|
|
21
|
+
const manifest = JSON.parse(content);
|
|
22
|
+
delete manifest[LibSource.manifestKey];
|
|
23
|
+
return JSON.stringify(manifest);
|
|
24
|
+
}
|
|
25
|
+
async computeHash() {
|
|
26
|
+
const files = (await this.#lib.workspace.listGitFiles([`libs/${this.#lib.name}`], { untracked: true })).filter((file) => this.#isHashed(file));
|
|
27
|
+
const hasher = new Bun.CryptoHasher("sha256");
|
|
28
|
+
for (const file of files) {
|
|
29
|
+
hasher.update(file);
|
|
30
|
+
hasher.update("\x00");
|
|
31
|
+
hasher.update(await this.#hashableContent(file));
|
|
32
|
+
hasher.update("\x00");
|
|
33
|
+
}
|
|
34
|
+
return hasher.digest("hex").slice(0, 32);
|
|
35
|
+
}
|
|
36
|
+
async read() {
|
|
37
|
+
const manifest = await this.#lib.getPackageJson();
|
|
38
|
+
const akan = manifest[LibSource.manifestKey];
|
|
39
|
+
return akan?.source ?? null;
|
|
40
|
+
}
|
|
41
|
+
async write({ origin, sha }) {
|
|
42
|
+
const [manifest, hash] = await Promise.all([this.#lib.getPackageJson(), this.computeHash()]);
|
|
43
|
+
const akan = manifest[LibSource.manifestKey] ?? {};
|
|
44
|
+
const stamp = { origin, sha, hash, syncedAt: new Date().toISOString() };
|
|
45
|
+
await this.#lib.setPackageJson({ ...manifest, [LibSource.manifestKey]: { ...akan, source: stamp } });
|
|
46
|
+
return stamp;
|
|
47
|
+
}
|
|
48
|
+
async syncStamp({ origin, sha }) {
|
|
49
|
+
const [current, hash] = await Promise.all([this.read(), this.computeHash()]);
|
|
50
|
+
if (current?.origin === origin && current.sha === sha && current.hash === hash)
|
|
51
|
+
return { stamp: current, changed: false };
|
|
52
|
+
return { stamp: await this.write({ origin, sha }), changed: true };
|
|
53
|
+
}
|
|
54
|
+
async status() {
|
|
55
|
+
const [stamp, hash] = await Promise.all([this.read(), this.computeHash()]);
|
|
56
|
+
const drift = !stamp ? "unstamped" : stamp.hash === hash ? "clean" : "drifted";
|
|
57
|
+
return { lib: this.#lib.name, drift, stamp, hash };
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
function formatLibStatuses(statuses) {
|
|
61
|
+
const marks = { clean: "clean ", drifted: "DRIFTED ", unstamped: "unstamped" };
|
|
62
|
+
const sections = [
|
|
63
|
+
"Akan Library Source Status",
|
|
64
|
+
"",
|
|
65
|
+
...statuses.map((status) => {
|
|
66
|
+
const origin = status.stamp ? `${status.stamp.origin}@${status.stamp.sha}` : "no akan.source in package.json";
|
|
67
|
+
return ` ${marks[status.drift]} libs/${status.lib} ${origin}`;
|
|
68
|
+
}),
|
|
69
|
+
"",
|
|
70
|
+
`drifted: ${statuses.filter((status) => status.drift === "drifted").length} / ${statuses.length}`
|
|
71
|
+
];
|
|
72
|
+
return sections.join(`
|
|
73
|
+
`);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export { LibSource, formatLibStatuses };
|
|
@@ -37,10 +37,10 @@ var resolveMobileTargets = async (app, selection) => {
|
|
|
37
37
|
if (!selection && targets.length === 1)
|
|
38
38
|
return targets;
|
|
39
39
|
if (!selection) {
|
|
40
|
-
const
|
|
41
|
-
if (
|
|
42
|
-
return resolveMobileTargets(app,
|
|
43
|
-
throw new Error(`Multiple mobile targets found for ${app.name}. Pass --target <${
|
|
40
|
+
const choices = await getMobileTargetChoices(app);
|
|
41
|
+
if (choices.length === 1)
|
|
42
|
+
return resolveMobileTargets(app, choices[0]);
|
|
43
|
+
throw new Error(`Multiple mobile targets found for ${app.name}. Pass --target <${choices.join("|")}|all>.`);
|
|
44
44
|
}
|
|
45
45
|
if (selection === "all") {
|
|
46
46
|
if (Object.keys(config.mobile.targets).length > 1)
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
import {
|
|
3
|
+
AppInfo
|
|
4
|
+
} from "./index-qsq3q8fy.js";
|
|
5
|
+
|
|
6
|
+
// pkgs/@akanjs/devkit/slicePlanner.ts
|
|
7
|
+
class SlicePlanner {
|
|
8
|
+
static memberDirs = ["apps", "libs", "pkgs"];
|
|
9
|
+
static toolchainDependencies = [
|
|
10
|
+
"@akanjs/cli",
|
|
11
|
+
"@akanjs/devkit",
|
|
12
|
+
"@biomejs/biome",
|
|
13
|
+
"@types/bun",
|
|
14
|
+
"akanjs",
|
|
15
|
+
"tailwindcss",
|
|
16
|
+
"typescript"
|
|
17
|
+
];
|
|
18
|
+
static akanPackages = ["akanjs", "@akanjs/devkit", "@akanjs/cli"];
|
|
19
|
+
static async#frameworkPeers(workspace) {
|
|
20
|
+
const peers = new Set;
|
|
21
|
+
let found = false;
|
|
22
|
+
for (const akanPackage of SlicePlanner.akanPackages) {
|
|
23
|
+
for (const prefix of ["node_modules", "pkgs"]) {
|
|
24
|
+
const manifestPath = `${prefix}/${akanPackage}/package.json`;
|
|
25
|
+
if (!await workspace.exists(manifestPath))
|
|
26
|
+
continue;
|
|
27
|
+
const manifest = await workspace.readJson(manifestPath);
|
|
28
|
+
for (const peer of Object.keys(manifest.peerDependencies ?? {}))
|
|
29
|
+
peers.add(peer);
|
|
30
|
+
found = true;
|
|
31
|
+
break;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
return found ? peers : null;
|
|
35
|
+
}
|
|
36
|
+
static typesPackageOf(dependency) {
|
|
37
|
+
return dependency.startsWith("@") ? `@types/${dependency.slice(1).replace("/", "__")}` : `@types/${dependency}`;
|
|
38
|
+
}
|
|
39
|
+
static async pruneDependencies(workspace, rootPackageJson, required) {
|
|
40
|
+
const peers = await SlicePlanner.#frameworkPeers(workspace);
|
|
41
|
+
const { workspaces: _workspaces, ...rest } = rootPackageJson;
|
|
42
|
+
if (!peers)
|
|
43
|
+
return {
|
|
44
|
+
packageJson: rest,
|
|
45
|
+
pruned: [],
|
|
46
|
+
warnings: [`dependencies carried whole \u2014 none of ${SlicePlanner.akanPackages.join(", ")} is installed`]
|
|
47
|
+
};
|
|
48
|
+
const keep = new Set([...SlicePlanner.toolchainDependencies, ...peers, ...required]);
|
|
49
|
+
for (const dependency of [...keep])
|
|
50
|
+
keep.add(SlicePlanner.typesPackageOf(dependency));
|
|
51
|
+
const pick = (entries) => Object.fromEntries(Object.entries(entries ?? {}).filter(([name]) => keep.has(name)));
|
|
52
|
+
const patched = rootPackageJson.patchedDependencies ?? {};
|
|
53
|
+
const packageJson = {
|
|
54
|
+
...rest,
|
|
55
|
+
dependencies: pick(rootPackageJson.dependencies),
|
|
56
|
+
devDependencies: pick(rootPackageJson.devDependencies),
|
|
57
|
+
...Object.keys(patched).length ? {
|
|
58
|
+
patchedDependencies: Object.fromEntries(Object.entries(patched).filter(([spec]) => keep.has(spec.slice(0, spec.lastIndexOf("@")))))
|
|
59
|
+
} : {}
|
|
60
|
+
};
|
|
61
|
+
const pruned = Object.keys({ ...rootPackageJson.dependencies, ...rootPackageJson.devDependencies }).filter((name) => !keep.has(name)).sort();
|
|
62
|
+
return { packageJson, pruned, warnings: [] };
|
|
63
|
+
}
|
|
64
|
+
#app;
|
|
65
|
+
constructor(app) {
|
|
66
|
+
this.#app = app;
|
|
67
|
+
}
|
|
68
|
+
async#trackedFiles(paths) {
|
|
69
|
+
return await this.#app.workspace.listGitFiles(paths);
|
|
70
|
+
}
|
|
71
|
+
async#untrackedFiles(paths) {
|
|
72
|
+
const [tracked, all] = await Promise.all([
|
|
73
|
+
this.#app.workspace.listGitFiles(paths),
|
|
74
|
+
this.#app.workspace.listGitFiles(paths, { untracked: true })
|
|
75
|
+
]);
|
|
76
|
+
const trackedSet = new Set(tracked);
|
|
77
|
+
return all.filter((file) => !trackedSet.has(file));
|
|
78
|
+
}
|
|
79
|
+
#isMemberFile(file) {
|
|
80
|
+
return SlicePlanner.memberDirs.includes(file.split("/")[0] ?? "");
|
|
81
|
+
}
|
|
82
|
+
static #requiredDependencies(appInfo) {
|
|
83
|
+
const scanResults = [
|
|
84
|
+
appInfo.getScanResult(),
|
|
85
|
+
...[...appInfo.getLibInfos().values()].map((lib) => lib.getScanResult())
|
|
86
|
+
];
|
|
87
|
+
return new Set([
|
|
88
|
+
...scanResults.flatMap((scanResult) => [
|
|
89
|
+
...scanResult.dependencies,
|
|
90
|
+
...scanResult.devDependencies,
|
|
91
|
+
...scanResult.pkgDeps
|
|
92
|
+
])
|
|
93
|
+
]);
|
|
94
|
+
}
|
|
95
|
+
async#patchWarnings(packageJson) {
|
|
96
|
+
const patchedDependencies = packageJson.patchedDependencies ?? {};
|
|
97
|
+
const missing = (await Promise.all(Object.entries(patchedDependencies).map(async ([spec, patchPath]) => await this.#app.workspace.exists(patchPath) ? null : `${spec} -> ${patchPath}`))).filter((entry) => !!entry);
|
|
98
|
+
return missing.length ? [`patchedDependencies references a missing patch file: ${missing.join(", ")}`] : [];
|
|
99
|
+
}
|
|
100
|
+
async plan() {
|
|
101
|
+
const appInfo = await AppInfo.fromExecutor(this.#app);
|
|
102
|
+
const libs = appInfo.getLibs();
|
|
103
|
+
const slicePaths = [`apps/${this.#app.name}`, ...libs.map((lib) => `libs/${lib}`)];
|
|
104
|
+
const [appFiles, allTracked, untracked, rootPackageJson] = await Promise.all([
|
|
105
|
+
this.#trackedFiles([`apps/${this.#app.name}`]),
|
|
106
|
+
this.#trackedFiles(["."]),
|
|
107
|
+
this.#untrackedFiles(slicePaths),
|
|
108
|
+
this.#app.workspace.getPackageJson()
|
|
109
|
+
]);
|
|
110
|
+
const libFiles = Object.fromEntries(await Promise.all(libs.map(async (lib) => [lib, await this.#trackedFiles([`libs/${lib}`])])));
|
|
111
|
+
const rootFiles = allTracked.filter((file) => !this.#isMemberFile(file));
|
|
112
|
+
const required = SlicePlanner.#requiredDependencies(appInfo);
|
|
113
|
+
const {
|
|
114
|
+
packageJson,
|
|
115
|
+
pruned,
|
|
116
|
+
warnings: manifestWarnings
|
|
117
|
+
} = await SlicePlanner.pruneDependencies(this.#app.workspace, rootPackageJson, required);
|
|
118
|
+
const warnings = [
|
|
119
|
+
...untracked.length ? [`${untracked.length} untracked file(s) under the slice paths: ${untracked.join(", ")}`] : [],
|
|
120
|
+
...rootPackageJson.workspaces ? ["root `workspaces` dropped \u2014 a slice consumes akanjs from the registry"] : [],
|
|
121
|
+
...manifestWarnings,
|
|
122
|
+
...await this.#patchWarnings(rootPackageJson)
|
|
123
|
+
];
|
|
124
|
+
return {
|
|
125
|
+
app: this.#app.name,
|
|
126
|
+
libs,
|
|
127
|
+
appFiles,
|
|
128
|
+
libFiles,
|
|
129
|
+
rootFiles,
|
|
130
|
+
packageJson,
|
|
131
|
+
requiredDependencies: [...required].sort(),
|
|
132
|
+
unusedDependencies: pruned,
|
|
133
|
+
warnings
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
var rootEntriesOf = (rootFiles) => [...new Set(rootFiles.map((file) => file.split("/")[0] ?? file))].sort();
|
|
138
|
+
function formatSlicePlan(plan) {
|
|
139
|
+
const libCounts = Object.entries(plan.libFiles).map(([lib, files]) => ` - libs/${lib}: ${files.length} files`);
|
|
140
|
+
const sections = [
|
|
141
|
+
"Akan Slice Plan",
|
|
142
|
+
`app: ${plan.app} (apps/${plan.app}: ${plan.appFiles.length} files)`,
|
|
143
|
+
`libs: ${plan.libs.length ? plan.libs.join(", ") : "(none)"}`,
|
|
144
|
+
...libCounts,
|
|
145
|
+
`workspace shell: ${plan.rootFiles.length} files across ${rootEntriesOf(plan.rootFiles).join(", ")}`,
|
|
146
|
+
"",
|
|
147
|
+
`Root dependencies this slice does not use (${plan.unusedDependencies.length}) \u2014 pruned:`,
|
|
148
|
+
"",
|
|
149
|
+
...plan.unusedDependencies.length ? plan.unusedDependencies.map((dep) => ` - ${dep}`) : [" (none)"],
|
|
150
|
+
"",
|
|
151
|
+
`Warnings (${plan.warnings.length}):`,
|
|
152
|
+
"",
|
|
153
|
+
...plan.warnings.length ? plan.warnings.map((warning) => ` - ${warning}`) : [" (none)"]
|
|
154
|
+
];
|
|
155
|
+
return sections.join(`
|
|
156
|
+
`);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
export { SlicePlanner, formatSlicePlan };
|
|
@@ -2,6 +2,6 @@
|
|
|
2
2
|
// pkgs/@akanjs/devkit/getDirname.ts
|
|
3
3
|
import path from "path";
|
|
4
4
|
import { fileURLToPath } from "url";
|
|
5
|
-
var
|
|
5
|
+
var getDirname2 = (url) => path.dirname(fileURLToPath(url));
|
|
6
6
|
|
|
7
|
-
export {
|
|
7
|
+
export { getDirname2 };
|
|
@@ -2,16 +2,16 @@
|
|
|
2
2
|
import {
|
|
3
3
|
runner,
|
|
4
4
|
script
|
|
5
|
-
} from "./index-
|
|
5
|
+
} from "./index-znynzt5w.js";
|
|
6
6
|
import {
|
|
7
|
-
|
|
8
|
-
} from "./index-
|
|
7
|
+
FileSys
|
|
8
|
+
} from "./index-q0y2jq9j.js";
|
|
9
9
|
import {
|
|
10
|
-
|
|
11
|
-
} from "./index-
|
|
10
|
+
PkgExecutor
|
|
11
|
+
} from "./index-qsq3q8fy.js";
|
|
12
12
|
import {
|
|
13
|
-
|
|
14
|
-
} from "./index-
|
|
13
|
+
TypeScriptDependencyScanner2
|
|
14
|
+
} from "./index-kcxmv48c.js";
|
|
15
15
|
|
|
16
16
|
// pkgs/@akanjs/cli/package/package.runner.ts
|
|
17
17
|
import path2 from "path";
|
|
@@ -140,7 +140,7 @@ class PackageRunner extends runner("package") {
|
|
|
140
140
|
await workspace.setPkgTsPaths(pkgName);
|
|
141
141
|
}
|
|
142
142
|
async removePackage(pkg) {
|
|
143
|
-
await pkg.workspace.
|
|
143
|
+
await pkg.workspace.removeDir(`pkgs/${pkg.name}`);
|
|
144
144
|
await pkg.workspace.unsetPkgTsPaths(pkg.name);
|
|
145
145
|
}
|
|
146
146
|
async scanSync(pkg) {
|
|
@@ -150,7 +150,7 @@ class PackageRunner extends runner("package") {
|
|
|
150
150
|
async buildPackage(pkg) {
|
|
151
151
|
await $`rm -rf ${pkg.dist.cwdPath}`;
|
|
152
152
|
await pkg.dist.mkdir(pkg.dist.cwdPath);
|
|
153
|
-
const scanner = await
|
|
153
|
+
const scanner = await TypeScriptDependencyScanner2.from(pkg);
|
|
154
154
|
const { npmDeps, npmDevDeps, missingDeps } = await scanner.getPackageBuildDependencies(pkg.name);
|
|
155
155
|
const packageRuntimeDependencies = {
|
|
156
156
|
"@akanjs/devkit": ["tailwind-scrollbar"]
|
|
@@ -163,13 +163,17 @@ class PackageRunner extends runner("package") {
|
|
|
163
163
|
"tailwind-scrollbar"
|
|
164
164
|
].filter((dep) => dep !== "akanjs" && dep !== "@akanjs/devkit");
|
|
165
165
|
}
|
|
166
|
-
const
|
|
166
|
+
const packageBundledRuntimeDependencies = {
|
|
167
|
+
"@akanjs/cli": ["@akanjs/devkit"],
|
|
168
|
+
akanjs: ["use-agentic"]
|
|
169
|
+
};
|
|
170
|
+
const bundledRuntimeDeps = new Set(packageBundledRuntimeDependencies[pkg.name] ?? []);
|
|
167
171
|
const forcedRuntimeDeps = packageRuntimeDependencies[pkg.name] ?? [];
|
|
168
172
|
const forcedRuntimeDevDeps = packageRuntimeDevDependencies[pkg.name] ?? [];
|
|
169
173
|
const [rootPackageJson, pkgJson] = await Promise.all([pkg.workspace.getPackageJson(), pkg.getPackageJson()]);
|
|
170
174
|
const optionalPeerDeps = new Set(Object.entries(pkgJson.peerDependenciesMeta ?? {}).filter(([, meta]) => meta.optional).map(([dep]) => dep));
|
|
171
175
|
const packageRuntimeDeps = [...new Set([...npmDeps, ...forcedRuntimeDeps])].filter((dep) => !optionalPeerDeps.has(dep) && !bundledRuntimeDeps.has(dep));
|
|
172
|
-
const packageRuntimeDevDeps = [...new Set([...npmDevDeps, ...forcedRuntimeDevDeps])].filter((dep) => !optionalPeerDeps.has(dep));
|
|
176
|
+
const packageRuntimeDevDeps = [...new Set([...npmDevDeps, ...forcedRuntimeDevDeps])].filter((dep) => !optionalPeerDeps.has(dep) && !bundledRuntimeDeps.has(dep));
|
|
173
177
|
const rootDeps = { ...rootPackageJson.dependencies, ...rootPackageJson.devDependencies };
|
|
174
178
|
const missingForcedDeps = forcedRuntimeDeps.filter((dep) => !rootDeps[dep]);
|
|
175
179
|
const missingForcedDevDeps = forcedRuntimeDevDeps.filter((dep) => !rootDeps[dep]);
|
|
@@ -268,7 +272,7 @@ class PackageRunner extends runner("package") {
|
|
|
268
272
|
}
|
|
269
273
|
if (!pkgJson.version)
|
|
270
274
|
throw new Error(`[package] dist package version is missing for ${pkg.name}`);
|
|
271
|
-
if (
|
|
275
|
+
if (pkgJson.publishConfig?.access !== "public") {
|
|
272
276
|
throw new Error(`[package] ${pkg.name} must publish with publishConfig.access=public`);
|
|
273
277
|
}
|
|
274
278
|
if (!await Bun.file(`${pkg.dist.cwdPath}/README.md`).exists()) {
|
|
@@ -1,22 +1,22 @@
|
|
|
1
1
|
// @bun
|
|
2
2
|
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
AiSession
|
|
7
|
-
} from "./index-0cj2zxbm.js";
|
|
3
|
+
runner,
|
|
4
|
+
script
|
|
5
|
+
} from "./index-znynzt5w.js";
|
|
8
6
|
import {
|
|
9
|
-
createPassedPrimitiveReport,
|
|
10
7
|
generatedFilesForSync,
|
|
8
|
+
createPassedPrimitiveReport,
|
|
11
9
|
scalarChangedFiles
|
|
12
|
-
} from "./index-
|
|
10
|
+
} from "./index-fc1bh0a7.js";
|
|
11
|
+
import {
|
|
12
|
+
AiSession
|
|
13
|
+
} from "./index-c69j78kk.js";
|
|
13
14
|
import {
|
|
14
15
|
Prompter
|
|
15
|
-
} from "./index-
|
|
16
|
+
} from "./index-h7yw2z9n.js";
|
|
16
17
|
import {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
} from "./index-kdh76j26.js";
|
|
18
|
+
pluralizeName
|
|
19
|
+
} from "./index-nz8prx9g.js";
|
|
20
20
|
|
|
21
21
|
// pkgs/@akanjs/cli/scalar/scalar.prompt.ts
|
|
22
22
|
import { input } from "@inquirer/prompts";
|
|
@@ -192,9 +192,9 @@ class ScalarRunner extends runner("scalar") {
|
|
|
192
192
|
const { request, validate } = await prompt.requestUpdateDictonaryWithInstruction();
|
|
193
193
|
await session.writeTypescripts(request, sys, { validate });
|
|
194
194
|
for (const scalarName of followingScalarNames) {
|
|
195
|
-
const
|
|
196
|
-
const { request
|
|
197
|
-
await session.writeTypescripts(
|
|
195
|
+
const prompt = new ScalarPrompt(sys, scalarName);
|
|
196
|
+
const { request, validate } = await prompt.requestUpdateDictonaryWithFollowing();
|
|
197
|
+
await session.writeTypescripts(request, sys, { validate });
|
|
198
198
|
}
|
|
199
199
|
}
|
|
200
200
|
}
|