@akanjs/cli 3.0.0-alpha.83 → 3.0.0-alpha.85
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-gp3kwz7x.js} +2 -1
- package/{agent.command-180hh0ye.js → agent.command-dzys24ee.js} +7 -5
- package/{application.command-4fq5pmdd.js → application.command-m96rteme.js} +7 -5
- package/{applicationBuildRunner-tavpx3fv.js → applicationBuildRunner-d95dswfy.js} +5 -4
- package/{applicationReleasePackager-ktjt0erc.js → applicationReleasePackager-3cnjss29.js} +1 -1
- package/buildBatch.proc.js +4 -2
- package/{capacitorApp-kwa67kzs.js → capacitorApp-zrj7q1z4.js} +4 -2
- package/{cloud.command-wm3mtfve.js → cloud.command-eng6hqd4.js} +11 -9
- package/{context.command-dk2m2sjx.js → context.command-s96e60h6.js} +15 -13
- package/{guideline.command-w6ddv13r.js → guideline.command-0raa8ng7.js} +5 -3
- package/guidelines/conventions/conventions.instruction.md +9 -0
- package/incrementalBuilder.proc.js +3 -1
- package/{index-b2nt0w0k.js → index-1q83gs77.js} +1 -1
- package/index-5es51p0n.js +66 -0
- package/index-7nr23j55.js +344 -0
- package/{index-z3c9mmw4.js → index-7vvqsanf.js} +1 -1
- package/{index-qcracvc9.js → index-aknp5f6x.js} +3 -3
- package/{index-k86zc21w.js → index-azkj85kx.js} +7 -7
- package/{index-k1n0h7dk.js → index-c6rfvayh.js} +73 -472
- package/{index-a8h184wr.js → index-cnfawb2y.js} +2 -2
- package/{index-1tgp56ke.js → index-fqwtcy9j.js} +6 -6
- package/{index-dq6wq1tv.js → index-ktkm3ht3.js} +10 -10
- package/{index-1kzsn94d.js → index-ktnvnp7h.js} +1 -1
- package/{index-saheq2bs.js → index-md3wv29p.js} +1 -1
- package/{index-wet2ytnr.js → index-mr9b7nkd.js} +1 -1
- package/{index-ft1sfjz0.js → index-n0x82fhs.js} +1 -1
- package/{index-v0s24t8j.js → index-nf4zam3r.js} +3 -3
- package/{index-cd5x18qh.js → index-nr8w8h7y.js} +4 -4
- package/{index-ypvdw8nr.js → index-q2xqmbcq.js} +8 -8
- package/{index-5n0hf8r9.js → index-rna7cj75.js} +3 -3
- package/{index-m9c7k0gm.js → index-sc7s8927.js} +1 -1
- package/{index-5y7qba1c.js → index-vfwdwq5c.js} +2 -2
- package/{index-j9vnq8tr.js → index-y429w5m5.js} +3 -3
- package/{index-m7e0f1sy.js → index-yagad3ht.js} +8 -8
- package/{index-xxe90kqy.js → index-zp8y6zbb.js} +2 -2
- package/index.js +21 -19
- package/{library.command-wpedct6c.js → library.command-9cv75y0z.js} +5 -3
- package/{localRegistry.command-gk773cte.js → localRegistry.command-csgtnbb1.js} +10 -8
- package/{module.command-8n4kct3e.js → module.command-jafd05sa.js} +8 -6
- package/{package.command-fcbd0b1d.js → package.command-1kmswspp.js} +5 -3
- package/package.json +2 -2
- package/{page.command-x4379grq.js → page.command-p186hd45.js} +5 -3
- package/{primitive.command-8etmnqhq.js → primitive.command-a5w19jdg.js} +9 -7
- package/{quality.command-hfx7z8yr.js → quality.command-gcxmxqss.js} +4 -2
- package/{repair.command-j0fs5qkz.js → repair.command-z642bc2h.js} +7 -5
- package/{scalar.command-2emk89eh.js → scalar.command-9hgcdztr.js} +7 -5
- package/{subspace.command-nr32nm35.js → subspace.command-9x4nhzn2.js} +5 -3
- package/templates/workspaceRoot/.gitignore.template +2 -1
- package/templates/workspaceRoot/.husky/pre-commit.template +21 -0
- package/templates/workspaceRoot/.vscode/settings.json.template +1 -1
- package/templates/workspaceRoot/biome.json.template +1 -1
- package/{workflow.command-cvpmzwjg.js → workflow.command-camcqd0s.js} +12 -10
- package/{workspace.command-4ztb4fdh.js → workspace.command-n1nvp28s.js} +91 -50
|
@@ -1,74 +1,17 @@
|
|
|
1
1
|
// @bun
|
|
2
|
+
import {
|
|
3
|
+
getRootBoundarySegments,
|
|
4
|
+
isRootBoundarySegments
|
|
5
|
+
} from "./index-7nr23j55.js";
|
|
2
6
|
import {
|
|
3
7
|
FileSys
|
|
4
8
|
} from "./index-ayy5ecax.js";
|
|
5
9
|
import {
|
|
6
10
|
getDirname2
|
|
7
11
|
} from "./index-6wwzs1bc.js";
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
class Spinner {
|
|
13
|
-
static padding = 12;
|
|
14
|
-
static oraOptions = { discardStdin: false };
|
|
15
|
-
static canAnimate(stream = process.stderr) {
|
|
16
|
-
return !stream.isTTY || stream.columns > 0;
|
|
17
|
-
}
|
|
18
|
-
spinner;
|
|
19
|
-
stopWatch = null;
|
|
20
|
-
startAt = new Date;
|
|
21
|
-
prefix;
|
|
22
|
-
message;
|
|
23
|
-
enableSpin;
|
|
24
|
-
constructor(message, { prefix = "", indent = 0, enableSpin = true } = {}) {
|
|
25
|
-
Spinner.padding = Math.max(Spinner.padding, prefix.length);
|
|
26
|
-
this.prefix = prefix;
|
|
27
|
-
this.message = message;
|
|
28
|
-
this.spinner = ora({ ...Spinner.oraOptions, text: message });
|
|
29
|
-
this.spinner.prefixText = prefix.padStart(Spinner.padding, " ");
|
|
30
|
-
this.spinner.indent = indent;
|
|
31
|
-
this.enableSpin = enableSpin && Spinner.canAnimate();
|
|
32
|
-
}
|
|
33
|
-
start() {
|
|
34
|
-
this.startAt = new Date;
|
|
35
|
-
if (this.enableSpin) {
|
|
36
|
-
this.spinner.start();
|
|
37
|
-
this.stopWatch = setInterval(() => {
|
|
38
|
-
this.spinner.prefixText = this.prefix.padStart(Spinner.padding, " ");
|
|
39
|
-
this.spinner.text = `${this.message} (${this.#getElapsedTimeStr({ floor: true })})`;
|
|
40
|
-
}, 1000);
|
|
41
|
-
} else
|
|
42
|
-
this.spinner.info();
|
|
43
|
-
return this;
|
|
44
|
-
}
|
|
45
|
-
succeed(message) {
|
|
46
|
-
this.spinner.succeed(`${message} (${this.#getElapsedTimeStr()})`);
|
|
47
|
-
this.#reset();
|
|
48
|
-
}
|
|
49
|
-
fail(message) {
|
|
50
|
-
this.spinner.fail(`${message} (${this.#getElapsedTimeStr()})`);
|
|
51
|
-
this.#reset();
|
|
52
|
-
}
|
|
53
|
-
isSpinning() {
|
|
54
|
-
return this.spinner.isSpinning;
|
|
55
|
-
}
|
|
56
|
-
#reset() {
|
|
57
|
-
if (this.stopWatch)
|
|
58
|
-
clearInterval(this.stopWatch);
|
|
59
|
-
this.stopWatch = null;
|
|
60
|
-
}
|
|
61
|
-
#getElapsedTimeStr({ floor = false } = {}) {
|
|
62
|
-
const ms = Date.now() - this.startAt.getTime();
|
|
63
|
-
if (ms < 1000)
|
|
64
|
-
return `${ms}ms`;
|
|
65
|
-
const s = Math.floor(ms / 1000);
|
|
66
|
-
if (s < 60)
|
|
67
|
-
return `${floor ? Math.floor(ms / 1000) : Math.floor(ms / 100) / 10}s`;
|
|
68
|
-
const m = Math.floor(s / 60);
|
|
69
|
-
return `${m}m ${s % 60}s`;
|
|
70
|
-
}
|
|
71
|
-
}
|
|
12
|
+
import {
|
|
13
|
+
Spinner
|
|
14
|
+
} from "./index-5es51p0n.js";
|
|
72
15
|
|
|
73
16
|
// pkgs/@akanjs/devkit/executors.ts
|
|
74
17
|
import {
|
|
@@ -80,14 +23,14 @@ import { readFileSync as readFileSync2 } from "fs";
|
|
|
80
23
|
import {
|
|
81
24
|
copyFile,
|
|
82
25
|
cp as cpEntry,
|
|
83
|
-
mkdir
|
|
26
|
+
mkdir,
|
|
84
27
|
readdir as readDirEntries,
|
|
85
28
|
realpath,
|
|
86
29
|
rm as rm2,
|
|
87
30
|
stat,
|
|
88
31
|
symlink
|
|
89
32
|
} from "fs/promises";
|
|
90
|
-
import
|
|
33
|
+
import path5 from "path";
|
|
91
34
|
import { pathToFileURL } from "url";
|
|
92
35
|
import {
|
|
93
36
|
capitalize,
|
|
@@ -769,352 +712,10 @@ var decreaseBuildNum = async (app) => {
|
|
|
769
712
|
const akanConfigContent = akanConfig.replace(`buildNum: ${appConfig.mobile.buildNum}`, `buildNum: ${appConfig.mobile.buildNum - 1}`);
|
|
770
713
|
fs.writeFileSync(akanConfigPath, akanConfigContent);
|
|
771
714
|
};
|
|
772
|
-
// pkgs/@akanjs/devkit/artifact/implicitRootLayout.ts
|
|
773
|
-
import { mkdir } from "fs/promises";
|
|
774
|
-
import path3 from "path";
|
|
775
|
-
|
|
776
|
-
// pkgs/@akanjs/devkit/transforms/asyncDefaultExportDetector.ts
|
|
777
|
-
import fs2 from "fs";
|
|
778
|
-
import path2 from "path";
|
|
779
|
-
|
|
780
|
-
class AsyncDefaultExportDetector {
|
|
781
|
-
static #typescriptLoad;
|
|
782
|
-
static #loadTypescript() {
|
|
783
|
-
AsyncDefaultExportDetector.#typescriptLoad ??= import("typescript").then((mod) => mod.default ?? mod);
|
|
784
|
-
return AsyncDefaultExportDetector.#typescriptLoad;
|
|
785
|
-
}
|
|
786
|
-
static async detect(moduleAbsPath) {
|
|
787
|
-
try {
|
|
788
|
-
const typescript = await AsyncDefaultExportDetector.#loadTypescript();
|
|
789
|
-
const source = fs2.readFileSync(path2.resolve(moduleAbsPath), "utf8");
|
|
790
|
-
const sourceFile = typescript.createSourceFile(moduleAbsPath, source, typescript.ScriptTarget.Latest, true, AsyncDefaultExportDetector.#scriptKind(typescript, moduleAbsPath));
|
|
791
|
-
return new AsyncDefaultExportDetector(typescript).detectInSourceFile(sourceFile);
|
|
792
|
-
} catch {
|
|
793
|
-
return false;
|
|
794
|
-
}
|
|
795
|
-
}
|
|
796
|
-
#ts;
|
|
797
|
-
constructor(typescript) {
|
|
798
|
-
this.#ts = typescript;
|
|
799
|
-
}
|
|
800
|
-
detectInSourceFile(sourceFile) {
|
|
801
|
-
const ts = this.#ts;
|
|
802
|
-
const asyncBindings = new Map;
|
|
803
|
-
let defaultIdentifier = null;
|
|
804
|
-
for (const statement of sourceFile.statements) {
|
|
805
|
-
if (ts.isFunctionDeclaration(statement)) {
|
|
806
|
-
if (this.#hasModifier(statement, ts.SyntaxKind.DefaultKeyword)) {
|
|
807
|
-
return this.#hasModifier(statement, ts.SyntaxKind.AsyncKeyword);
|
|
808
|
-
}
|
|
809
|
-
if (statement.name) {
|
|
810
|
-
asyncBindings.set(statement.name.text, this.#hasModifier(statement, ts.SyntaxKind.AsyncKeyword));
|
|
811
|
-
}
|
|
812
|
-
continue;
|
|
813
|
-
}
|
|
814
|
-
if (ts.isVariableStatement(statement)) {
|
|
815
|
-
for (const declaration of statement.declarationList.declarations) {
|
|
816
|
-
if (!ts.isIdentifier(declaration.name))
|
|
817
|
-
continue;
|
|
818
|
-
asyncBindings.set(declaration.name.text, this.#isAsyncFunctionExpression(declaration.initializer));
|
|
819
|
-
}
|
|
820
|
-
continue;
|
|
821
|
-
}
|
|
822
|
-
if (ts.isExportAssignment(statement)) {
|
|
823
|
-
if (this.#isAsyncFunctionExpression(statement.expression))
|
|
824
|
-
return true;
|
|
825
|
-
if (ts.isIdentifier(statement.expression))
|
|
826
|
-
defaultIdentifier = statement.expression.text;
|
|
827
|
-
continue;
|
|
828
|
-
}
|
|
829
|
-
if (ts.isExportDeclaration(statement) && statement.exportClause && ts.isNamedExports(statement.exportClause)) {
|
|
830
|
-
const exportClause = statement.exportClause;
|
|
831
|
-
for (const specifier of exportClause.elements) {
|
|
832
|
-
if (specifier.name.text !== "default")
|
|
833
|
-
continue;
|
|
834
|
-
defaultIdentifier = specifier.propertyName?.text ?? specifier.name.text;
|
|
835
|
-
}
|
|
836
|
-
}
|
|
837
|
-
}
|
|
838
|
-
return defaultIdentifier ? asyncBindings.get(defaultIdentifier) === true : false;
|
|
839
|
-
}
|
|
840
|
-
#hasModifier(node, kind) {
|
|
841
|
-
const ts = this.#ts;
|
|
842
|
-
return ts.canHaveModifiers(node) && (ts.getModifiers(node)?.some((modifier) => modifier.kind === kind) ?? false);
|
|
843
|
-
}
|
|
844
|
-
#isAsyncFunctionExpression(node) {
|
|
845
|
-
const ts = this.#ts;
|
|
846
|
-
return Boolean(node && (ts.isArrowFunction(node) || ts.isFunctionExpression(node)) && this.#hasModifier(node, ts.SyntaxKind.AsyncKeyword));
|
|
847
|
-
}
|
|
848
|
-
static #scriptKind(typescript, moduleAbsPath) {
|
|
849
|
-
return moduleAbsPath.endsWith(".tsx") || moduleAbsPath.endsWith(".jsx") ? typescript.ScriptKind.TSX : typescript.ScriptKind.TS;
|
|
850
|
-
}
|
|
851
|
-
}
|
|
852
|
-
|
|
853
|
-
// pkgs/@akanjs/devkit/artifact/implicitRootLayout.ts
|
|
854
|
-
var LAYOUT_KEY_RE = /^\.\/(.+\/)?_layout\.(tsx|ts|jsx|js)$/;
|
|
855
|
-
async function appHasStModule(appCwdPath) {
|
|
856
|
-
return Bun.file(path3.join(appCwdPath, "lib", "st.ts")).exists();
|
|
857
|
-
}
|
|
858
|
-
var IMPLICIT_LAYOUT_DIR = path3.join(".akan", "generated", "root-layouts");
|
|
859
|
-
var IMPLICIT_DICT_DIR = path3.join(".akan", "generated", "dict");
|
|
860
|
-
var IMPLICIT_OVERRIDES_DIR = path3.join(".akan", "generated", "overrides");
|
|
861
|
-
var OVERRIDES_KEY_RE = /^\.\/(.+\/)?_overrides\.(tsx|ts|jsx|js)$/;
|
|
862
|
-
async function writeGeneratedOverridesLayoutFile(opts) {
|
|
863
|
-
const filename = `${opts.key.replace(/^\.\//, "").replace(/[^a-zA-Z0-9]+/g, "_")}.tsx`;
|
|
864
|
-
const absPath = path3.join(path3.resolve(opts.appCwdPath), IMPLICIT_OVERRIDES_DIR, filename);
|
|
865
|
-
const userRel = path3.relative(path3.dirname(absPath), opts.userAbsPath).split(path3.sep).join("/");
|
|
866
|
-
const userSpecifier = userRel.startsWith(".") ? userRel : `./${userRel}`;
|
|
867
|
-
const source = `"use client";
|
|
868
|
-
import { UiOverrideProvider } from "akanjs/ui";
|
|
869
|
-
import { createElement, type ReactNode } from "react";
|
|
870
|
-
import value from ${JSON.stringify(userSpecifier)};
|
|
871
|
-
|
|
872
|
-
export default function AkanUiOverridesLayout({ children }: { children?: ReactNode }) {
|
|
873
|
-
return createElement(UiOverrideProvider, { value }, children);
|
|
874
|
-
}
|
|
875
|
-
`;
|
|
876
|
-
await Bun.write(absPath, source);
|
|
877
|
-
return absPath;
|
|
878
|
-
}
|
|
879
|
-
function getRootBoundarySegments(key) {
|
|
880
|
-
const match = LAYOUT_KEY_RE.exec(key);
|
|
881
|
-
if (!match)
|
|
882
|
-
return null;
|
|
883
|
-
const prefix = match[1]?.replace(/\/$/, "");
|
|
884
|
-
if (!prefix)
|
|
885
|
-
return [];
|
|
886
|
-
return prefix.split("/").filter(Boolean);
|
|
887
|
-
}
|
|
888
|
-
function implicitRootLayoutKey(segments) {
|
|
889
|
-
return `./${[...segments, "__root_layout"].join("/")}.tsx`;
|
|
890
|
-
}
|
|
891
|
-
function implicitRootLayoutAbsPath(appCwdPath, segments) {
|
|
892
|
-
const filename = segments.length ? `${segments.join("__")}__root_layout.tsx` : "__root_layout.tsx";
|
|
893
|
-
return path3.join(path3.resolve(appCwdPath), IMPLICIT_LAYOUT_DIR, filename);
|
|
894
|
-
}
|
|
895
|
-
function implicitDictionaryMacroAbsPath(appCwdPath) {
|
|
896
|
-
return path3.join(path3.resolve(appCwdPath), IMPLICIT_DICT_DIR, "useDict.ts");
|
|
897
|
-
}
|
|
898
|
-
function isRootBoundarySegments(segments, basePaths) {
|
|
899
|
-
const firstVisibleIndex = segments.findIndex((segment) => !/^\(.+\)$/.test(segment));
|
|
900
|
-
if (firstVisibleIndex === -1)
|
|
901
|
-
return segments.length <= 1;
|
|
902
|
-
if (segments.slice(firstVisibleIndex + 1).some((segment) => /^\(.+\)$/.test(segment)))
|
|
903
|
-
return false;
|
|
904
|
-
const visible = segments.slice(firstVisibleIndex);
|
|
905
|
-
const allowedBasePaths = new Set([...basePaths].map((basePath) => basePath.trim()).filter(Boolean));
|
|
906
|
-
return visible.length === 1 && (firstVisibleIndex > 0 || allowedBasePaths.has(visible[0] ?? ""));
|
|
907
|
-
}
|
|
908
|
-
function findRootBoundaries(pageKeys, appCwdPath, basePaths) {
|
|
909
|
-
const boundaries = new Map;
|
|
910
|
-
for (const key of pageKeys) {
|
|
911
|
-
const segments = getRootBoundarySegments(key);
|
|
912
|
-
if (!segments)
|
|
913
|
-
continue;
|
|
914
|
-
if (!isRootBoundarySegments(segments, basePaths))
|
|
915
|
-
continue;
|
|
916
|
-
const id = segments.join("/");
|
|
917
|
-
boundaries.set(id, {
|
|
918
|
-
sourceKey: key,
|
|
919
|
-
sourceAbsPath: path3.resolve(appCwdPath, "page", key.replace(/^\.\//, "")),
|
|
920
|
-
segments
|
|
921
|
-
});
|
|
922
|
-
}
|
|
923
|
-
const hasExplicitRootBoundary = [...boundaries.values()].some((boundary) => boundary.segments.length === 0);
|
|
924
|
-
if (!hasExplicitRootBoundary && boundaries.size === 0) {
|
|
925
|
-
boundaries.set("", { sourceKey: null, sourceAbsPath: null, segments: [] });
|
|
926
|
-
}
|
|
927
|
-
return [...boundaries.values()].sort((a, b) => a.segments.join("/").localeCompare(b.segments.join("/")));
|
|
928
|
-
}
|
|
929
|
-
function hasAncestorRootBoundary(boundary, boundaries) {
|
|
930
|
-
return boundaries.some((candidate) => candidate !== boundary && candidate.segments.length < boundary.segments.length && candidate.segments.every((segment, index) => boundary.segments[index] === segment));
|
|
931
|
-
}
|
|
932
|
-
function findExplicitRootLayoutAbsPath(pageKeys, appCwdPath) {
|
|
933
|
-
const rootLayoutKey = pageKeys.find((key) => {
|
|
934
|
-
const segments = getRootBoundarySegments(key);
|
|
935
|
-
return segments !== null && segments.length === 0;
|
|
936
|
-
});
|
|
937
|
-
return rootLayoutKey ? path3.resolve(appCwdPath, "page", rootLayoutKey.replace(/^\.\//, "")) : null;
|
|
938
|
-
}
|
|
939
|
-
function routePrefixForSegments(segments) {
|
|
940
|
-
const visible = segments.filter((segment) => !/^\(.+\)$/.test(segment));
|
|
941
|
-
return visible[0] ?? null;
|
|
942
|
-
}
|
|
943
|
-
async function assertEnvClientConvention(appCwdPath, appName) {
|
|
944
|
-
const envPath = path3.join(appCwdPath, "env", "env.client.ts");
|
|
945
|
-
if (!await Bun.file(envPath).exists()) {
|
|
946
|
-
throw new Error(`[route-convention] app "${appName}" must provide env/env.client.ts exporting "env" for generated System.Provider`);
|
|
947
|
-
}
|
|
948
|
-
}
|
|
949
|
-
async function writeGeneratedDictionaryMacroFile(appCwdPath, appName) {
|
|
950
|
-
const absPath = implicitDictionaryMacroAbsPath(appCwdPath);
|
|
951
|
-
await mkdir(path3.dirname(absPath), { recursive: true });
|
|
952
|
-
await Bun.write(absPath, `import { getAllDictionary } from "@apps/${appName}/lib/dict" with { type: "macro" };
|
|
953
|
-
|
|
954
|
-
export const allDictionary = getAllDictionary();
|
|
955
|
-
`);
|
|
956
|
-
return absPath;
|
|
957
|
-
}
|
|
958
|
-
async function writeGeneratedRootLayoutFile(opts) {
|
|
959
|
-
await assertEnvClientConvention(opts.appCwdPath, opts.appName);
|
|
960
|
-
const dictMacroAbsPath = opts.includeSystemProvider ? await writeGeneratedDictionaryMacroFile(opts.appCwdPath, opts.appName) : null;
|
|
961
|
-
const absPath = implicitRootLayoutAbsPath(opts.appCwdPath, opts.boundary.segments);
|
|
962
|
-
await mkdir(path3.dirname(absPath), { recursive: true });
|
|
963
|
-
const dictMacroRel = dictMacroAbsPath ? path3.relative(path3.dirname(absPath), dictMacroAbsPath).split(path3.sep).join("/") : null;
|
|
964
|
-
const dictMacroSpecifier = dictMacroRel ? dictMacroRel.startsWith(".") ? dictMacroRel : `./${dictMacroRel}` : null;
|
|
965
|
-
const sourceRel = opts.boundary.sourceAbsPath ? path3.relative(path3.dirname(absPath), opts.boundary.sourceAbsPath).split(path3.sep).join("/") : null;
|
|
966
|
-
const sourceSpecifier = sourceRel ? sourceRel.startsWith(".") ? sourceRel : `./${sourceRel}` : null;
|
|
967
|
-
const inheritedSourceAbsPath = opts.rootSourceAbsPath && opts.rootSourceAbsPath !== opts.boundary.sourceAbsPath ? opts.rootSourceAbsPath : null;
|
|
968
|
-
const inheritedSourceRel = inheritedSourceAbsPath ? path3.relative(path3.dirname(absPath), inheritedSourceAbsPath).split(path3.sep).join("/") : null;
|
|
969
|
-
const inheritedSourceSpecifier = inheritedSourceRel ? inheritedSourceRel.startsWith(".") ? inheritedSourceRel : `./${inheritedSourceRel}` : null;
|
|
970
|
-
const clientImport = opts.includeStInit ? `import { st } from "@apps/${opts.appName}/client";
|
|
971
|
-
void st;
|
|
972
|
-
` : `import "@apps/${opts.appName}/client";
|
|
973
|
-
`;
|
|
974
|
-
const inheritedImport = inheritedSourceSpecifier ? `import * as inheritedLayout from ${JSON.stringify(inheritedSourceSpecifier)};
|
|
975
|
-
` : `const inheritedLayout = {};
|
|
976
|
-
`;
|
|
977
|
-
const prefix = routePrefixForSegments(opts.boundary.segments);
|
|
978
|
-
const userImport = sourceSpecifier ? `import UserLayout, * as userLayout from ${JSON.stringify(sourceSpecifier)};
|
|
979
|
-
` : `const UserLayout = ({ children }) => children;
|
|
980
|
-
const userLayout = {};
|
|
981
|
-
`;
|
|
982
|
-
const isAsyncUserLayout = opts.boundary.sourceAbsPath ? await AsyncDefaultExportDetector.detect(opts.boundary.sourceAbsPath) : false;
|
|
983
|
-
const userLayoutElement = "<UserLayout params={params} searchParams={searchParams}>{children}</UserLayout>";
|
|
984
|
-
const layoutSignature = isAsyncUserLayout ? "export default async function GeneratedLayout" : "export default function GeneratedLayout";
|
|
985
|
-
const layoutBinding = isAsyncUserLayout ? ` const layout =
|
|
986
|
-
process.env.AKAN_PUBLIC_RENDER_ENV === "csr"
|
|
987
|
-
? await UserLayout({ params, searchParams, children })
|
|
988
|
-
: ${userLayoutElement};
|
|
989
|
-
` : "";
|
|
990
|
-
const layoutChild = isAsyncUserLayout ? "{layout}" : userLayoutElement;
|
|
991
|
-
const layoutReturn = isAsyncUserLayout ? "layout" : userLayoutElement;
|
|
992
|
-
const source = opts.includeSystemProvider ? `import type { LayoutProps, PageProps } from "akanjs/client";
|
|
993
|
-
import { loadFonts } from "akanjs/client";
|
|
994
|
-
import { System } from "akanjs/ui";
|
|
995
|
-
import { env } from "@apps/${opts.appName}/env/env.client";
|
|
996
|
-
import { allDictionary } from ${JSON.stringify(dictMacroSpecifier)};
|
|
997
|
-
${clientImport}${inheritedImport}${userImport}
|
|
998
|
-
const userFonts = userLayout.fonts ?? inheritedLayout.fonts ?? [];
|
|
999
|
-
const defaultFonts = userFonts.filter((font) => font.default);
|
|
1000
|
-
if (defaultFonts.length > 1) throw new Error("[route-convention] only one default font is allowed per root layout");
|
|
1001
|
-
const defaultFont = defaultFonts[0];
|
|
1002
|
-
const defaultFontClassName = defaultFont ? (defaultFont.className ?? \`font-\${defaultFont.name}\`) : undefined;
|
|
1003
|
-
|
|
1004
|
-
export async function generateHead(props: PageProps) {
|
|
1005
|
-
if (userLayout.generateHead) return userLayout.generateHead(props);
|
|
1006
|
-
if (userLayout.head !== undefined) return userLayout.head;
|
|
1007
|
-
if (inheritedLayout.generateHead) return inheritedLayout.generateHead(props);
|
|
1008
|
-
return inheritedLayout.head;
|
|
1009
|
-
}
|
|
1010
|
-
|
|
1011
|
-
export async function generateMetadata(props: PageProps) {
|
|
1012
|
-
if (userLayout.generateMetadata) return userLayout.generateMetadata(props);
|
|
1013
|
-
if (userLayout.metadata !== undefined) return userLayout.metadata;
|
|
1014
|
-
if (inheritedLayout.generateMetadata) return inheritedLayout.generateMetadata(props);
|
|
1015
|
-
return inheritedLayout.metadata;
|
|
1016
|
-
}
|
|
1017
|
-
|
|
1018
|
-
export const NotFound = userLayout.NotFound ?? inheritedLayout.NotFound;
|
|
1019
|
-
export const Error = userLayout.Error ?? inheritedLayout.Error;
|
|
1020
|
-
export const pageConfig = userLayout.pageConfig ?? inheritedLayout.pageConfig;
|
|
1021
|
-
|
|
1022
|
-
${layoutSignature}({ children, params, searchParams }: LayoutProps) {
|
|
1023
|
-
${layoutBinding} return (
|
|
1024
|
-
<System.Provider
|
|
1025
|
-
of={GeneratedLayout as never}
|
|
1026
|
-
appName=${JSON.stringify(opts.appName)}
|
|
1027
|
-
${prefix ? `prefix=${JSON.stringify(prefix)}
|
|
1028
|
-
` : ""}params={params}
|
|
1029
|
-
manifest={userLayout.manifest ?? inheritedLayout.manifest}
|
|
1030
|
-
env={env}
|
|
1031
|
-
theme={userLayout.theme ?? inheritedLayout.theme}
|
|
1032
|
-
fonts={loadFonts(userFonts)}
|
|
1033
|
-
className={defaultFontClassName}
|
|
1034
|
-
gaTrackingId={userLayout.gaTrackingId ?? inheritedLayout.gaTrackingId}
|
|
1035
|
-
layoutStyle={userLayout.layoutStyle ?? inheritedLayout.layoutStyle}
|
|
1036
|
-
reconnect={userLayout.reconnect ?? inheritedLayout.reconnect ?? false}
|
|
1037
|
-
wsConnect={userLayout.wsConnect ?? inheritedLayout.wsConnect ?? true}
|
|
1038
|
-
allDictionary={process.env.AKAN_PUBLIC_RENDER_ENV === "ssr" ? allDictionary : undefined}
|
|
1039
|
-
>
|
|
1040
|
-
${layoutChild}
|
|
1041
|
-
</System.Provider>
|
|
1042
|
-
);
|
|
1043
|
-
}
|
|
1044
|
-
` : `import type { LayoutProps, PageProps } from "akanjs/client";
|
|
1045
|
-
${inheritedImport}${userImport}
|
|
1046
|
-
export async function generateHead(props: PageProps) {
|
|
1047
|
-
if (userLayout.generateHead) return userLayout.generateHead(props);
|
|
1048
|
-
if (userLayout.head !== undefined) return userLayout.head;
|
|
1049
|
-
if (inheritedLayout.generateHead) return inheritedLayout.generateHead(props);
|
|
1050
|
-
return inheritedLayout.head;
|
|
1051
|
-
}
|
|
1052
|
-
|
|
1053
|
-
export async function generateMetadata(props: PageProps) {
|
|
1054
|
-
if (userLayout.generateMetadata) return userLayout.generateMetadata(props);
|
|
1055
|
-
if (userLayout.metadata !== undefined) return userLayout.metadata;
|
|
1056
|
-
if (inheritedLayout.generateMetadata) return inheritedLayout.generateMetadata(props);
|
|
1057
|
-
return inheritedLayout.metadata;
|
|
1058
|
-
}
|
|
1059
|
-
|
|
1060
|
-
export const NotFound = userLayout.NotFound ?? inheritedLayout.NotFound;
|
|
1061
|
-
export const Error = userLayout.Error ?? inheritedLayout.Error;
|
|
1062
|
-
export const pageConfig = userLayout.pageConfig ?? inheritedLayout.pageConfig;
|
|
1063
|
-
|
|
1064
|
-
${layoutSignature}({ children, params, searchParams }: LayoutProps) {
|
|
1065
|
-
${layoutBinding} return ${layoutReturn};
|
|
1066
|
-
}
|
|
1067
|
-
`;
|
|
1068
|
-
await Bun.write(absPath, source);
|
|
1069
|
-
return absPath;
|
|
1070
|
-
}
|
|
1071
|
-
async function resolveSsrPageEntries(opts) {
|
|
1072
|
-
const absPageDir = path3.resolve(opts.appCwdPath, "page");
|
|
1073
|
-
const hasSt = await appHasStModule(opts.appCwdPath);
|
|
1074
|
-
const basePaths = opts.basePaths ?? [];
|
|
1075
|
-
const rootSourceAbsPath = findExplicitRootLayoutAbsPath(opts.pageKeys, opts.appCwdPath);
|
|
1076
|
-
const rootBoundaries = findRootBoundaries(opts.pageKeys, opts.appCwdPath, basePaths);
|
|
1077
|
-
const rootLayoutKeys = new Set(opts.pageKeys.filter((key) => {
|
|
1078
|
-
const segments = getRootBoundarySegments(key);
|
|
1079
|
-
return segments !== null && isRootBoundarySegments(segments, basePaths);
|
|
1080
|
-
}));
|
|
1081
|
-
const base = await Promise.all(opts.pageKeys.filter((key) => !rootLayoutKeys.has(key)).map(async (key) => {
|
|
1082
|
-
const userAbsPath = path3.resolve(absPageDir, key);
|
|
1083
|
-
if (OVERRIDES_KEY_RE.test(key)) {
|
|
1084
|
-
const moduleAbsPath = await writeGeneratedOverridesLayoutFile({
|
|
1085
|
-
appCwdPath: opts.appCwdPath,
|
|
1086
|
-
key,
|
|
1087
|
-
userAbsPath
|
|
1088
|
-
});
|
|
1089
|
-
return { key, moduleAbsPath, seedAbsPaths: [userAbsPath] };
|
|
1090
|
-
}
|
|
1091
|
-
return { key, moduleAbsPath: userAbsPath };
|
|
1092
|
-
}));
|
|
1093
|
-
const generated = await Promise.all(rootBoundaries.map(async (boundary) => ({
|
|
1094
|
-
key: implicitRootLayoutKey(boundary.segments),
|
|
1095
|
-
moduleAbsPath: await writeGeneratedRootLayoutFile({
|
|
1096
|
-
appCwdPath: opts.appCwdPath,
|
|
1097
|
-
appName: opts.appName,
|
|
1098
|
-
boundary,
|
|
1099
|
-
rootSourceAbsPath,
|
|
1100
|
-
includeStInit: hasSt && boundary.segments.length === 0,
|
|
1101
|
-
includeSystemProvider: !hasAncestorRootBoundary(boundary, rootBoundaries)
|
|
1102
|
-
}),
|
|
1103
|
-
seedAbsPaths: [...new Set([boundary.sourceAbsPath, rootSourceAbsPath].filter((absPath) => absPath !== null))]
|
|
1104
|
-
})));
|
|
1105
|
-
const entries = [...base, ...generated];
|
|
1106
|
-
entries.sort((a, b) => a.key.localeCompare(b.key));
|
|
1107
|
-
return entries;
|
|
1108
|
-
}
|
|
1109
|
-
async function resolveSsrPageEntriesForApp(app, pageKeys) {
|
|
1110
|
-
const config = await app.getConfig();
|
|
1111
|
-
return resolveSsrPageEntries({ appCwdPath: app.cwdPath, appName: app.name, pageKeys, basePaths: config.basePaths });
|
|
1112
|
-
}
|
|
1113
|
-
|
|
1114
715
|
// pkgs/@akanjs/devkit/linter.ts
|
|
1115
716
|
import { spawn } from "child_process";
|
|
1116
717
|
import { existsSync, readFileSync } from "fs";
|
|
1117
|
-
import
|
|
718
|
+
import path2 from "path";
|
|
1118
719
|
import chalk from "chalk";
|
|
1119
720
|
var parseBiomeReport = (output) => {
|
|
1120
721
|
for (let start = output.indexOf("{");start !== -1; start = output.indexOf("{", start + 1)) {
|
|
@@ -1171,13 +772,13 @@ class Linter {
|
|
|
1171
772
|
#biomeBin;
|
|
1172
773
|
constructor(cwdPath) {
|
|
1173
774
|
this.lintRoot = this.#findBiomeRootPath(cwdPath);
|
|
1174
|
-
this.configPath = Linter.#configPathIn(this.lintRoot) ??
|
|
1175
|
-
const localBiomeBin =
|
|
775
|
+
this.configPath = Linter.#configPathIn(this.lintRoot) ?? path2.join(this.lintRoot, "biome.json");
|
|
776
|
+
const localBiomeBin = path2.join(this.lintRoot, "node_modules/.bin/biome");
|
|
1176
777
|
this.#biomeBin = existsSync(localBiomeBin) ? localBiomeBin : "biome";
|
|
1177
778
|
}
|
|
1178
779
|
static #configPathIn(dir) {
|
|
1179
780
|
for (const fileName of BIOME_CONFIG_FILES) {
|
|
1180
|
-
const configPath =
|
|
781
|
+
const configPath = path2.join(dir, fileName);
|
|
1181
782
|
if (existsSync(configPath))
|
|
1182
783
|
return configPath;
|
|
1183
784
|
}
|
|
@@ -1186,19 +787,19 @@ class Linter {
|
|
|
1186
787
|
#findBiomeRootPath(dir) {
|
|
1187
788
|
if (Linter.#configPathIn(dir))
|
|
1188
789
|
return dir;
|
|
1189
|
-
const parentDir =
|
|
790
|
+
const parentDir = path2.dirname(dir);
|
|
1190
791
|
if (parentDir === dir)
|
|
1191
792
|
throw new Error(`biome.json not found from ${dir}`);
|
|
1192
793
|
return this.#findBiomeRootPath(parentDir);
|
|
1193
794
|
}
|
|
1194
795
|
#toBiomePath(filePath) {
|
|
1195
|
-
const relativePath =
|
|
1196
|
-
if (!relativePath.startsWith("..") && !
|
|
796
|
+
const relativePath = path2.relative(this.lintRoot, filePath);
|
|
797
|
+
if (!relativePath.startsWith("..") && !path2.isAbsolute(relativePath))
|
|
1197
798
|
return relativePath;
|
|
1198
799
|
return filePath;
|
|
1199
800
|
}
|
|
1200
801
|
#resolveFilePath(filePath) {
|
|
1201
|
-
return
|
|
802
|
+
return path2.isAbsolute(filePath) ? filePath : path2.join(this.lintRoot, filePath);
|
|
1202
803
|
}
|
|
1203
804
|
async#runBiome(args, input) {
|
|
1204
805
|
return await new Promise((resolve, reject) => {
|
|
@@ -1223,7 +824,7 @@ class Linter {
|
|
|
1223
824
|
const diagnosticPath = diagnostic.location?.path;
|
|
1224
825
|
if (!diagnosticPath)
|
|
1225
826
|
return fallbackFilePath;
|
|
1226
|
-
return
|
|
827
|
+
return path2.isAbsolute(diagnosticPath) ? diagnosticPath : path2.join(this.lintRoot, diagnosticPath);
|
|
1227
828
|
}
|
|
1228
829
|
#createLintMessage(diagnostic) {
|
|
1229
830
|
const start = diagnostic.location?.start;
|
|
@@ -1453,7 +1054,7 @@ ${errorText}, ${warningText} found`];
|
|
|
1453
1054
|
|
|
1454
1055
|
// pkgs/@akanjs/devkit/repoIdentity.ts
|
|
1455
1056
|
import { execFileSync } from "child_process";
|
|
1456
|
-
import
|
|
1057
|
+
import path3 from "path";
|
|
1457
1058
|
var resolved = new Map;
|
|
1458
1059
|
var readRemoteName = (workspaceRoot) => {
|
|
1459
1060
|
try {
|
|
@@ -1471,14 +1072,14 @@ var resolveRepoName = (workspaceRoot) => {
|
|
|
1471
1072
|
const cached = resolved.get(workspaceRoot);
|
|
1472
1073
|
if (cached)
|
|
1473
1074
|
return cached;
|
|
1474
|
-
const repoName = readRemoteName(workspaceRoot) ??
|
|
1075
|
+
const repoName = readRemoteName(workspaceRoot) ?? path3.basename(workspaceRoot);
|
|
1475
1076
|
resolved.set(workspaceRoot, repoName);
|
|
1476
1077
|
return repoName;
|
|
1477
1078
|
};
|
|
1478
1079
|
|
|
1479
1080
|
// pkgs/@akanjs/devkit/scanInfo.ts
|
|
1480
1081
|
import { rm } from "fs/promises";
|
|
1481
|
-
import
|
|
1082
|
+
import path4 from "path";
|
|
1482
1083
|
|
|
1483
1084
|
// pkgs/@akanjs/devkit/workspaceLayout.ts
|
|
1484
1085
|
var appRootAllowedFiles = new Set([
|
|
@@ -1584,14 +1185,14 @@ var moduleUiFileTypes = {
|
|
|
1584
1185
|
var testFilePattern = /\.(test|spec)\.(ts|tsx)$/;
|
|
1585
1186
|
var createDependencyScanner = async (exec) => (await import("./dependencyScanner-c64m6fxp.js")).TypeScriptDependencyScanner.from(exec);
|
|
1586
1187
|
var isAllowedTestFile = (filename) => testFilePattern.test(filename);
|
|
1587
|
-
var getScanPath = (exec, relativePath) =>
|
|
1188
|
+
var getScanPath = (exec, relativePath) => path4.posix.join(`${exec.type}s`, exec.name, relativePath.split(path4.sep).join("/"));
|
|
1588
1189
|
async function clearGeneratedRootCapacitorConfigs(exec) {
|
|
1589
1190
|
if (exec.type !== "app")
|
|
1590
1191
|
return;
|
|
1591
1192
|
await Promise.all(generatedRootCapacitorConfigFiles.map((filename) => rm(exec.getPath(filename), { force: true })));
|
|
1592
1193
|
}
|
|
1593
1194
|
var getModuleNameFromPath = (kind, modulePath) => {
|
|
1594
|
-
const dirname =
|
|
1195
|
+
const dirname = path4.basename(modulePath);
|
|
1595
1196
|
return kind === "service" ? dirname.replace(/^_+/, "") : dirname;
|
|
1596
1197
|
};
|
|
1597
1198
|
async function assertScanConvention(exec, libRoot) {
|
|
@@ -1613,18 +1214,18 @@ async function assertScanConvention(exec, libRoot) {
|
|
|
1613
1214
|
for (const { relativePath, reason } of await exec.getPageConventionViolations())
|
|
1614
1215
|
addViolation(relativePath, reason);
|
|
1615
1216
|
libRoot.files.filter((filename) => !isAllowedLibFacetRootFile(filename)).forEach((filename) => {
|
|
1616
|
-
addViolation(
|
|
1217
|
+
addViolation(path4.join("lib", filename), "unsupported lib facet root file");
|
|
1617
1218
|
});
|
|
1618
1219
|
libRoot.dirs.filter((dirname) => dirname.startsWith("__") && !internalLibDirs.has(dirname)).forEach((dirname) => {
|
|
1619
|
-
addViolation(
|
|
1220
|
+
addViolation(path4.join("lib", dirname), "unsupported internal lib folder");
|
|
1620
1221
|
});
|
|
1621
1222
|
const databaseDirs = libRoot.dirs.filter((dirname) => !dirname.startsWith("_"));
|
|
1622
1223
|
const serviceDirs = libRoot.dirs.filter((dirname) => dirname.startsWith("_") && !dirname.startsWith("__"));
|
|
1623
1224
|
const scalarDirs = await exec.readdir("lib/__scalar");
|
|
1624
1225
|
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",
|
|
1226
|
+
...databaseDirs.map((dirname) => validateModuleFiles(exec, violations, "database", path4.join("lib", dirname))),
|
|
1227
|
+
...serviceDirs.map((dirname) => validateModuleFiles(exec, violations, "service", path4.join("lib", dirname))),
|
|
1228
|
+
...scalarDirs.map((dirname) => validateModuleFiles(exec, violations, "scalar", path4.join("lib/__scalar", dirname)))
|
|
1628
1229
|
]);
|
|
1629
1230
|
if (violations.length > 0) {
|
|
1630
1231
|
throw new Error(`[scan-convention]
|
|
@@ -1636,11 +1237,11 @@ async function validateModuleFiles(exec, violations, kind, modulePath) {
|
|
|
1636
1237
|
const { files, dirs } = await exec.getFilesAndDirs(modulePath);
|
|
1637
1238
|
const moduleName = getModuleNameFromPath(kind, modulePath);
|
|
1638
1239
|
dirs.forEach((dirname) => {
|
|
1639
|
-
violations.push(`${getScanPath(exec,
|
|
1240
|
+
violations.push(`${getScanPath(exec, path4.join(modulePath, dirname))}: unsupported module folder`);
|
|
1640
1241
|
});
|
|
1641
1242
|
const uiModuleName = moduleName[0].toUpperCase() + moduleName.slice(1);
|
|
1642
1243
|
files.forEach((filename) => {
|
|
1643
|
-
const filePath =
|
|
1244
|
+
const filePath = path4.join(modulePath, filename);
|
|
1644
1245
|
if (filename === "index.ts" || filename === "index.tsx" || isAllowedTestFile(filename))
|
|
1645
1246
|
return;
|
|
1646
1247
|
if (filename === `${moduleName}.abstract.md`)
|
|
@@ -1720,7 +1321,7 @@ class ScanInfo {
|
|
|
1720
1321
|
});
|
|
1721
1322
|
await Promise.all([
|
|
1722
1323
|
...databaseDirs.map(async (name) => {
|
|
1723
|
-
const filenames = await exec.readdir(
|
|
1324
|
+
const filenames = await exec.readdir(path4.join("lib", name));
|
|
1724
1325
|
filenames.forEach((filename) => {
|
|
1725
1326
|
if (filename.endsWith(".constant.ts"))
|
|
1726
1327
|
files.constant.databases.push(name);
|
|
@@ -1748,7 +1349,7 @@ class ScanInfo {
|
|
|
1748
1349
|
}),
|
|
1749
1350
|
...serviceDirs.map(async (dirname) => {
|
|
1750
1351
|
const name = dirname.slice(1);
|
|
1751
|
-
const filenames = await exec.readdir(
|
|
1352
|
+
const filenames = await exec.readdir(path4.join("lib", dirname));
|
|
1752
1353
|
filenames.forEach((filename) => {
|
|
1753
1354
|
if (filename.endsWith(".dictionary.ts"))
|
|
1754
1355
|
files.dictionary.services.push(name);
|
|
@@ -1771,7 +1372,7 @@ class ScanInfo {
|
|
|
1771
1372
|
});
|
|
1772
1373
|
}),
|
|
1773
1374
|
...scalarDirs.map(async (name) => {
|
|
1774
|
-
const filenames = await exec.readdir(
|
|
1375
|
+
const filenames = await exec.readdir(path4.join("lib/__scalar", name));
|
|
1775
1376
|
filenames.forEach((filename) => {
|
|
1776
1377
|
if (filename.endsWith(".constant.ts"))
|
|
1777
1378
|
files.constant.scalars.push(name);
|
|
@@ -1797,7 +1398,7 @@ class ScanInfo {
|
|
|
1797
1398
|
name: exec.name,
|
|
1798
1399
|
type: exec.type,
|
|
1799
1400
|
repoName: exec.workspace.repoName,
|
|
1800
|
-
serveDomain: WorkspaceExecutor.getBaseDevEnv(
|
|
1401
|
+
serveDomain: WorkspaceExecutor.getBaseDevEnv(path4.join(exec.workspace.workspaceRoot, ".env")).serveDomain,
|
|
1801
1402
|
files,
|
|
1802
1403
|
libDeps,
|
|
1803
1404
|
pkgDeps,
|
|
@@ -2345,10 +1946,10 @@ class Executor {
|
|
|
2345
1946
|
});
|
|
2346
1947
|
}
|
|
2347
1948
|
getPath(filePath) {
|
|
2348
|
-
if (
|
|
1949
|
+
if (path5.isAbsolute(filePath))
|
|
2349
1950
|
return filePath;
|
|
2350
1951
|
if (filePath.startsWith("."))
|
|
2351
|
-
return
|
|
1952
|
+
return path5.join(this.cwdPath, filePath);
|
|
2352
1953
|
const baseParts = this.cwdPath.split(/[\\/]/).filter(Boolean);
|
|
2353
1954
|
const targetParts = filePath.split(/[\\/]/).filter(Boolean);
|
|
2354
1955
|
let overlapLength = 0;
|
|
@@ -2362,12 +1963,12 @@ class Executor {
|
|
|
2362
1963
|
if (isOverlap)
|
|
2363
1964
|
overlapLength = i;
|
|
2364
1965
|
}
|
|
2365
|
-
return
|
|
1966
|
+
return path5.join(this.cwdPath, ...targetParts.slice(overlapLength));
|
|
2366
1967
|
}
|
|
2367
1968
|
async mkdir(dirPath) {
|
|
2368
1969
|
const writePath = this.getPath(dirPath);
|
|
2369
1970
|
if (!await FileSys.dirExists(writePath))
|
|
2370
|
-
await
|
|
1971
|
+
await mkdir(writePath, { recursive: true });
|
|
2371
1972
|
this.logger.verbose(`Make directory ${writePath}`);
|
|
2372
1973
|
return this;
|
|
2373
1974
|
}
|
|
@@ -2405,7 +2006,7 @@ class Executor {
|
|
|
2405
2006
|
return this;
|
|
2406
2007
|
}
|
|
2407
2008
|
async removeDir(dirPath) {
|
|
2408
|
-
const readPath =
|
|
2009
|
+
const readPath = path5.join(this.getPath(dirPath), ".");
|
|
2409
2010
|
if (await FileSys.entryExists(readPath))
|
|
2410
2011
|
await rm2(readPath, { recursive: true, force: true });
|
|
2411
2012
|
this.logger.verbose(`Remove directory ${readPath}`);
|
|
@@ -2413,9 +2014,9 @@ class Executor {
|
|
|
2413
2014
|
}
|
|
2414
2015
|
async writeFile(filePath, content, { overwrite = true, silent = false } = {}) {
|
|
2415
2016
|
const writePath = this.getPath(filePath);
|
|
2416
|
-
const dir =
|
|
2017
|
+
const dir = path5.dirname(writePath);
|
|
2417
2018
|
if (!await FileSys.dirExists(dir))
|
|
2418
|
-
await
|
|
2019
|
+
await mkdir(dir, { recursive: true });
|
|
2419
2020
|
let contentStr = typeof content === "string" ? content : `${JSON.stringify(content, null, 2)}
|
|
2420
2021
|
`;
|
|
2421
2022
|
if (await FileSys.fileExists(writePath)) {
|
|
@@ -2439,7 +2040,7 @@ class Executor {
|
|
|
2439
2040
|
await this.writeFile(filePath, content);
|
|
2440
2041
|
}
|
|
2441
2042
|
async getLocalFile(targetPath) {
|
|
2442
|
-
const filePath =
|
|
2043
|
+
const filePath = path5.isAbsolute(targetPath) ? targetPath : targetPath.replace(this.cwdPath, "");
|
|
2443
2044
|
const content = await this.readFile(filePath);
|
|
2444
2045
|
return { filePath, content };
|
|
2445
2046
|
}
|
|
@@ -2458,7 +2059,7 @@ class Executor {
|
|
|
2458
2059
|
return;
|
|
2459
2060
|
const isDirectory = (await stat(src)).isDirectory();
|
|
2460
2061
|
if (!await FileSys.exists(dest) && isDirectory)
|
|
2461
|
-
await
|
|
2062
|
+
await mkdir(dest, { recursive: true });
|
|
2462
2063
|
if (dereference)
|
|
2463
2064
|
await cpEntry(src, dest, { recursive: isDirectory, dereference: true, force: true });
|
|
2464
2065
|
else
|
|
@@ -2536,9 +2137,9 @@ class Executor {
|
|
|
2536
2137
|
const result = await getContent.default(scanInfo ?? null, dict, options);
|
|
2537
2138
|
if (result === null)
|
|
2538
2139
|
return null;
|
|
2539
|
-
const filename = typeof result === "object" ? result.filename :
|
|
2140
|
+
const filename = typeof result === "object" ? result.filename : path5.basename(targetPath).replace(".js", ".ts");
|
|
2540
2141
|
const content = typeof result === "object" ? result.content : result;
|
|
2541
|
-
const dirname =
|
|
2142
|
+
const dirname = path5.dirname(targetPath);
|
|
2542
2143
|
const convertedTargetPath = Object.entries(dict).reduce((path, [key, value]) => path.replace(new RegExp(`__${key}__`, "g"), value), `${dirname}/${filename}`);
|
|
2543
2144
|
this.logger.verbose(`Apply template ${templatePath} to ${convertedTargetPath}`);
|
|
2544
2145
|
return this.writeFile(convertedTargetPath, content, { overwrite });
|
|
@@ -2550,12 +2151,12 @@ class Executor {
|
|
|
2550
2151
|
return this.writeFile(convertedTargetPath, convertedContent, {
|
|
2551
2152
|
overwrite
|
|
2552
2153
|
});
|
|
2553
|
-
} else if (staticTemplateFileExtensions.has(
|
|
2154
|
+
} else if (staticTemplateFileExtensions.has(path5.extname(targetPath).toLowerCase())) {
|
|
2554
2155
|
const convertedTargetPath = Object.entries(dict).reduce((path, [key, value]) => path.replace(new RegExp(`__${key}__`, "g"), value), targetPath);
|
|
2555
2156
|
const writePath = this.getPath(convertedTargetPath);
|
|
2556
|
-
const dirname =
|
|
2157
|
+
const dirname = path5.dirname(writePath);
|
|
2557
2158
|
if (!await FileSys.dirExists(dirname))
|
|
2558
|
-
await
|
|
2159
|
+
await mkdir(dirname, { recursive: true });
|
|
2559
2160
|
await copyFile(templatePath, writePath);
|
|
2560
2161
|
this.logger.verbose(`Apply template ${templatePath} to ${convertedTargetPath}`);
|
|
2561
2162
|
return { filePath: writePath, content: "" };
|
|
@@ -2574,10 +2175,10 @@ class Executor {
|
|
|
2574
2175
|
const templatePath = `${templateRoot}${template ? `/${template}` : ""}`;
|
|
2575
2176
|
const prefixTemplatePath = templatePath;
|
|
2576
2177
|
if ((await stat(prefixTemplatePath)).isFile()) {
|
|
2577
|
-
const filename =
|
|
2178
|
+
const filename = path5.basename(prefixTemplatePath);
|
|
2578
2179
|
const fileContent = await this.#applyTemplateFile({
|
|
2579
2180
|
templatePath: prefixTemplatePath,
|
|
2580
|
-
targetPath:
|
|
2181
|
+
targetPath: path5.join(basePath, filename),
|
|
2581
2182
|
scanInfo,
|
|
2582
2183
|
overwrite
|
|
2583
2184
|
}, dict, options);
|
|
@@ -2585,19 +2186,19 @@ class Executor {
|
|
|
2585
2186
|
} else {
|
|
2586
2187
|
const subdirs = await readDirEntries(templatePath);
|
|
2587
2188
|
const fileContents = (await Promise.all(subdirs.map(async (subdir) => {
|
|
2588
|
-
const subpath =
|
|
2189
|
+
const subpath = path5.join(templatePath, subdir);
|
|
2589
2190
|
if ((await stat(subpath)).isFile()) {
|
|
2590
2191
|
const fileContent = await this.#applyTemplateFile({
|
|
2591
2192
|
templatePath: subpath,
|
|
2592
|
-
targetPath:
|
|
2193
|
+
targetPath: path5.join(basePath, subdir),
|
|
2593
2194
|
scanInfo,
|
|
2594
2195
|
overwrite
|
|
2595
2196
|
}, dict, options);
|
|
2596
2197
|
return fileContent ? [fileContent] : [];
|
|
2597
2198
|
} else
|
|
2598
2199
|
return await this._applyTemplate({
|
|
2599
|
-
basePath:
|
|
2600
|
-
template:
|
|
2200
|
+
basePath: path5.join(basePath, subdir),
|
|
2201
|
+
template: path5.join(template, subdir),
|
|
2601
2202
|
scanInfo,
|
|
2602
2203
|
dict,
|
|
2603
2204
|
overwrite,
|
|
@@ -2609,8 +2210,8 @@ class Executor {
|
|
|
2609
2210
|
}
|
|
2610
2211
|
async#resolveTemplateRoot() {
|
|
2611
2212
|
const candidates = [
|
|
2612
|
-
|
|
2613
|
-
|
|
2213
|
+
path5.resolve(getDirname2(import.meta.url), "templates"),
|
|
2214
|
+
path5.resolve(getDirname2(import.meta.url), "../cli/templates")
|
|
2614
2215
|
];
|
|
2615
2216
|
for (const candidate of candidates) {
|
|
2616
2217
|
if (await FileSys.dirExists(candidate))
|
|
@@ -2682,11 +2283,11 @@ class Executor {
|
|
|
2682
2283
|
async#resolveTypecheckWorkerEntry() {
|
|
2683
2284
|
const dirname = getDirname2(import.meta.url);
|
|
2684
2285
|
const candidates = [
|
|
2685
|
-
|
|
2686
|
-
|
|
2687
|
-
|
|
2688
|
-
|
|
2689
|
-
|
|
2286
|
+
path5.join(process.cwd(), "pkgs/@akanjs/devkit/typecheck/typecheck.proc.ts"),
|
|
2287
|
+
path5.join(process.cwd(), "node_modules/@akanjs/devkit/typecheck/typecheck.proc.ts"),
|
|
2288
|
+
path5.join(dirname, "typecheck/typecheck.proc.ts"),
|
|
2289
|
+
path5.join(dirname, "typecheck.proc.js"),
|
|
2290
|
+
path5.join(dirname, "typecheck.proc.ts")
|
|
2690
2291
|
];
|
|
2691
2292
|
for (const candidate of candidates)
|
|
2692
2293
|
if (await Bun.file(candidate).exists())
|
|
@@ -2813,7 +2414,7 @@ class WorkspaceExecutor extends Executor {
|
|
|
2813
2414
|
await Promise.all(dirs.map(async (dir) => {
|
|
2814
2415
|
if (dir.includes("_") || AVOID_DIRS.includes(dir))
|
|
2815
2416
|
return;
|
|
2816
|
-
const dirPath =
|
|
2417
|
+
const dirPath = path5.join(dirname, dir);
|
|
2817
2418
|
if ((await stat(dirPath)).isDirectory()) {
|
|
2818
2419
|
results.push(`${prefix}${dir}`);
|
|
2819
2420
|
if (maxDepth > 0)
|
|
@@ -2848,9 +2449,9 @@ class WorkspaceExecutor extends Executor {
|
|
|
2848
2449
|
await Promise.all(dirs.map(async (dir) => {
|
|
2849
2450
|
if (AVOID_DIRS.includes(dir))
|
|
2850
2451
|
return;
|
|
2851
|
-
const dirPath =
|
|
2452
|
+
const dirPath = path5.join(dirname, dir);
|
|
2852
2453
|
if (await FileSys.dirExists(dirPath)) {
|
|
2853
|
-
const hasTargetFile = await FileSys.fileExists(
|
|
2454
|
+
const hasTargetFile = await FileSys.fileExists(path5.join(dirPath, targetFilename));
|
|
2854
2455
|
if (hasTargetFile)
|
|
2855
2456
|
results.push(`${prefix}${dir}`);
|
|
2856
2457
|
if (maxDepth > 0)
|
|
@@ -2924,7 +2525,7 @@ class SysExecutor extends Executor {
|
|
|
2924
2525
|
return [];
|
|
2925
2526
|
const violations = [];
|
|
2926
2527
|
for (const entry of await this.getAllFiles("**/*", { cwd: this.getPath("page") })) {
|
|
2927
|
-
const relativePath = entry.split(
|
|
2528
|
+
const relativePath = entry.split(path5.sep).join("/");
|
|
2928
2529
|
const reason = getPageSourceFileViolation(relativePath);
|
|
2929
2530
|
if (reason)
|
|
2930
2531
|
violations.push({ relativePath: `page/${relativePath}`, reason });
|
|
@@ -3033,7 +2634,7 @@ class SysExecutor extends Executor {
|
|
|
3033
2634
|
await this.setPackageJson(libPkgJsonWithDeps);
|
|
3034
2635
|
}
|
|
3035
2636
|
async getLocalFile(targetPath) {
|
|
3036
|
-
const filePath =
|
|
2637
|
+
const filePath = path5.isAbsolute(targetPath) ? targetPath : `${this.type}s/${this.name}/${targetPath}`;
|
|
3037
2638
|
const content = await this.workspace.readFile(filePath);
|
|
3038
2639
|
return { filePath, content };
|
|
3039
2640
|
}
|
|
@@ -3252,11 +2853,11 @@ class AppExecutor extends SysExecutor {
|
|
|
3252
2853
|
absolute: false,
|
|
3253
2854
|
onlyFiles: true
|
|
3254
2855
|
})) {
|
|
3255
|
-
const segments = rel.split(
|
|
2856
|
+
const segments = rel.split(path5.sep);
|
|
3256
2857
|
if (segments.some((s) => s === "node_modules"))
|
|
3257
2858
|
continue;
|
|
3258
2859
|
const posix = `${root.keyPrefix}${segments.join("/")}`;
|
|
3259
|
-
const absPath =
|
|
2860
|
+
const absPath = path5.join(root.dir, ...segments);
|
|
3260
2861
|
validatePageSourceFile(posix, { filePath: absPath });
|
|
3261
2862
|
if (!isRouteSourceFile(posix))
|
|
3262
2863
|
continue;
|
|
@@ -3395,12 +2996,12 @@ class AppExecutor extends SysExecutor {
|
|
|
3395
2996
|
static async#linkLibAsset(targetPath, linkPath) {
|
|
3396
2997
|
const isWindows = process.platform === "win32";
|
|
3397
2998
|
try {
|
|
3398
|
-
const target = isWindows ? targetPath :
|
|
2999
|
+
const target = isWindows ? targetPath : path5.relative(path5.dirname(linkPath), targetPath);
|
|
3399
3000
|
await symlink(target, linkPath, isWindows ? "junction" : "dir");
|
|
3400
3001
|
} catch (error) {
|
|
3401
3002
|
if (!isWindows)
|
|
3402
3003
|
throw error;
|
|
3403
|
-
await
|
|
3004
|
+
await mkdir(linkPath, { recursive: true });
|
|
3404
3005
|
await cpEntry(targetPath, linkPath, { recursive: true, dereference: true, force: true });
|
|
3405
3006
|
}
|
|
3406
3007
|
}
|
|
@@ -3437,7 +3038,7 @@ class AppExecutor extends SysExecutor {
|
|
|
3437
3038
|
await this.writeFile(rel, content, opts);
|
|
3438
3039
|
},
|
|
3439
3040
|
readEnvClient: async () => {
|
|
3440
|
-
const envClientPath =
|
|
3041
|
+
const envClientPath = path5.join(this.cwdPath, "env", "env.client.ts");
|
|
3441
3042
|
if (!await FileSys.fileExists(envClientPath))
|
|
3442
3043
|
return null;
|
|
3443
3044
|
try {
|
|
@@ -3547,7 +3148,7 @@ class PkgExecutor extends Executor {
|
|
|
3547
3148
|
return rootVersion;
|
|
3548
3149
|
try {
|
|
3549
3150
|
const packageJsonPath = `pkgs/${dep}/package.json`;
|
|
3550
|
-
if (!await Bun.file(
|
|
3151
|
+
if (!await Bun.file(path5.join(this.workspace.workspaceRoot, packageJsonPath)).exists())
|
|
3551
3152
|
return;
|
|
3552
3153
|
const packageJson = await this.workspace.readJson(packageJsonPath);
|
|
3553
3154
|
if (packageJson.name === dep)
|
|
@@ -3648,4 +3249,4 @@ class ModuleExecutor extends Executor {
|
|
|
3648
3249
|
}
|
|
3649
3250
|
}
|
|
3650
3251
|
|
|
3651
|
-
export { AGENT_BLOCK_START, AGENT_BLOCK_END, stampBlockVersion, extractBlockVersion, readDevkitVersion, upsertAgentBlock, extractAgentBlock, renderRecipeEntries, collectScopeRecipeSources, renderScopeAgentBlock, CLAUDE_COMMENT_RULE,
|
|
3252
|
+
export { AGENT_BLOCK_START, AGENT_BLOCK_END, stampBlockVersion, extractBlockVersion, readDevkitVersion, upsertAgentBlock, extractAgentBlock, renderRecipeEntries, collectScopeRecipeSources, renderScopeAgentBlock, CLAUDE_COMMENT_RULE, rootAllowedFiles, rootAllowedDirs, isAllowedLibFacetRootFile, isScannedRootEntry, AppInfo, CommandExecutionError, Executor, WorkspaceExecutor, SysExecutor, AppExecutor, LibExecutor, PkgExecutor, ModuleExecutor };
|