@akanjs/cli 3.0.0-alpha.8 → 3.0.0-alpha.81
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-pwc6d6yk.js} +3 -5
- package/{agent.command-pggr92jj.js → agent.command-180hh0ye.js} +11 -12
- package/{application.command-692yap1d.js → application.command-4fq5pmdd.js} +59 -35
- package/{applicationBuildRunner-ha3y8ew8.js → applicationBuildRunner-tavpx3fv.js} +22 -20
- package/{applicationReleasePackager-gg8ccbeh.js → applicationReleasePackager-ktjt0erc.js} +8 -9
- package/buildBatch.proc.js +12 -13
- package/capacitorApp-kwa67kzs.js +12 -0
- package/{cloud.command-wqfsyzv2.js → cloud.command-wm3mtfve.js} +15 -17
- package/commandManifest.json +1 -1
- package/{context.command-9bxtdn0w.js → context.command-dk2m2sjx.js} +19 -22
- package/dependencyScanner-c64m6fxp.js +8 -0
- package/getDirname-dr3jz1xg.js +7 -0
- package/{guideline.command-nfqahxex.js → guideline.command-w6ddv13r.js} +16 -17
- package/guidelines/agentRule/agentRule.generate.json +31 -0
- package/guidelines/agentRule/agentRule.instruction.md +525 -0
- package/guidelines/conventions/conventions.generate.json +25 -0
- package/guidelines/conventions/conventions.instruction.md +847 -0
- 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/queryRule/queryRule.generate.json +31 -0
- package/guidelines/queryRule/queryRule.instruction.md +143 -0
- package/guidelines/runtimeRule/runtimeRule.generate.json +25 -0
- package/guidelines/runtimeRule/runtimeRule.instruction.md +176 -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.generate.json +24 -0
- package/guidelines/workspaceOnboarding/workspaceOnboarding.instruction.md +263 -0
- package/guidelines/workspaceRecipes/workspaceRecipes.generate.json +33 -0
- package/guidelines/workspaceRecipes/workspaceRecipes.instruction.md +402 -0
- package/incrementalBuilder.proc.js +21 -22
- package/{index-4hek879p.js → index-1kzsn94d.js} +1 -1
- package/{index-p3f4q532.js → index-1tgp56ke.js} +31 -30
- package/index-3d9y066c.js +76 -0
- package/{index-76rn3g2c.js → index-47pj3aee.js} +4 -4
- package/{index-gex7c8kd.js → index-5n0hf8r9.js} +65 -38
- package/{index-mssqn2sq.js → index-5y7qba1c.js} +79 -33
- package/index-6wwzs1bc.js +7 -0
- package/{index-wnp7hwq7.js → index-92zztqy1.js} +7 -7
- package/{index-fgc8r6dj.js → index-a5vmm6x4.js} +3 -1
- package/{index-azv0xjb5.js → index-a8h184wr.js} +15 -11
- package/{index-67546d0j.js → index-ayy5ecax.js} +1 -1
- package/{index-xhgtkekh.js → index-b2nt0w0k.js} +27 -27
- package/{index-xys926f2.js → index-by5gpp8x.js} +4 -4
- package/{index-bz2sfzzt.js → index-cd5x18qh.js} +32 -32
- package/{index-bjpxzr6s.js → index-ctphds8v.js} +1 -1
- package/{index-w6wbb612.js → index-dq6wq1tv.js} +94 -61
- package/{index-6rhabeev.js → index-ft1sfjz0.js} +36 -25
- package/{index-7myvn0f0.js → index-h7yw2z9n.js} +7 -7
- package/{index-5pmx7bkg.js → index-j9vnq8tr.js} +18 -18
- package/{index-vg0sj9nc.js → index-k1n0h7dk.js} +840 -201
- package/{index-vtj3zps1.js → index-k86zc21w.js} +57 -57
- package/{index-5dw57f0d.js → index-m7e0f1sy.js} +155 -76
- package/index-m9c7k0gm.js +159 -0
- package/{index-46tjzh6s.js → index-mfm35dhh.js} +29 -29
- package/{index-xjd3rqzj.js → index-n68jx79w.js} +6 -15
- package/{index-ztpw544k.js → index-qcracvc9.js} +8 -8
- package/{index-2c3e2xh8.js → index-saheq2bs.js} +4 -4
- package/{index-gmy45vz2.js → index-v0s24t8j.js} +14 -14
- package/{index-0cj2zxbm.js → index-wet2ytnr.js} +12 -11
- package/{index-j9cxndc0.js → index-x23688ar.js} +12 -7
- package/{index-a1e0j63x.js → index-xxe90kqy.js} +58 -25
- package/{index-js368gk9.js → index-ypvdw8nr.js} +13 -13
- package/{index-qb61h0k7.js → index-z3c9mmw4.js} +1098 -1360
- package/index.js +22 -24
- package/{library.command-md9715jz.js → library.command-wpedct6c.js} +11 -9
- package/{localRegistry.command-exkbamyj.js → localRegistry.command-gk773cte.js} +20 -22
- package/{module.command-w5aaddxk.js → module.command-8n4kct3e.js} +13 -15
- package/{package.command-yfkrcy0z.js → package.command-fcbd0b1d.js} +8 -9
- package/package.json +5 -7
- package/{page.command-echbavp4.js → page.command-x4379grq.js} +7 -8
- package/{primitive.command-9fbhspw2.js → primitive.command-8etmnqhq.js} +13 -15
- package/{quality.command-3pnt9yep.js → quality.command-hfx7z8yr.js} +226 -104
- package/recipeScanner-fpagtgc1.js +11 -0
- package/{repair.command-carj4vax.js → repair.command-j0fs5qkz.js} +12 -13
- package/{routeSourceValidator-e4jmbfcx.js → routeSourceValidator-ze6x894c.js} +0 -2
- package/{scalar.command-51ryzypc.js → scalar.command-2emk89eh.js} +11 -13
- package/subspace.command-3w3s1zas.js +714 -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 +6 -6
- package/templates/crudPages/[__model__Id]/page.tsx +10 -13
- package/templates/crudPages/new/page.tsx +6 -6
- 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 +1 -1
- package/templates/lib/srv.ts +6 -2
- package/templates/module/__Model__.Util.tsx +1 -1
- package/templates/module/__Model__.Zone.tsx +3 -5
- 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/AGENTS.md.template +4 -972
- package/templates/workspaceRoot/CLAUDE.md.template +19 -0
- package/templates/workspaceRoot/biome.json.template +4 -244
- 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-91wmvm8k.js → workflow.command-cvpmzwjg.js} +21 -23
- package/{workspace.command-wa10mfd9.js → workspace.command-4ztb4fdh.js} +108 -91
- package/capacitorApp-p0z5yab2.js +0 -60
- package/dependencyScanner-f6grrep3.js +0 -9
- package/index-mxvakhsm.js +0 -66
- package/index-r24hmh0q.js +0 -4
- package/recipeScanner-tghkzrrt.js +0 -12
- package/templates/workspaceRoot/.cursor/rules/akan-page-routing.mdc.template +0 -43
- package/templates/workspaceRoot/.cursor/rules/akan-sync-conventions.mdc.template +0 -34
- package/templates/workspaceRoot/.cursor/rules/application-test-commands.mdc.template +0 -16
- package/templates/workspaceRoot/.cursor/rules/change-scope.mdc.template +0 -12
- package/templates/workspaceRoot/.cursor/rules/client-server-boundaries.mdc.template +0 -18
- package/templates/workspaceRoot/.cursor/rules/coding-comments.mdc.template +0 -25
- package/templates/workspaceRoot/.cursor/rules/coding-style.mdc.template +0 -44
- package/templates/workspaceRoot/.cursor/rules/domain-module-conventions.mdc.template +0 -17
- package/templates/workspaceRoot/.cursor/rules/format-lint.mdc.template +0 -12
- package/templates/workspaceRoot/.cursor/rules/lint-enforced-rules.mdc.template +0 -19
- package/templates/workspaceRoot/.cursor/rules/module-file-playbook.mdc.template +0 -62
- package/templates/workspaceRoot/.cursor/rules/naming-conventions.mdc.template +0 -15
- package/templates/workspaceRoot/.cursor/rules/react-component-style.mdc.template +0 -21
- package/templates/workspaceRoot/.cursor/rules/repo-overview.mdc.template +0 -17
- package/templates/workspaceRoot/.cursor/rules/scalar-modeling.mdc.template +0 -99
- package/templates/workspaceRoot/.cursor/rules/secrets-and-env.mdc.template +0 -13
- package/templates/workspaceRoot/.cursor/rules/service-signal-conventions.mdc.template +0 -83
- package/templates/workspaceRoot/.cursor/rules/srvkit-adapters-and-guards.mdc.template +0 -50
- package/templates/workspaceRoot/.cursor/rules/ssr-first.mdc.template +0 -59
- package/templates/workspaceRoot/.cursor/rules/typescript-imports.mdc.template +0 -16
- package/typeChecker-kravn7ns.js +0 -8
- /package/{index-0wae5ebk.js → index-meh558jy.js} +0 -0
- /package/{index-ss469dec.js → index-nz8prx9g.js} +0 -0
|
@@ -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)
|
|
@@ -1,26 +1,29 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import {
|
|
3
|
-
AkanContextAnalyzer
|
|
4
|
-
} from "./index-mssqn2sq.js";
|
|
5
|
-
import {
|
|
6
|
-
Prompter
|
|
7
|
-
} from "./index-7myvn0f0.js";
|
|
8
2
|
import {
|
|
9
3
|
runner,
|
|
10
4
|
script
|
|
11
|
-
} from "./index-
|
|
5
|
+
} from "./index-ft1sfjz0.js";
|
|
12
6
|
import {
|
|
13
|
-
AGENT_BLOCK_END,
|
|
14
7
|
AGENT_BLOCK_START,
|
|
15
|
-
|
|
16
|
-
|
|
8
|
+
AGENT_BLOCK_END,
|
|
9
|
+
stampBlockVersion,
|
|
10
|
+
readDevkitVersion,
|
|
11
|
+
upsertAgentBlock,
|
|
17
12
|
renderRecipeEntries,
|
|
18
|
-
|
|
19
|
-
|
|
13
|
+
CLAUDE_COMMENT_RULE,
|
|
14
|
+
AppExecutor,
|
|
15
|
+
LibExecutor
|
|
16
|
+
} from "./index-k1n0h7dk.js";
|
|
17
|
+
import {
|
|
18
|
+
collectRecipeSources2,
|
|
19
|
+
scanRecipes2
|
|
20
|
+
} from "./index-by5gpp8x.js";
|
|
20
21
|
import {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
22
|
+
AkanContextAnalyzer
|
|
23
|
+
} from "./index-5y7qba1c.js";
|
|
24
|
+
import {
|
|
25
|
+
Prompter
|
|
26
|
+
} from "./index-h7yw2z9n.js";
|
|
24
27
|
|
|
25
28
|
// pkgs/@akanjs/cli/agent/agent.script.ts
|
|
26
29
|
import { Logger as Logger2 } from "akanjs/common";
|
|
@@ -74,8 +77,8 @@ Keep a sample only while you are still learning its pattern; delete it once your
|
|
|
74
77
|
`;
|
|
75
78
|
};
|
|
76
79
|
var renderRecipeIndex = async (workspace) => {
|
|
77
|
-
const sources = await
|
|
78
|
-
const recipes =
|
|
80
|
+
const sources = await collectRecipeSources2(`${workspace.workspaceRoot}/pkgs/akanjs/ui`, "akanjs/ui", "recipe");
|
|
81
|
+
const recipes = scanRecipes2(sources);
|
|
79
82
|
const scopeIndexPointer = `App and lib recipes are **not** listed here. Each app/lib carries its own generated index \u2014
|
|
80
83
|
\`apps/<app>/AGENTS.md\` / \`libs/<lib>/AGENTS.md\` (\`## Recipes In Scope\`) \u2014 regenerated by \`akan sync\` and
|
|
81
84
|
verified by \`akan lint\`. When working inside an app or lib, consult that file before consuming or authoring a look.`;
|
|
@@ -87,15 +90,14 @@ ${scopeIndexPointer}
|
|
|
87
90
|
`;
|
|
88
91
|
return `## Recipes
|
|
89
92
|
|
|
90
|
-
Framework UI recipes (Tailwind-variant look factories), importable from every app and lib
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
the
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
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.
|
|
99
101
|
|
|
100
102
|
${renderRecipeEntries(recipes)}
|
|
101
103
|
|
|
@@ -103,19 +105,33 @@ ${scopeIndexPointer}
|
|
|
103
105
|
|
|
104
106
|
`;
|
|
105
107
|
};
|
|
108
|
+
var renderGuides = async (context) => {
|
|
109
|
+
const conventions = (await Prompter.getInstruction("conventions")).trim();
|
|
110
|
+
if (context.pkgs.some((pkg) => pkg.name === "akanjs"))
|
|
111
|
+
return conventions;
|
|
112
|
+
const onboarding = (await Prompter.getInstruction("workspaceOnboarding")).trim();
|
|
113
|
+
const appName = context.apps[0]?.name ?? "app";
|
|
114
|
+
return `${conventions}
|
|
115
|
+
|
|
116
|
+
${onboarding.replaceAll("<%= appName %>", appName)}`;
|
|
117
|
+
};
|
|
106
118
|
var renderManagedBlock = async (workspace) => {
|
|
107
119
|
const context = await AkanContextAnalyzer.analyze(workspace);
|
|
108
120
|
const frameworkGuide = await Prompter.getInstruction("framework");
|
|
109
121
|
const appNames = context.apps.map((app) => app.name);
|
|
110
122
|
const sampleCleanup = await renderSampleCleanup(workspace, appNames);
|
|
111
123
|
const recipeIndex = await renderRecipeIndex(workspace);
|
|
112
|
-
|
|
124
|
+
const guides = await renderGuides(context);
|
|
125
|
+
const version = await readDevkitVersion();
|
|
126
|
+
const block = `## Workspace
|
|
113
127
|
|
|
114
128
|
- Repo: ${context.repoName}
|
|
115
129
|
- Apps: ${context.apps.map((app) => app.name).join(", ") || "none"}
|
|
116
130
|
- Libraries: ${context.libs.map((lib) => lib.name).join(", ") || "none"}
|
|
117
131
|
- Packages: ${context.pkgs.map((pkg) => pkg.name).join(", ") || "none"}
|
|
118
132
|
|
|
133
|
+
${guides}
|
|
134
|
+
|
|
119
135
|
${sampleCleanup}## Akan Module Abstracts
|
|
120
136
|
|
|
121
137
|
- Before changing a domain, service, or scalar module, read its \`*.abstract.md\` file first.
|
|
@@ -131,15 +147,12 @@ If generated output is stale or broken, update the owning source file and run \`
|
|
|
131
147
|
|
|
132
148
|
${recipeIndex}## MCP Workflow Policy
|
|
133
149
|
|
|
134
|
-
- Prefer Akan
|
|
135
|
-
-
|
|
136
|
-
-
|
|
137
|
-
-
|
|
138
|
-
-
|
|
139
|
-
-
|
|
140
|
-
- 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.
|
|
141
|
-
- For compound requests, split the request into workflows and apply each \`planPath\` in order, such as \`create-module\` followed by \`add-field\`.
|
|
142
|
-
- **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.
|
|
143
156
|
|
|
144
157
|
## Validation
|
|
145
158
|
|
|
@@ -148,7 +161,19 @@ ${context.validationCommands.map((command) => `- \`${command}\``).join(`
|
|
|
148
161
|
|
|
149
162
|
## Framework Guide
|
|
150
163
|
|
|
151
|
-
${frameworkGuide.trim()}
|
|
164
|
+
${frameworkGuide.trim()}
|
|
165
|
+
|
|
166
|
+
## Before You Finish
|
|
167
|
+
|
|
168
|
+
1. \`bun run akan lint <appName>\` \u2014 Tailwind class order, \`Err\`, \`console\`, \`#private\` scope, unused imports.
|
|
169
|
+
2. \`bun run akan typecheck <appName>\` \u2014 server/client boundary violations.
|
|
170
|
+
3. \`bun run akan sync <appName>\` if you added, renamed, or deleted any file.
|
|
171
|
+
4. Did you write or change a \`.tsx\` file? \`bun run akan quality ssr\` \u2014 did the server share hold, and did you add
|
|
172
|
+
a \`"use client"\` you cannot justify?
|
|
173
|
+
5. Re-read the file you wrote against its section above.
|
|
174
|
+
6. Did you add a comment? Delete it unless it documents an external constraint or a security decision.
|
|
175
|
+
7. Did behavior or an invariant change? Update the module's \`*.abstract.md\`.`;
|
|
176
|
+
return version ? stampBlockVersion(block, version) : block;
|
|
152
177
|
};
|
|
153
178
|
var renderAgentsMd = async (workspace, existing) => {
|
|
154
179
|
const block = await renderManagedBlock(workspace);
|
|
@@ -171,6 +196,8 @@ var renderClaudeMd = async (workspace) => {
|
|
|
171
196
|
return `# ${context.repoName} \u2014 Claude Code Guide
|
|
172
197
|
|
|
173
198
|
@AGENTS.md
|
|
199
|
+
|
|
200
|
+
${CLAUDE_COMMENT_RULE}
|
|
174
201
|
`;
|
|
175
202
|
};
|
|
176
203
|
var renderCursorRule = () => `---
|
|
@@ -218,7 +245,7 @@ class AgentRunner extends runner("agent") {
|
|
|
218
245
|
written.push(`${exec.type}s/${exec.name}/AGENTS.md`);
|
|
219
246
|
} catch (error) {
|
|
220
247
|
const message = error instanceof Error ? error.message : String(error);
|
|
221
|
-
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");
|
|
222
249
|
}
|
|
223
250
|
};
|
|
224
251
|
for (const name of libNames)
|
|
@@ -1,36 +1,45 @@
|
|
|
1
1
|
// @bun
|
|
2
2
|
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
extractBlockVersion,
|
|
4
|
+
readDevkitVersion,
|
|
5
|
+
rootAllowedFiles,
|
|
6
|
+
rootAllowedDirs,
|
|
7
|
+
isScannedRootEntry,
|
|
7
8
|
AppExecutor,
|
|
8
|
-
LibExecutor
|
|
9
|
-
|
|
10
|
-
appRootAllowedFiles,
|
|
11
|
-
isScannedAppRootEntry
|
|
12
|
-
} from "./index-vg0sj9nc.js";
|
|
13
|
-
import {
|
|
14
|
-
collectRecipeSources,
|
|
15
|
-
findInlineRecipeDuplicates,
|
|
16
|
-
scanRecipes
|
|
17
|
-
} from "./index-xys926f2.js";
|
|
9
|
+
LibExecutor
|
|
10
|
+
} from "./index-k1n0h7dk.js";
|
|
18
11
|
import {
|
|
19
12
|
FileSys
|
|
20
|
-
} from "./index-
|
|
13
|
+
} from "./index-ayy5ecax.js";
|
|
14
|
+
import {
|
|
15
|
+
collectRecipeSources2,
|
|
16
|
+
scanRecipes2,
|
|
17
|
+
findInlineRecipeDuplicates2
|
|
18
|
+
} from "./index-by5gpp8x.js";
|
|
19
|
+
import {
|
|
20
|
+
workflowRunArtifactPath,
|
|
21
|
+
workflowSyncDir
|
|
22
|
+
} from "./index-saheq2bs.js";
|
|
21
23
|
|
|
22
24
|
// pkgs/@akanjs/devkit/akanContext.ts
|
|
23
25
|
import { readdir } from "fs/promises";
|
|
24
26
|
import path from "path";
|
|
25
27
|
import { capitalize } from "akanjs/common";
|
|
26
|
-
var
|
|
28
|
+
var guidelineResourceUri = (name) => `akan://guidelines/${name}`;
|
|
29
|
+
var staticResourceList = [
|
|
27
30
|
{ uri: "akan://docs/framework", name: "Akan framework guide", mimeType: "text/markdown" },
|
|
28
|
-
{ uri: "akan://guidelines/framework", name: "Framework guideline", mimeType: "text/markdown" },
|
|
29
|
-
{ uri: "akan://guidelines/modelSignal", name: "Model signal guideline", mimeType: "text/markdown" },
|
|
30
31
|
{ uri: "akan://workspace/summary", name: "Workspace summary", mimeType: "application/json" },
|
|
31
32
|
{ uri: "akan://workspace/apps", name: "Workspace apps", mimeType: "application/json" },
|
|
32
33
|
{ uri: "akan://workspace/modules", name: "Workspace modules", mimeType: "application/json" }
|
|
33
34
|
];
|
|
35
|
+
var buildResourceList = (guidelineNames) => [
|
|
36
|
+
...staticResourceList,
|
|
37
|
+
...guidelineNames.map((name) => ({
|
|
38
|
+
uri: guidelineResourceUri(name),
|
|
39
|
+
name: `${name} guideline`,
|
|
40
|
+
mimeType: "text/markdown"
|
|
41
|
+
}))
|
|
42
|
+
];
|
|
34
43
|
var cursorMcpConfigPath = ".cursor/mcp.json";
|
|
35
44
|
var claudeMcpConfigPath = ".mcp.json";
|
|
36
45
|
var codexMcpConfigPath = ".codex/config.toml";
|
|
@@ -124,7 +133,9 @@ var validationCommands = [
|
|
|
124
133
|
"akan typecheck <app-name>",
|
|
125
134
|
"akan test <app-or-lib-or-pkg>",
|
|
126
135
|
"akan build <app-name>",
|
|
127
|
-
"akan doctor --strict --format json"
|
|
136
|
+
"akan doctor --strict --format json",
|
|
137
|
+
"akan quality scan [--format json]",
|
|
138
|
+
"akan quality ssr [--format json]"
|
|
128
139
|
];
|
|
129
140
|
var unknownGeneratedFilesFreshness = {
|
|
130
141
|
status: "unknown",
|
|
@@ -365,6 +376,29 @@ class AkanContextAnalyzer {
|
|
|
365
376
|
validationCommands
|
|
366
377
|
};
|
|
367
378
|
}
|
|
379
|
+
static async#agentGuideDrift(workspace) {
|
|
380
|
+
const installed = await readDevkitVersion();
|
|
381
|
+
if (!installed)
|
|
382
|
+
return null;
|
|
383
|
+
const content = await safeReadText(path.join(workspace.workspaceRoot, "AGENTS.md"));
|
|
384
|
+
if (content === null)
|
|
385
|
+
return null;
|
|
386
|
+
const stamped = extractBlockVersion(content);
|
|
387
|
+
if (stamped === installed)
|
|
388
|
+
return null;
|
|
389
|
+
const hint = "Re-render the AGENTS.md managed block from the installed framework release.";
|
|
390
|
+
if (!stamped)
|
|
391
|
+
return {
|
|
392
|
+
code: "agent-guide-unstamped",
|
|
393
|
+
message: `AGENTS.md carries no generated-version stamp, so its conventions may predate @akanjs/devkit ${installed}`,
|
|
394
|
+
hint
|
|
395
|
+
};
|
|
396
|
+
return {
|
|
397
|
+
code: "agent-guide-stale",
|
|
398
|
+
message: `AGENTS.md was generated by @akanjs/devkit ${stamped}, but ${installed} is installed`,
|
|
399
|
+
hint
|
|
400
|
+
};
|
|
401
|
+
}
|
|
368
402
|
static async doctor(workspace, {
|
|
369
403
|
strict = false,
|
|
370
404
|
runIdOrPlan = null,
|
|
@@ -377,25 +411,37 @@ class AkanContextAnalyzer {
|
|
|
377
411
|
repairAction("generated", "akan repair generated --app <app-or-lib>", "Refresh generated Akan files.", true),
|
|
378
412
|
repairAction("format", "akan repair format --target <app-or-lib-or-pkg>", "Run the formatter/linter repair path.", true)
|
|
379
413
|
];
|
|
380
|
-
for (const
|
|
381
|
-
const
|
|
382
|
-
for (const entry of await safeReadDir(
|
|
383
|
-
if (!
|
|
414
|
+
for (const sys of [...context.apps, ...context.libs]) {
|
|
415
|
+
const sysPath = path.join(workspace.workspaceRoot, sys.path);
|
|
416
|
+
for (const entry of await safeReadDir(sysPath)) {
|
|
417
|
+
if (!isScannedRootEntry(sys.type, entry.name))
|
|
384
418
|
continue;
|
|
385
|
-
const allowed = entry.isDirectory() ?
|
|
419
|
+
const allowed = entry.isDirectory() ? rootAllowedDirs[sys.type].has(entry.name) : rootAllowedFiles[sys.type].has(entry.name);
|
|
386
420
|
if (!allowed) {
|
|
387
|
-
const action = repairAction("module-shape", `akan repair module-shape --app ${
|
|
421
|
+
const action = repairAction("module-shape", `akan repair module-shape --app ${sys.name}`, `Review ${sys.type} root shape and remove or move the unknown entry.`, false);
|
|
388
422
|
diagnostics.push({
|
|
389
423
|
severity: "error",
|
|
390
|
-
code:
|
|
391
|
-
path: `${
|
|
392
|
-
message: `Unexpected ${entry.isDirectory() ? "folder" : "file"} in
|
|
424
|
+
code: `${sys.type}-root-unknown-entry`,
|
|
425
|
+
path: `${sys.path}/${entry.name}`,
|
|
426
|
+
message: `Unexpected ${entry.isDirectory() ? "folder" : "file"} in ${sys.type} root: ${sys.path}/${entry.name}`,
|
|
393
427
|
repairActions: [action]
|
|
394
428
|
});
|
|
395
429
|
repairActions.push(action);
|
|
396
430
|
}
|
|
397
431
|
}
|
|
398
432
|
}
|
|
433
|
+
const agentDrift = await AkanContextAnalyzer.#agentGuideDrift(workspace);
|
|
434
|
+
if (agentDrift) {
|
|
435
|
+
const action = repairAction("generated", "akan agent install agents-md", agentDrift.hint, true);
|
|
436
|
+
diagnostics.push({
|
|
437
|
+
severity: "warning",
|
|
438
|
+
code: agentDrift.code,
|
|
439
|
+
path: "AGENTS.md",
|
|
440
|
+
message: agentDrift.message,
|
|
441
|
+
repairActions: [action]
|
|
442
|
+
});
|
|
443
|
+
repairActions.push(action);
|
|
444
|
+
}
|
|
399
445
|
for (const sys of [...context.apps, ...context.libs]) {
|
|
400
446
|
for (const module of sys.modules) {
|
|
401
447
|
if (!module.abstract.exists) {
|
|
@@ -447,10 +493,10 @@ class AkanContextAnalyzer {
|
|
|
447
493
|
}
|
|
448
494
|
}
|
|
449
495
|
for (const sys of [...context.apps, ...context.libs]) {
|
|
450
|
-
const sources = await
|
|
496
|
+
const sources = await collectRecipeSources2(path.join(workspace.workspaceRoot, sys.path, "ui"), "ui");
|
|
451
497
|
if (sources.length === 0)
|
|
452
498
|
continue;
|
|
453
|
-
const recipes =
|
|
499
|
+
const recipes = scanRecipes2(sources);
|
|
454
500
|
const files = [];
|
|
455
501
|
const glob = new Bun.Glob("**/*.tsx");
|
|
456
502
|
for await (const abs of glob.scan({ cwd: path.join(workspace.workspaceRoot, sys.path), absolute: true })) {
|
|
@@ -461,7 +507,7 @@ class AkanContextAnalyzer {
|
|
|
461
507
|
content: await Bun.file(abs).text().catch(() => "")
|
|
462
508
|
});
|
|
463
509
|
}
|
|
464
|
-
const duplicates =
|
|
510
|
+
const duplicates = findInlineRecipeDuplicates2(recipes, files);
|
|
465
511
|
if (duplicates.length === 0)
|
|
466
512
|
continue;
|
|
467
513
|
const preview = duplicates.slice(0, 3).map((duplicate) => `${path.relative(workspace.workspaceRoot, duplicate.path)}:${duplicate.line}`).join(", ");
|
|
@@ -472,7 +518,7 @@ class AkanContextAnalyzer {
|
|
|
472
518
|
message: `${sys.name}: ${duplicates.length} inline className(s) re-author a recipe fingerprint (${preview}${duplicates.length > 3 ? ", \u2026" : ""}) \u2014 consume the recipe instead.`
|
|
473
519
|
});
|
|
474
520
|
}
|
|
475
|
-
const scanNames = async (uiDirPath, basename) => new Set(
|
|
521
|
+
const scanNames = async (uiDirPath, basename) => new Set(scanRecipes2(await collectRecipeSources2(uiDirPath, "ui", basename)).map((info) => info.name));
|
|
476
522
|
const declaredByImport = new Map;
|
|
477
523
|
declaredByImport.set("akanjs/ui", await scanNames(path.join(workspace.workspaceRoot, "pkgs/akanjs/ui"), "recipe"));
|
|
478
524
|
for (const sys of [...context.apps, ...context.libs])
|
|
@@ -587,4 +633,4 @@ class AkanContextAnalyzer {
|
|
|
587
633
|
}
|
|
588
634
|
}
|
|
589
635
|
|
|
590
|
-
export {
|
|
636
|
+
export { buildResourceList, codexMcpConfigPath, akanMcpInstallTargets, akanMcpInstallConfigPaths, createAkanMcpServer, createAkanCodexMcpServerBlock, upsertCodexMcpServerBlock, renderDoctorText, AkanContextAnalyzer };
|
|
@@ -5,7 +5,7 @@ import * as path from "path";
|
|
|
5
5
|
import chalk from "chalk";
|
|
6
6
|
import * as ts from "typescript";
|
|
7
7
|
|
|
8
|
-
class
|
|
8
|
+
class TypeChecker2 {
|
|
9
9
|
configPath;
|
|
10
10
|
configFile;
|
|
11
11
|
config;
|
|
@@ -143,12 +143,12 @@ ${summary.join(", ")} found${output.join(`
|
|
|
143
143
|
try {
|
|
144
144
|
const { diagnostics } = this.check(filePath);
|
|
145
145
|
return diagnostics.length === 0;
|
|
146
|
-
} catch (
|
|
146
|
+
} catch (_error) {
|
|
147
147
|
return false;
|
|
148
148
|
}
|
|
149
149
|
}
|
|
150
150
|
static checkProject(configPath) {
|
|
151
|
-
const parsedConfig =
|
|
151
|
+
const parsedConfig = TypeChecker2.parseConfig(configPath);
|
|
152
152
|
const host = ts.createIncrementalCompilerHost(parsedConfig.options);
|
|
153
153
|
const builderProgram = ts.createIncrementalProgram({
|
|
154
154
|
rootNames: parsedConfig.fileNames,
|
|
@@ -166,19 +166,19 @@ ${summary.join(", ")} found${output.join(`
|
|
|
166
166
|
diagnostics,
|
|
167
167
|
errors,
|
|
168
168
|
warnings,
|
|
169
|
-
message:
|
|
169
|
+
message: TypeChecker2.formatDiagnosticMessages(diagnostics)
|
|
170
170
|
};
|
|
171
171
|
}
|
|
172
172
|
static parseConfig(configPath) {
|
|
173
173
|
const configFile = ts.readConfigFile(configPath, (fileName) => ts.sys.readFile(fileName));
|
|
174
174
|
const configDiagnostics = configFile.error ? [configFile.error] : [];
|
|
175
175
|
if (!configFile.config) {
|
|
176
|
-
const message =
|
|
176
|
+
const message = TypeChecker2.formatDiagnosticMessages(configDiagnostics);
|
|
177
177
|
throw new Error(message || `Error reading tsconfig.json: ${configPath}`);
|
|
178
178
|
}
|
|
179
179
|
const parsedConfig = ts.parseJsonConfigFileContent(configFile.config, ts.sys, path.dirname(configPath), undefined, configPath);
|
|
180
180
|
if (parsedConfig.errors.length > 0)
|
|
181
|
-
throw new Error(
|
|
181
|
+
throw new Error(TypeChecker2.formatDiagnosticMessages(parsedConfig.errors));
|
|
182
182
|
return parsedConfig;
|
|
183
183
|
}
|
|
184
184
|
static formatDiagnosticMessages(diagnostics) {
|
|
@@ -190,4 +190,4 @@ ${summary.join(", ")} found${output.join(`
|
|
|
190
190
|
}
|
|
191
191
|
}
|
|
192
192
|
|
|
193
|
-
export {
|
|
193
|
+
export { TypeChecker2 };
|
|
@@ -19,12 +19,14 @@ var prepareDevWatchBatch = ({
|
|
|
19
19
|
generatedFiles: indexSync.changedFiles
|
|
20
20
|
});
|
|
21
21
|
if (indexSync.errors.length > 0 && !devPlan.actions.includes("report-error")) {
|
|
22
|
-
|
|
22
|
+
const withReport = [...devPlan.actions, "report-error"];
|
|
23
|
+
devPlan.actions = withReport.sort();
|
|
23
24
|
}
|
|
24
25
|
return {
|
|
25
26
|
files,
|
|
26
27
|
kinds,
|
|
27
28
|
expandedBatch,
|
|
29
|
+
devPlan,
|
|
28
30
|
event: { type: "invalidate", kinds, files, generation, devPlan },
|
|
29
31
|
hasSyncErrors: indexSync.errors.length > 0
|
|
30
32
|
};
|
|
@@ -2,16 +2,16 @@
|
|
|
2
2
|
import {
|
|
3
3
|
runner,
|
|
4
4
|
script
|
|
5
|
-
} from "./index-
|
|
5
|
+
} from "./index-ft1sfjz0.js";
|
|
6
6
|
import {
|
|
7
7
|
PkgExecutor
|
|
8
|
-
} from "./index-
|
|
9
|
-
import {
|
|
10
|
-
TypeScriptDependencyScanner
|
|
11
|
-
} from "./index-46tjzh6s.js";
|
|
8
|
+
} from "./index-k1n0h7dk.js";
|
|
12
9
|
import {
|
|
13
10
|
FileSys
|
|
14
|
-
} from "./index-
|
|
11
|
+
} from "./index-ayy5ecax.js";
|
|
12
|
+
import {
|
|
13
|
+
TypeScriptDependencyScanner2
|
|
14
|
+
} from "./index-mfm35dhh.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()) {
|
|
@@ -9,7 +9,7 @@ class FileSys {
|
|
|
9
9
|
return await Bun.file(path).exists();
|
|
10
10
|
}
|
|
11
11
|
static async dirExists(path) {
|
|
12
|
-
return await stat(path).then((
|
|
12
|
+
return await stat(path).then((stat) => stat.isDirectory()).catch(() => false);
|
|
13
13
|
}
|
|
14
14
|
static async exists(path) {
|
|
15
15
|
return await stat(path).then(() => true).catch(() => false);
|