@akanjs/cli 3.0.0-alpha.88 → 3.0.0-alpha.89
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/{abstractCompactor-pwc6d6yk.js → abstractCompactor-cefxzggj.js} +2 -2
- package/{agent.command-180hh0ye.js → agent.command-r93wmq7m.js} +6 -6
- package/{application.command-v8dywdqh.js → application.command-5nqfqgdn.js} +9 -8
- package/{applicationBuildRunner-27wyznpv.js → applicationBuildRunner-b21m07fs.js} +4 -3
- package/{applicationReleasePackager-ktjt0erc.js → applicationReleasePackager-3wh58n2m.js} +2 -2
- package/buildBatch.proc.js +4 -4
- package/{capacitorApp-kwa67kzs.js → capacitorApp-gzcx6txb.js} +3 -3
- package/{cloud.command-12k4wy4x.js → cloud.command-g0pk0k60.js} +11 -11
- package/{context.command-dk2m2sjx.js → context.command-qd8kqrnh.js} +14 -14
- package/{dependencyScanner-c64m6fxp.js → dependencyScanner-shs82ynp.js} +2 -2
- package/devTui-2xf0meaq.js +552 -0
- package/devTuiView-7jy8f30g.js +9 -0
- package/{guideline.command-w6ddv13r.js → guideline.command-f38x8jhw.js} +4 -4
- package/guidelines/agentRule/agentRule.instruction.md +9 -1
- package/guidelines/conventions/conventions.instruction.md +30 -0
- package/guidelines/modelStore/modelStore.instruction.md +12 -0
- package/guidelines/modelTemplate/modelTemplate.instruction.md +5 -0
- package/guidelines/runtimeRule/runtimeRule.instruction.md +37 -0
- package/incrementalBuilder.proc.js +8 -5
- package/{index-5y7qba1c.js → index-0emb9eat.js} +3 -3
- package/{index-cd5x18qh.js → index-3vvbv974.js} +4 -4
- package/{index-v0s24t8j.js → index-5xdqxbn9.js} +3 -3
- package/{index-k86zc21w.js → index-9bwhxrqf.js} +6 -6
- package/{index-ft1sfjz0.js → index-cezy7yb3.js} +66 -7
- package/{index-a6c5pc4p.js → index-d61rcfa2.js} +614 -62
- package/{index-gz0c482j.js → index-deekbtkj.js} +6 -6
- package/{index-saheq2bs.js → index-e82dyeqy.js} +1 -1
- package/{index-j9vnq8tr.js → index-h759vjfa.js} +3 -3
- package/{index-z3c9mmw4.js → index-jydtyzva.js} +2 -2
- package/{index-mfm35dhh.js → index-kcxmv48c.js} +1 -1
- package/{index-6c3ex9qw.js → index-kfnr6c19.js} +4 -4
- package/{index-1kzsn94d.js → index-mpmyqm1y.js} +1 -1
- package/{index-wet2ytnr.js → index-n85fer99.js} +2 -2
- package/{index-b2nt0w0k.js → index-pgsswppj.js} +1 -1
- package/{index-m9c7k0gm.js → index-pvb4vdwr.js} +1 -1
- package/{index-ayy5ecax.js → index-q0y2jq9j.js} +13 -1
- package/{index-k1n0h7dk.js → index-q8sn827n.js} +254 -126
- package/{index-dq6wq1tv.js → index-r50qen0z.js} +10 -10
- package/{index-5n0hf8r9.js → index-rntcdss1.js} +3 -3
- package/{index-a8h184wr.js → index-sjak5v5b.js} +6 -6
- package/{index-x23688ar.js → index-w8kmx1b6.js} +8 -4
- package/{index-qcracvc9.js → index-y74k5anj.js} +3 -3
- package/{index-xxe90kqy.js → index-zkvpaggp.js} +2 -2
- package/index.js +20 -20
- package/{library.command-wpedct6c.js → library.command-em103wtn.js} +4 -4
- package/{localRegistry.command-3cew8f75.js → localRegistry.command-gz8apn4y.js} +10 -10
- package/{module.command-8n4kct3e.js → module.command-451pztkc.js} +7 -7
- package/{package.command-fcbd0b1d.js → package.command-rfhyf38t.js} +5 -5
- package/package.json +2 -2
- package/{page.command-x4379grq.js → page.command-kt19da5g.js} +4 -4
- package/{primitive.command-8etmnqhq.js → primitive.command-pgy69ere.js} +8 -8
- package/{quality.command-hfx7z8yr.js → quality.command-gpe2vqb5.js} +3 -3
- package/{repair.command-j0fs5qkz.js → repair.command-2sbrz187.js} +6 -6
- package/{scalar.command-2emk89eh.js → scalar.command-jcf4e5sv.js} +6 -6
- package/{subspace.command-nr32nm35.js → subspace.command-kqzqtk0p.js} +6 -6
- package/{workflow.command-cvpmzwjg.js → workflow.command-m4z25a2p.js} +11 -11
- package/{workspace.command-rqnms515.js → workspace.command-dqgj9zbk.js} +22 -22
|
@@ -1,11 +1,126 @@
|
|
|
1
1
|
// @bun
|
|
2
2
|
import {
|
|
3
3
|
FileSys
|
|
4
|
-
} from "./index-
|
|
4
|
+
} from "./index-q0y2jq9j.js";
|
|
5
5
|
import {
|
|
6
6
|
getDirname2
|
|
7
7
|
} from "./index-6wwzs1bc.js";
|
|
8
8
|
|
|
9
|
+
// pkgs/@akanjs/devkit/codegenLock.ts
|
|
10
|
+
import { mkdir, open, readFile, rm, stat } from "fs/promises";
|
|
11
|
+
import path from "path";
|
|
12
|
+
import { Logger } from "akanjs/common";
|
|
13
|
+
|
|
14
|
+
class CodegenLock {
|
|
15
|
+
static fileName = "codegen.lock";
|
|
16
|
+
static waitTimeoutMs = 1e4;
|
|
17
|
+
static unknownHolderStaleMs = 60000;
|
|
18
|
+
static #pollMs = 25;
|
|
19
|
+
static #logger = new Logger("CodegenLock");
|
|
20
|
+
static #queue = Promise.resolve();
|
|
21
|
+
static pathIn(workspaceRoot) {
|
|
22
|
+
return path.join(workspaceRoot, "local", ".akan", CodegenLock.fileName);
|
|
23
|
+
}
|
|
24
|
+
static async run(workspaceRoot, label, fn) {
|
|
25
|
+
const ahead = CodegenLock.#queue;
|
|
26
|
+
let done;
|
|
27
|
+
CodegenLock.#queue = new Promise((resolve) => {
|
|
28
|
+
done = resolve;
|
|
29
|
+
});
|
|
30
|
+
try {
|
|
31
|
+
await CodegenLock.#waitForQueue(ahead, label);
|
|
32
|
+
return await CodegenLock.#withFileLock(workspaceRoot, label, fn);
|
|
33
|
+
} finally {
|
|
34
|
+
done();
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
static async#waitForQueue(ahead, label) {
|
|
38
|
+
let timer = null;
|
|
39
|
+
const expired = new Promise((resolve) => {
|
|
40
|
+
timer = setTimeout(() => resolve("expired"), CodegenLock.waitTimeoutMs);
|
|
41
|
+
});
|
|
42
|
+
try {
|
|
43
|
+
if (await Promise.race([ahead.then(() => "done"), expired]) === "expired")
|
|
44
|
+
CodegenLock.#logger.warn(`codegen lock queued past ${CodegenLock.waitTimeoutMs}ms in this process; continuing without waiting (${label})`);
|
|
45
|
+
} finally {
|
|
46
|
+
if (timer)
|
|
47
|
+
clearTimeout(timer);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
static async#withFileLock(workspaceRoot, label, fn) {
|
|
51
|
+
const lockPath = CodegenLock.pathIn(workspaceRoot);
|
|
52
|
+
await mkdir(path.dirname(lockPath), { recursive: true }).catch(() => {
|
|
53
|
+
return;
|
|
54
|
+
});
|
|
55
|
+
const held = await CodegenLock.#acquire(lockPath, label);
|
|
56
|
+
try {
|
|
57
|
+
return await fn();
|
|
58
|
+
} finally {
|
|
59
|
+
if (held)
|
|
60
|
+
await rm(lockPath, { force: true }).catch(() => {
|
|
61
|
+
return;
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
static async#acquire(lockPath, label) {
|
|
66
|
+
const deadline = Date.now() + CodegenLock.waitTimeoutMs;
|
|
67
|
+
for (;; ) {
|
|
68
|
+
const handle = await open(lockPath, "wx").catch(() => null);
|
|
69
|
+
if (handle) {
|
|
70
|
+
await handle.writeFile(JSON.stringify({ pid: process.pid, at: Date.now(), label })).catch(() => {
|
|
71
|
+
return;
|
|
72
|
+
});
|
|
73
|
+
await handle.close().catch(() => {
|
|
74
|
+
return;
|
|
75
|
+
});
|
|
76
|
+
return true;
|
|
77
|
+
}
|
|
78
|
+
if (await CodegenLock.#reclaimIfAbandoned(lockPath))
|
|
79
|
+
continue;
|
|
80
|
+
if (Date.now() >= deadline) {
|
|
81
|
+
CodegenLock.#logger.warn(`codegen lock at ${lockPath} held past ${CodegenLock.waitTimeoutMs}ms; continuing without it (${label})`);
|
|
82
|
+
return false;
|
|
83
|
+
}
|
|
84
|
+
await Bun.sleep(CodegenLock.#pollMs);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
static async#reclaimIfAbandoned(lockPath) {
|
|
88
|
+
const info = await stat(lockPath).catch(() => null);
|
|
89
|
+
if (!info)
|
|
90
|
+
return true;
|
|
91
|
+
const holder = CodegenLock.#parseHolder(await readFile(lockPath, "utf8").catch(() => ""));
|
|
92
|
+
if (holder) {
|
|
93
|
+
if (CodegenLock.#isAlive(holder.pid))
|
|
94
|
+
return false;
|
|
95
|
+
} else if (Date.now() - info.mtimeMs < CodegenLock.unknownHolderStaleMs)
|
|
96
|
+
return false;
|
|
97
|
+
await rm(lockPath, { force: true }).catch(() => {
|
|
98
|
+
return;
|
|
99
|
+
});
|
|
100
|
+
return true;
|
|
101
|
+
}
|
|
102
|
+
static #parseHolder(raw) {
|
|
103
|
+
try {
|
|
104
|
+
const parsed = JSON.parse(raw);
|
|
105
|
+
if (typeof parsed.pid !== "number" || typeof parsed.at !== "number")
|
|
106
|
+
return null;
|
|
107
|
+
return { pid: parsed.pid, at: parsed.at, label: typeof parsed.label === "string" ? parsed.label : "" };
|
|
108
|
+
} catch {
|
|
109
|
+
return null;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
static #isAlive(pid) {
|
|
113
|
+
if (!Number.isInteger(pid) || pid <= 0)
|
|
114
|
+
return false;
|
|
115
|
+
try {
|
|
116
|
+
process.kill(pid, 0);
|
|
117
|
+
return true;
|
|
118
|
+
} catch (error) {
|
|
119
|
+
return error.code === "EPERM";
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
9
124
|
// pkgs/@akanjs/devkit/spinner.ts
|
|
10
125
|
import ora from "ora";
|
|
11
126
|
|
|
@@ -80,20 +195,20 @@ import { readFileSync as readFileSync2 } from "fs";
|
|
|
80
195
|
import {
|
|
81
196
|
copyFile,
|
|
82
197
|
cp as cpEntry,
|
|
83
|
-
mkdir as
|
|
198
|
+
mkdir as mkdir3,
|
|
84
199
|
readdir as readDirEntries,
|
|
85
200
|
realpath,
|
|
86
|
-
rm as
|
|
87
|
-
stat,
|
|
201
|
+
rm as rm3,
|
|
202
|
+
stat as stat2,
|
|
88
203
|
symlink
|
|
89
204
|
} from "fs/promises";
|
|
90
|
-
import
|
|
205
|
+
import path8 from "path";
|
|
91
206
|
import { pathToFileURL } from "url";
|
|
92
207
|
import {
|
|
93
208
|
capitalize,
|
|
94
209
|
getPageSourceFileViolation,
|
|
95
210
|
isRouteSourceFile,
|
|
96
|
-
Logger,
|
|
211
|
+
Logger as Logger2,
|
|
97
212
|
parseRouteModuleKey,
|
|
98
213
|
validatePageSourceFile,
|
|
99
214
|
validateSubRoutePageKey
|
|
@@ -241,8 +356,9 @@ ${CLAUDE_COMMENT_RULE}
|
|
|
241
356
|
|
|
242
357
|
// pkgs/@akanjs/devkit/akanConfig/akanConfig.ts
|
|
243
358
|
import fs from "fs";
|
|
244
|
-
import
|
|
359
|
+
import path2 from "path";
|
|
245
360
|
import { fileURLToPath } from "url";
|
|
361
|
+
import { normalizeRoutePrefix } from "akanjs/base";
|
|
246
362
|
import { resolveAkanI18nConfig } from "akanjs/common";
|
|
247
363
|
|
|
248
364
|
// pkgs/@akanjs/devkit/akanConfig/types.ts
|
|
@@ -329,8 +445,8 @@ var normalizeIndexPath = (indexPath) => {
|
|
|
329
445
|
const normalized = indexPath?.trim();
|
|
330
446
|
if (!normalized)
|
|
331
447
|
return;
|
|
332
|
-
const
|
|
333
|
-
return
|
|
448
|
+
const path = `/${normalized.replace(/^\/+|\/+$/g, "")}`;
|
|
449
|
+
return path === "/" ? "/" : path;
|
|
334
450
|
};
|
|
335
451
|
var normalizeStringList = (values) => {
|
|
336
452
|
const normalized = values?.map((value) => value.trim()).filter(Boolean) ?? [];
|
|
@@ -397,6 +513,7 @@ class AkanAppConfig {
|
|
|
397
513
|
optimizeImports;
|
|
398
514
|
images;
|
|
399
515
|
i18n;
|
|
516
|
+
api;
|
|
400
517
|
publicEnv;
|
|
401
518
|
mobile;
|
|
402
519
|
hasMobileConfig;
|
|
@@ -430,6 +547,12 @@ class AkanAppConfig {
|
|
|
430
547
|
this.i18n = resolveAkanI18nConfig(config?.i18n);
|
|
431
548
|
process.env.AKAN_PUBLIC_DEFAULT_LOCALE = this.i18n.defaultLocale;
|
|
432
549
|
process.env.AKAN_PUBLIC_LOCALES = this.i18n.locales.join(",");
|
|
550
|
+
this.api = {
|
|
551
|
+
prefix: normalizeRoutePrefix(config?.api?.prefix) ?? "/api",
|
|
552
|
+
websocketPrefix: normalizeRoutePrefix(config?.api?.websocketPrefix) ?? "/ws"
|
|
553
|
+
};
|
|
554
|
+
process.env.AKAN_PUBLIC_API_PREFIX = this.api.prefix;
|
|
555
|
+
process.env.AKAN_PUBLIC_WS_PREFIX = this.api.websocketPrefix;
|
|
433
556
|
this.publicEnv = config?.publicEnv ?? [];
|
|
434
557
|
this.secrets = config?.secrets ?? [];
|
|
435
558
|
this.assets = {
|
|
@@ -604,6 +727,8 @@ ENV AKAN_PUBLIC_ENV=${this.baseDevEnv.env}
|
|
|
604
727
|
${this.basePaths.size ? `ENV AKAN_PUBLIC_BASE_PATHS=${[...this.basePaths].join(",")}` : ""}
|
|
605
728
|
ENV AKAN_PUBLIC_DEFAULT_LOCALE=${this.i18n.defaultLocale}
|
|
606
729
|
ENV AKAN_PUBLIC_LOCALES=${this.i18n.locales.join(",")}
|
|
730
|
+
ENV AKAN_PUBLIC_API_PREFIX=${this.api.prefix}
|
|
731
|
+
ENV AKAN_PUBLIC_WS_PREFIX=${this.api.websocketPrefix}
|
|
607
732
|
ENV AKAN_PUBLIC_OPERATION_MODE=cloud
|
|
608
733
|
ENV AKAN_LOG_TO_FILE=0
|
|
609
734
|
${webEnvLines}
|
|
@@ -618,7 +743,7 @@ CMD [${command.map((c) => `"${c}"`).join(",")}]`;
|
|
|
618
743
|
static async from(app, { bustImportCache = false } = {}) {
|
|
619
744
|
const [configImp, baseDevEnv, libs, rootPackageJson] = await Promise.all([
|
|
620
745
|
AkanAppConfig.importConfigModule(app.cwdPath, { bustImportCache }),
|
|
621
|
-
WorkspaceExecutor.getBaseDevEnv(
|
|
746
|
+
WorkspaceExecutor.getBaseDevEnv(path2.join(app.workspace.workspaceRoot, ".env")),
|
|
622
747
|
app.workspace.getLibs(),
|
|
623
748
|
app.workspace.getPackageJson()
|
|
624
749
|
]);
|
|
@@ -698,11 +823,11 @@ var akanPackageJson = null;
|
|
|
698
823
|
function getAkanPackageJson() {
|
|
699
824
|
if (akanPackageJson)
|
|
700
825
|
return akanPackageJson;
|
|
701
|
-
const sourceDir =
|
|
826
|
+
const sourceDir = path2.dirname(fileURLToPath(import.meta.url));
|
|
702
827
|
const packageJsonPaths = [
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
828
|
+
path2.join(sourceDir, "../../../akanjs/package.json"),
|
|
829
|
+
path2.join(process.cwd(), "pkgs/akanjs/package.json"),
|
|
830
|
+
path2.join(path2.dirname(Bun.main), "node_modules/akanjs/package.json")
|
|
706
831
|
];
|
|
707
832
|
try {
|
|
708
833
|
packageJsonPaths.unshift(Bun.resolveSync("akanjs/package.json", sourceDir));
|
|
@@ -757,25 +882,25 @@ class AkanLibConfig {
|
|
|
757
882
|
//! need to refactor
|
|
758
883
|
var increaseBuildNum = async (app) => {
|
|
759
884
|
const appConfig = await AkanAppConfig.from(app);
|
|
760
|
-
const akanConfigPath =
|
|
885
|
+
const akanConfigPath = path2.join(app.cwdPath, "akan.config.ts");
|
|
761
886
|
const akanConfig = fs.readFileSync(akanConfigPath, "utf8");
|
|
762
887
|
const akanConfigContent = akanConfig.replace(`buildNum: ${appConfig.mobile.buildNum}`, `buildNum: ${appConfig.mobile.buildNum + 1}`);
|
|
763
888
|
fs.writeFileSync(akanConfigPath, akanConfigContent);
|
|
764
889
|
};
|
|
765
890
|
var decreaseBuildNum = async (app) => {
|
|
766
891
|
const appConfig = await AkanAppConfig.from(app);
|
|
767
|
-
const akanConfigPath =
|
|
892
|
+
const akanConfigPath = path2.join(app.cwdPath, "akan.config.ts");
|
|
768
893
|
const akanConfig = fs.readFileSync(akanConfigPath, "utf8");
|
|
769
894
|
const akanConfigContent = akanConfig.replace(`buildNum: ${appConfig.mobile.buildNum}`, `buildNum: ${appConfig.mobile.buildNum - 1}`);
|
|
770
895
|
fs.writeFileSync(akanConfigPath, akanConfigContent);
|
|
771
896
|
};
|
|
772
897
|
// pkgs/@akanjs/devkit/artifact/implicitRootLayout.ts
|
|
773
|
-
import { mkdir } from "fs/promises";
|
|
774
|
-
import
|
|
898
|
+
import { mkdir as mkdir2 } from "fs/promises";
|
|
899
|
+
import path4 from "path";
|
|
775
900
|
|
|
776
901
|
// pkgs/@akanjs/devkit/transforms/asyncDefaultExportDetector.ts
|
|
777
902
|
import fs2 from "fs";
|
|
778
|
-
import
|
|
903
|
+
import path3 from "path";
|
|
779
904
|
|
|
780
905
|
class AsyncDefaultExportDetector {
|
|
781
906
|
static #typescriptLoad;
|
|
@@ -786,7 +911,7 @@ class AsyncDefaultExportDetector {
|
|
|
786
911
|
static async detect(moduleAbsPath) {
|
|
787
912
|
try {
|
|
788
913
|
const typescript = await AsyncDefaultExportDetector.#loadTypescript();
|
|
789
|
-
const source = fs2.readFileSync(
|
|
914
|
+
const source = fs2.readFileSync(path3.resolve(moduleAbsPath), "utf8");
|
|
790
915
|
const sourceFile = typescript.createSourceFile(moduleAbsPath, source, typescript.ScriptTarget.Latest, true, AsyncDefaultExportDetector.#scriptKind(typescript, moduleAbsPath));
|
|
791
916
|
return new AsyncDefaultExportDetector(typescript).detectInSourceFile(sourceFile);
|
|
792
917
|
} catch {
|
|
@@ -853,16 +978,16 @@ class AsyncDefaultExportDetector {
|
|
|
853
978
|
// pkgs/@akanjs/devkit/artifact/implicitRootLayout.ts
|
|
854
979
|
var LAYOUT_KEY_RE = /^\.\/(.+\/)?_layout\.(tsx|ts|jsx|js)$/;
|
|
855
980
|
async function appHasStModule(appCwdPath) {
|
|
856
|
-
return Bun.file(
|
|
981
|
+
return Bun.file(path4.join(appCwdPath, "lib", "st.ts")).exists();
|
|
857
982
|
}
|
|
858
|
-
var IMPLICIT_LAYOUT_DIR =
|
|
859
|
-
var IMPLICIT_DICT_DIR =
|
|
860
|
-
var IMPLICIT_OVERRIDES_DIR =
|
|
983
|
+
var IMPLICIT_LAYOUT_DIR = path4.join(".akan", "generated", "root-layouts");
|
|
984
|
+
var IMPLICIT_DICT_DIR = path4.join(".akan", "generated", "dict");
|
|
985
|
+
var IMPLICIT_OVERRIDES_DIR = path4.join(".akan", "generated", "overrides");
|
|
861
986
|
var OVERRIDES_KEY_RE = /^\.\/(.+\/)?_overrides\.(tsx|ts|jsx|js)$/;
|
|
862
987
|
async function writeGeneratedOverridesLayoutFile(opts) {
|
|
863
988
|
const filename = `${opts.key.replace(/^\.\//, "").replace(/[^a-zA-Z0-9]+/g, "_")}.tsx`;
|
|
864
|
-
const absPath =
|
|
865
|
-
const userRel =
|
|
989
|
+
const absPath = path4.join(path4.resolve(opts.appCwdPath), IMPLICIT_OVERRIDES_DIR, filename);
|
|
990
|
+
const userRel = path4.relative(path4.dirname(absPath), opts.userAbsPath).split(path4.sep).join("/");
|
|
866
991
|
const userSpecifier = userRel.startsWith(".") ? userRel : `./${userRel}`;
|
|
867
992
|
const source = `"use client";
|
|
868
993
|
import { UiOverrideProvider } from "akanjs/ui";
|
|
@@ -890,10 +1015,10 @@ function implicitRootLayoutKey(segments) {
|
|
|
890
1015
|
}
|
|
891
1016
|
function implicitRootLayoutAbsPath(appCwdPath, segments) {
|
|
892
1017
|
const filename = segments.length ? `${segments.join("__")}__root_layout.tsx` : "__root_layout.tsx";
|
|
893
|
-
return
|
|
1018
|
+
return path4.join(path4.resolve(appCwdPath), IMPLICIT_LAYOUT_DIR, filename);
|
|
894
1019
|
}
|
|
895
1020
|
function implicitDictionaryMacroAbsPath(appCwdPath) {
|
|
896
|
-
return
|
|
1021
|
+
return path4.join(path4.resolve(appCwdPath), IMPLICIT_DICT_DIR, "useDict.ts");
|
|
897
1022
|
}
|
|
898
1023
|
function isRootBoundarySegments(segments, basePaths) {
|
|
899
1024
|
const firstVisibleIndex = segments.findIndex((segment) => !/^\(.+\)$/.test(segment));
|
|
@@ -916,7 +1041,7 @@ function findRootBoundaries(pageKeys, appCwdPath, basePaths) {
|
|
|
916
1041
|
const id = segments.join("/");
|
|
917
1042
|
boundaries.set(id, {
|
|
918
1043
|
sourceKey: key,
|
|
919
|
-
sourceAbsPath:
|
|
1044
|
+
sourceAbsPath: path4.resolve(appCwdPath, "page", key.replace(/^\.\//, "")),
|
|
920
1045
|
segments
|
|
921
1046
|
});
|
|
922
1047
|
}
|
|
@@ -934,21 +1059,21 @@ function findExplicitRootLayoutAbsPath(pageKeys, appCwdPath) {
|
|
|
934
1059
|
const segments = getRootBoundarySegments(key);
|
|
935
1060
|
return segments !== null && segments.length === 0;
|
|
936
1061
|
});
|
|
937
|
-
return rootLayoutKey ?
|
|
1062
|
+
return rootLayoutKey ? path4.resolve(appCwdPath, "page", rootLayoutKey.replace(/^\.\//, "")) : null;
|
|
938
1063
|
}
|
|
939
1064
|
function routePrefixForSegments(segments) {
|
|
940
1065
|
const visible = segments.filter((segment) => !/^\(.+\)$/.test(segment));
|
|
941
1066
|
return visible[0] ?? null;
|
|
942
1067
|
}
|
|
943
1068
|
async function assertEnvClientConvention(appCwdPath, appName) {
|
|
944
|
-
const envPath =
|
|
1069
|
+
const envPath = path4.join(appCwdPath, "env", "env.client.ts");
|
|
945
1070
|
if (!await Bun.file(envPath).exists()) {
|
|
946
1071
|
throw new Error(`[route-convention] app "${appName}" must provide env/env.client.ts exporting "env" for generated System.Provider`);
|
|
947
1072
|
}
|
|
948
1073
|
}
|
|
949
1074
|
async function writeGeneratedDictionaryMacroFile(appCwdPath, appName) {
|
|
950
1075
|
const absPath = implicitDictionaryMacroAbsPath(appCwdPath);
|
|
951
|
-
await
|
|
1076
|
+
await mkdir2(path4.dirname(absPath), { recursive: true });
|
|
952
1077
|
await Bun.write(absPath, `import { getAllDictionary } from "@apps/${appName}/lib/dict" with { type: "macro" };
|
|
953
1078
|
|
|
954
1079
|
export const allDictionary = getAllDictionary();
|
|
@@ -959,13 +1084,13 @@ async function writeGeneratedRootLayoutFile(opts) {
|
|
|
959
1084
|
await assertEnvClientConvention(opts.appCwdPath, opts.appName);
|
|
960
1085
|
const dictMacroAbsPath = opts.includeSystemProvider ? await writeGeneratedDictionaryMacroFile(opts.appCwdPath, opts.appName) : null;
|
|
961
1086
|
const absPath = implicitRootLayoutAbsPath(opts.appCwdPath, opts.boundary.segments);
|
|
962
|
-
await
|
|
963
|
-
const dictMacroRel = dictMacroAbsPath ?
|
|
1087
|
+
await mkdir2(path4.dirname(absPath), { recursive: true });
|
|
1088
|
+
const dictMacroRel = dictMacroAbsPath ? path4.relative(path4.dirname(absPath), dictMacroAbsPath).split(path4.sep).join("/") : null;
|
|
964
1089
|
const dictMacroSpecifier = dictMacroRel ? dictMacroRel.startsWith(".") ? dictMacroRel : `./${dictMacroRel}` : null;
|
|
965
|
-
const sourceRel = opts.boundary.sourceAbsPath ?
|
|
1090
|
+
const sourceRel = opts.boundary.sourceAbsPath ? path4.relative(path4.dirname(absPath), opts.boundary.sourceAbsPath).split(path4.sep).join("/") : null;
|
|
966
1091
|
const sourceSpecifier = sourceRel ? sourceRel.startsWith(".") ? sourceRel : `./${sourceRel}` : null;
|
|
967
1092
|
const inheritedSourceAbsPath = opts.rootSourceAbsPath && opts.rootSourceAbsPath !== opts.boundary.sourceAbsPath ? opts.rootSourceAbsPath : null;
|
|
968
|
-
const inheritedSourceRel = inheritedSourceAbsPath ?
|
|
1093
|
+
const inheritedSourceRel = inheritedSourceAbsPath ? path4.relative(path4.dirname(absPath), inheritedSourceAbsPath).split(path4.sep).join("/") : null;
|
|
969
1094
|
const inheritedSourceSpecifier = inheritedSourceRel ? inheritedSourceRel.startsWith(".") ? inheritedSourceRel : `./${inheritedSourceRel}` : null;
|
|
970
1095
|
const clientImport = opts.includeStInit ? `import { st } from "@apps/${opts.appName}/client";
|
|
971
1096
|
void st;
|
|
@@ -1069,7 +1194,7 @@ ${layoutBinding} return ${layoutReturn};
|
|
|
1069
1194
|
return absPath;
|
|
1070
1195
|
}
|
|
1071
1196
|
async function resolveSsrPageEntries(opts) {
|
|
1072
|
-
const absPageDir =
|
|
1197
|
+
const absPageDir = path4.resolve(opts.appCwdPath, "page");
|
|
1073
1198
|
const hasSt = await appHasStModule(opts.appCwdPath);
|
|
1074
1199
|
const basePaths = opts.basePaths ?? [];
|
|
1075
1200
|
const rootSourceAbsPath = findExplicitRootLayoutAbsPath(opts.pageKeys, opts.appCwdPath);
|
|
@@ -1079,7 +1204,7 @@ async function resolveSsrPageEntries(opts) {
|
|
|
1079
1204
|
return segments !== null && isRootBoundarySegments(segments, basePaths);
|
|
1080
1205
|
}));
|
|
1081
1206
|
const base = await Promise.all(opts.pageKeys.filter((key) => !rootLayoutKeys.has(key)).map(async (key) => {
|
|
1082
|
-
const userAbsPath =
|
|
1207
|
+
const userAbsPath = path4.resolve(absPageDir, key);
|
|
1083
1208
|
if (OVERRIDES_KEY_RE.test(key)) {
|
|
1084
1209
|
const moduleAbsPath = await writeGeneratedOverridesLayoutFile({
|
|
1085
1210
|
appCwdPath: opts.appCwdPath,
|
|
@@ -1114,7 +1239,7 @@ async function resolveSsrPageEntriesForApp(app, pageKeys) {
|
|
|
1114
1239
|
// pkgs/@akanjs/devkit/linter.ts
|
|
1115
1240
|
import { spawn } from "child_process";
|
|
1116
1241
|
import { existsSync, readFileSync } from "fs";
|
|
1117
|
-
import
|
|
1242
|
+
import path5 from "path";
|
|
1118
1243
|
import chalk from "chalk";
|
|
1119
1244
|
var parseBiomeReport = (output) => {
|
|
1120
1245
|
for (let start = output.indexOf("{");start !== -1; start = output.indexOf("{", start + 1)) {
|
|
@@ -1171,13 +1296,13 @@ class Linter {
|
|
|
1171
1296
|
#biomeBin;
|
|
1172
1297
|
constructor(cwdPath) {
|
|
1173
1298
|
this.lintRoot = this.#findBiomeRootPath(cwdPath);
|
|
1174
|
-
this.configPath = Linter.#configPathIn(this.lintRoot) ??
|
|
1175
|
-
const localBiomeBin =
|
|
1299
|
+
this.configPath = Linter.#configPathIn(this.lintRoot) ?? path5.join(this.lintRoot, "biome.json");
|
|
1300
|
+
const localBiomeBin = path5.join(this.lintRoot, "node_modules/.bin/biome");
|
|
1176
1301
|
this.#biomeBin = existsSync(localBiomeBin) ? localBiomeBin : "biome";
|
|
1177
1302
|
}
|
|
1178
1303
|
static #configPathIn(dir) {
|
|
1179
1304
|
for (const fileName of BIOME_CONFIG_FILES) {
|
|
1180
|
-
const configPath =
|
|
1305
|
+
const configPath = path5.join(dir, fileName);
|
|
1181
1306
|
if (existsSync(configPath))
|
|
1182
1307
|
return configPath;
|
|
1183
1308
|
}
|
|
@@ -1186,19 +1311,19 @@ class Linter {
|
|
|
1186
1311
|
#findBiomeRootPath(dir) {
|
|
1187
1312
|
if (Linter.#configPathIn(dir))
|
|
1188
1313
|
return dir;
|
|
1189
|
-
const parentDir =
|
|
1314
|
+
const parentDir = path5.dirname(dir);
|
|
1190
1315
|
if (parentDir === dir)
|
|
1191
1316
|
throw new Error(`biome.json not found from ${dir}`);
|
|
1192
1317
|
return this.#findBiomeRootPath(parentDir);
|
|
1193
1318
|
}
|
|
1194
1319
|
#toBiomePath(filePath) {
|
|
1195
|
-
const relativePath =
|
|
1196
|
-
if (!relativePath.startsWith("..") && !
|
|
1320
|
+
const relativePath = path5.relative(this.lintRoot, filePath);
|
|
1321
|
+
if (!relativePath.startsWith("..") && !path5.isAbsolute(relativePath))
|
|
1197
1322
|
return relativePath;
|
|
1198
1323
|
return filePath;
|
|
1199
1324
|
}
|
|
1200
1325
|
#resolveFilePath(filePath) {
|
|
1201
|
-
return
|
|
1326
|
+
return path5.isAbsolute(filePath) ? filePath : path5.join(this.lintRoot, filePath);
|
|
1202
1327
|
}
|
|
1203
1328
|
async#runBiome(args, input) {
|
|
1204
1329
|
return await new Promise((resolve, reject) => {
|
|
@@ -1223,7 +1348,7 @@ class Linter {
|
|
|
1223
1348
|
const diagnosticPath = diagnostic.location?.path;
|
|
1224
1349
|
if (!diagnosticPath)
|
|
1225
1350
|
return fallbackFilePath;
|
|
1226
|
-
return
|
|
1351
|
+
return path5.isAbsolute(diagnosticPath) ? diagnosticPath : path5.join(this.lintRoot, diagnosticPath);
|
|
1227
1352
|
}
|
|
1228
1353
|
#createLintMessage(diagnostic) {
|
|
1229
1354
|
const start = diagnostic.location?.start;
|
|
@@ -1453,7 +1578,7 @@ ${errorText}, ${warningText} found`];
|
|
|
1453
1578
|
|
|
1454
1579
|
// pkgs/@akanjs/devkit/repoIdentity.ts
|
|
1455
1580
|
import { execFileSync } from "child_process";
|
|
1456
|
-
import
|
|
1581
|
+
import path6 from "path";
|
|
1457
1582
|
var resolved = new Map;
|
|
1458
1583
|
var readRemoteName = (workspaceRoot) => {
|
|
1459
1584
|
try {
|
|
@@ -1471,14 +1596,14 @@ var resolveRepoName = (workspaceRoot) => {
|
|
|
1471
1596
|
const cached = resolved.get(workspaceRoot);
|
|
1472
1597
|
if (cached)
|
|
1473
1598
|
return cached;
|
|
1474
|
-
const repoName = readRemoteName(workspaceRoot) ??
|
|
1599
|
+
const repoName = readRemoteName(workspaceRoot) ?? path6.basename(workspaceRoot);
|
|
1475
1600
|
resolved.set(workspaceRoot, repoName);
|
|
1476
1601
|
return repoName;
|
|
1477
1602
|
};
|
|
1478
1603
|
|
|
1479
1604
|
// pkgs/@akanjs/devkit/scanInfo.ts
|
|
1480
|
-
import { rm } from "fs/promises";
|
|
1481
|
-
import
|
|
1605
|
+
import { rm as rm2 } from "fs/promises";
|
|
1606
|
+
import path7 from "path";
|
|
1482
1607
|
|
|
1483
1608
|
// pkgs/@akanjs/devkit/workspaceLayout.ts
|
|
1484
1609
|
var appRootAllowedFiles = new Set([
|
|
@@ -1582,16 +1707,16 @@ var moduleUiFileTypes = {
|
|
|
1582
1707
|
scalar: new Set(["Template", "Unit"])
|
|
1583
1708
|
};
|
|
1584
1709
|
var testFilePattern = /\.(test|spec)\.(ts|tsx)$/;
|
|
1585
|
-
var createDependencyScanner = async (exec) => (await import("./dependencyScanner-
|
|
1710
|
+
var createDependencyScanner = async (exec) => (await import("./dependencyScanner-shs82ynp.js")).TypeScriptDependencyScanner.from(exec);
|
|
1586
1711
|
var isAllowedTestFile = (filename) => testFilePattern.test(filename);
|
|
1587
|
-
var getScanPath = (exec, relativePath) =>
|
|
1712
|
+
var getScanPath = (exec, relativePath) => path7.posix.join(`${exec.type}s`, exec.name, relativePath.split(path7.sep).join("/"));
|
|
1588
1713
|
async function clearGeneratedRootCapacitorConfigs(exec) {
|
|
1589
1714
|
if (exec.type !== "app")
|
|
1590
1715
|
return;
|
|
1591
|
-
await Promise.all(generatedRootCapacitorConfigFiles.map((filename) =>
|
|
1716
|
+
await Promise.all(generatedRootCapacitorConfigFiles.map((filename) => rm2(exec.getPath(filename), { force: true })));
|
|
1592
1717
|
}
|
|
1593
1718
|
var getModuleNameFromPath = (kind, modulePath) => {
|
|
1594
|
-
const dirname =
|
|
1719
|
+
const dirname = path7.basename(modulePath);
|
|
1595
1720
|
return kind === "service" ? dirname.replace(/^_+/, "") : dirname;
|
|
1596
1721
|
};
|
|
1597
1722
|
async function assertScanConvention(exec, libRoot) {
|
|
@@ -1613,18 +1738,18 @@ async function assertScanConvention(exec, libRoot) {
|
|
|
1613
1738
|
for (const { relativePath, reason } of await exec.getPageConventionViolations())
|
|
1614
1739
|
addViolation(relativePath, reason);
|
|
1615
1740
|
libRoot.files.filter((filename) => !isAllowedLibFacetRootFile(filename)).forEach((filename) => {
|
|
1616
|
-
addViolation(
|
|
1741
|
+
addViolation(path7.join("lib", filename), "unsupported lib facet root file");
|
|
1617
1742
|
});
|
|
1618
1743
|
libRoot.dirs.filter((dirname) => dirname.startsWith("__") && !internalLibDirs.has(dirname)).forEach((dirname) => {
|
|
1619
|
-
addViolation(
|
|
1744
|
+
addViolation(path7.join("lib", dirname), "unsupported internal lib folder");
|
|
1620
1745
|
});
|
|
1621
1746
|
const databaseDirs = libRoot.dirs.filter((dirname) => !dirname.startsWith("_"));
|
|
1622
1747
|
const serviceDirs = libRoot.dirs.filter((dirname) => dirname.startsWith("_") && !dirname.startsWith("__"));
|
|
1623
1748
|
const scalarDirs = await exec.readdir("lib/__scalar");
|
|
1624
1749
|
await Promise.all([
|
|
1625
|
-
...databaseDirs.map((dirname) => validateModuleFiles(exec, violations, "database",
|
|
1626
|
-
...serviceDirs.map((dirname) => validateModuleFiles(exec, violations, "service",
|
|
1627
|
-
...scalarDirs.map((dirname) => validateModuleFiles(exec, violations, "scalar",
|
|
1750
|
+
...databaseDirs.map((dirname) => validateModuleFiles(exec, violations, "database", path7.join("lib", dirname))),
|
|
1751
|
+
...serviceDirs.map((dirname) => validateModuleFiles(exec, violations, "service", path7.join("lib", dirname))),
|
|
1752
|
+
...scalarDirs.map((dirname) => validateModuleFiles(exec, violations, "scalar", path7.join("lib/__scalar", dirname)))
|
|
1628
1753
|
]);
|
|
1629
1754
|
if (violations.length > 0) {
|
|
1630
1755
|
throw new Error(`[scan-convention]
|
|
@@ -1636,11 +1761,11 @@ async function validateModuleFiles(exec, violations, kind, modulePath) {
|
|
|
1636
1761
|
const { files, dirs } = await exec.getFilesAndDirs(modulePath);
|
|
1637
1762
|
const moduleName = getModuleNameFromPath(kind, modulePath);
|
|
1638
1763
|
dirs.forEach((dirname) => {
|
|
1639
|
-
violations.push(`${getScanPath(exec,
|
|
1764
|
+
violations.push(`${getScanPath(exec, path7.join(modulePath, dirname))}: unsupported module folder`);
|
|
1640
1765
|
});
|
|
1641
1766
|
const uiModuleName = moduleName[0].toUpperCase() + moduleName.slice(1);
|
|
1642
1767
|
files.forEach((filename) => {
|
|
1643
|
-
const filePath =
|
|
1768
|
+
const filePath = path7.join(modulePath, filename);
|
|
1644
1769
|
if (filename === "index.ts" || filename === "index.tsx" || isAllowedTestFile(filename))
|
|
1645
1770
|
return;
|
|
1646
1771
|
if (filename === `${moduleName}.abstract.md`)
|
|
@@ -1720,7 +1845,7 @@ class ScanInfo {
|
|
|
1720
1845
|
});
|
|
1721
1846
|
await Promise.all([
|
|
1722
1847
|
...databaseDirs.map(async (name) => {
|
|
1723
|
-
const filenames = await exec.readdir(
|
|
1848
|
+
const filenames = await exec.readdir(path7.join("lib", name));
|
|
1724
1849
|
filenames.forEach((filename) => {
|
|
1725
1850
|
if (filename.endsWith(".constant.ts"))
|
|
1726
1851
|
files.constant.databases.push(name);
|
|
@@ -1748,7 +1873,7 @@ class ScanInfo {
|
|
|
1748
1873
|
}),
|
|
1749
1874
|
...serviceDirs.map(async (dirname) => {
|
|
1750
1875
|
const name = dirname.slice(1);
|
|
1751
|
-
const filenames = await exec.readdir(
|
|
1876
|
+
const filenames = await exec.readdir(path7.join("lib", dirname));
|
|
1752
1877
|
filenames.forEach((filename) => {
|
|
1753
1878
|
if (filename.endsWith(".dictionary.ts"))
|
|
1754
1879
|
files.dictionary.services.push(name);
|
|
@@ -1771,7 +1896,7 @@ class ScanInfo {
|
|
|
1771
1896
|
});
|
|
1772
1897
|
}),
|
|
1773
1898
|
...scalarDirs.map(async (name) => {
|
|
1774
|
-
const filenames = await exec.readdir(
|
|
1899
|
+
const filenames = await exec.readdir(path7.join("lib/__scalar", name));
|
|
1775
1900
|
filenames.forEach((filename) => {
|
|
1776
1901
|
if (filename.endsWith(".constant.ts"))
|
|
1777
1902
|
files.constant.scalars.push(name);
|
|
@@ -1797,7 +1922,7 @@ class ScanInfo {
|
|
|
1797
1922
|
name: exec.name,
|
|
1798
1923
|
type: exec.type,
|
|
1799
1924
|
repoName: exec.workspace.repoName,
|
|
1800
|
-
serveDomain: WorkspaceExecutor.getBaseDevEnv(
|
|
1925
|
+
serveDomain: WorkspaceExecutor.getBaseDevEnv(path7.join(exec.workspace.workspaceRoot, ".env")).serveDomain,
|
|
1801
1926
|
files,
|
|
1802
1927
|
libDeps,
|
|
1803
1928
|
pkgDeps,
|
|
@@ -2194,16 +2319,16 @@ class Executor {
|
|
|
2194
2319
|
linter = null;
|
|
2195
2320
|
constructor(name, cwdPath) {
|
|
2196
2321
|
this.name = name;
|
|
2197
|
-
this.logger = new
|
|
2322
|
+
this.logger = new Logger2(name);
|
|
2198
2323
|
this.logs = [];
|
|
2199
2324
|
this.cwdPath = cwdPath;
|
|
2200
2325
|
}
|
|
2201
2326
|
#stdout(data) {
|
|
2202
2327
|
if (Executor.verbose)
|
|
2203
|
-
|
|
2328
|
+
Logger2.raw(chalk2.dim(data.toString()));
|
|
2204
2329
|
}
|
|
2205
2330
|
#stderr(data) {
|
|
2206
|
-
|
|
2331
|
+
Logger2.raw(chalk2.red(data.toString()));
|
|
2207
2332
|
}
|
|
2208
2333
|
exec(command, options = {}) {
|
|
2209
2334
|
const cwd = options.cwd?.toString() ?? this.cwdPath;
|
|
@@ -2345,10 +2470,10 @@ class Executor {
|
|
|
2345
2470
|
});
|
|
2346
2471
|
}
|
|
2347
2472
|
getPath(filePath) {
|
|
2348
|
-
if (
|
|
2473
|
+
if (path8.isAbsolute(filePath))
|
|
2349
2474
|
return filePath;
|
|
2350
2475
|
if (filePath.startsWith("."))
|
|
2351
|
-
return
|
|
2476
|
+
return path8.join(this.cwdPath, filePath);
|
|
2352
2477
|
const baseParts = this.cwdPath.split(/[\\/]/).filter(Boolean);
|
|
2353
2478
|
const targetParts = filePath.split(/[\\/]/).filter(Boolean);
|
|
2354
2479
|
let overlapLength = 0;
|
|
@@ -2362,12 +2487,12 @@ class Executor {
|
|
|
2362
2487
|
if (isOverlap)
|
|
2363
2488
|
overlapLength = i;
|
|
2364
2489
|
}
|
|
2365
|
-
return
|
|
2490
|
+
return path8.join(this.cwdPath, ...targetParts.slice(overlapLength));
|
|
2366
2491
|
}
|
|
2367
2492
|
async mkdir(dirPath) {
|
|
2368
2493
|
const writePath = this.getPath(dirPath);
|
|
2369
2494
|
if (!await FileSys.dirExists(writePath))
|
|
2370
|
-
await
|
|
2495
|
+
await mkdir3(writePath, { recursive: true });
|
|
2371
2496
|
this.logger.verbose(`Make directory ${writePath}`);
|
|
2372
2497
|
return this;
|
|
2373
2498
|
}
|
|
@@ -2405,17 +2530,17 @@ class Executor {
|
|
|
2405
2530
|
return this;
|
|
2406
2531
|
}
|
|
2407
2532
|
async removeDir(dirPath) {
|
|
2408
|
-
const readPath =
|
|
2533
|
+
const readPath = path8.join(this.getPath(dirPath), ".");
|
|
2409
2534
|
if (await FileSys.entryExists(readPath))
|
|
2410
|
-
await
|
|
2535
|
+
await rm3(readPath, { recursive: true, force: true });
|
|
2411
2536
|
this.logger.verbose(`Remove directory ${readPath}`);
|
|
2412
2537
|
return this;
|
|
2413
2538
|
}
|
|
2414
2539
|
async writeFile(filePath, content, { overwrite = true, silent = false } = {}) {
|
|
2415
2540
|
const writePath = this.getPath(filePath);
|
|
2416
|
-
const dir =
|
|
2541
|
+
const dir = path8.dirname(writePath);
|
|
2417
2542
|
if (!await FileSys.dirExists(dir))
|
|
2418
|
-
await
|
|
2543
|
+
await mkdir3(dir, { recursive: true });
|
|
2419
2544
|
let contentStr = typeof content === "string" ? content : `${JSON.stringify(content, null, 2)}
|
|
2420
2545
|
`;
|
|
2421
2546
|
if (await FileSys.fileExists(writePath)) {
|
|
@@ -2425,7 +2550,7 @@ class Executor {
|
|
|
2425
2550
|
contentStr = currentContent;
|
|
2426
2551
|
} else {
|
|
2427
2552
|
await FileSys.writeText(writePath, contentStr);
|
|
2428
|
-
if (
|
|
2553
|
+
if (Logger2.isVerbose())
|
|
2429
2554
|
this.logger.rawLog(chalk2.yellow(`File Update: ${filePath}`));
|
|
2430
2555
|
}
|
|
2431
2556
|
} else {
|
|
@@ -2439,7 +2564,7 @@ class Executor {
|
|
|
2439
2564
|
await this.writeFile(filePath, content);
|
|
2440
2565
|
}
|
|
2441
2566
|
async getLocalFile(targetPath) {
|
|
2442
|
-
const filePath =
|
|
2567
|
+
const filePath = path8.isAbsolute(targetPath) ? targetPath : targetPath.replace(this.cwdPath, "");
|
|
2443
2568
|
const content = await this.readFile(filePath);
|
|
2444
2569
|
return { filePath, content };
|
|
2445
2570
|
}
|
|
@@ -2456,9 +2581,9 @@ class Executor {
|
|
|
2456
2581
|
const dest = this.getPath(destPath);
|
|
2457
2582
|
if (!await FileSys.exists(src))
|
|
2458
2583
|
return;
|
|
2459
|
-
const isDirectory = (await
|
|
2584
|
+
const isDirectory = (await stat2(src)).isDirectory();
|
|
2460
2585
|
if (!await FileSys.exists(dest) && isDirectory)
|
|
2461
|
-
await
|
|
2586
|
+
await mkdir3(dest, { recursive: true });
|
|
2462
2587
|
if (dereference)
|
|
2463
2588
|
await cpEntry(src, dest, { recursive: isDirectory, dereference: true, force: true });
|
|
2464
2589
|
else
|
|
@@ -2536,9 +2661,9 @@ class Executor {
|
|
|
2536
2661
|
const result = await getContent.default(scanInfo ?? null, dict, options);
|
|
2537
2662
|
if (result === null)
|
|
2538
2663
|
return null;
|
|
2539
|
-
const filename = typeof result === "object" ? result.filename :
|
|
2664
|
+
const filename = typeof result === "object" ? result.filename : path8.basename(targetPath).replace(".js", ".ts");
|
|
2540
2665
|
const content = typeof result === "object" ? result.content : result;
|
|
2541
|
-
const dirname =
|
|
2666
|
+
const dirname = path8.dirname(targetPath);
|
|
2542
2667
|
const convertedTargetPath = Object.entries(dict).reduce((path, [key, value]) => path.replace(new RegExp(`__${key}__`, "g"), value), `${dirname}/${filename}`);
|
|
2543
2668
|
this.logger.verbose(`Apply template ${templatePath} to ${convertedTargetPath}`);
|
|
2544
2669
|
return this.writeFile(convertedTargetPath, content, { overwrite });
|
|
@@ -2550,12 +2675,12 @@ class Executor {
|
|
|
2550
2675
|
return this.writeFile(convertedTargetPath, convertedContent, {
|
|
2551
2676
|
overwrite
|
|
2552
2677
|
});
|
|
2553
|
-
} else if (staticTemplateFileExtensions.has(
|
|
2678
|
+
} else if (staticTemplateFileExtensions.has(path8.extname(targetPath).toLowerCase())) {
|
|
2554
2679
|
const convertedTargetPath = Object.entries(dict).reduce((path, [key, value]) => path.replace(new RegExp(`__${key}__`, "g"), value), targetPath);
|
|
2555
2680
|
const writePath = this.getPath(convertedTargetPath);
|
|
2556
|
-
const dirname =
|
|
2681
|
+
const dirname = path8.dirname(writePath);
|
|
2557
2682
|
if (!await FileSys.dirExists(dirname))
|
|
2558
|
-
await
|
|
2683
|
+
await mkdir3(dirname, { recursive: true });
|
|
2559
2684
|
await copyFile(templatePath, writePath);
|
|
2560
2685
|
this.logger.verbose(`Apply template ${templatePath} to ${convertedTargetPath}`);
|
|
2561
2686
|
return { filePath: writePath, content: "" };
|
|
@@ -2573,11 +2698,11 @@ class Executor {
|
|
|
2573
2698
|
const templateRoot = await this.#resolveTemplateRoot();
|
|
2574
2699
|
const templatePath = `${templateRoot}${template ? `/${template}` : ""}`;
|
|
2575
2700
|
const prefixTemplatePath = templatePath;
|
|
2576
|
-
if ((await
|
|
2577
|
-
const filename =
|
|
2701
|
+
if ((await stat2(prefixTemplatePath)).isFile()) {
|
|
2702
|
+
const filename = path8.basename(prefixTemplatePath);
|
|
2578
2703
|
const fileContent = await this.#applyTemplateFile({
|
|
2579
2704
|
templatePath: prefixTemplatePath,
|
|
2580
|
-
targetPath:
|
|
2705
|
+
targetPath: path8.join(basePath, filename),
|
|
2581
2706
|
scanInfo,
|
|
2582
2707
|
overwrite
|
|
2583
2708
|
}, dict, options);
|
|
@@ -2585,19 +2710,19 @@ class Executor {
|
|
|
2585
2710
|
} else {
|
|
2586
2711
|
const subdirs = await readDirEntries(templatePath);
|
|
2587
2712
|
const fileContents = (await Promise.all(subdirs.map(async (subdir) => {
|
|
2588
|
-
const subpath =
|
|
2589
|
-
if ((await
|
|
2713
|
+
const subpath = path8.join(templatePath, subdir);
|
|
2714
|
+
if ((await stat2(subpath)).isFile()) {
|
|
2590
2715
|
const fileContent = await this.#applyTemplateFile({
|
|
2591
2716
|
templatePath: subpath,
|
|
2592
|
-
targetPath:
|
|
2717
|
+
targetPath: path8.join(basePath, subdir),
|
|
2593
2718
|
scanInfo,
|
|
2594
2719
|
overwrite
|
|
2595
2720
|
}, dict, options);
|
|
2596
2721
|
return fileContent ? [fileContent] : [];
|
|
2597
2722
|
} else
|
|
2598
2723
|
return await this._applyTemplate({
|
|
2599
|
-
basePath:
|
|
2600
|
-
template:
|
|
2724
|
+
basePath: path8.join(basePath, subdir),
|
|
2725
|
+
template: path8.join(template, subdir),
|
|
2601
2726
|
scanInfo,
|
|
2602
2727
|
dict,
|
|
2603
2728
|
overwrite,
|
|
@@ -2609,8 +2734,8 @@ class Executor {
|
|
|
2609
2734
|
}
|
|
2610
2735
|
async#resolveTemplateRoot() {
|
|
2611
2736
|
const candidates = [
|
|
2612
|
-
|
|
2613
|
-
|
|
2737
|
+
path8.resolve(getDirname2(import.meta.url), "templates"),
|
|
2738
|
+
path8.resolve(getDirname2(import.meta.url), "../cli/templates")
|
|
2614
2739
|
];
|
|
2615
2740
|
for (const candidate of candidates) {
|
|
2616
2741
|
if (await FileSys.dirExists(candidate))
|
|
@@ -2682,11 +2807,11 @@ class Executor {
|
|
|
2682
2807
|
async#resolveTypecheckWorkerEntry() {
|
|
2683
2808
|
const dirname = getDirname2(import.meta.url);
|
|
2684
2809
|
const candidates = [
|
|
2685
|
-
|
|
2686
|
-
|
|
2687
|
-
|
|
2688
|
-
|
|
2689
|
-
|
|
2810
|
+
path8.join(process.cwd(), "pkgs/@akanjs/devkit/typecheck/typecheck.proc.ts"),
|
|
2811
|
+
path8.join(process.cwd(), "node_modules/@akanjs/devkit/typecheck/typecheck.proc.ts"),
|
|
2812
|
+
path8.join(dirname, "typecheck/typecheck.proc.ts"),
|
|
2813
|
+
path8.join(dirname, "typecheck.proc.js"),
|
|
2814
|
+
path8.join(dirname, "typecheck.proc.ts")
|
|
2690
2815
|
];
|
|
2691
2816
|
for (const candidate of candidates)
|
|
2692
2817
|
if (await Bun.file(candidate).exists())
|
|
@@ -2813,8 +2938,8 @@ class WorkspaceExecutor extends Executor {
|
|
|
2813
2938
|
await Promise.all(dirs.map(async (dir) => {
|
|
2814
2939
|
if (dir.includes("_") || AVOID_DIRS.includes(dir))
|
|
2815
2940
|
return;
|
|
2816
|
-
const dirPath =
|
|
2817
|
-
if ((await
|
|
2941
|
+
const dirPath = path8.join(dirname, dir);
|
|
2942
|
+
if ((await stat2(dirPath)).isDirectory()) {
|
|
2818
2943
|
results.push(`${prefix}${dir}`);
|
|
2819
2944
|
if (maxDepth > 0)
|
|
2820
2945
|
await getDirs(dirPath, maxDepth - 1, results, `${prefix}${dir}/`);
|
|
@@ -2848,9 +2973,9 @@ class WorkspaceExecutor extends Executor {
|
|
|
2848
2973
|
await Promise.all(dirs.map(async (dir) => {
|
|
2849
2974
|
if (AVOID_DIRS.includes(dir))
|
|
2850
2975
|
return;
|
|
2851
|
-
const dirPath =
|
|
2976
|
+
const dirPath = path8.join(dirname, dir);
|
|
2852
2977
|
if (await FileSys.dirExists(dirPath)) {
|
|
2853
|
-
const hasTargetFile = await FileSys.fileExists(
|
|
2978
|
+
const hasTargetFile = await FileSys.fileExists(path8.join(dirPath, targetFilename));
|
|
2854
2979
|
if (hasTargetFile)
|
|
2855
2980
|
results.push(`${prefix}${dir}`);
|
|
2856
2981
|
if (maxDepth > 0)
|
|
@@ -2924,7 +3049,7 @@ class SysExecutor extends Executor {
|
|
|
2924
3049
|
return [];
|
|
2925
3050
|
const violations = [];
|
|
2926
3051
|
for (const entry of await this.getAllFiles("**/*", { cwd: this.getPath("page") })) {
|
|
2927
|
-
const relativePath = entry.split(
|
|
3052
|
+
const relativePath = entry.split(path8.sep).join("/");
|
|
2928
3053
|
const reason = getPageSourceFileViolation(relativePath);
|
|
2929
3054
|
if (reason)
|
|
2930
3055
|
violations.push({ relativePath: `page/${relativePath}`, reason });
|
|
@@ -2987,18 +3112,19 @@ class SysExecutor extends Executor {
|
|
|
2987
3112
|
}) : await LibInfo.fromExecutor(this, {
|
|
2988
3113
|
refresh
|
|
2989
3114
|
});
|
|
2990
|
-
if (write)
|
|
2991
|
-
await
|
|
2992
|
-
|
|
2993
|
-
|
|
2994
|
-
this
|
|
2995
|
-
|
|
2996
|
-
|
|
2997
|
-
|
|
2998
|
-
|
|
2999
|
-
|
|
3000
|
-
|
|
3001
|
-
|
|
3115
|
+
if (write)
|
|
3116
|
+
await CodegenLock.run(this.workspace.workspaceRoot, `scan:${this.name}`, async () => {
|
|
3117
|
+
await Promise.all(this.#getScanTemplateTasks(scanInfo));
|
|
3118
|
+
await this.writeJson(`akan.${this.type}.json`, scanInfo.getScanResult());
|
|
3119
|
+
if (this.type === "lib")
|
|
3120
|
+
this.#updateDependencies(scanInfo);
|
|
3121
|
+
if (writeLib) {
|
|
3122
|
+
const libInfos = [...scanInfo.getLibInfos().values()];
|
|
3123
|
+
await this.#updateDependencies(scanInfo);
|
|
3124
|
+
await Promise.all(libInfos.flatMap((libInfo) => libInfo.exec.#getScanTemplateTasks(libInfo)));
|
|
3125
|
+
}
|
|
3126
|
+
await this.syncAgentsIndex(scanInfo);
|
|
3127
|
+
});
|
|
3002
3128
|
this.#scanInfo = scanInfo;
|
|
3003
3129
|
return scanInfo;
|
|
3004
3130
|
}
|
|
@@ -3033,7 +3159,7 @@ class SysExecutor extends Executor {
|
|
|
3033
3159
|
await this.setPackageJson(libPkgJsonWithDeps);
|
|
3034
3160
|
}
|
|
3035
3161
|
async getLocalFile(targetPath) {
|
|
3036
|
-
const filePath =
|
|
3162
|
+
const filePath = path8.isAbsolute(targetPath) ? targetPath : `${this.type}s/${this.name}/${targetPath}`;
|
|
3037
3163
|
const content = await this.workspace.readFile(filePath);
|
|
3038
3164
|
return { filePath, content };
|
|
3039
3165
|
}
|
|
@@ -3172,6 +3298,8 @@ class AppExecutor extends SysExecutor {
|
|
|
3172
3298
|
const databaseMode = process.env.AKAN_DATABASE_MODE ?? akanConfig.defaultDatabaseMode ?? "single";
|
|
3173
3299
|
const routeEnv = {
|
|
3174
3300
|
AKAN_PUBLIC_BASE_PATHS: [...akanConfig.basePaths].join(","),
|
|
3301
|
+
AKAN_PUBLIC_API_PREFIX: akanConfig.api.prefix,
|
|
3302
|
+
AKAN_PUBLIC_WS_PREFIX: akanConfig.api.websocketPrefix,
|
|
3175
3303
|
AKAN_DATABASE_MODE: databaseMode
|
|
3176
3304
|
};
|
|
3177
3305
|
Object.assign(process.env, routeEnv);
|
|
@@ -3252,11 +3380,11 @@ class AppExecutor extends SysExecutor {
|
|
|
3252
3380
|
absolute: false,
|
|
3253
3381
|
onlyFiles: true
|
|
3254
3382
|
})) {
|
|
3255
|
-
const segments = rel.split(
|
|
3383
|
+
const segments = rel.split(path8.sep);
|
|
3256
3384
|
if (segments.some((s) => s === "node_modules"))
|
|
3257
3385
|
continue;
|
|
3258
3386
|
const posix = `${root.keyPrefix}${segments.join("/")}`;
|
|
3259
|
-
const absPath =
|
|
3387
|
+
const absPath = path8.join(root.dir, ...segments);
|
|
3260
3388
|
validatePageSourceFile(posix, { filePath: absPath });
|
|
3261
3389
|
if (!isRouteSourceFile(posix))
|
|
3262
3390
|
continue;
|
|
@@ -3395,12 +3523,12 @@ class AppExecutor extends SysExecutor {
|
|
|
3395
3523
|
static async#linkLibAsset(targetPath, linkPath) {
|
|
3396
3524
|
const isWindows = process.platform === "win32";
|
|
3397
3525
|
try {
|
|
3398
|
-
const target = isWindows ? targetPath :
|
|
3526
|
+
const target = isWindows ? targetPath : path8.relative(path8.dirname(linkPath), targetPath);
|
|
3399
3527
|
await symlink(target, linkPath, isWindows ? "junction" : "dir");
|
|
3400
3528
|
} catch (error) {
|
|
3401
3529
|
if (!isWindows)
|
|
3402
3530
|
throw error;
|
|
3403
|
-
await
|
|
3531
|
+
await mkdir3(linkPath, { recursive: true });
|
|
3404
3532
|
await cpEntry(targetPath, linkPath, { recursive: true, dereference: true, force: true });
|
|
3405
3533
|
}
|
|
3406
3534
|
}
|
|
@@ -3437,7 +3565,7 @@ class AppExecutor extends SysExecutor {
|
|
|
3437
3565
|
await this.writeFile(rel, content, opts);
|
|
3438
3566
|
},
|
|
3439
3567
|
readEnvClient: async () => {
|
|
3440
|
-
const envClientPath =
|
|
3568
|
+
const envClientPath = path8.join(this.cwdPath, "env", "env.client.ts");
|
|
3441
3569
|
if (!await FileSys.fileExists(envClientPath))
|
|
3442
3570
|
return null;
|
|
3443
3571
|
try {
|
|
@@ -3547,7 +3675,7 @@ class PkgExecutor extends Executor {
|
|
|
3547
3675
|
return rootVersion;
|
|
3548
3676
|
try {
|
|
3549
3677
|
const packageJsonPath = `pkgs/${dep}/package.json`;
|
|
3550
|
-
if (!await Bun.file(
|
|
3678
|
+
if (!await Bun.file(path8.join(this.workspace.workspaceRoot, packageJsonPath)).exists())
|
|
3551
3679
|
return;
|
|
3552
3680
|
const packageJson = await this.workspace.readJson(packageJsonPath);
|
|
3553
3681
|
if (packageJson.name === dep)
|
|
@@ -3648,4 +3776,4 @@ class ModuleExecutor extends Executor {
|
|
|
3648
3776
|
}
|
|
3649
3777
|
}
|
|
3650
3778
|
|
|
3651
|
-
export { AGENT_BLOCK_START, AGENT_BLOCK_END, stampBlockVersion, extractBlockVersion, readDevkitVersion, upsertAgentBlock, extractAgentBlock, renderRecipeEntries, collectScopeRecipeSources, renderScopeAgentBlock, CLAUDE_COMMENT_RULE, AsyncDefaultExportDetector, resolveSsrPageEntriesForApp, rootAllowedFiles, rootAllowedDirs, isAllowedLibFacetRootFile, isScannedRootEntry, AppInfo, Spinner, CommandExecutionError, Executor, WorkspaceExecutor, SysExecutor, AppExecutor, LibExecutor, PkgExecutor, ModuleExecutor };
|
|
3779
|
+
export { AGENT_BLOCK_START, AGENT_BLOCK_END, stampBlockVersion, extractBlockVersion, readDevkitVersion, upsertAgentBlock, extractAgentBlock, renderRecipeEntries, collectScopeRecipeSources, renderScopeAgentBlock, CLAUDE_COMMENT_RULE, AsyncDefaultExportDetector, resolveSsrPageEntriesForApp, CodegenLock, rootAllowedFiles, rootAllowedDirs, isAllowedLibFacetRootFile, isScannedRootEntry, AppInfo, Spinner, CommandExecutionError, Executor, WorkspaceExecutor, SysExecutor, AppExecutor, LibExecutor, PkgExecutor, ModuleExecutor };
|