@akanjs/cli 3.0.0-alpha.7 → 3.0.0-alpha.71
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-20e0cwbs.js} +2 -2
- package/{agent.command-pggr92jj.js → agent.command-xdvw642m.js} +9 -7
- package/{application.command-692yap1d.js → application.command-g3f7xj25.js} +31 -6
- package/{applicationBuildRunner-ha3y8ew8.js → applicationBuildRunner-af0wtspv.js} +19 -14
- package/{applicationReleasePackager-gg8ccbeh.js → applicationReleasePackager-93nzdfsy.js} +1 -1
- package/buildBatch.proc.js +7 -5
- package/{capacitorApp-p0z5yab2.js → capacitorApp-b0ppke3m.js} +29 -27
- package/{cloud.command-wqfsyzv2.js → cloud.command-0hmsv44q.js} +12 -10
- package/commandManifest.json +1 -1
- package/{context.command-9bxtdn0w.js → context.command-x92afrnf.js} +17 -15
- package/{dependencyScanner-f6grrep3.js → dependencyScanner-rbs2407b.js} +1 -1
- package/getDirname-ka11hm7e.js +8 -0
- package/{guideline.command-nfqahxex.js → guideline.command-hpq08q66.js} +8 -6
- 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 +839 -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/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 +8 -6
- package/index-1577bej2.js +7 -0
- package/{index-vg0sj9nc.js → index-5f4gnt4c.js} +258 -97
- package/{index-bjpxzr6s.js → index-5vy2jzar.js} +1 -1
- package/{index-mssqn2sq.js → index-6d5r8q6k.js} +54 -15
- package/{index-p3f4q532.js → index-737aj4fm.js} +14 -13
- package/{index-2c3e2xh8.js → index-8besc14m.js} +1 -1
- package/{index-qb61h0k7.js → index-abyjt72y.js} +333 -540
- package/{index-xhgtkekh.js → index-cbfp5wyp.js} +1 -1
- package/{index-5dw57f0d.js → index-cp00yns2.js} +80 -14
- package/{index-ztpw544k.js → index-ety6takb.js} +3 -3
- package/index-f39512t6.js +255 -0
- package/{index-6rhabeev.js → index-gvq17wqn.js} +5 -3
- package/{index-js368gk9.js → index-hs70d8ed.js} +6 -6
- package/{index-7myvn0f0.js → index-j37qq1f2.js} +1 -1
- package/{index-azv0xjb5.js → index-jybbmwed.js} +8 -4
- package/{index-4hek879p.js → index-m5gfc86a.js} +1 -1
- package/{index-w6wbb612.js → index-nq3avsf6.js} +13 -13
- package/{index-vtj3zps1.js → index-p27h7535.js} +8 -8
- package/{index-5pmx7bkg.js → index-pehn44hr.js} +3 -3
- package/{index-j9cxndc0.js → index-qnv0aqmm.js} +9 -6
- package/{index-gmy45vz2.js → index-r691v756.js} +4 -4
- package/{index-0cj2zxbm.js → index-sh01r3pm.js} +1 -1
- package/{index-a1e0j63x.js → index-sqsfv8wg.js} +15 -7
- package/{index-gex7c8kd.js → index-wbbswwqt.js} +51 -24
- package/{index-bz2sfzzt.js → index-wybbcgxn.js} +4 -4
- package/index.js +21 -19
- package/{library.command-md9715jz.js → library.command-8vgrdtwy.js} +6 -4
- package/{localRegistry.command-exkbamyj.js → localRegistry.command-0gtqj0r0.js} +11 -9
- package/{module.command-w5aaddxk.js → module.command-rama4zya.js} +10 -8
- package/{package.command-yfkrcy0z.js → package.command-6jxapdsg.js} +6 -4
- package/package.json +4 -5
- package/{page.command-echbavp4.js → page.command-hxy7x525.js} +6 -4
- package/{primitive.command-9fbhspw2.js → primitive.command-4bf6xcc3.js} +11 -9
- package/{quality.command-3pnt9yep.js → quality.command-h5edwegz.js} +192 -97
- package/{recipeScanner-tghkzrrt.js → recipeScanner-zrzev25x.js} +3 -3
- package/{repair.command-carj4vax.js → repair.command-rgqf6px6.js} +8 -6
- package/{routeSourceValidator-e4jmbfcx.js → routeSourceValidator-7fycdqyv.js} +1 -1
- package/{scalar.command-51ryzypc.js → scalar.command-6krkz6tw.js} +9 -7
- 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/app/page/styles.css.template +3 -3
- package/templates/appSample/srvkit/AuthGuard.ts +9 -5
- package/templates/appSample/srvkit/SessionInternalArg.ts +4 -3
- package/templates/crudPages/[__model__Id]/edit/page.tsx +1 -1
- package/templates/crudPages/new/page.tsx +1 -1
- package/templates/crudSinglePage/page.tsx +1 -1
- 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/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 +1 -1
- package/{typeChecker-kravn7ns.js → typeChecker-g6bh0xfv.js} +1 -1
- package/typecheck.proc.js +1 -1
- package/{workflow.command-91wmvm8k.js → workflow.command-dwhwrqhd.js} +16 -14
- package/{workspace.command-wa10mfd9.js → workspace.command-f5h11gjn.js} +71 -52
- 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/{index-r24hmh0q.js → index-yb2wsc7f.js} +0 -0
|
@@ -1,13 +1,20 @@
|
|
|
1
1
|
// @bun
|
|
2
|
+
import {
|
|
3
|
+
getRootBoundarySegments,
|
|
4
|
+
isRootBoundarySegments
|
|
5
|
+
} from "./index-f39512t6.js";
|
|
2
6
|
import {
|
|
3
7
|
Spinner
|
|
4
8
|
} from "./index-mxvakhsm.js";
|
|
9
|
+
import {
|
|
10
|
+
getDirname
|
|
11
|
+
} from "./index-1577bej2.js";
|
|
5
12
|
import {
|
|
6
13
|
FileSys
|
|
7
14
|
} from "./index-67546d0j.js";
|
|
8
15
|
import {
|
|
9
16
|
__require
|
|
10
|
-
} from "./index-
|
|
17
|
+
} from "./index-yb2wsc7f.js";
|
|
11
18
|
|
|
12
19
|
// pkgs/@akanjs/devkit/executors.ts
|
|
13
20
|
import {
|
|
@@ -30,6 +37,7 @@ import path5 from "path";
|
|
|
30
37
|
import { pathToFileURL } from "url";
|
|
31
38
|
import {
|
|
32
39
|
capitalize,
|
|
40
|
+
getPageSourceFileViolation,
|
|
33
41
|
isRouteSourceFile,
|
|
34
42
|
Logger,
|
|
35
43
|
parseRouteModuleKey,
|
|
@@ -41,9 +49,24 @@ import chalk2 from "chalk";
|
|
|
41
49
|
|
|
42
50
|
// pkgs/@akanjs/devkit/agentsIndex.ts
|
|
43
51
|
var recipeScannerLoad = null;
|
|
44
|
-
var loadRecipeScanner = () => recipeScannerLoad ??= import("./recipeScanner-
|
|
52
|
+
var loadRecipeScanner = () => recipeScannerLoad ??= import("./recipeScanner-zrzev25x.js");
|
|
45
53
|
var AGENT_BLOCK_START = "<!-- akan:agent:start -->";
|
|
46
54
|
var AGENT_BLOCK_END = "<!-- akan:agent:end -->";
|
|
55
|
+
var AGENT_VERSION_PREFIX = "<!-- akan:agent:version ";
|
|
56
|
+
var stampBlockVersion = (block, version) => `${AGENT_VERSION_PREFIX}${version} -->
|
|
57
|
+
|
|
58
|
+
${block}`;
|
|
59
|
+
var extractBlockVersion = (content) => content.match(/<!-- akan:agent:version ([^\s]+) -->/)?.[1] ?? null;
|
|
60
|
+
var readDevkitVersion = async () => {
|
|
61
|
+
const { readFile } = await import("fs/promises");
|
|
62
|
+
const { getDirname: getDirname2 } = await import("./getDirname-ka11hm7e.js");
|
|
63
|
+
try {
|
|
64
|
+
const raw = await readFile(`${getDirname2(import.meta.url)}/package.json`, "utf-8");
|
|
65
|
+
return JSON.parse(raw).version ?? null;
|
|
66
|
+
} catch {
|
|
67
|
+
return null;
|
|
68
|
+
}
|
|
69
|
+
};
|
|
47
70
|
var upsertAgentBlock = (existing, block) => {
|
|
48
71
|
const managed = `${AGENT_BLOCK_START}
|
|
49
72
|
${block}
|
|
@@ -137,9 +160,29 @@ ${AGENT_BLOCK_START}
|
|
|
137
160
|
${block}
|
|
138
161
|
${AGENT_BLOCK_END}
|
|
139
162
|
`;
|
|
163
|
+
var CLAUDE_COMMENT_RULE = `## Comments \u2014 Overrides Your Default
|
|
164
|
+
|
|
165
|
+
Write **no comments** unless the comment passes the test below. This is the rule agents break most often here, so it
|
|
166
|
+
is repeated outside the guide: a diff that adds a comment the test rejects is a diff to redo.
|
|
167
|
+
|
|
168
|
+
Before typing \`//\`, \`/*\`, or a doc block, ask \u2014 **does this sentence carry a fact that is nowhere in the code?**
|
|
169
|
+
|
|
170
|
+
- Restates the identifier, the signature, or the line under it \u2192 delete it.
|
|
171
|
+
- Labels a section (\`// helpers\`, \`// state\`) or narrates a step (\`// fetch the user\`, \`// then save\`) \u2192 delete it.
|
|
172
|
+
- JSDoc on an ordinary function, or a why/how preamble on ordinary logic \u2192 delete it.
|
|
173
|
+
- Explains the edit you just made, for whoever reads the diff \u2192 say it in your reply, not in the file.
|
|
174
|
+
- Names a vendor or protocol quirk, an infrastructure constraint, a library gotcha, security reasoning, a math
|
|
175
|
+
derivation, a domain field's business meaning, a state transition, or why an obvious alternative was rejected \u2192
|
|
176
|
+
keep it, one line.
|
|
177
|
+
|
|
178
|
+
That keep-list is exact \u2014 \`Comments\` in the guide is the full version. "It aids readability" and "this logic is
|
|
179
|
+
subtle" are not on it: rename or split the code instead. When you edit an existing file, match its density; if the
|
|
180
|
+
surrounding code carries none, your diff carries none.`;
|
|
140
181
|
var renderScopeClaudeMd = (scope) => `# ${scope.name} \u2014 Claude Code Guide
|
|
141
182
|
|
|
142
183
|
@AGENTS.md
|
|
184
|
+
|
|
185
|
+
${CLAUDE_COMMENT_RULE}
|
|
143
186
|
`;
|
|
144
187
|
|
|
145
188
|
// pkgs/@akanjs/devkit/akanConfig/akanConfig.ts
|
|
@@ -181,9 +224,8 @@ var DEFAULT_OPTIMIZE_IMPORTS = [
|
|
|
181
224
|
"react-icons/*"
|
|
182
225
|
];
|
|
183
226
|
var WORKSPACE_BARREL_FACETS = ["ui", "webkit", "common", "client", "server"];
|
|
227
|
+
var DEFAULT_DOCKER_IMAGE = "oven/bun:1-slim";
|
|
184
228
|
var SSR_RUNTIME_PACKAGES = ["react", "react-dom", "react-server-dom-webpack"];
|
|
185
|
-
var NATIVE_RUNTIME_PACKAGES = ["sharp"];
|
|
186
|
-
var DEFAULT_BACKEND_RUNTIME_PACKAGES = ["croner"];
|
|
187
229
|
var MOBILE_RUNTIME_PACKAGES = [
|
|
188
230
|
"@capacitor/cli",
|
|
189
231
|
"@capacitor/core",
|
|
@@ -212,8 +254,6 @@ var DATABASE_MODE_RUNTIME_PACKAGES = {
|
|
|
212
254
|
};
|
|
213
255
|
var AKAN_RUNTIME_PACKAGES = new Set([
|
|
214
256
|
...SSR_RUNTIME_PACKAGES,
|
|
215
|
-
...NATIVE_RUNTIME_PACKAGES,
|
|
216
|
-
...DEFAULT_BACKEND_RUNTIME_PACKAGES,
|
|
217
257
|
...MOBILE_RUNTIME_PACKAGES,
|
|
218
258
|
...Object.values(DATABASE_MODE_RUNTIME_PACKAGES).flat()
|
|
219
259
|
]);
|
|
@@ -228,7 +268,8 @@ var DEFAULT_AKAN_IMAGE_CONFIG = {
|
|
|
228
268
|
dangerouslyAllowSVG: false,
|
|
229
269
|
maximumRedirects: 3,
|
|
230
270
|
fetchTimeoutMs: 7000,
|
|
231
|
-
maxRemoteBytes: 25 * 1024 * 1024
|
|
271
|
+
maxRemoteBytes: 25 * 1024 * 1024,
|
|
272
|
+
maxConcurrency: 0
|
|
232
273
|
};
|
|
233
274
|
var normalizeIndexPath = (indexPath) => {
|
|
234
275
|
const normalized = indexPath?.trim();
|
|
@@ -275,12 +316,28 @@ var normalizeDeepLinks = (deepLinks) => {
|
|
|
275
316
|
...sha256CertFingerprints ? { android: { sha256CertFingerprints } } : {}
|
|
276
317
|
};
|
|
277
318
|
};
|
|
319
|
+
var emptyLibContributions = () => ({
|
|
320
|
+
externalLibs: [],
|
|
321
|
+
docker: { preRuns: [], postRuns: [] },
|
|
322
|
+
keepFonts: []
|
|
323
|
+
});
|
|
324
|
+
var normalizeKeepFonts = (keepFonts) => [
|
|
325
|
+
...new Set((keepFonts ?? []).map((glob) => glob.trim().replace(/^\/+/, "")).filter(Boolean))
|
|
326
|
+
];
|
|
327
|
+
var dedupeDockerRuns = (runs) => {
|
|
328
|
+
const byKey = new Map;
|
|
329
|
+
for (const run of runs)
|
|
330
|
+
byKey.set(typeof run === "string" ? run : JSON.stringify(run), run);
|
|
331
|
+
return [...byKey.values()];
|
|
332
|
+
};
|
|
278
333
|
|
|
279
334
|
class AkanAppConfig {
|
|
280
335
|
app;
|
|
281
336
|
rootPackageJson;
|
|
282
337
|
docker;
|
|
338
|
+
dockerfile;
|
|
283
339
|
defaultDatabaseMode;
|
|
340
|
+
web;
|
|
284
341
|
externalLibs;
|
|
285
342
|
barrelImports;
|
|
286
343
|
optimizeImports;
|
|
@@ -290,6 +347,7 @@ class AkanAppConfig {
|
|
|
290
347
|
mobile;
|
|
291
348
|
hasMobileConfig;
|
|
292
349
|
secrets;
|
|
350
|
+
assets;
|
|
293
351
|
syncPageLibs;
|
|
294
352
|
baseDevEnv;
|
|
295
353
|
libs;
|
|
@@ -298,7 +356,7 @@ class AkanAppConfig {
|
|
|
298
356
|
subRoutes = new Map;
|
|
299
357
|
basePaths = new Set;
|
|
300
358
|
branches = new Set(["debug", "develop", "main"]);
|
|
301
|
-
constructor(app, libs, rootPackageJson, config, baseDevEnv, plugins = []) {
|
|
359
|
+
constructor(app, libs, rootPackageJson, config, baseDevEnv, plugins = [], libContributions = emptyLibContributions()) {
|
|
302
360
|
this.app = app;
|
|
303
361
|
this.rootPackageJson = rootPackageJson;
|
|
304
362
|
this.libs = libs;
|
|
@@ -306,7 +364,7 @@ class AkanAppConfig {
|
|
|
306
364
|
this.plugins = plugins;
|
|
307
365
|
this.#applyRoutes(config?.routes);
|
|
308
366
|
this.defaultDatabaseMode = config?.defaultDatabaseMode ?? "single";
|
|
309
|
-
this.externalLibs = config?.externalLibs ?? [];
|
|
367
|
+
this.externalLibs = [...new Set([...config?.externalLibs ?? [], ...libContributions.externalLibs])];
|
|
310
368
|
this.barrelImports = [
|
|
311
369
|
...DEFAULT_BARREL_IMPORTS,
|
|
312
370
|
...WORKSPACE_BARREL_FACETS.map((facet) => `@apps/${app.name}/${facet}`),
|
|
@@ -320,10 +378,25 @@ class AkanAppConfig {
|
|
|
320
378
|
process.env.AKAN_PUBLIC_LOCALES = this.i18n.locales.join(",");
|
|
321
379
|
this.publicEnv = config?.publicEnv ?? [];
|
|
322
380
|
this.secrets = config?.secrets ?? [];
|
|
381
|
+
this.assets = {
|
|
382
|
+
pruneFonts: config?.assets?.pruneFonts ?? true,
|
|
383
|
+
keepFonts: [
|
|
384
|
+
...normalizeKeepFonts(config?.assets?.keepFonts),
|
|
385
|
+
...libContributions.keepFonts ?? []
|
|
386
|
+
]
|
|
387
|
+
};
|
|
323
388
|
this.syncPageLibs = config?.syncPageLibs ?? false;
|
|
324
389
|
this.hasMobileConfig = Boolean(config.mobile);
|
|
325
390
|
this.mobile = this.#resolveMobileConfig(config.mobile);
|
|
326
|
-
this.
|
|
391
|
+
this.web = this.#resolveWebConfig(config.web);
|
|
392
|
+
this.docker = AkanAppConfig.#resolveDocker(config.docker, libContributions.docker);
|
|
393
|
+
this.dockerfile = this.#makeDockerfile();
|
|
394
|
+
}
|
|
395
|
+
#resolveWebConfig(web) {
|
|
396
|
+
const resolved = typeof web === "object" ? { ssr: true, csr: web.csr } : { ssr: web ?? true, csr: web ?? true };
|
|
397
|
+
if (!resolved.csr && this.hasMobileConfig)
|
|
398
|
+
throw new Error(`apps/${this.app.name}/akan.config.ts turns the CSR bundle off but declares mobile targets; the Capacitor build ships that bundle. Drop the mobile section or leave CSR on.`);
|
|
399
|
+
return resolved;
|
|
327
400
|
}
|
|
328
401
|
#resolveMobileConfig(mobile) {
|
|
329
402
|
const {
|
|
@@ -433,23 +506,31 @@ class AkanAppConfig {
|
|
|
433
506
|
return archs.map((arch) => `FROM ${image[arch] ?? defaultImage} AS ${arch}`).join(`
|
|
434
507
|
`);
|
|
435
508
|
}
|
|
436
|
-
#
|
|
437
|
-
if (docker
|
|
438
|
-
return
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
const
|
|
509
|
+
static #resolveDocker(docker, libDocker) {
|
|
510
|
+
if (typeof docker === "string")
|
|
511
|
+
return docker;
|
|
512
|
+
return {
|
|
513
|
+
image: docker?.image ?? DEFAULT_DOCKER_IMAGE,
|
|
514
|
+
preRuns: dedupeDockerRuns([...libDocker.preRuns, ...docker?.preRuns ?? []]),
|
|
515
|
+
postRuns: dedupeDockerRuns([...libDocker.postRuns, ...docker?.postRuns ?? []]),
|
|
516
|
+
command: docker?.command ?? ["bun", "main.js"]
|
|
517
|
+
};
|
|
518
|
+
}
|
|
519
|
+
#makeDockerfile() {
|
|
520
|
+
if (typeof this.docker === "string")
|
|
521
|
+
return this.docker;
|
|
522
|
+
const { image, preRuns, postRuns, command } = this.docker;
|
|
523
|
+
const preRunScripts = this.#getDockerRunScripts(preRuns);
|
|
524
|
+
const postRunScripts = this.#getDockerRunScripts(postRuns);
|
|
525
|
+
const imageScript = this.#getDockerImageScript(image, DEFAULT_DOCKER_IMAGE);
|
|
526
|
+
const webEnvLines = [
|
|
527
|
+
...this.web.ssr ? [] : ["ENV AKAN_SSR=false"],
|
|
528
|
+
...this.web.csr ? [] : ["ENV AKAN_CSR=false"]
|
|
529
|
+
].join(`
|
|
530
|
+
`);
|
|
531
|
+
return `${imageScript}
|
|
532
|
+
RUN apt-get update && apt-get upgrade -y && apt-get install -y --no-install-recommends ca-certificates tzdata && rm -rf /var/lib/apt/lists/*
|
|
450
533
|
RUN ln -sf /usr/share/zoneinfo/Asia/Seoul /etc/localtime
|
|
451
|
-
RUN apt-get update && apt-get upgrade -y
|
|
452
|
-
RUN apt-get install -y --no-install-recommends git redis build-essential python3 ca-certificates fonts-liberation libappindicator3-1 libasound2 libatk-bridge2.0-0 libatk1.0-0 libc6 libcairo2 libcups2 libdbus-1-3 libexpat1 libfontconfig1 libgbm1 libgcc1 libglib2.0-0 libgtk-3-0 libnspr4 libnss3 libpango-1.0-0 libpangocairo-1.0-0 libstdc++6 libx11-6 libx11-xcb1 libxcb1 libxcomposite1 libxcursor1 libxdamage1 libxext6 libxfixes3 libxi6 libxrandr2 libxrender1 libxss1 libxtst6 lsb-release wget xdg-utils udev ffmpeg
|
|
453
534
|
ARG TARGETARCH
|
|
454
535
|
${preRunScripts.join(`
|
|
455
536
|
`)}
|
|
@@ -470,15 +551,9 @@ ${this.basePaths.size ? `ENV AKAN_PUBLIC_BASE_PATHS=${[...this.basePaths].join("
|
|
|
470
551
|
ENV AKAN_PUBLIC_DEFAULT_LOCALE=${this.i18n.defaultLocale}
|
|
471
552
|
ENV AKAN_PUBLIC_LOCALES=${this.i18n.locales.join(",")}
|
|
472
553
|
ENV AKAN_PUBLIC_OPERATION_MODE=cloud
|
|
473
|
-
|
|
554
|
+
ENV AKAN_LOG_TO_FILE=0
|
|
555
|
+
${webEnvLines}
|
|
474
556
|
CMD [${command.map((c) => `"${c}"`).join(",")}]`;
|
|
475
|
-
return {
|
|
476
|
-
content,
|
|
477
|
-
image: imageScript,
|
|
478
|
-
preRuns: docker.preRuns ?? [],
|
|
479
|
-
postRuns: docker.postRuns ?? [],
|
|
480
|
-
command
|
|
481
|
-
};
|
|
482
557
|
}
|
|
483
558
|
static #importGeneration = 0;
|
|
484
559
|
static async importConfigModule(cwdPath, { bustImportCache = false } = {}) {
|
|
@@ -495,7 +570,22 @@ CMD [${command.map((c) => `"${c}"`).join(",")}]`;
|
|
|
495
570
|
]);
|
|
496
571
|
const resolved = typeof configImp === "function" ? configImp(app) : configImp;
|
|
497
572
|
const { plugins, ...config } = resolved ?? {};
|
|
498
|
-
|
|
573
|
+
const libContributions = await AkanAppConfig.#collectLibContributions(app, libs, bustImportCache);
|
|
574
|
+
return new AkanAppConfig(app, libs, rootPackageJson, config, baseDevEnv, plugins ?? [], libContributions);
|
|
575
|
+
}
|
|
576
|
+
static async#collectLibContributions(app, libs, bustImportCache) {
|
|
577
|
+
const libConfigs = await Promise.all(libs.map(async (libName) => LibExecutor.from(app, libName).getConfig({ refresh: bustImportCache }).catch((error) => {
|
|
578
|
+
app.logger.warn(`Skipped libs/${libName}/akan.config.ts contributions: ${String(error)}`);
|
|
579
|
+
return null;
|
|
580
|
+
})));
|
|
581
|
+
return {
|
|
582
|
+
externalLibs: libConfigs.flatMap((libConfig) => libConfig?.externalLibs ?? []),
|
|
583
|
+
docker: {
|
|
584
|
+
preRuns: libConfigs.flatMap((libConfig) => libConfig?.docker.preRuns ?? []),
|
|
585
|
+
postRuns: libConfigs.flatMap((libConfig) => libConfig?.docker.postRuns ?? [])
|
|
586
|
+
},
|
|
587
|
+
keepFonts: libConfigs.flatMap((libConfig) => (libConfig?.assets.keepFonts ?? []).map((glob) => `libs/${libConfig?.lib.name}/${glob}`))
|
|
588
|
+
};
|
|
499
589
|
}
|
|
500
590
|
#resolveProductionDependencyVersion(lib) {
|
|
501
591
|
const rootVersion = this.rootPackageJson.dependencies?.[lib] ?? this.rootPackageJson.devDependencies?.[lib];
|
|
@@ -505,13 +595,7 @@ CMD [${command.map((c) => `"${c}"`).join(",")}]`;
|
|
|
505
595
|
return akanPackageJson.dependencies?.[lib] ?? akanPackageJson.peerDependencies?.[lib];
|
|
506
596
|
}
|
|
507
597
|
#getProductionRuntimePackages() {
|
|
508
|
-
return [
|
|
509
|
-
...this.externalLibs,
|
|
510
|
-
...SSR_RUNTIME_PACKAGES,
|
|
511
|
-
...NATIVE_RUNTIME_PACKAGES,
|
|
512
|
-
...DEFAULT_BACKEND_RUNTIME_PACKAGES,
|
|
513
|
-
...this.getDatabaseModeRuntimePackages()
|
|
514
|
-
];
|
|
598
|
+
return [...this.externalLibs, ...SSR_RUNTIME_PACKAGES, ...this.getDatabaseModeRuntimePackages()];
|
|
515
599
|
}
|
|
516
600
|
getDatabaseModeRuntimePackages(databaseMode = this.defaultDatabaseMode) {
|
|
517
601
|
return [...DATABASE_MODE_RUNTIME_PACKAGES[databaseMode]];
|
|
@@ -599,14 +683,18 @@ function mergeImageConfig(config = {}) {
|
|
|
599
683
|
class AkanLibConfig {
|
|
600
684
|
lib;
|
|
601
685
|
externalLibs;
|
|
686
|
+
docker;
|
|
687
|
+
assets;
|
|
602
688
|
plugins;
|
|
603
689
|
constructor(lib, config, plugins = []) {
|
|
604
690
|
this.lib = lib;
|
|
605
691
|
this.externalLibs = config?.externalLibs ?? [];
|
|
692
|
+
this.docker = { preRuns: config?.docker?.preRuns ?? [], postRuns: config?.docker?.postRuns ?? [] };
|
|
693
|
+
this.assets = { keepFonts: normalizeKeepFonts(config?.assets?.keepFonts) };
|
|
606
694
|
this.plugins = plugins;
|
|
607
695
|
}
|
|
608
|
-
static async from(lib) {
|
|
609
|
-
const
|
|
696
|
+
static async from(lib, { bustImportCache = false } = {}) {
|
|
697
|
+
const configImp = await AkanAppConfig.importConfigModule(lib.cwdPath, { bustImportCache });
|
|
610
698
|
const resolved = typeof configImp === "function" ? configImp(lib) : configImp;
|
|
611
699
|
const { plugins, ...config } = resolved ?? {};
|
|
612
700
|
return new AkanLibConfig(lib, config, plugins ?? []);
|
|
@@ -627,42 +715,47 @@ var decreaseBuildNum = async (app) => {
|
|
|
627
715
|
const akanConfigContent = akanConfig.replace(`buildNum: ${appConfig.mobile.buildNum}`, `buildNum: ${appConfig.mobile.buildNum - 1}`);
|
|
628
716
|
fs.writeFileSync(akanConfigPath, akanConfigContent);
|
|
629
717
|
};
|
|
630
|
-
// pkgs/@akanjs/devkit/getDirname.ts
|
|
631
|
-
import path2 from "path";
|
|
632
|
-
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
633
|
-
var getDirname = (url) => path2.dirname(fileURLToPath2(url));
|
|
634
|
-
|
|
635
718
|
// pkgs/@akanjs/devkit/linter.ts
|
|
636
719
|
import { spawn } from "child_process";
|
|
637
720
|
import { existsSync, readFileSync } from "fs";
|
|
638
|
-
import
|
|
721
|
+
import path2 from "path";
|
|
639
722
|
import chalk from "chalk";
|
|
723
|
+
var BIOME_CONFIG_FILES = ["biome.json", "biome.jsonc"];
|
|
640
724
|
|
|
641
725
|
class Linter {
|
|
642
726
|
lintRoot;
|
|
727
|
+
configPath;
|
|
643
728
|
#biomeBin;
|
|
644
729
|
constructor(cwdPath) {
|
|
645
730
|
this.lintRoot = this.#findBiomeRootPath(cwdPath);
|
|
646
|
-
|
|
731
|
+
this.configPath = Linter.#configPathIn(this.lintRoot) ?? path2.join(this.lintRoot, "biome.json");
|
|
732
|
+
const localBiomeBin = path2.join(this.lintRoot, "node_modules/.bin/biome");
|
|
647
733
|
this.#biomeBin = existsSync(localBiomeBin) ? localBiomeBin : "biome";
|
|
648
734
|
}
|
|
735
|
+
static #configPathIn(dir) {
|
|
736
|
+
for (const fileName of BIOME_CONFIG_FILES) {
|
|
737
|
+
const configPath = path2.join(dir, fileName);
|
|
738
|
+
if (existsSync(configPath))
|
|
739
|
+
return configPath;
|
|
740
|
+
}
|
|
741
|
+
return null;
|
|
742
|
+
}
|
|
649
743
|
#findBiomeRootPath(dir) {
|
|
650
|
-
|
|
651
|
-
if (existsSync(configPath))
|
|
744
|
+
if (Linter.#configPathIn(dir))
|
|
652
745
|
return dir;
|
|
653
|
-
const parentDir =
|
|
746
|
+
const parentDir = path2.dirname(dir);
|
|
654
747
|
if (parentDir === dir)
|
|
655
748
|
throw new Error(`biome.json not found from ${dir}`);
|
|
656
749
|
return this.#findBiomeRootPath(parentDir);
|
|
657
750
|
}
|
|
658
751
|
#toBiomePath(filePath) {
|
|
659
|
-
const relativePath =
|
|
660
|
-
if (!relativePath.startsWith("..") && !
|
|
752
|
+
const relativePath = path2.relative(this.lintRoot, filePath);
|
|
753
|
+
if (!relativePath.startsWith("..") && !path2.isAbsolute(relativePath))
|
|
661
754
|
return relativePath;
|
|
662
755
|
return filePath;
|
|
663
756
|
}
|
|
664
757
|
#resolveFilePath(filePath) {
|
|
665
|
-
return
|
|
758
|
+
return path2.isAbsolute(filePath) ? filePath : path2.join(this.lintRoot, filePath);
|
|
666
759
|
}
|
|
667
760
|
async#runBiome(args, input) {
|
|
668
761
|
return await new Promise((resolve, reject) => {
|
|
@@ -694,7 +787,7 @@ class Linter {
|
|
|
694
787
|
const diagnosticPath = diagnostic.location?.path;
|
|
695
788
|
if (!diagnosticPath)
|
|
696
789
|
return fallbackFilePath;
|
|
697
|
-
return
|
|
790
|
+
return path2.isAbsolute(diagnosticPath) ? diagnosticPath : path2.join(this.lintRoot, diagnosticPath);
|
|
698
791
|
}
|
|
699
792
|
#createLintMessage(diagnostic) {
|
|
700
793
|
const start = diagnostic.location?.start;
|
|
@@ -759,7 +852,7 @@ class Linter {
|
|
|
759
852
|
"--max-diagnostics=none",
|
|
760
853
|
"--no-errors-on-unmatched",
|
|
761
854
|
"--config-path",
|
|
762
|
-
|
|
855
|
+
this.configPath,
|
|
763
856
|
this.#toBiomePath(filePath)
|
|
764
857
|
]);
|
|
765
858
|
const report = this.#parseBiomeReport(stdout || stderr);
|
|
@@ -880,14 +973,7 @@ ${errorText}, ${warningText} found`];
|
|
|
880
973
|
if (!dryRun)
|
|
881
974
|
return await this.#checkFile(resolvedFilePath, { write: true });
|
|
882
975
|
const source = readFileSync(resolvedFilePath, "utf8");
|
|
883
|
-
const { stdout } = await this.#runBiome([
|
|
884
|
-
"check",
|
|
885
|
-
"--write",
|
|
886
|
-
"--config-path",
|
|
887
|
-
path3.join(this.lintRoot, "biome.json"),
|
|
888
|
-
"--stdin-file-path",
|
|
889
|
-
this.#toBiomePath(resolvedFilePath)
|
|
890
|
-
], source);
|
|
976
|
+
const { stdout } = await this.#runBiome(["check", "--write", "--config-path", this.configPath, "--stdin-file-path", this.#toBiomePath(resolvedFilePath)], source);
|
|
891
977
|
const lintResult = await this.lintFile(resolvedFilePath);
|
|
892
978
|
return { ...lintResult, fixed: stdout !== source, output: stdout };
|
|
893
979
|
}
|
|
@@ -895,7 +981,7 @@ ${errorText}, ${warningText} found`];
|
|
|
895
981
|
const resolvedFilePath = this.#resolveFilePath(filePath);
|
|
896
982
|
if (!existsSync(resolvedFilePath))
|
|
897
983
|
throw new Error(`File not found: ${filePath}`);
|
|
898
|
-
return JSON.parse(readFileSync(
|
|
984
|
+
return JSON.parse(readFileSync(this.configPath, "utf8"));
|
|
899
985
|
}
|
|
900
986
|
async getProblematicRules(filePath) {
|
|
901
987
|
const { results } = await this.lintFile(filePath);
|
|
@@ -910,6 +996,31 @@ ${errorText}, ${warningText} found`];
|
|
|
910
996
|
}
|
|
911
997
|
}
|
|
912
998
|
|
|
999
|
+
// pkgs/@akanjs/devkit/repoIdentity.ts
|
|
1000
|
+
import { execFileSync } from "child_process";
|
|
1001
|
+
import path3 from "path";
|
|
1002
|
+
var resolved = new Map;
|
|
1003
|
+
var readRemoteName = (workspaceRoot) => {
|
|
1004
|
+
try {
|
|
1005
|
+
const url = execFileSync("git", ["config", "--get", "remote.origin.url"], {
|
|
1006
|
+
cwd: workspaceRoot,
|
|
1007
|
+
encoding: "utf-8",
|
|
1008
|
+
stdio: ["ignore", "pipe", "ignore"]
|
|
1009
|
+
}).trim();
|
|
1010
|
+
return url.replace(/\.git$/, "").split(/[/:]/).pop() || null;
|
|
1011
|
+
} catch {
|
|
1012
|
+
return null;
|
|
1013
|
+
}
|
|
1014
|
+
};
|
|
1015
|
+
var resolveRepoName = (workspaceRoot) => {
|
|
1016
|
+
const cached = resolved.get(workspaceRoot);
|
|
1017
|
+
if (cached)
|
|
1018
|
+
return cached;
|
|
1019
|
+
const repoName = readRemoteName(workspaceRoot) ?? path3.basename(workspaceRoot);
|
|
1020
|
+
resolved.set(workspaceRoot, repoName);
|
|
1021
|
+
return repoName;
|
|
1022
|
+
};
|
|
1023
|
+
|
|
913
1024
|
// pkgs/@akanjs/devkit/scanInfo.ts
|
|
914
1025
|
import { rm } from "fs/promises";
|
|
915
1026
|
import path4 from "path";
|
|
@@ -946,6 +1057,34 @@ var appRootAllowedDirs = new Set([
|
|
|
946
1057
|
"ui",
|
|
947
1058
|
"webkit"
|
|
948
1059
|
]);
|
|
1060
|
+
var libRootAllowedFiles = new Set([
|
|
1061
|
+
"AGENTS.md",
|
|
1062
|
+
"CLAUDE.md",
|
|
1063
|
+
"README.md",
|
|
1064
|
+
"akan.config.ts",
|
|
1065
|
+
"akan.lib.json",
|
|
1066
|
+
"client.ts",
|
|
1067
|
+
"index.ts",
|
|
1068
|
+
"package.json",
|
|
1069
|
+
"server.ts",
|
|
1070
|
+
"tsconfig.json",
|
|
1071
|
+
"tsconfig.spec.json",
|
|
1072
|
+
"tsconfig.tsbuildinfo"
|
|
1073
|
+
]);
|
|
1074
|
+
var libRootAllowedDirs = new Set([
|
|
1075
|
+
"common",
|
|
1076
|
+
"env",
|
|
1077
|
+
"lib",
|
|
1078
|
+
"page",
|
|
1079
|
+
"plugin",
|
|
1080
|
+
"private",
|
|
1081
|
+
"public",
|
|
1082
|
+
"srvkit",
|
|
1083
|
+
"ui",
|
|
1084
|
+
"webkit"
|
|
1085
|
+
]);
|
|
1086
|
+
var rootAllowedFiles = { app: appRootAllowedFiles, lib: libRootAllowedFiles };
|
|
1087
|
+
var rootAllowedDirs = { app: appRootAllowedDirs, lib: libRootAllowedDirs };
|
|
949
1088
|
var libFacetRootAllowedFiles = new Set([
|
|
950
1089
|
"cnst.ts",
|
|
951
1090
|
"db.ts",
|
|
@@ -957,7 +1096,9 @@ var libFacetRootAllowedFiles = new Set([
|
|
|
957
1096
|
"useClient.ts",
|
|
958
1097
|
"useServer.ts"
|
|
959
1098
|
]);
|
|
960
|
-
var
|
|
1099
|
+
var libFacetRootTestPattern = /^[A-Za-z][A-Za-z0-9_-]*\.signal\.(test|spec)\.(ts|tsx)$/;
|
|
1100
|
+
var isAllowedLibFacetRootFile = (filename) => libFacetRootAllowedFiles.has(filename) || libFacetRootTestPattern.test(filename);
|
|
1101
|
+
var isScannedRootEntry = (type, name) => !name.startsWith(".") || rootAllowedDirs[type].has(name);
|
|
961
1102
|
|
|
962
1103
|
// pkgs/@akanjs/devkit/scanInfo.ts
|
|
963
1104
|
var databaseFileTypes = [
|
|
@@ -986,10 +1127,8 @@ var moduleUiFileTypes = {
|
|
|
986
1127
|
scalar: new Set(["Template", "Unit"])
|
|
987
1128
|
};
|
|
988
1129
|
var testFilePattern = /\.(test|spec)\.(ts|tsx)$/;
|
|
989
|
-
var
|
|
990
|
-
var createDependencyScanner = async (exec) => (await import("./dependencyScanner-f6grrep3.js")).TypeScriptDependencyScanner.from(exec);
|
|
1130
|
+
var createDependencyScanner = async (exec) => (await import("./dependencyScanner-rbs2407b.js")).TypeScriptDependencyScanner.from(exec);
|
|
991
1131
|
var isAllowedTestFile = (filename) => testFilePattern.test(filename);
|
|
992
|
-
var isAllowedLibRootFile = (filename) => libFacetRootAllowedFiles.has(filename) || rootSignalTestFilePattern.test(filename);
|
|
993
1132
|
var getScanPath = (exec, relativePath) => path4.posix.join(`${exec.type}s`, exec.name, relativePath.split(path4.sep).join("/"));
|
|
994
1133
|
async function clearGeneratedRootCapacitorConfigs(exec) {
|
|
995
1134
|
if (exec.type !== "app")
|
|
@@ -1006,17 +1145,20 @@ async function assertScanConvention(exec, libRoot) {
|
|
|
1006
1145
|
const addViolation = (relativePath, reason) => {
|
|
1007
1146
|
violations.push(`${getScanPath(exec, relativePath)}: ${reason}`);
|
|
1008
1147
|
};
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
});
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
});
|
|
1017
|
-
}
|
|
1018
|
-
|
|
1019
|
-
|
|
1148
|
+
const allowedRootFiles = rootAllowedFiles[exec.type];
|
|
1149
|
+
const allowedRootDirs = rootAllowedDirs[exec.type];
|
|
1150
|
+
const { files, dirs } = await exec.getFilesAndDirs(".");
|
|
1151
|
+
files.filter((filename) => !allowedRootFiles.has(filename)).forEach((filename) => {
|
|
1152
|
+
addViolation(filename, `unsupported ${exec.type} root file`);
|
|
1153
|
+
});
|
|
1154
|
+
dirs.filter((dirname) => !allowedRootDirs.has(dirname)).forEach((dirname) => {
|
|
1155
|
+
addViolation(dirname, `unsupported ${exec.type} root folder`);
|
|
1156
|
+
});
|
|
1157
|
+
if (exec.type === "lib")
|
|
1158
|
+
for (const { relativePath, reason } of await exec.getPageConventionViolations())
|
|
1159
|
+
addViolation(relativePath, reason);
|
|
1160
|
+
libRoot.files.filter((filename) => !isAllowedLibFacetRootFile(filename)).forEach((filename) => {
|
|
1161
|
+
addViolation(path4.join("lib", filename), "unsupported lib facet root file");
|
|
1020
1162
|
});
|
|
1021
1163
|
libRoot.dirs.filter((dirname) => dirname.startsWith("__") && !internalLibDirs.has(dirname)).forEach((dirname) => {
|
|
1022
1164
|
addViolation(path4.join("lib", dirname), "unsupported internal lib folder");
|
|
@@ -1196,12 +1338,11 @@ class ScanInfo {
|
|
|
1196
1338
|
})
|
|
1197
1339
|
]);
|
|
1198
1340
|
const routes = exec.type === "lib" ? [] : await exec.getPageKeys();
|
|
1199
|
-
const
|
|
1341
|
+
const common = {
|
|
1200
1342
|
name: exec.name,
|
|
1201
1343
|
type: exec.type,
|
|
1202
1344
|
repoName: exec.workspace.repoName,
|
|
1203
1345
|
serveDomain: WorkspaceExecutor.getBaseDevEnv(path4.join(exec.workspace.workspaceRoot, ".env")).serveDomain,
|
|
1204
|
-
akanConfig: akanConfig2,
|
|
1205
1346
|
files,
|
|
1206
1347
|
libDeps,
|
|
1207
1348
|
pkgDeps,
|
|
@@ -1209,6 +1350,7 @@ class ScanInfo {
|
|
|
1209
1350
|
devDependencies: npmDevDeps.filter((dep) => !isAkanFrameworkDependency(dep)),
|
|
1210
1351
|
routes
|
|
1211
1352
|
};
|
|
1353
|
+
const scanResult = akanConfig2 instanceof AkanAppConfig ? { ...common, akanConfig: akanConfig2 } : { ...common, akanConfig: akanConfig2 };
|
|
1212
1354
|
return scanResult;
|
|
1213
1355
|
}
|
|
1214
1356
|
constructor(scanResult) {
|
|
@@ -1634,7 +1776,7 @@ class Executor {
|
|
|
1634
1776
|
}));
|
|
1635
1777
|
});
|
|
1636
1778
|
proc.on("exit", (code, signal) => {
|
|
1637
|
-
if (
|
|
1779
|
+
if (code || signal)
|
|
1638
1780
|
reject(new CommandExecutionError({
|
|
1639
1781
|
command,
|
|
1640
1782
|
cwd,
|
|
@@ -1732,7 +1874,7 @@ class Executor {
|
|
|
1732
1874
|
}));
|
|
1733
1875
|
});
|
|
1734
1876
|
proc.on("exit", (code, signal) => {
|
|
1735
|
-
if (
|
|
1877
|
+
if (code || signal)
|
|
1736
1878
|
reject(new CommandExecutionError({
|
|
1737
1879
|
command: modulePath,
|
|
1738
1880
|
args,
|
|
@@ -1819,7 +1961,8 @@ class Executor {
|
|
|
1819
1961
|
const dir = path5.dirname(writePath);
|
|
1820
1962
|
if (!await FileSys.dirExists(dir))
|
|
1821
1963
|
await mkdir(dir, { recursive: true });
|
|
1822
|
-
let contentStr = typeof content === "string" ? content : JSON.stringify(content, null, 2)
|
|
1964
|
+
let contentStr = typeof content === "string" ? content : `${JSON.stringify(content, null, 2)}
|
|
1965
|
+
`;
|
|
1823
1966
|
if (await FileSys.fileExists(writePath)) {
|
|
1824
1967
|
const currentContent = await FileSys.readText(writePath);
|
|
1825
1968
|
if (currentContent === contentStr || !overwrite) {
|
|
@@ -2028,7 +2171,7 @@ class Executor {
|
|
|
2028
2171
|
return this._applyTemplate({ ...options, dict });
|
|
2029
2172
|
}
|
|
2030
2173
|
async getTypeChecker() {
|
|
2031
|
-
const { TypeChecker } = await import("./typeChecker-
|
|
2174
|
+
const { TypeChecker } = await import("./typeChecker-g6bh0xfv.js");
|
|
2032
2175
|
this.typeChecker ??= new TypeChecker(this);
|
|
2033
2176
|
return this.typeChecker;
|
|
2034
2177
|
}
|
|
@@ -2109,7 +2252,7 @@ class WorkspaceExecutor extends Executor {
|
|
|
2109
2252
|
static #execs = new Map;
|
|
2110
2253
|
static fromRoot({
|
|
2111
2254
|
workspaceRoot = process.cwd(),
|
|
2112
|
-
repoName =
|
|
2255
|
+
repoName = resolveRepoName(workspaceRoot)
|
|
2113
2256
|
} = {}) {
|
|
2114
2257
|
return WorkspaceExecutor.#execs.get(repoName) ?? new WorkspaceExecutor({ workspaceRoot, repoName });
|
|
2115
2258
|
}
|
|
@@ -2297,6 +2440,18 @@ class SysExecutor extends Executor {
|
|
|
2297
2440
|
const path6 = this.type === "app" ? `apps/${this.name}/lib` : `libs/${this.name}/lib`;
|
|
2298
2441
|
return await this.workspace.getDirInModule(path6, this.name);
|
|
2299
2442
|
}
|
|
2443
|
+
async getPageConventionViolations() {
|
|
2444
|
+
if (!await this.exists("page"))
|
|
2445
|
+
return [];
|
|
2446
|
+
const violations = [];
|
|
2447
|
+
for (const entry of await this.getAllFiles("**/*", { cwd: this.getPath("page") })) {
|
|
2448
|
+
const relativePath = entry.split(path5.sep).join("/");
|
|
2449
|
+
const reason = getPageSourceFileViolation(relativePath);
|
|
2450
|
+
if (reason)
|
|
2451
|
+
violations.push({ relativePath: `page/${relativePath}`, reason });
|
|
2452
|
+
}
|
|
2453
|
+
return violations;
|
|
2454
|
+
}
|
|
2300
2455
|
#scanInfo = null;
|
|
2301
2456
|
hasScanInfo() {
|
|
2302
2457
|
return this.#scanInfo !== null;
|
|
@@ -2485,7 +2640,7 @@ class SysExecutor extends Executor {
|
|
|
2485
2640
|
class AppExecutor extends SysExecutor {
|
|
2486
2641
|
static #routeSourceValidator = null;
|
|
2487
2642
|
static async#getRouteSourceValidator() {
|
|
2488
|
-
AppExecutor.#routeSourceValidator ??= (await import("./routeSourceValidator-
|
|
2643
|
+
AppExecutor.#routeSourceValidator ??= (await import("./routeSourceValidator-7fycdqyv.js")).RouteSourceValidator;
|
|
2489
2644
|
return AppExecutor.#routeSourceValidator;
|
|
2490
2645
|
}
|
|
2491
2646
|
dist;
|
|
@@ -2549,10 +2704,15 @@ class AppExecutor extends SysExecutor {
|
|
|
2549
2704
|
await Promise.all([this.dist.mkdir("private"), this.dist.mkdir("public")]);
|
|
2550
2705
|
await Promise.all([
|
|
2551
2706
|
this.cp("private", `${this.dist.cwdPath}/private`, { dereference: true }),
|
|
2552
|
-
this.cp("public", `${this.dist.cwdPath}/public`, { dereference: true })
|
|
2707
|
+
...akanConfig2.web.ssr ? [this.cp("public", `${this.dist.cwdPath}/public`, { dereference: true })] : []
|
|
2553
2708
|
]);
|
|
2554
|
-
} else
|
|
2709
|
+
} else {
|
|
2555
2710
|
await this.removeDir(".akan");
|
|
2711
|
+
if (!akanConfig2.web.ssr || !akanConfig2.web.csr)
|
|
2712
|
+
this.logger.verbose(`akan.config.ts disables web.${!akanConfig2.web.ssr ? "ssr" : "csr"}; \`akan start\` still serves it, \`akan build\` will not`);
|
|
2713
|
+
}
|
|
2714
|
+
if (type === "start")
|
|
2715
|
+
process.env.NODE_ENV = "development";
|
|
2556
2716
|
const devPort = type === "start" ? (await this.getDevPort()).toString() : undefined;
|
|
2557
2717
|
const env = this.getCommandEnv({
|
|
2558
2718
|
AKAN_COMMAND_TYPE: type,
|
|
@@ -2641,7 +2801,8 @@ class AppExecutor extends SysExecutor {
|
|
|
2641
2801
|
}
|
|
2642
2802
|
if (!owner)
|
|
2643
2803
|
owners.set(routeId, { absPath, fromLib });
|
|
2644
|
-
const
|
|
2804
|
+
const layoutSegments = getRootBoundarySegments(key);
|
|
2805
|
+
const isRootLayout = layoutSegments !== null && isRootBoundarySegments(layoutSegments, akanConfig2.basePaths);
|
|
2645
2806
|
const routeSource = await Bun.file(absPath).text();
|
|
2646
2807
|
const validator = await AppExecutor.#getRouteSourceValidator();
|
|
2647
2808
|
if (parsed.kind === "overrides")
|
|
@@ -2869,7 +3030,7 @@ class LibExecutor extends SysExecutor {
|
|
|
2869
3030
|
async getConfig({ refresh } = {}) {
|
|
2870
3031
|
if (this.#akanConfig && !refresh)
|
|
2871
3032
|
return this.#akanConfig;
|
|
2872
|
-
this.#akanConfig = await AkanLibConfig.from(this);
|
|
3033
|
+
this.#akanConfig = await AkanLibConfig.from(this, { bustImportCache: refresh });
|
|
2873
3034
|
return this.#akanConfig;
|
|
2874
3035
|
}
|
|
2875
3036
|
}
|
|
@@ -2966,7 +3127,7 @@ class PkgExecutor extends Executor {
|
|
|
2966
3127
|
default: "./index.ts"
|
|
2967
3128
|
}
|
|
2968
3129
|
},
|
|
2969
|
-
engines: { bun: ">=1.
|
|
3130
|
+
engines: { bun: ">=1.4.0" },
|
|
2970
3131
|
...dependencyMaps
|
|
2971
3132
|
};
|
|
2972
3133
|
await Promise.all([this.dist.writeJson("package.json", distPkgJson), this.writeJson("package.json", distPkgJson)]);
|
|
@@ -3009,4 +3170,4 @@ class ModuleExecutor extends Executor {
|
|
|
3009
3170
|
}
|
|
3010
3171
|
}
|
|
3011
3172
|
|
|
3012
|
-
export { AGENT_BLOCK_START, AGENT_BLOCK_END, upsertAgentBlock, extractAgentBlock, renderRecipeEntries, collectScopeRecipeSources, renderScopeAgentBlock,
|
|
3173
|
+
export { AGENT_BLOCK_START, AGENT_BLOCK_END, stampBlockVersion, extractBlockVersion, readDevkitVersion, upsertAgentBlock, extractAgentBlock, renderRecipeEntries, collectScopeRecipeSources, renderScopeAgentBlock, CLAUDE_COMMENT_RULE, rootAllowedFiles, rootAllowedDirs, isAllowedLibFacetRootFile, isScannedRootEntry, CommandExecutionError, Executor, WorkspaceExecutor, SysExecutor, AppExecutor, LibExecutor, PkgExecutor, ModuleExecutor };
|