@akanjs/cli 3.0.0 → 3.0.2-rc.0
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/{CodeAgent-2vmp9qe0.js → CodeAgent-szbjv4gv.js} +2 -2
- package/{CodeTui-5ed6bg2a.js → CodeTui-5nw86ab6.js} +1 -1
- package/{agent.command-gn73rhe7.js → agent.command-np1dffkb.js} +5 -5
- package/akanCode.js +2 -2
- package/{application.command-e968t0hw.js → application.command-fyjy9ryc.js} +8 -8
- package/{applicationBuildRunner-64taxseg.js → applicationBuildRunner-etrzfwjj.js} +3 -3
- package/buildBatch.proc.js +4 -4
- package/{cloud.command-0jm301rr.js → cloud.command-c0rnwy65.js} +10 -10
- package/cloud.script-6ba8e9v8.js +20 -0
- package/{code.command-18kcm7hq.js → code.command-hmtx14b2.js} +6 -6
- package/{context.command-trd9bn18.js → context.command-6aqvdx43.js} +13 -13
- package/context.runner-hnkvv3z3.js +21 -0
- package/{guideline.command-bdmdn2de.js → guideline.command-axvf68gc.js} +2 -2
- package/guidelines/conventions/conventions.instruction.md +93 -17
- package/guidelines/queryRule/queryRule.instruction.md +4 -2
- package/guidelines/runtimeRule/runtimeRule.instruction.md +10 -5
- package/guidelines/transportRule/transportRule.instruction.md +40 -4
- package/guidelines/workspaceOnboarding/workspaceOnboarding.instruction.md +1 -1
- package/incrementalBuilder.proc.js +3 -3
- package/{index-mgxpx3f2.js → index-1bjkfvm9.js} +29 -27
- package/{index-wprnsjms.js → index-1gs9g12n.js} +3 -3
- package/{index-by9pxkr0.js → index-3xmzr1p1.js} +2 -2
- package/{index-jmrn54tt.js → index-50jjwg8y.js} +1 -1
- package/{index-3w94e7n3.js → index-50wb2a26.js} +315 -94
- package/{index-p993efkq.js → index-61mmsdjg.js} +9 -8
- package/{index-kqabytj7.js → index-6keyf4sg.js} +4 -4
- package/{index-f3c78nd6.js → index-bsv901fd.js} +7 -7
- package/{index-hsmtysz4.js → index-cb6yc5mb.js} +2 -2
- package/{index-kcdj1z5v.js → index-d95tfg3n.js} +15 -11
- package/{index-4npz05nm.js → index-f4e08ptp.js} +4 -4
- package/{index-mbxbhay5.js → index-g38nhv87.js} +1 -1
- package/{index-pmhqttv3.js → index-gvpvxdm1.js} +5 -5
- package/{index-y3mphr1m.js → index-h9ht6s60.js} +1 -1
- package/{index-93j60em0.js → index-hp3stk1m.js} +3 -3
- package/{index-drehwpdt.js → index-hxnnfy57.js} +6 -5
- package/{index-abxpehf8.js → index-j38qkvkk.js} +7 -7
- package/{index-0wpybxtr.js → index-jb0hmt3k.js} +3 -3
- package/{index-gbggbqcp.js → index-jk9xnck6.js} +33 -11
- package/{index-6he6gvfg.js → index-krjcg4y6.js} +29 -11
- package/{index-vpj42xwt.js → index-q6ft9fkc.js} +4 -4
- package/{index-48k96p55.js → index-senscydg.js} +6 -0
- package/{index-tqm7jjcn.js → index-xwprn9nr.js} +1 -1
- package/{index-yg7jhz8x.js → index-zwd84m0w.js} +4 -4
- package/{index-9z771ptz.js → index-zyw622y1.js} +12 -2
- package/index.js +21 -21
- package/{library.command-9h749a1x.js → library.command-9m2rdwwz.js} +3 -3
- package/{localRegistry.command-2bqqhxyz.js → localRegistry.command-vacc2njh.js} +9 -9
- package/{module.command-nv8nzgft.js → module.command-q63dffya.js} +5 -5
- package/{package.command-mq4bggp6.js → package.command-y2jh0m99.js} +3 -3
- package/package.json +2 -2
- package/{page.command-j639n707.js → page.command-f3e4cwhh.js} +3 -3
- package/{primitive.command-kz6849th.js → primitive.command-r4kq75qj.js} +6 -6
- package/{quality.command-4hyabwkb.js → quality.command-f7gzh26z.js} +9 -2
- package/{repair.command-a9awpbqr.js → repair.command-0qmyr6qa.js} +5 -5
- package/{scalar.command-ma4fpm9m.js → scalar.command-kddn7av4.js} +4 -4
- package/{subspace.command-3k2pmrs4.js → subspace.command-j7ayp382.js} +5 -7
- package/templates/app/ui/Recipe/jellyButton.ts +1 -0
- package/templates/facetIndex/index.ts +21 -6
- package/templates/lib/dict.ts +9 -1
- package/templates/lib/srv.ts +2 -3
- package/templates/libRoot/common/index.ts +2 -7
- package/templates/libRoot/srvkit/index.ts +2 -7
- package/templates/libRoot/ui/index.ts +2 -7
- package/templates/libRoot/webkit/index.ts +2 -7
- package/templates/moduleRoot/index.tsx +3 -3
- package/{tunnel.command-xwr46b66.js → tunnel.command-b3ymdk4f.js} +2 -2
- package/{workflow.command-t7wqe4h7.js → workflow.command-z1srcdfw.js} +10 -10
- package/{workspace.command-4derhzrh.js → workspace.command-17c46dbp.js} +21 -21
- package/cloud.script-nemnzjpv.js +0 -20
- package/context.runner-y5hwh673.js +0 -21
- package/index-bjwxs904.js +0 -77
- package/templates/libRoot/common/commonLogic.ts +0 -14
- package/templates/libRoot/srvkit/backendLogic.ts +0 -13
- package/templates/libRoot/webkit/frontendLogic.ts +0 -13
|
@@ -242,6 +242,7 @@ const defaultFonts = userFonts.filter((font) => font.default);
|
|
|
242
242
|
if (defaultFonts.length > 1) throw new Error("[route-convention] only one default font is allowed per root layout");
|
|
243
243
|
const defaultFont = defaultFonts[0];
|
|
244
244
|
const defaultFontClassName = defaultFont ? (defaultFont.className ?? \`font-\${defaultFont.name}\`) : undefined;
|
|
245
|
+
export const theme = userLayout.theme ?? inheritedLayout.theme;
|
|
245
246
|
|
|
246
247
|
${layoutExports}(
|
|
247
248
|
<System.Provider
|
|
@@ -251,7 +252,7 @@ ${layoutExports}(
|
|
|
251
252
|
` : ""}params={params}
|
|
252
253
|
manifest={userLayout.manifest ?? inheritedLayout.manifest}
|
|
253
254
|
env={env}
|
|
254
|
-
theme={
|
|
255
|
+
theme={theme}
|
|
255
256
|
fonts={loadFonts(userFonts)}
|
|
256
257
|
className={defaultFontClassName}
|
|
257
258
|
layoutStyle={userLayout.layoutStyle ?? inheritedLayout.layoutStyle}
|
|
@@ -516,7 +517,7 @@ import {
|
|
|
516
517
|
stat as stat2,
|
|
517
518
|
symlink
|
|
518
519
|
} from "fs/promises";
|
|
519
|
-
import
|
|
520
|
+
import path10 from "path";
|
|
520
521
|
import { pathToFileURL } from "url";
|
|
521
522
|
import {
|
|
522
523
|
capitalize,
|
|
@@ -1043,8 +1044,9 @@ class AkanAppConfig {
|
|
|
1043
1044
|
"activity",
|
|
1044
1045
|
"files"
|
|
1045
1046
|
],
|
|
1046
|
-
desktop: ["indexPath", "server", "recovery", "window", "screenCapture", "entitlements"],
|
|
1047
|
+
desktop: ["indexPath", "server", "recovery", "window", "screenCapture", "entitlements", "dmg"],
|
|
1047
1048
|
desktopServer: ["omit"],
|
|
1049
|
+
dmg: ["background", "background2x", "window", "iconSize", "textSize", "app", "applications"],
|
|
1048
1050
|
deepLinks: ["schemes", "domains"]
|
|
1049
1051
|
};
|
|
1050
1052
|
static #movedKeys = {
|
|
@@ -1073,6 +1075,7 @@ class AkanAppConfig {
|
|
|
1073
1075
|
check(settings.android, AkanAppConfig.#nativeKeys.android, `${where}.android`, "android");
|
|
1074
1076
|
check(settings.desktop, AkanAppConfig.#nativeKeys.desktop, `${where}.desktop`, "desktop");
|
|
1075
1077
|
check(settings.desktop?.server, AkanAppConfig.#nativeKeys.desktopServer, `${where}.desktop.server`, "desktopServer");
|
|
1078
|
+
check(settings.desktop?.dmg, AkanAppConfig.#nativeKeys.dmg, `${where}.desktop.dmg`, "dmg");
|
|
1076
1079
|
check(settings.deepLinks, AkanAppConfig.#nativeKeys.deepLinks, `${where}.deepLinks`, "deepLinks");
|
|
1077
1080
|
}
|
|
1078
1081
|
static #androidFilePattern = /^(?:res\/[^/]+\/[^/]+|assets\/.+)$/;
|
|
@@ -1351,10 +1354,85 @@ var shiftBuildNum = async (app, delta) => {
|
|
|
1351
1354
|
};
|
|
1352
1355
|
var increaseBuildNum = async (app) => await shiftBuildNum(app, 1);
|
|
1353
1356
|
var decreaseBuildNum = async (app) => await shiftBuildNum(app, -1);
|
|
1357
|
+
// pkgs/@akanjs/devkit/jsonFormatter.ts
|
|
1358
|
+
import path6 from "path";
|
|
1359
|
+
|
|
1360
|
+
class JsonFormatter {
|
|
1361
|
+
static lineWidth = 120;
|
|
1362
|
+
static stringify(value, filePath) {
|
|
1363
|
+
const json = JSON.stringify(value, null, 2);
|
|
1364
|
+
if (path6.basename(filePath) === "package.json")
|
|
1365
|
+
return `${json}
|
|
1366
|
+
`;
|
|
1367
|
+
return `${JsonFormatter.#print(JSON.parse(json), 0, { column: 0, trailing: 0 })}
|
|
1368
|
+
`;
|
|
1369
|
+
}
|
|
1370
|
+
static #print(value, depth, placement) {
|
|
1371
|
+
if (Array.isArray(value))
|
|
1372
|
+
return JsonFormatter.#printArray(value, depth, placement);
|
|
1373
|
+
if (value === null || typeof value !== "object")
|
|
1374
|
+
return JSON.stringify(value);
|
|
1375
|
+
const entries = Object.entries(value);
|
|
1376
|
+
if (!entries.length)
|
|
1377
|
+
return "{}";
|
|
1378
|
+
const indent = " ".repeat(depth + 1);
|
|
1379
|
+
const members = entries.map(([key, member], idx) => {
|
|
1380
|
+
const prefix = `${indent}${JSON.stringify(key)}: `;
|
|
1381
|
+
const trailing = idx < entries.length - 1 ? 1 : 0;
|
|
1382
|
+
return `${prefix}${JsonFormatter.#print(member, depth + 1, { column: Bun.stringWidth(prefix), trailing })}`;
|
|
1383
|
+
});
|
|
1384
|
+
return `{
|
|
1385
|
+
${members.join(`,
|
|
1386
|
+
`)}
|
|
1387
|
+
${" ".repeat(depth)}}`;
|
|
1388
|
+
}
|
|
1389
|
+
static #printArray(items, depth, { column, trailing }) {
|
|
1390
|
+
if (!items.length)
|
|
1391
|
+
return "[]";
|
|
1392
|
+
const flat = JsonFormatter.#flat(items);
|
|
1393
|
+
if (flat !== null && column + Bun.stringWidth(flat) + trailing <= JsonFormatter.lineWidth)
|
|
1394
|
+
return flat;
|
|
1395
|
+
const indent = " ".repeat(depth + 1);
|
|
1396
|
+
const isLast = (idx) => idx === items.length - 1;
|
|
1397
|
+
const body = items.every((item) => typeof item === "number") ? JsonFormatter.#fill(items.map((item, idx) => `${JSON.stringify(item)}${isLast(idx) ? "" : ","}`), indent) : items.map((item, idx) => {
|
|
1398
|
+
const placement = { column: indent.length, trailing: isLast(idx) ? 0 : 1 };
|
|
1399
|
+
return `${indent}${JsonFormatter.#print(item, depth + 1, placement)}`;
|
|
1400
|
+
}).join(`,
|
|
1401
|
+
`);
|
|
1402
|
+
return `[
|
|
1403
|
+
${body}
|
|
1404
|
+
${" ".repeat(depth)}]`;
|
|
1405
|
+
}
|
|
1406
|
+
static #fill(tokens, indent) {
|
|
1407
|
+
const lines = [];
|
|
1408
|
+
let line = "";
|
|
1409
|
+
for (const token of tokens) {
|
|
1410
|
+
if (line && Bun.stringWidth(line) + 1 + Bun.stringWidth(token) <= JsonFormatter.lineWidth) {
|
|
1411
|
+
line = `${line} ${token}`;
|
|
1412
|
+
continue;
|
|
1413
|
+
}
|
|
1414
|
+
if (line)
|
|
1415
|
+
lines.push(line);
|
|
1416
|
+
line = `${indent}${token}`;
|
|
1417
|
+
}
|
|
1418
|
+
return [...lines, line].join(`
|
|
1419
|
+
`);
|
|
1420
|
+
}
|
|
1421
|
+
static #flat(value) {
|
|
1422
|
+
if (Array.isArray(value)) {
|
|
1423
|
+
const items = value.map((item) => JsonFormatter.#flat(item));
|
|
1424
|
+
return items.includes(null) ? null : `[${items.join(", ")}]`;
|
|
1425
|
+
}
|
|
1426
|
+
if (value === null || typeof value !== "object")
|
|
1427
|
+
return JSON.stringify(value);
|
|
1428
|
+
return Object.keys(value).length ? null : "{}";
|
|
1429
|
+
}
|
|
1430
|
+
}
|
|
1431
|
+
|
|
1354
1432
|
// pkgs/@akanjs/devkit/linter.ts
|
|
1355
1433
|
import { spawn } from "child_process";
|
|
1356
1434
|
import { existsSync, readFileSync } from "fs";
|
|
1357
|
-
import
|
|
1435
|
+
import path7 from "path";
|
|
1358
1436
|
import chalk from "chalk";
|
|
1359
1437
|
var parseBiomeReport = (output) => {
|
|
1360
1438
|
for (let start = output.indexOf("{");start !== -1; start = output.indexOf("{", start + 1)) {
|
|
@@ -1420,13 +1498,13 @@ class Linter {
|
|
|
1420
1498
|
#biomeBin;
|
|
1421
1499
|
constructor(cwdPath) {
|
|
1422
1500
|
this.lintRoot = this.#findBiomeRootPath(cwdPath);
|
|
1423
|
-
this.configPath = Linter.#configPathIn(this.lintRoot) ??
|
|
1424
|
-
const localBiomeBin =
|
|
1501
|
+
this.configPath = Linter.#configPathIn(this.lintRoot) ?? path7.join(this.lintRoot, "biome.json");
|
|
1502
|
+
const localBiomeBin = path7.join(this.lintRoot, "node_modules", ".bin", Linter.biomeBinName);
|
|
1425
1503
|
this.#biomeBin = existsSync(localBiomeBin) ? localBiomeBin : "biome";
|
|
1426
1504
|
}
|
|
1427
1505
|
static #configPathIn(dir) {
|
|
1428
1506
|
for (const fileName of BIOME_CONFIG_FILES) {
|
|
1429
|
-
const configPath =
|
|
1507
|
+
const configPath = path7.join(dir, fileName);
|
|
1430
1508
|
if (existsSync(configPath))
|
|
1431
1509
|
return configPath;
|
|
1432
1510
|
}
|
|
@@ -1435,19 +1513,19 @@ class Linter {
|
|
|
1435
1513
|
#findBiomeRootPath(dir) {
|
|
1436
1514
|
if (Linter.#configPathIn(dir))
|
|
1437
1515
|
return dir;
|
|
1438
|
-
const parentDir =
|
|
1516
|
+
const parentDir = path7.dirname(dir);
|
|
1439
1517
|
if (parentDir === dir)
|
|
1440
1518
|
throw new Error(`biome.json not found from ${dir}`);
|
|
1441
1519
|
return this.#findBiomeRootPath(parentDir);
|
|
1442
1520
|
}
|
|
1443
1521
|
#toBiomePath(filePath) {
|
|
1444
|
-
const relativePath =
|
|
1445
|
-
if (!relativePath.startsWith("..") && !
|
|
1522
|
+
const relativePath = path7.relative(this.lintRoot, filePath);
|
|
1523
|
+
if (!relativePath.startsWith("..") && !path7.isAbsolute(relativePath))
|
|
1446
1524
|
return relativePath;
|
|
1447
1525
|
return filePath;
|
|
1448
1526
|
}
|
|
1449
1527
|
#resolveFilePath(filePath) {
|
|
1450
|
-
return
|
|
1528
|
+
return path7.isAbsolute(filePath) ? filePath : path7.join(this.lintRoot, filePath);
|
|
1451
1529
|
}
|
|
1452
1530
|
async#runBiome(args, input) {
|
|
1453
1531
|
return await new Promise((resolve, reject) => {
|
|
@@ -1472,7 +1550,7 @@ class Linter {
|
|
|
1472
1550
|
const diagnosticPath = diagnostic.location?.path;
|
|
1473
1551
|
if (!diagnosticPath)
|
|
1474
1552
|
return fallbackFilePath;
|
|
1475
|
-
return
|
|
1553
|
+
return path7.isAbsolute(diagnosticPath) ? diagnosticPath : path7.join(this.lintRoot, diagnosticPath);
|
|
1476
1554
|
}
|
|
1477
1555
|
#createLintMessage(diagnostic) {
|
|
1478
1556
|
const start = diagnostic.location?.start;
|
|
@@ -1678,9 +1756,137 @@ ${errorText}, ${warningText} found`];
|
|
|
1678
1756
|
}
|
|
1679
1757
|
}
|
|
1680
1758
|
|
|
1759
|
+
// pkgs/@akanjs/devkit/libSource.ts
|
|
1760
|
+
class LibSource {
|
|
1761
|
+
static manifestKey = "akan";
|
|
1762
|
+
static unhashedDirs = ["env"];
|
|
1763
|
+
#lib;
|
|
1764
|
+
constructor(lib) {
|
|
1765
|
+
this.#lib = lib;
|
|
1766
|
+
}
|
|
1767
|
+
get #prefix() {
|
|
1768
|
+
return `libs/${this.#lib.name}/`;
|
|
1769
|
+
}
|
|
1770
|
+
#isHashed(file) {
|
|
1771
|
+
const relative = file.slice(this.#prefix.length);
|
|
1772
|
+
return !LibSource.unhashedDirs.includes(relative.split("/")[0] ?? "");
|
|
1773
|
+
}
|
|
1774
|
+
static unstamped(manifestContent) {
|
|
1775
|
+
const manifest = JSON.parse(manifestContent);
|
|
1776
|
+
delete manifest[LibSource.manifestKey];
|
|
1777
|
+
return JSON.stringify(manifest);
|
|
1778
|
+
}
|
|
1779
|
+
static async hashFiles(files, manifestFile, read) {
|
|
1780
|
+
const hasher = new Bun.CryptoHasher("sha256");
|
|
1781
|
+
for (const file of files) {
|
|
1782
|
+
const content = await read(file);
|
|
1783
|
+
hasher.update(file);
|
|
1784
|
+
hasher.update("\x00");
|
|
1785
|
+
hasher.update(file === manifestFile ? LibSource.unstamped(content) : content);
|
|
1786
|
+
hasher.update("\x00");
|
|
1787
|
+
}
|
|
1788
|
+
return hasher.digest("hex").slice(0, 32);
|
|
1789
|
+
}
|
|
1790
|
+
async computeHash() {
|
|
1791
|
+
const files = (await this.#lib.workspace.listGitFiles([`libs/${this.#lib.name}`], { untracked: true })).filter((file) => this.#isHashed(file));
|
|
1792
|
+
return await LibSource.hashFiles(files, `${this.#prefix}package.json`, (file) => this.#lib.workspace.readFile(file));
|
|
1793
|
+
}
|
|
1794
|
+
async read() {
|
|
1795
|
+
const manifest = await this.#lib.getPackageJson();
|
|
1796
|
+
const akan = manifest[LibSource.manifestKey];
|
|
1797
|
+
return akan?.source ?? null;
|
|
1798
|
+
}
|
|
1799
|
+
async write({ origin, sha }) {
|
|
1800
|
+
const [manifest, hash] = await Promise.all([this.#lib.getPackageJson(), this.computeHash()]);
|
|
1801
|
+
const akan = manifest[LibSource.manifestKey] ?? {};
|
|
1802
|
+
const stamp = { origin, sha, hash, syncedAt: new Date().toISOString() };
|
|
1803
|
+
await this.#lib.setPackageJson({ ...manifest, [LibSource.manifestKey]: { ...akan, source: stamp } });
|
|
1804
|
+
return stamp;
|
|
1805
|
+
}
|
|
1806
|
+
async syncStamp({ origin, sha }) {
|
|
1807
|
+
const [current, hash] = await Promise.all([this.read(), this.computeHash()]);
|
|
1808
|
+
if (current?.origin === origin && current.sha === sha && current.hash === hash)
|
|
1809
|
+
return { stamp: current, changed: false };
|
|
1810
|
+
return { stamp: await this.write({ origin, sha }), changed: true };
|
|
1811
|
+
}
|
|
1812
|
+
async status() {
|
|
1813
|
+
const [stamp, hash] = await Promise.all([this.read(), this.computeHash()]);
|
|
1814
|
+
const drift = !stamp ? "unstamped" : stamp.hash === hash ? "clean" : "drifted";
|
|
1815
|
+
return { lib: this.#lib.name, drift, stamp, hash };
|
|
1816
|
+
}
|
|
1817
|
+
}
|
|
1818
|
+
function formatLibStatuses(statuses) {
|
|
1819
|
+
const marks = { clean: "clean ", drifted: "DRIFTED ", unstamped: "unstamped" };
|
|
1820
|
+
const sections = [
|
|
1821
|
+
"Akan Library Source Status",
|
|
1822
|
+
"",
|
|
1823
|
+
...statuses.map((status) => {
|
|
1824
|
+
const origin = status.stamp ? `${status.stamp.origin}@${status.stamp.sha}` : "no akan.source in package.json";
|
|
1825
|
+
return ` ${marks[status.drift]} libs/${status.lib} ${origin}`;
|
|
1826
|
+
}),
|
|
1827
|
+
"",
|
|
1828
|
+
`drifted: ${statuses.filter((status) => status.drift === "drifted").length} / ${statuses.length}`
|
|
1829
|
+
];
|
|
1830
|
+
return sections.join(`
|
|
1831
|
+
`);
|
|
1832
|
+
}
|
|
1833
|
+
|
|
1834
|
+
// pkgs/@akanjs/devkit/manifestDependencies.ts
|
|
1835
|
+
class ManifestDependencies {
|
|
1836
|
+
#root;
|
|
1837
|
+
#runtime;
|
|
1838
|
+
#typeOnly;
|
|
1839
|
+
#isKept;
|
|
1840
|
+
constructor(root, { runtime, typeOnly }, isKept) {
|
|
1841
|
+
this.#root = root;
|
|
1842
|
+
this.#runtime = new Set(runtime);
|
|
1843
|
+
this.#typeOnly = new Set(typeOnly);
|
|
1844
|
+
this.#isKept = isKept;
|
|
1845
|
+
}
|
|
1846
|
+
static keptBy(manifest) {
|
|
1847
|
+
const { keepDependencies } = manifest[LibSource.manifestKey] ?? {};
|
|
1848
|
+
return Array.isArray(keepDependencies) ? keepDependencies.filter((dep) => typeof dep === "string") : [];
|
|
1849
|
+
}
|
|
1850
|
+
realign(manifest) {
|
|
1851
|
+
const removed = [];
|
|
1852
|
+
const unverifiable = [];
|
|
1853
|
+
const dependencies = {};
|
|
1854
|
+
for (const [dep, version] of Object.entries(manifest.dependencies ?? {})) {
|
|
1855
|
+
if (this.#typeOnly.has(dep))
|
|
1856
|
+
continue;
|
|
1857
|
+
const rootVersion = this.#rootVersionOf(dep);
|
|
1858
|
+
if (!rootVersion) {
|
|
1859
|
+
unverifiable.push(dep);
|
|
1860
|
+
dependencies[dep] = version;
|
|
1861
|
+
} else if (this.#runtime.has(dep) || this.#isKept(dep))
|
|
1862
|
+
dependencies[dep] = rootVersion;
|
|
1863
|
+
else
|
|
1864
|
+
removed.push(dep);
|
|
1865
|
+
}
|
|
1866
|
+
const runtimeOfRootDependencies = [...this.#runtime].filter((dep) => this.#root.dependencies?.[dep]);
|
|
1867
|
+
this.#append(dependencies, runtimeOfRootDependencies);
|
|
1868
|
+
const devDependencies = {};
|
|
1869
|
+
for (const [dep, version] of Object.entries(manifest.devDependencies ?? {}))
|
|
1870
|
+
if (!Object.hasOwn(dependencies, dep))
|
|
1871
|
+
devDependencies[dep] = this.#rootVersionOf(dep) ?? version;
|
|
1872
|
+
this.#append(devDependencies, [...this.#typeOnly]);
|
|
1873
|
+
return { dependencies, devDependencies, removed, unverifiable };
|
|
1874
|
+
}
|
|
1875
|
+
#append(map, deps) {
|
|
1876
|
+
for (const dep of deps.filter((dep) => !Object.hasOwn(map, dep)).sort((a, b) => a < b ? -1 : 1)) {
|
|
1877
|
+
const rootVersion = this.#rootVersionOf(dep);
|
|
1878
|
+
if (rootVersion)
|
|
1879
|
+
map[dep] = rootVersion;
|
|
1880
|
+
}
|
|
1881
|
+
}
|
|
1882
|
+
#rootVersionOf(dep) {
|
|
1883
|
+
return this.#root.dependencies?.[dep] ?? this.#root.devDependencies?.[dep];
|
|
1884
|
+
}
|
|
1885
|
+
}
|
|
1886
|
+
|
|
1681
1887
|
// pkgs/@akanjs/devkit/repoIdentity.ts
|
|
1682
1888
|
import { execFileSync } from "child_process";
|
|
1683
|
-
import
|
|
1889
|
+
import path8 from "path";
|
|
1684
1890
|
var resolved = new Map;
|
|
1685
1891
|
var readRemoteName = (workspaceRoot) => {
|
|
1686
1892
|
try {
|
|
@@ -1698,13 +1904,13 @@ var resolveRepoName = (workspaceRoot) => {
|
|
|
1698
1904
|
const cached = resolved.get(workspaceRoot);
|
|
1699
1905
|
if (cached)
|
|
1700
1906
|
return cached;
|
|
1701
|
-
const repoName = readRemoteName(workspaceRoot) ??
|
|
1907
|
+
const repoName = readRemoteName(workspaceRoot) ?? path8.basename(workspaceRoot);
|
|
1702
1908
|
resolved.set(workspaceRoot, repoName);
|
|
1703
1909
|
return repoName;
|
|
1704
1910
|
};
|
|
1705
1911
|
|
|
1706
1912
|
// pkgs/@akanjs/devkit/scanInfo.ts
|
|
1707
|
-
import
|
|
1913
|
+
import path9 from "path";
|
|
1708
1914
|
|
|
1709
1915
|
// pkgs/@akanjs/devkit/workspaceLayout.ts
|
|
1710
1916
|
var appRootAllowedFiles = new Set([
|
|
@@ -1777,6 +1983,14 @@ var libFacetRootAllowedFiles = new Set([
|
|
|
1777
1983
|
]);
|
|
1778
1984
|
var libFacetRootTestPattern = /^[A-Za-z][A-Za-z0-9_-]*\.signal\.(test|spec)\.(ts|tsx)$/;
|
|
1779
1985
|
var isAllowedLibFacetRootFile = (filename) => libFacetRootAllowedFiles.has(filename) || libFacetRootTestPattern.test(filename);
|
|
1986
|
+
var barrelFacetDirs = ["ui", "webkit", "srvkit", "common", "plugin"];
|
|
1987
|
+
var barrelShadowingIndexFiles = new Set(["index.tsx", "index.jsx", "index.mts"]);
|
|
1988
|
+
var facetIndexShadowOf = (sysRelativePath) => {
|
|
1989
|
+
const [facet, filename = "", ...nested] = sysRelativePath.split("/");
|
|
1990
|
+
if (nested.length || !barrelShadowingIndexFiles.has(filename) || !barrelFacetDirs.some((dir) => dir === facet))
|
|
1991
|
+
return null;
|
|
1992
|
+
return `shadows the generated ${facet}/index.ts: Bun loads ${filename} and TypeScript checks index.ts, so a name only ` + `the generated barrel exports typechecks and is undefined at runtime. Delete it, since the generated barrel ` + `re-exports every file and folder in ${facet}/; a namespace it builds belongs in ${facet}/<Folder>/index.tsx`;
|
|
1993
|
+
};
|
|
1780
1994
|
var retiredAppRootEntries = new Set([
|
|
1781
1995
|
"android",
|
|
1782
1996
|
"ios",
|
|
@@ -1785,7 +1999,7 @@ var retiredAppRootEntries = new Set([
|
|
|
1785
1999
|
"capacitor.config.js",
|
|
1786
2000
|
"capacitor.config.json"
|
|
1787
2001
|
]);
|
|
1788
|
-
var rootEntryHintOf = (type, name) => type === "app" && retiredAppRootEntries.has(name) ? "a Capacitor-era entry; the native runtime generates its projects under
|
|
2002
|
+
var rootEntryHintOf = (type, name) => type === "app" && retiredAppRootEntries.has(name) ? "a Capacitor-era entry; the native runtime generates its projects under dist/native/<app>/<target>, so delete it" : null;
|
|
1789
2003
|
var isScannedRootEntry = (type, name) => !name.startsWith(".") || rootAllowedDirs[type].has(name);
|
|
1790
2004
|
|
|
1791
2005
|
// pkgs/@akanjs/devkit/scanInfo.ts
|
|
@@ -1815,9 +2029,9 @@ var moduleUiFileTypes = {
|
|
|
1815
2029
|
scalar: new Set(["Template", "Unit"])
|
|
1816
2030
|
};
|
|
1817
2031
|
var createDependencyScanner = async (exec) => (await import("./dependencyScanner-06z2dmrr.js")).TypeScriptDependencyScanner.from(exec);
|
|
1818
|
-
var getScanPath = (exec, relativePath) =>
|
|
2032
|
+
var getScanPath = (exec, relativePath) => path9.posix.join(`${exec.type}s`, exec.name, relativePath.split(path9.sep).join("/"));
|
|
1819
2033
|
var getModuleNameFromPath = (kind, modulePath) => {
|
|
1820
|
-
const dirname =
|
|
2034
|
+
const dirname = path9.basename(modulePath);
|
|
1821
2035
|
return kind === "service" ? dirname.replace(/^_+/, "") : dirname;
|
|
1822
2036
|
};
|
|
1823
2037
|
async function assertScanConvention(exec, libRoot) {
|
|
@@ -1834,22 +2048,28 @@ async function assertScanConvention(exec, libRoot) {
|
|
|
1834
2048
|
for (const dirname of dirs)
|
|
1835
2049
|
if (!allowedRootDirs.has(dirname))
|
|
1836
2050
|
addViolation(dirname, rootEntryHintOf(exec.type, dirname) ?? `unsupported ${exec.type} root folder`);
|
|
2051
|
+
for (const facet of barrelFacetDirs)
|
|
2052
|
+
for (const filename of await exec.readdir(facet)) {
|
|
2053
|
+
const shadow = facetIndexShadowOf(`${facet}/${filename}`);
|
|
2054
|
+
if (shadow)
|
|
2055
|
+
addViolation(path9.join(facet, filename), shadow);
|
|
2056
|
+
}
|
|
1837
2057
|
if (exec.type === "lib")
|
|
1838
2058
|
for (const { relativePath, reason } of await exec.getPageConventionViolations())
|
|
1839
2059
|
addViolation(relativePath, reason);
|
|
1840
2060
|
for (const filename of libRoot.files)
|
|
1841
2061
|
if (!isAllowedLibFacetRootFile(filename))
|
|
1842
|
-
addViolation(
|
|
2062
|
+
addViolation(path9.join("lib", filename), "unsupported lib facet root file");
|
|
1843
2063
|
for (const dirname of libRoot.dirs)
|
|
1844
2064
|
if (dirname.startsWith("__") && !internalLibDirs.has(dirname))
|
|
1845
|
-
addViolation(
|
|
2065
|
+
addViolation(path9.join("lib", dirname), "unsupported internal lib folder");
|
|
1846
2066
|
const databaseDirs = libRoot.dirs.filter((dirname) => !dirname.startsWith("_"));
|
|
1847
2067
|
const serviceDirs = libRoot.dirs.filter((dirname) => dirname.startsWith("_") && !dirname.startsWith("__"));
|
|
1848
2068
|
const scalarDirs = await exec.readdir("lib/__scalar");
|
|
1849
2069
|
await Promise.all([
|
|
1850
|
-
...databaseDirs.map((dirname) => validateModuleFiles(exec, violations, "database",
|
|
1851
|
-
...serviceDirs.map((dirname) => validateModuleFiles(exec, violations, "service",
|
|
1852
|
-
...scalarDirs.map((dirname) => validateModuleFiles(exec, violations, "scalar",
|
|
2070
|
+
...databaseDirs.map((dirname) => validateModuleFiles(exec, violations, "database", path9.join("lib", dirname))),
|
|
2071
|
+
...serviceDirs.map((dirname) => validateModuleFiles(exec, violations, "service", path9.join("lib", dirname))),
|
|
2072
|
+
...scalarDirs.map((dirname) => validateModuleFiles(exec, violations, "scalar", path9.join("lib/__scalar", dirname)))
|
|
1853
2073
|
]);
|
|
1854
2074
|
if (violations.length > 0) {
|
|
1855
2075
|
throw new Error(`[scan-convention]
|
|
@@ -1861,11 +2081,11 @@ async function validateModuleFiles(exec, violations, kind, modulePath) {
|
|
|
1861
2081
|
const { files, dirs } = await exec.getFilesAndDirs(modulePath);
|
|
1862
2082
|
const moduleName = getModuleNameFromPath(kind, modulePath);
|
|
1863
2083
|
dirs.forEach((dirname) => {
|
|
1864
|
-
violations.push(`${getScanPath(exec,
|
|
2084
|
+
violations.push(`${getScanPath(exec, path9.join(modulePath, dirname))}: unsupported module folder`);
|
|
1865
2085
|
});
|
|
1866
2086
|
const uiModuleName = moduleName[0].toUpperCase() + moduleName.slice(1);
|
|
1867
2087
|
for (const filename of files) {
|
|
1868
|
-
const scanPath = getScanPath(exec,
|
|
2088
|
+
const scanPath = getScanPath(exec, path9.join(modulePath, filename));
|
|
1869
2089
|
if (filename === "index.ts" || filename === "index.tsx" || /\.(test|spec)\.(ts|tsx)$/.test(filename))
|
|
1870
2090
|
continue;
|
|
1871
2091
|
if (filename === `${moduleName}.abstract.md`)
|
|
@@ -1938,16 +2158,16 @@ class ScanInfo {
|
|
|
1938
2158
|
}
|
|
1939
2159
|
};
|
|
1940
2160
|
await Promise.all([
|
|
1941
|
-
...databaseDirs.map((name) => collect(
|
|
1942
|
-
...serviceDirs.map((dirname) => collect(
|
|
1943
|
-
...scalarDirs.map((name) => collect(
|
|
2161
|
+
...databaseDirs.map((name) => collect(path9.join("lib", name), name, "databases")),
|
|
2162
|
+
...serviceDirs.map((dirname) => collect(path9.join("lib", dirname), dirname.slice(1), "services")),
|
|
2163
|
+
...scalarDirs.map((name) => collect(path9.join("lib/__scalar", name), name, "scalars"))
|
|
1944
2164
|
]);
|
|
1945
2165
|
const routes = exec.type === "lib" ? [] : await exec.getPageKeys();
|
|
1946
2166
|
const common = {
|
|
1947
2167
|
name: exec.name,
|
|
1948
2168
|
type: exec.type,
|
|
1949
2169
|
repoName: exec.workspace.repoName,
|
|
1950
|
-
serveDomain: WorkspaceExecutor.getBaseDevEnv(
|
|
2170
|
+
serveDomain: WorkspaceExecutor.getBaseDevEnv(path9.join(exec.workspace.workspaceRoot, ".env")).serveDomain,
|
|
1951
2171
|
files,
|
|
1952
2172
|
libDeps,
|
|
1953
2173
|
pkgDeps,
|
|
@@ -2329,10 +2549,10 @@ class Executor {
|
|
|
2329
2549
|
return this.#settle(proc, target, { redStderr: true }).then(({ code, signal }) => ({ code, signal }));
|
|
2330
2550
|
}
|
|
2331
2551
|
getPath(filePath) {
|
|
2332
|
-
if (
|
|
2552
|
+
if (path10.isAbsolute(filePath))
|
|
2333
2553
|
return filePath;
|
|
2334
2554
|
if (filePath.startsWith("."))
|
|
2335
|
-
return
|
|
2555
|
+
return path10.join(this.cwdPath, filePath);
|
|
2336
2556
|
const baseParts = this.cwdPath.split(/[\\/]/).filter(Boolean);
|
|
2337
2557
|
const targetParts = filePath.split(/[\\/]/).filter(Boolean);
|
|
2338
2558
|
let overlapLength = 0;
|
|
@@ -2346,7 +2566,7 @@ class Executor {
|
|
|
2346
2566
|
if (isOverlap)
|
|
2347
2567
|
overlapLength = i;
|
|
2348
2568
|
}
|
|
2349
|
-
return
|
|
2569
|
+
return path10.join(this.cwdPath, ...targetParts.slice(overlapLength));
|
|
2350
2570
|
}
|
|
2351
2571
|
async mkdir(dirPath) {
|
|
2352
2572
|
const writePath = this.getPath(dirPath);
|
|
@@ -2387,7 +2607,7 @@ class Executor {
|
|
|
2387
2607
|
return this;
|
|
2388
2608
|
}
|
|
2389
2609
|
async removeDir(dirPath) {
|
|
2390
|
-
const readPath =
|
|
2610
|
+
const readPath = path10.join(this.getPath(dirPath), ".");
|
|
2391
2611
|
if (await FileSys2.entryExists(readPath))
|
|
2392
2612
|
await rm3(readPath, { recursive: true, force: true });
|
|
2393
2613
|
this.logger.verbose(`Remove directory ${readPath}`);
|
|
@@ -2395,11 +2615,10 @@ class Executor {
|
|
|
2395
2615
|
}
|
|
2396
2616
|
async writeFile(filePath, content, { overwrite = true, silent = false } = {}) {
|
|
2397
2617
|
const writePath = this.getPath(filePath);
|
|
2398
|
-
const dir =
|
|
2618
|
+
const dir = path10.dirname(writePath);
|
|
2399
2619
|
if (!await FileSys2.dirExists(dir))
|
|
2400
2620
|
await mkdir2(dir, { recursive: true });
|
|
2401
|
-
let contentStr = typeof content === "string" ? content :
|
|
2402
|
-
`;
|
|
2621
|
+
let contentStr = typeof content === "string" ? content : JsonFormatter.stringify(content, writePath);
|
|
2403
2622
|
if (await FileSys2.fileExists(writePath)) {
|
|
2404
2623
|
const currentContent = await FileSys2.readText(writePath);
|
|
2405
2624
|
if (currentContent === contentStr || !overwrite) {
|
|
@@ -2421,7 +2640,7 @@ class Executor {
|
|
|
2421
2640
|
await this.writeFile(filePath, content);
|
|
2422
2641
|
}
|
|
2423
2642
|
async getLocalFile(targetPath) {
|
|
2424
|
-
const filePath =
|
|
2643
|
+
const filePath = path10.isAbsolute(targetPath) ? targetPath : targetPath.replace(this.cwdPath, "");
|
|
2425
2644
|
const content = await this.readFile(filePath);
|
|
2426
2645
|
return { filePath, content };
|
|
2427
2646
|
}
|
|
@@ -2508,9 +2727,9 @@ class Executor {
|
|
|
2508
2727
|
const result = await getContent.default(scanInfo ?? null, dict, options);
|
|
2509
2728
|
if (result === null)
|
|
2510
2729
|
return null;
|
|
2511
|
-
const filename = typeof result === "object" ? result.filename :
|
|
2730
|
+
const filename = typeof result === "object" ? result.filename : path10.basename(targetPath).replace(".js", ".ts");
|
|
2512
2731
|
const content = typeof result === "object" ? result.content : result;
|
|
2513
|
-
const convertedTargetPath = convertPath(`${
|
|
2732
|
+
const convertedTargetPath = convertPath(`${path10.dirname(targetPath)}/${filename}`);
|
|
2514
2733
|
this.logger.verbose(`Apply template ${templatePath} to ${convertedTargetPath}`);
|
|
2515
2734
|
return this.writeFile(convertedTargetPath, content, { overwrite });
|
|
2516
2735
|
} else if (targetPath.endsWith(".template")) {
|
|
@@ -2519,10 +2738,10 @@ class Executor {
|
|
|
2519
2738
|
const convertedContent = Object.entries(dict).reduce((data, [key, value]) => data.replace(new RegExp(`<%= ${key} %>`, "g"), value), content);
|
|
2520
2739
|
this.logger.verbose(`Apply template ${templatePath} to ${convertedTargetPath}`);
|
|
2521
2740
|
return this.writeFile(convertedTargetPath, convertedContent, { overwrite });
|
|
2522
|
-
} else if (staticTemplateFileExtensions.has(
|
|
2741
|
+
} else if (staticTemplateFileExtensions.has(path10.extname(targetPath).toLowerCase())) {
|
|
2523
2742
|
const convertedTargetPath = convertPath(targetPath);
|
|
2524
2743
|
const writePath = this.getPath(convertedTargetPath);
|
|
2525
|
-
const dirname =
|
|
2744
|
+
const dirname = path10.dirname(writePath);
|
|
2526
2745
|
if (!await FileSys2.dirExists(dirname))
|
|
2527
2746
|
await mkdir2(dirname, { recursive: true });
|
|
2528
2747
|
await copyFile(templatePath, writePath);
|
|
@@ -2544,7 +2763,7 @@ class Executor {
|
|
|
2544
2763
|
if ((await stat2(templatePath)).isFile()) {
|
|
2545
2764
|
const fileContent = await this.#applyTemplateFile({
|
|
2546
2765
|
templatePath,
|
|
2547
|
-
targetPath:
|
|
2766
|
+
targetPath: path10.join(basePath, path10.basename(templatePath)),
|
|
2548
2767
|
scanInfo,
|
|
2549
2768
|
overwrite
|
|
2550
2769
|
}, dict, options);
|
|
@@ -2552,19 +2771,19 @@ class Executor {
|
|
|
2552
2771
|
} else {
|
|
2553
2772
|
const subdirs = await readDirEntries(templatePath);
|
|
2554
2773
|
const fileContents = (await Promise.all(subdirs.map(async (subdir) => {
|
|
2555
|
-
const subpath =
|
|
2774
|
+
const subpath = path10.join(templatePath, subdir);
|
|
2556
2775
|
if ((await stat2(subpath)).isFile()) {
|
|
2557
2776
|
const fileContent = await this.#applyTemplateFile({
|
|
2558
2777
|
templatePath: subpath,
|
|
2559
|
-
targetPath:
|
|
2778
|
+
targetPath: path10.join(basePath, subdir),
|
|
2560
2779
|
scanInfo,
|
|
2561
2780
|
overwrite
|
|
2562
2781
|
}, dict, options);
|
|
2563
2782
|
return fileContent ? [fileContent] : [];
|
|
2564
2783
|
} else
|
|
2565
2784
|
return await this._applyTemplate({
|
|
2566
|
-
basePath:
|
|
2567
|
-
template:
|
|
2785
|
+
basePath: path10.join(basePath, subdir),
|
|
2786
|
+
template: path10.join(template, subdir),
|
|
2568
2787
|
scanInfo,
|
|
2569
2788
|
dict,
|
|
2570
2789
|
overwrite,
|
|
@@ -2576,8 +2795,8 @@ class Executor {
|
|
|
2576
2795
|
}
|
|
2577
2796
|
async#resolveTemplateRoot() {
|
|
2578
2797
|
const candidates = [
|
|
2579
|
-
|
|
2580
|
-
|
|
2798
|
+
path10.resolve(getDirname2(import.meta.url), "templates"),
|
|
2799
|
+
path10.resolve(getDirname2(import.meta.url), "../cli/templates")
|
|
2581
2800
|
];
|
|
2582
2801
|
for (const candidate of candidates) {
|
|
2583
2802
|
if (await FileSys2.dirExists(candidate))
|
|
@@ -2645,11 +2864,11 @@ class Executor {
|
|
|
2645
2864
|
async#resolveTypecheckWorkerEntry() {
|
|
2646
2865
|
const dirname = getDirname2(import.meta.url);
|
|
2647
2866
|
const candidates = [
|
|
2648
|
-
|
|
2649
|
-
|
|
2650
|
-
|
|
2651
|
-
|
|
2652
|
-
|
|
2867
|
+
path10.join(process.cwd(), "pkgs/@akanjs/devkit/typecheck/typecheck.proc.ts"),
|
|
2868
|
+
path10.join(process.cwd(), "node_modules/@akanjs/devkit/typecheck/typecheck.proc.ts"),
|
|
2869
|
+
path10.join(dirname, "typecheck/typecheck.proc.ts"),
|
|
2870
|
+
path10.join(dirname, "typecheck.proc.js"),
|
|
2871
|
+
path10.join(dirname, "typecheck.proc.ts")
|
|
2653
2872
|
];
|
|
2654
2873
|
for (const candidate of candidates)
|
|
2655
2874
|
if (await Bun.file(candidate).exists())
|
|
@@ -2769,7 +2988,7 @@ class WorkspaceExecutor extends Executor {
|
|
|
2769
2988
|
await Promise.all(dirs.map(async (dir) => {
|
|
2770
2989
|
if (dir.includes("_") || AVOID_DIRS.includes(dir))
|
|
2771
2990
|
return;
|
|
2772
|
-
const dirPath =
|
|
2991
|
+
const dirPath = path10.join(dirname, dir);
|
|
2773
2992
|
if ((await stat2(dirPath)).isDirectory()) {
|
|
2774
2993
|
results.push(`${prefix}${dir}`);
|
|
2775
2994
|
if (maxDepth > 0)
|
|
@@ -2806,9 +3025,9 @@ class WorkspaceExecutor extends Executor {
|
|
|
2806
3025
|
await Promise.all(dirs.map(async (dir) => {
|
|
2807
3026
|
if (AVOID_DIRS.includes(dir))
|
|
2808
3027
|
return;
|
|
2809
|
-
const dirPath =
|
|
3028
|
+
const dirPath = path10.join(dirname, dir);
|
|
2810
3029
|
if (await FileSys2.dirExists(dirPath)) {
|
|
2811
|
-
const hasTargetFile = await FileSys2.fileExists(
|
|
3030
|
+
const hasTargetFile = await FileSys2.fileExists(path10.join(dirPath, targetFilename));
|
|
2812
3031
|
if (hasTargetFile)
|
|
2813
3032
|
results.push(`${prefix}${dir}`);
|
|
2814
3033
|
if (maxDepth > 0)
|
|
@@ -2838,7 +3057,6 @@ class WorkspaceExecutor extends Executor {
|
|
|
2838
3057
|
return await this.#fromEverySys((sys) => sys.getViewsSourceCode());
|
|
2839
3058
|
}
|
|
2840
3059
|
}
|
|
2841
|
-
var scanFacetDirs = ["ui", "webkit", "srvkit", "common", "plugin"];
|
|
2842
3060
|
|
|
2843
3061
|
class SysExecutor extends Executor {
|
|
2844
3062
|
workspace;
|
|
@@ -2868,7 +3086,7 @@ class SysExecutor extends Executor {
|
|
|
2868
3086
|
return [];
|
|
2869
3087
|
const violations = [];
|
|
2870
3088
|
for (const entry of await this.getAllFiles("**/*", { cwd: this.getPath("page") })) {
|
|
2871
|
-
const relativePath = entry.split(
|
|
3089
|
+
const relativePath = entry.split(path10.sep).join("/");
|
|
2872
3090
|
const reason = getPageSourceFileViolation(relativePath);
|
|
2873
3091
|
if (reason)
|
|
2874
3092
|
violations.push({ relativePath: `page/${relativePath}`, reason });
|
|
@@ -2893,7 +3111,7 @@ class SysExecutor extends Executor {
|
|
|
2893
3111
|
this._applyTemplate({ basePath: ".", template: "server.ts", scanInfo }),
|
|
2894
3112
|
this._applyTemplate({ basePath: ".", template: "client.ts", scanInfo }),
|
|
2895
3113
|
this.type === "lib" ? this._applyTemplate({ basePath: ".", template: "index.ts", scanInfo }) : null,
|
|
2896
|
-
...
|
|
3114
|
+
...barrelFacetDirs.map((facet) => this._applyTemplate({
|
|
2897
3115
|
basePath: facet,
|
|
2898
3116
|
template: "facetIndex/index.ts",
|
|
2899
3117
|
scanInfo,
|
|
@@ -2922,11 +3140,9 @@ class SysExecutor extends Executor {
|
|
|
2922
3140
|
await CodegenLock.run(this.workspace.workspaceRoot, `scan:${this.name}`, async () => {
|
|
2923
3141
|
await Promise.all(this.#getScanTemplateTasks(scanInfo));
|
|
2924
3142
|
await this.writeJson(`akan.${this.type}.json`, scanInfo.getScanResult());
|
|
2925
|
-
|
|
2926
|
-
this.#updateDependencies(scanInfo);
|
|
3143
|
+
await this.#updateDependencies(scanInfo);
|
|
2927
3144
|
if (writeLib) {
|
|
2928
3145
|
const libInfos = [...scanInfo.getLibInfos().values()];
|
|
2929
|
-
await this.#updateDependencies(scanInfo);
|
|
2930
3146
|
await Promise.all(libInfos.flatMap((libInfo) => libInfo.exec.#getScanTemplateTasks(libInfo)));
|
|
2931
3147
|
}
|
|
2932
3148
|
await this.syncAgentsIndex(scanInfo);
|
|
@@ -2945,27 +3161,27 @@ class SysExecutor extends Executor {
|
|
|
2945
3161
|
await this.writeFile("CLAUDE.md", renderScopeClaudeMd(scope));
|
|
2946
3162
|
}
|
|
2947
3163
|
async#updateDependencies(scanInfo) {
|
|
2948
|
-
const rootPackageJson = await
|
|
2949
|
-
|
|
2950
|
-
|
|
2951
|
-
|
|
2952
|
-
const
|
|
2953
|
-
const
|
|
2954
|
-
|
|
2955
|
-
...
|
|
2956
|
-
|
|
2957
|
-
|
|
2958
|
-
|
|
2959
|
-
|
|
2960
|
-
|
|
2961
|
-
|
|
2962
|
-
|
|
2963
|
-
|
|
2964
|
-
|
|
2965
|
-
await this.setPackageJson(
|
|
3164
|
+
const [rootPackageJson, packageJson] = await Promise.all([
|
|
3165
|
+
this.workspace.getPackageJson(),
|
|
3166
|
+
this.getPackageJson({ refresh: true })
|
|
3167
|
+
]);
|
|
3168
|
+
const { dependencies: runtime, devDependencies: typeOnly, akanConfig } = scanInfo.getScanResult();
|
|
3169
|
+
const kept = new Set([
|
|
3170
|
+
...ManifestDependencies.keptBy(packageJson),
|
|
3171
|
+
...akanConfig.externalLibs,
|
|
3172
|
+
...akanConfig.trustedDependencies
|
|
3173
|
+
]);
|
|
3174
|
+
const isKept = (dep) => kept.has(dep) || isAkanFrameworkDependency(dep);
|
|
3175
|
+
const { dependencies, devDependencies, removed, unverifiable } = new ManifestDependencies(rootPackageJson, { runtime, typeOnly }, isKept).realign(packageJson);
|
|
3176
|
+
const manifestPath = `${this.type}s/${this.name}/package.json`;
|
|
3177
|
+
if (removed.length)
|
|
3178
|
+
this.logger.info(`Removed from ${manifestPath}, declared by the root and imported nowhere: ${removed.join(", ")} (list one in akan.keepDependencies to keep it)`);
|
|
3179
|
+
if (unverifiable.length)
|
|
3180
|
+
this.logger.warn(`${manifestPath} lists ${unverifiable.join(", ")}, which the root package.json does not declare, so sync cannot tell whether it is used; kept as is`);
|
|
3181
|
+
await this.setPackageJson({ ...packageJson, dependencies, devDependencies });
|
|
2966
3182
|
}
|
|
2967
3183
|
async getLocalFile(targetPath) {
|
|
2968
|
-
const filePath =
|
|
3184
|
+
const filePath = path10.isAbsolute(targetPath) ? targetPath : `${this.type}s/${this.name}/${targetPath}`;
|
|
2969
3185
|
const content = await this.workspace.readFile(filePath);
|
|
2970
3186
|
return { filePath, content };
|
|
2971
3187
|
}
|
|
@@ -3053,14 +3269,19 @@ class AppExecutor extends SysExecutor {
|
|
|
3053
3269
|
static from(executor, name) {
|
|
3054
3270
|
return new AppExecutor({ workspace: executor instanceof WorkspaceExecutor ? executor : executor.workspace, name });
|
|
3055
3271
|
}
|
|
3056
|
-
static #keptOnStart = [
|
|
3272
|
+
static #keptOnStart = [path10.join(".akan", "cache", "bin")];
|
|
3273
|
+
static #legacyNative = path10.join(".akan", "native");
|
|
3057
3274
|
async#removeDevOutput(dir = ".akan") {
|
|
3058
3275
|
const entries = await readDirEntries(this.getPath(dir)).catch(() => []);
|
|
3059
3276
|
await Promise.all(entries.map(async (name) => {
|
|
3060
|
-
const entry =
|
|
3277
|
+
const entry = path10.join(dir, name);
|
|
3278
|
+
if (entry === AppExecutor.#legacyNative) {
|
|
3279
|
+
this.logger.warn(`apps/${this.name}/.akan/native holds native builds from before they moved to dist/native/${this.name}: upload any release waiting in its updates folders, then delete it.`);
|
|
3280
|
+
return;
|
|
3281
|
+
}
|
|
3061
3282
|
if (AppExecutor.#keptOnStart.includes(entry))
|
|
3062
3283
|
return;
|
|
3063
|
-
if (AppExecutor.#keptOnStart.some((kept) => kept.startsWith(`${entry}${
|
|
3284
|
+
if (AppExecutor.#keptOnStart.some((kept) => kept.startsWith(`${entry}${path10.sep}`)))
|
|
3064
3285
|
return await this.#removeDevOutput(entry);
|
|
3065
3286
|
await this.removeDir(entry);
|
|
3066
3287
|
}));
|
|
@@ -3132,10 +3353,10 @@ class AppExecutor extends SysExecutor {
|
|
|
3132
3353
|
});
|
|
3133
3354
|
if (type === "build") {
|
|
3134
3355
|
const buildEnv = { ...env };
|
|
3135
|
-
|
|
3136
|
-
|
|
3137
|
-
|
|
3138
|
-
|
|
3356
|
+
for (const key of ["AKAN_PUBLIC_CLIENT_PORT", "AKAN_PUBLIC_SERVER_PORT", "AKAN_PUBLIC_OPERATION_MODE"]) {
|
|
3357
|
+
delete buildEnv[key];
|
|
3358
|
+
delete process.env[key];
|
|
3359
|
+
}
|
|
3139
3360
|
Object.assign(process.env, buildEnv);
|
|
3140
3361
|
}
|
|
3141
3362
|
return { env };
|
|
@@ -3184,13 +3405,13 @@ class AppExecutor extends SysExecutor {
|
|
|
3184
3405
|
absolute: false,
|
|
3185
3406
|
onlyFiles: true
|
|
3186
3407
|
})) {
|
|
3187
|
-
const segments = rel.split(
|
|
3408
|
+
const segments = rel.split(path10.sep);
|
|
3188
3409
|
if (segments.some((s) => s === "node_modules"))
|
|
3189
3410
|
continue;
|
|
3190
3411
|
const posix = `${root.keyPrefix}${segments.join("/")}`;
|
|
3191
3412
|
if (!root.keyPrefix && libKeyPrefixes.some((prefix) => posix.startsWith(prefix)))
|
|
3192
3413
|
continue;
|
|
3193
|
-
const absPath =
|
|
3414
|
+
const absPath = path10.join(root.dir, ...segments);
|
|
3194
3415
|
validatePageSourceFile(posix, { filePath: absPath });
|
|
3195
3416
|
if (!isRouteSourceFile(posix))
|
|
3196
3417
|
continue;
|
|
@@ -3331,7 +3552,7 @@ class AppExecutor extends SysExecutor {
|
|
|
3331
3552
|
static async#linkLibAsset(targetPath, linkPath) {
|
|
3332
3553
|
const isWindows = process.platform === "win32";
|
|
3333
3554
|
try {
|
|
3334
|
-
const target = isWindows ? targetPath :
|
|
3555
|
+
const target = isWindows ? targetPath : path10.relative(path10.dirname(linkPath), targetPath);
|
|
3335
3556
|
await symlink(target, linkPath, isWindows ? "junction" : "dir");
|
|
3336
3557
|
} catch (error) {
|
|
3337
3558
|
if (!isWindows)
|
|
@@ -3374,7 +3595,7 @@ class AppExecutor extends SysExecutor {
|
|
|
3374
3595
|
await this.writeFile(rel, content, opts);
|
|
3375
3596
|
},
|
|
3376
3597
|
readEnvClient: async () => {
|
|
3377
|
-
const envClientPath =
|
|
3598
|
+
const envClientPath = path10.join(this.cwdPath, "env", "env.client.ts");
|
|
3378
3599
|
if (!await FileSys2.fileExists(envClientPath))
|
|
3379
3600
|
return null;
|
|
3380
3601
|
try {
|
|
@@ -3468,7 +3689,7 @@ class PkgExecutor extends Executor {
|
|
|
3468
3689
|
return overrideVersion;
|
|
3469
3690
|
try {
|
|
3470
3691
|
const packageJsonPath = `pkgs/${dep}/package.json`;
|
|
3471
|
-
if (!await Bun.file(
|
|
3692
|
+
if (!await Bun.file(path10.join(this.workspace.workspaceRoot, packageJsonPath)).exists())
|
|
3472
3693
|
return;
|
|
3473
3694
|
const packageJson = await this.workspace.readJson(packageJsonPath);
|
|
3474
3695
|
if (packageJson.name === dep)
|
|
@@ -3561,4 +3782,4 @@ class ModuleExecutor extends Executor {
|
|
|
3561
3782
|
}
|
|
3562
3783
|
}
|
|
3563
3784
|
|
|
3564
|
-
export { AGENT_BLOCK_START, AGENT_BLOCK_END, stampBlockVersion, extractBlockVersion, readDevkitVersion, upsertAgentBlock, extractAgentBlock, renderRecipeEntries, collectScopeRecipeSources, renderScopeAgentBlock, CLAUDE_COMMENT_RULE, binPlatforms, AsyncDefaultExportDetector, resolveSsrPageEntriesForApp, CodegenLock, Linter, rootAllowedFiles, rootAllowedDirs, isAllowedLibFacetRootFile, rootEntryHintOf, isScannedRootEntry, AppInfo, Spinner, Executor, WorkspaceExecutor, SysExecutor, AppExecutor, LibExecutor, PkgExecutor, ModuleExecutor };
|
|
3785
|
+
export { AGENT_BLOCK_START, AGENT_BLOCK_END, stampBlockVersion, extractBlockVersion, readDevkitVersion, upsertAgentBlock, extractAgentBlock, renderRecipeEntries, collectScopeRecipeSources, renderScopeAgentBlock, CLAUDE_COMMENT_RULE, binPlatforms, AsyncDefaultExportDetector, resolveSsrPageEntriesForApp, CodegenLock, Linter, LibSource, formatLibStatuses, rootAllowedFiles, rootAllowedDirs, isAllowedLibFacetRootFile, barrelFacetDirs, facetIndexShadowOf, rootEntryHintOf, isScannedRootEntry, AppInfo, Spinner, Executor, WorkspaceExecutor, SysExecutor, AppExecutor, LibExecutor, PkgExecutor, ModuleExecutor };
|