@akanjs/cli 3.0.0-beta.27 → 3.0.0-beta.29
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-h19atbr3.js → CodeAgent-86q8d13j.js} +2 -2
- package/{CodeTui-46zygq8p.js → CodeTui-r8tgxsyb.js} +1 -1
- package/{agent.command-rp505zxa.js → agent.command-q9bmqrag.js} +5 -5
- package/akanCode.js +2 -2
- package/{application.command-1p0cpt6y.js → application.command-712jd2z8.js} +70 -8
- package/{applicationBuildRunner-r6b9rkb8.js → applicationBuildRunner-ez37p161.js} +67 -22
- package/buildBatch.proc.js +3 -3
- package/{cloud.command-ps9dabbg.js → cloud.command-8eegwcsc.js} +9 -9
- package/cloud.script-55s1cmz9.js +20 -0
- package/{code.command-78qw3q3f.js → code.command-n0c2tyzx.js} +6 -6
- package/commandManifest.json +1 -1
- package/{context.command-x5f7t3gk.js → context.command-vxf6d7q2.js} +13 -13
- package/context.runner-70r2fmty.js +21 -0
- package/{guideline.command-d5qmxx29.js → guideline.command-ene55fkr.js} +2 -2
- package/guidelines/conventions/conventions.instruction.md +27 -7
- package/guidelines/runtimeRule/runtimeRule.instruction.md +116 -1
- package/incrementalBuilder.proc.js +2 -2
- package/{index-hzy4pe24.js → index-0pqzrbpr.js} +2 -2
- package/{index-w5pet0nq.js → index-16k7m3cs.js} +11 -9
- package/index-1hs6jrys.js +994 -0
- package/{index-6dt6zft6.js → index-20r2g1t3.js} +4 -4
- package/{index-xfgdmm5d.js → index-2ctqegdm.js} +2 -2
- package/{index-d65fzxvd.js → index-2s2e5qnd.js} +1 -1
- package/{index-j9z8vg2n.js → index-2yvy9ztj.js} +4 -4
- package/{index-t02g6dpn.js → index-2z30v4k5.js} +3 -3
- package/{index-vxqe24mp.js → index-8ej6r02m.js} +1 -1
- package/{index-58cyna2s.js → index-b68zfsvz.js} +1 -1
- package/{index-bp9b1g2r.js → index-fy42hyb9.js} +7 -3
- package/{index-tg09x14f.js → index-g44da4r2.js} +5 -5
- package/{index-zazvn45w.js → index-genegfnt.js} +4 -4
- package/{index-da72pfdv.js → index-h9ed99ax.js} +7 -7
- package/{index-per2kqy9.js → index-k7809wmg.js} +2 -2
- package/{index-2zcm7fjd.js → index-krwz9ek9.js} +3 -3
- package/{index-118vq9dh.js → index-n9gxx7bp.js} +247 -47
- package/{index-860zjnr1.js → index-nbg9bfnr.js} +1 -1
- package/{index-5mm3g24t.js → index-qtz88kh0.js} +2 -2
- package/{index-0n9q1f23.js → index-r8gp8zk3.js} +231 -98
- package/{index-ggfhz9ab.js → index-rbeahw6j.js} +3 -3
- package/{index-56xwsgyn.js → index-rrt9pnb4.js} +2 -2
- package/{index-v4hnkqz9.js → index-ss828r32.js} +1 -1
- package/{index-5kjsr2pg.js → index-ttn00pr3.js} +38 -3
- package/index.js +21 -21
- package/{library.command-sv6g1h2g.js → library.command-tz7vnwea.js} +3 -3
- package/{localRegistry.command-zppa6w7q.js → localRegistry.command-7dd85czz.js} +8 -8
- package/{module.command-ccdeder9.js → module.command-qhc9ns0s.js} +5 -5
- package/{package.command-xmw605b1.js → package.command-z3epnvas.js} +3 -3
- package/package.json +3 -3
- package/{page.command-ky7vafsn.js → page.command-exd2vakz.js} +3 -3
- package/{primitive.command-bh6j8nfs.js → primitive.command-0w6cha4j.js} +6 -6
- package/{quality.command-rqqrpe98.js → quality.command-je4kc9yv.js} +2 -2
- package/{repair.command-n9nsm9qe.js → repair.command-knvwfgtg.js} +5 -5
- package/{scalar.command-t09gmck8.js → scalar.command-60nxfchc.js} +4 -4
- package/{subspace.command-gx2cjpnv.js → subspace.command-683qxcw9.js} +4 -4
- package/templates/server.ts +1 -1
- package/{tunnel.command-4g95vhsn.js → tunnel.command-7m2kxtat.js} +2 -2
- package/{workflow.command-b91ph8sx.js → workflow.command-j5tk13ds.js} +10 -10
- package/{workspace.command-1r29qzzk.js → workspace.command-jxdm0wrb.js} +20 -20
- package/README.ko.md +0 -72
- package/README.md +0 -88
- package/cloud.script-wrw1kz6k.js +0 -20
- package/context.runner-nfs8ksh3.js +0 -21
- package/index-y736f42m.js +0 -556
|
@@ -516,7 +516,7 @@ import {
|
|
|
516
516
|
stat as stat2,
|
|
517
517
|
symlink
|
|
518
518
|
} from "fs/promises";
|
|
519
|
-
import
|
|
519
|
+
import path9 from "path";
|
|
520
520
|
import { pathToFileURL } from "url";
|
|
521
521
|
import {
|
|
522
522
|
capitalize,
|
|
@@ -668,17 +668,83 @@ var renderScopeClaudeMd = (scope) => `# ${scope.name} \u2014 Claude Code Guide
|
|
|
668
668
|
${CLAUDE_COMMENT_RULE}
|
|
669
669
|
`;
|
|
670
670
|
|
|
671
|
-
// pkgs/@akanjs/devkit/akanConfig/
|
|
672
|
-
import fs2 from "fs";
|
|
671
|
+
// pkgs/@akanjs/devkit/akanConfig/akanBin.ts
|
|
673
672
|
import path4 from "path";
|
|
674
|
-
import { fileURLToPath } from "url";
|
|
675
|
-
import { DatabaseModes, normalizeRoutePrefix } from "akanjs/base";
|
|
676
|
-
import { resolveAkanI18nConfig } from "akanjs/common";
|
|
677
673
|
|
|
678
674
|
// pkgs/@akanjs/devkit/akanConfig/types.ts
|
|
679
|
-
import { archs } from "akanjs";
|
|
675
|
+
import { archs, binPlatforms } from "akanjs";
|
|
680
676
|
|
|
677
|
+
// pkgs/@akanjs/devkit/akanConfig/akanBin.ts
|
|
678
|
+
class AkanBin {
|
|
679
|
+
static archive = /\.(zip|tar\.gz|tgz|tar\.xz|txz|tar\.bz2|tbz2|tar)$/i;
|
|
680
|
+
static fileName = /^[A-Za-z0-9][A-Za-z0-9._-]*$/;
|
|
681
|
+
static parse(declared, owner, baseDir) {
|
|
682
|
+
if (declared === undefined)
|
|
683
|
+
return {};
|
|
684
|
+
if (!declared || typeof declared !== "object" || Array.isArray(declared))
|
|
685
|
+
throw new Error(`${owner}: bin maps each executable's name to its platforms`);
|
|
686
|
+
return Object.fromEntries(Object.entries(declared).map(([name, platforms]) => [name, AkanBin.#platforms(name, platforms, owner, baseDir)]));
|
|
687
|
+
}
|
|
688
|
+
static isArchive(source) {
|
|
689
|
+
return AkanBin.archive.test("url" in source ? new URL(source.url).pathname : source.path);
|
|
690
|
+
}
|
|
691
|
+
static #platforms(name, platforms, owner, baseDir) {
|
|
692
|
+
if (!AkanBin.fileName.test(name))
|
|
693
|
+
throw new Error(`${owner}: bin.${name} is not a file name`);
|
|
694
|
+
if (!platforms || typeof platforms !== "object" || Array.isArray(platforms))
|
|
695
|
+
throw new Error(`${owner}: bin.${name} maps platforms (${binPlatforms.join(", ")}) to where the file comes from`);
|
|
696
|
+
const resolved = {};
|
|
697
|
+
for (const [platform, source] of Object.entries(platforms)) {
|
|
698
|
+
if (!binPlatforms.includes(platform))
|
|
699
|
+
throw new Error(`${owner}: bin.${name}.${platform} is not one of ${binPlatforms.join(", ")}`);
|
|
700
|
+
resolved[platform] = AkanBin.#source(`${owner}: bin.${name}.${platform}`, source, baseDir);
|
|
701
|
+
}
|
|
702
|
+
return resolved;
|
|
703
|
+
}
|
|
704
|
+
static #source(at, source, baseDir) {
|
|
705
|
+
if (!source || typeof source !== "object" || Array.isArray(source))
|
|
706
|
+
throw new Error(`${at} must be { url, sha256 } or { path }`);
|
|
707
|
+
const { url, sha256, path: localPath, file, ...rest } = source;
|
|
708
|
+
const extra = Object.keys(rest);
|
|
709
|
+
if (extra.length)
|
|
710
|
+
throw new Error(`${at}: unknown key ${extra.join(", ")}`);
|
|
711
|
+
if (url === undefined === (localPath === undefined))
|
|
712
|
+
throw new Error(`${at} takes either url and sha256, or path`);
|
|
713
|
+
const resolved = url !== undefined ? AkanBin.#urlSource(at, url, sha256) : AkanBin.#pathSource(at, localPath, sha256, baseDir);
|
|
714
|
+
const archive = AkanBin.isArchive(resolved);
|
|
715
|
+
if (file === undefined) {
|
|
716
|
+
if (archive)
|
|
717
|
+
throw new Error(`${at} names an archive: file picks the executable inside it`);
|
|
718
|
+
return resolved;
|
|
719
|
+
}
|
|
720
|
+
if (!archive)
|
|
721
|
+
throw new Error(`${at}: file picks the executable out of an archive, and this source is none`);
|
|
722
|
+
const parts = typeof file === "string" ? file.split(/[\\/]/).filter((part) => part && part !== ".") : [];
|
|
723
|
+
if (!parts.length || path4.isAbsolute(file) || parts.includes(".."))
|
|
724
|
+
throw new Error(`${at}: file must be a path inside the archive (got ${JSON.stringify(file)})`);
|
|
725
|
+
return { ...resolved, file: parts.join("/") };
|
|
726
|
+
}
|
|
727
|
+
static #urlSource(at, url, sha256) {
|
|
728
|
+
if (typeof url !== "string" || !URL.canParse(url) || !/^https?:$/.test(new URL(url).protocol))
|
|
729
|
+
throw new Error(`${at}: url must be an http(s) address`);
|
|
730
|
+
if (typeof sha256 !== "string" || !/^[0-9a-f]{64}$/i.test(sha256))
|
|
731
|
+
throw new Error(`${at}: sha256 must be the downloaded file's 64-digit hex digest`);
|
|
732
|
+
return { url, sha256: sha256.toLowerCase() };
|
|
733
|
+
}
|
|
734
|
+
static #pathSource(at, localPath, sha256, baseDir) {
|
|
735
|
+
if (typeof localPath !== "string" || !localPath)
|
|
736
|
+
throw new Error(`${at}: path must name a file`);
|
|
737
|
+
if (sha256 !== undefined)
|
|
738
|
+
throw new Error(`${at}: sha256 checks a download, and a path source downloads nothing`);
|
|
739
|
+
return { path: path4.resolve(baseDir, localPath) };
|
|
740
|
+
}
|
|
741
|
+
}
|
|
681
742
|
// pkgs/@akanjs/devkit/akanConfig/akanConfig.ts
|
|
743
|
+
import fs2 from "fs";
|
|
744
|
+
import path5 from "path";
|
|
745
|
+
import { fileURLToPath } from "url";
|
|
746
|
+
import { DatabaseModes, normalizeRoutePrefix } from "akanjs/base";
|
|
747
|
+
import { resolveAkanI18nConfig } from "akanjs/common";
|
|
682
748
|
var DEFAULT_BARREL_IMPORTS = ["akanjs/webkit", "akanjs/common", "akanjs/ui", "akanjs/server"];
|
|
683
749
|
var DEFAULT_OPTIMIZE_IMPORTS = [
|
|
684
750
|
"lucide-react date-fns lodash-es ramda antd react-bootstrap ahooks @ant-design/icons @headlessui/react",
|
|
@@ -750,9 +816,18 @@ var normalizeDeepLinks = (deepLinks) => {
|
|
|
750
816
|
};
|
|
751
817
|
var emptyLibContributions = () => ({
|
|
752
818
|
externalLibs: [],
|
|
819
|
+
trustedDependencies: [],
|
|
820
|
+
bin: [],
|
|
753
821
|
docker: { preRuns: [], postRuns: [] },
|
|
754
822
|
keepFonts: []
|
|
755
823
|
});
|
|
824
|
+
var normalizePackageNames = (names, owner) => {
|
|
825
|
+
if (names === undefined)
|
|
826
|
+
return [];
|
|
827
|
+
if (!Array.isArray(names) || names.some((name) => typeof name !== "string" || !name.trim()))
|
|
828
|
+
throw new Error(`${owner}: trustedDependencies lists package names`);
|
|
829
|
+
return [...new Set(names.map((name) => name.trim()))];
|
|
830
|
+
};
|
|
756
831
|
var normalizeKeepFonts = (keepFonts) => [
|
|
757
832
|
...new Set((keepFonts ?? []).map((glob) => glob.trim().replace(/^\/+/, "")).filter(Boolean))
|
|
758
833
|
];
|
|
@@ -771,6 +846,9 @@ class AkanAppConfig {
|
|
|
771
846
|
database;
|
|
772
847
|
web;
|
|
773
848
|
externalLibs;
|
|
849
|
+
trustedDependencies;
|
|
850
|
+
bin;
|
|
851
|
+
libBins;
|
|
774
852
|
barrelImports;
|
|
775
853
|
optimizeImports;
|
|
776
854
|
images;
|
|
@@ -798,6 +876,15 @@ class AkanAppConfig {
|
|
|
798
876
|
this.#applyRoutes(config?.routes);
|
|
799
877
|
this.database = AkanAppConfig.#database(app, config);
|
|
800
878
|
this.externalLibs = [...new Set([...config?.externalLibs ?? [], ...libContributions.externalLibs])];
|
|
879
|
+
const owner = `apps/${app.name}/akan.config.ts`;
|
|
880
|
+
this.trustedDependencies = [
|
|
881
|
+
...new Set([
|
|
882
|
+
...normalizePackageNames(config?.trustedDependencies, owner),
|
|
883
|
+
...libContributions.trustedDependencies ?? []
|
|
884
|
+
])
|
|
885
|
+
];
|
|
886
|
+
this.bin = AkanBin.parse(config?.bin, owner, app.cwdPath);
|
|
887
|
+
this.libBins = libContributions.bin ?? [];
|
|
801
888
|
this.barrelImports = [
|
|
802
889
|
...DEFAULT_BARREL_IMPORTS,
|
|
803
890
|
...WORKSPACE_BARREL_FACETS.map((facet) => `@apps/${app.name}/${facet}`),
|
|
@@ -851,6 +938,7 @@ class AkanAppConfig {
|
|
|
851
938
|
const buildNum = rawMobile.buildNum ?? 1;
|
|
852
939
|
const files = AkanAppConfig.#resolveMobileFiles(rawMobile.files, "mobile", configPath);
|
|
853
940
|
const native = rawMobile.native;
|
|
941
|
+
const updates = rawMobile.updates;
|
|
854
942
|
const defaultTargetName = this.#defaultMobileTargetName(rawTargets);
|
|
855
943
|
const targetEntries = Object.entries(rawTargets ?? {
|
|
856
944
|
[defaultTargetName]: {}
|
|
@@ -868,6 +956,9 @@ class AkanAppConfig {
|
|
|
868
956
|
}
|
|
869
957
|
const targetFiles = AkanAppConfig.#resolveMobileFiles(target.files, where, configPath);
|
|
870
958
|
const fileName = target.fileName ?? rawMobile.fileName;
|
|
959
|
+
const targetUpdates = updates || target.updates ? { ...updates, ...target.updates } : undefined;
|
|
960
|
+
if (targetUpdates && (!targetUpdates.url || !targetUpdates.publicKey))
|
|
961
|
+
throw new Error(`${where}.updates in ${configPath} has no url or publicKey; give them in mobile.updates or the target's own.`);
|
|
871
962
|
const resolved = {
|
|
872
963
|
name,
|
|
873
964
|
basePath,
|
|
@@ -881,7 +972,8 @@ class AkanAppConfig {
|
|
|
881
972
|
...target.assets ? { assets: target.assets } : {},
|
|
882
973
|
...target.permissions ? { permissions: target.permissions } : {},
|
|
883
974
|
...files || targetFiles ? { files: { ...files, ...targetFiles } } : {},
|
|
884
|
-
...native || target.native ? { native: AkanAppConfig.#mergeNative(native, target.native) } : {}
|
|
975
|
+
...native || target.native ? { native: AkanAppConfig.#mergeNative(native, target.native) } : {},
|
|
976
|
+
...targetUpdates ? { updates: targetUpdates } : {}
|
|
885
977
|
};
|
|
886
978
|
return [name, resolved];
|
|
887
979
|
}));
|
|
@@ -893,10 +985,11 @@ class AkanAppConfig {
|
|
|
893
985
|
buildNum,
|
|
894
986
|
...files ? { files } : {},
|
|
895
987
|
...native ? { native } : {},
|
|
988
|
+
...updates ? { updates } : {},
|
|
896
989
|
targets
|
|
897
990
|
};
|
|
898
991
|
}
|
|
899
|
-
static #mobileKeys = ["appName", "appId", "fileName", "version", "buildNum", "files", "native"];
|
|
992
|
+
static #mobileKeys = ["appName", "appId", "fileName", "version", "buildNum", "files", "native", "updates"];
|
|
900
993
|
static #targetKeys = [
|
|
901
994
|
"basePath",
|
|
902
995
|
"indexPath",
|
|
@@ -909,7 +1002,8 @@ class AkanAppConfig {
|
|
|
909
1002
|
"permissions",
|
|
910
1003
|
"deepLinks",
|
|
911
1004
|
"files",
|
|
912
|
-
"native"
|
|
1005
|
+
"native",
|
|
1006
|
+
"updates"
|
|
913
1007
|
];
|
|
914
1008
|
static #assertMobileKeys(section, known, where, configPath) {
|
|
915
1009
|
for (const key of Object.keys(section)) {
|
|
@@ -946,10 +1040,21 @@ class AkanAppConfig {
|
|
|
946
1040
|
else
|
|
947
1041
|
delete android[key];
|
|
948
1042
|
}
|
|
1043
|
+
const pushAndroid = { ...base?.push?.android, ...override?.push?.android };
|
|
1044
|
+
const privacy = { ...base?.privacy, ...override?.privacy };
|
|
1045
|
+
const window = { ...base?.desktop?.window, ...override?.desktop?.window };
|
|
1046
|
+
const desktop = {
|
|
1047
|
+
...base?.desktop,
|
|
1048
|
+
...override?.desktop,
|
|
1049
|
+
...Object.keys(window).length ? { window } : {}
|
|
1050
|
+
};
|
|
949
1051
|
return {
|
|
950
1052
|
...plugins.length ? { plugins } : {},
|
|
951
1053
|
...Object.keys(ios).length ? { ios } : {},
|
|
952
|
-
...Object.keys(android).length ? { android } : {}
|
|
1054
|
+
...Object.keys(android).length ? { android } : {},
|
|
1055
|
+
...Object.keys(pushAndroid).length ? { push: { android: pushAndroid } } : {},
|
|
1056
|
+
...Object.keys(privacy).length ? { privacy } : {},
|
|
1057
|
+
...Object.keys(desktop).length ? { desktop } : {}
|
|
953
1058
|
};
|
|
954
1059
|
}
|
|
955
1060
|
#defaultMobileTargetName(rawTargets) {
|
|
@@ -1004,18 +1109,37 @@ class AkanAppConfig {
|
|
|
1004
1109
|
command: docker?.command ?? ["bun", "main.js"]
|
|
1005
1110
|
};
|
|
1006
1111
|
}
|
|
1007
|
-
|
|
1112
|
+
getProductionEnv(environment = this.baseDevEnv.env) {
|
|
1113
|
+
return {
|
|
1114
|
+
PORT: "8282",
|
|
1115
|
+
NODE_ENV: "production",
|
|
1116
|
+
AKAN_PUBLIC_REPO_NAME: this.baseDevEnv.repoName,
|
|
1117
|
+
AKAN_PUBLIC_SERVE_DOMAIN: this.baseDevEnv.serveDomain,
|
|
1118
|
+
AKAN_PUBLIC_APP_NAME: this.app.name,
|
|
1119
|
+
AKAN_PUBLIC_ENV: environment,
|
|
1120
|
+
...this.basePaths.size ? { AKAN_PUBLIC_BASE_PATHS: [...this.basePaths].join(",") } : {},
|
|
1121
|
+
AKAN_PUBLIC_DEFAULT_LOCALE: this.i18n.defaultLocale,
|
|
1122
|
+
AKAN_PUBLIC_LOCALES: this.i18n.locales.join(","),
|
|
1123
|
+
AKAN_PUBLIC_API_PREFIX: this.api.prefix,
|
|
1124
|
+
AKAN_PUBLIC_WS_PREFIX: this.api.websocketPrefix,
|
|
1125
|
+
AKAN_PUBLIC_OPERATION_MODE: "cloud",
|
|
1126
|
+
AKAN_DATABASE_MODES: this.database.modes.join(","),
|
|
1127
|
+
AKAN_LOG_TO_FILE: "0",
|
|
1128
|
+
...this.web.ssr ? {} : { AKAN_SSR: "false" },
|
|
1129
|
+
...this.web.csr ? {} : { AKAN_CSR: "false" }
|
|
1130
|
+
};
|
|
1131
|
+
}
|
|
1132
|
+
dockerfileFor(environment) {
|
|
1133
|
+
return this.#makeDockerfile(environment);
|
|
1134
|
+
}
|
|
1135
|
+
#makeDockerfile(environment) {
|
|
1008
1136
|
if (typeof this.docker === "string")
|
|
1009
1137
|
return this.docker;
|
|
1010
1138
|
const { image, preRuns, postRuns, command } = this.docker;
|
|
1011
1139
|
const preRunScripts = this.#getDockerRunScripts(preRuns);
|
|
1012
1140
|
const postRunScripts = this.#getDockerRunScripts(postRuns);
|
|
1013
1141
|
const imageScript = this.#getDockerImageScript(image, DEFAULT_DOCKER_IMAGE);
|
|
1014
|
-
const
|
|
1015
|
-
...this.web.ssr ? [] : ["ENV AKAN_SSR=false"],
|
|
1016
|
-
...this.web.csr ? [] : ["ENV AKAN_CSR=false"]
|
|
1017
|
-
].join(`
|
|
1018
|
-
`);
|
|
1142
|
+
const envLines = Object.entries(this.getProductionEnv(environment)).map(([key, value]) => `ENV ${key}=${value}`);
|
|
1019
1143
|
return `${imageScript}
|
|
1020
1144
|
RUN apt-get update && apt-get upgrade -y && apt-get install -y --no-install-recommends ca-certificates tzdata && rm -rf /var/lib/apt/lists/*
|
|
1021
1145
|
RUN ln -sf /usr/share/zoneinfo/Asia/Seoul /etc/localtime
|
|
@@ -1029,21 +1153,8 @@ RUN bun install --production
|
|
|
1029
1153
|
${postRunScripts.join(`
|
|
1030
1154
|
`)}
|
|
1031
1155
|
COPY . .
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
ENV AKAN_PUBLIC_REPO_NAME=${this.baseDevEnv.repoName}
|
|
1035
|
-
ENV AKAN_PUBLIC_SERVE_DOMAIN=${this.baseDevEnv.serveDomain}
|
|
1036
|
-
ENV AKAN_PUBLIC_APP_NAME=${this.app.name}
|
|
1037
|
-
ENV AKAN_PUBLIC_ENV=${this.baseDevEnv.env}
|
|
1038
|
-
${this.basePaths.size ? `ENV AKAN_PUBLIC_BASE_PATHS=${[...this.basePaths].join(",")}` : ""}
|
|
1039
|
-
ENV AKAN_PUBLIC_DEFAULT_LOCALE=${this.i18n.defaultLocale}
|
|
1040
|
-
ENV AKAN_PUBLIC_LOCALES=${this.i18n.locales.join(",")}
|
|
1041
|
-
ENV AKAN_PUBLIC_API_PREFIX=${this.api.prefix}
|
|
1042
|
-
ENV AKAN_PUBLIC_WS_PREFIX=${this.api.websocketPrefix}
|
|
1043
|
-
ENV AKAN_PUBLIC_OPERATION_MODE=cloud
|
|
1044
|
-
ENV AKAN_DATABASE_MODES=${this.database.modes.join(",")}
|
|
1045
|
-
ENV AKAN_LOG_TO_FILE=0
|
|
1046
|
-
${webEnvLines}
|
|
1156
|
+
${envLines.join(`
|
|
1157
|
+
`)}
|
|
1047
1158
|
CMD [${command.map((c) => `"${c}"`).join(",")}]`;
|
|
1048
1159
|
}
|
|
1049
1160
|
static #importGeneration = 0;
|
|
@@ -1055,7 +1166,7 @@ CMD [${command.map((c) => `"${c}"`).join(",")}]`;
|
|
|
1055
1166
|
static async from(app, { bustImportCache = false } = {}) {
|
|
1056
1167
|
const [configImp, baseDevEnv, libs, rootPackageJson] = await Promise.all([
|
|
1057
1168
|
AkanAppConfig.importConfigModule(app.cwdPath, { bustImportCache }),
|
|
1058
|
-
WorkspaceExecutor.getBaseDevEnv(
|
|
1169
|
+
WorkspaceExecutor.getBaseDevEnv(path5.join(app.workspace.workspaceRoot, ".env")),
|
|
1059
1170
|
app.workspace.getLibs(),
|
|
1060
1171
|
app.workspace.getPackageJson()
|
|
1061
1172
|
]);
|
|
@@ -1071,6 +1182,8 @@ CMD [${command.map((c) => `"${c}"`).join(",")}]`;
|
|
|
1071
1182
|
})));
|
|
1072
1183
|
return {
|
|
1073
1184
|
externalLibs: libConfigs.flatMap((libConfig) => libConfig?.externalLibs ?? []),
|
|
1185
|
+
trustedDependencies: libConfigs.flatMap((libConfig) => libConfig?.trustedDependencies ?? []),
|
|
1186
|
+
bin: libConfigs.flatMap((libConfig) => libConfig && Object.keys(libConfig.bin).length ? [{ lib: libConfig.lib.name, bin: libConfig.bin }] : []),
|
|
1074
1187
|
docker: {
|
|
1075
1188
|
preRuns: libConfigs.flatMap((libConfig) => libConfig?.docker.preRuns ?? []),
|
|
1076
1189
|
postRuns: libConfigs.flatMap((libConfig) => libConfig?.docker.postRuns ?? [])
|
|
@@ -1133,6 +1246,7 @@ CMD [${command.map((c) => `"${c}"`).join(",")}]`;
|
|
|
1133
1246
|
lib,
|
|
1134
1247
|
this.#resolveProductionDependencyVersion(lib)
|
|
1135
1248
|
])),
|
|
1249
|
+
...this.trustedDependencies.length ? { trustedDependencies: this.trustedDependencies } : {},
|
|
1136
1250
|
...data
|
|
1137
1251
|
};
|
|
1138
1252
|
}
|
|
@@ -1141,11 +1255,11 @@ var akanPackageJson = null;
|
|
|
1141
1255
|
function getAkanPackageJson() {
|
|
1142
1256
|
if (akanPackageJson)
|
|
1143
1257
|
return akanPackageJson;
|
|
1144
|
-
const sourceDir =
|
|
1258
|
+
const sourceDir = path5.dirname(fileURLToPath(import.meta.url));
|
|
1145
1259
|
const packageJsonPaths = [
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1260
|
+
path5.join(sourceDir, "../../../akanjs/package.json"),
|
|
1261
|
+
path5.join(process.cwd(), "pkgs/akanjs/package.json"),
|
|
1262
|
+
path5.join(path5.dirname(Bun.main), "node_modules/akanjs/package.json")
|
|
1149
1263
|
];
|
|
1150
1264
|
try {
|
|
1151
1265
|
packageJsonPaths.unshift(Bun.resolveSync("akanjs/package.json", sourceDir));
|
|
@@ -1180,12 +1294,17 @@ function mergeImageConfig(config = {}) {
|
|
|
1180
1294
|
class AkanLibConfig {
|
|
1181
1295
|
lib;
|
|
1182
1296
|
externalLibs;
|
|
1297
|
+
trustedDependencies;
|
|
1298
|
+
bin;
|
|
1183
1299
|
docker;
|
|
1184
1300
|
assets;
|
|
1185
1301
|
plugins;
|
|
1186
1302
|
constructor(lib, config, plugins = []) {
|
|
1187
1303
|
this.lib = lib;
|
|
1188
1304
|
this.externalLibs = config?.externalLibs ?? [];
|
|
1305
|
+
const owner = `libs/${lib.name}/akan.config.ts`;
|
|
1306
|
+
this.trustedDependencies = normalizePackageNames(config?.trustedDependencies, owner);
|
|
1307
|
+
this.bin = AkanBin.parse(config?.bin, owner, lib.cwdPath);
|
|
1189
1308
|
this.docker = { preRuns: config?.docker?.preRuns ?? [], postRuns: config?.docker?.postRuns ?? [] };
|
|
1190
1309
|
this.assets = { keepFonts: normalizeKeepFonts(config?.assets?.keepFonts) };
|
|
1191
1310
|
this.plugins = plugins;
|
|
@@ -1200,7 +1319,7 @@ class AkanLibConfig {
|
|
|
1200
1319
|
//! need to refactor
|
|
1201
1320
|
var shiftBuildNum = async (app, delta) => {
|
|
1202
1321
|
const { buildNum } = (await AkanAppConfig.from(app)).mobile;
|
|
1203
|
-
const akanConfigPath =
|
|
1322
|
+
const akanConfigPath = path5.join(app.cwdPath, "akan.config.ts");
|
|
1204
1323
|
const akanConfig = fs2.readFileSync(akanConfigPath, "utf8");
|
|
1205
1324
|
fs2.writeFileSync(akanConfigPath, akanConfig.replace(`buildNum: ${buildNum}`, `buildNum: ${buildNum + delta}`));
|
|
1206
1325
|
};
|
|
@@ -1209,7 +1328,7 @@ var decreaseBuildNum = async (app) => await shiftBuildNum(app, -1);
|
|
|
1209
1328
|
// pkgs/@akanjs/devkit/linter.ts
|
|
1210
1329
|
import { spawn } from "child_process";
|
|
1211
1330
|
import { existsSync, readFileSync } from "fs";
|
|
1212
|
-
import
|
|
1331
|
+
import path6 from "path";
|
|
1213
1332
|
import chalk from "chalk";
|
|
1214
1333
|
var parseBiomeReport = (output) => {
|
|
1215
1334
|
for (let start = output.indexOf("{");start !== -1; start = output.indexOf("{", start + 1)) {
|
|
@@ -1275,13 +1394,13 @@ class Linter {
|
|
|
1275
1394
|
#biomeBin;
|
|
1276
1395
|
constructor(cwdPath) {
|
|
1277
1396
|
this.lintRoot = this.#findBiomeRootPath(cwdPath);
|
|
1278
|
-
this.configPath = Linter.#configPathIn(this.lintRoot) ??
|
|
1279
|
-
const localBiomeBin =
|
|
1397
|
+
this.configPath = Linter.#configPathIn(this.lintRoot) ?? path6.join(this.lintRoot, "biome.json");
|
|
1398
|
+
const localBiomeBin = path6.join(this.lintRoot, "node_modules", ".bin", Linter.biomeBinName);
|
|
1280
1399
|
this.#biomeBin = existsSync(localBiomeBin) ? localBiomeBin : "biome";
|
|
1281
1400
|
}
|
|
1282
1401
|
static #configPathIn(dir) {
|
|
1283
1402
|
for (const fileName of BIOME_CONFIG_FILES) {
|
|
1284
|
-
const configPath =
|
|
1403
|
+
const configPath = path6.join(dir, fileName);
|
|
1285
1404
|
if (existsSync(configPath))
|
|
1286
1405
|
return configPath;
|
|
1287
1406
|
}
|
|
@@ -1290,19 +1409,19 @@ class Linter {
|
|
|
1290
1409
|
#findBiomeRootPath(dir) {
|
|
1291
1410
|
if (Linter.#configPathIn(dir))
|
|
1292
1411
|
return dir;
|
|
1293
|
-
const parentDir =
|
|
1412
|
+
const parentDir = path6.dirname(dir);
|
|
1294
1413
|
if (parentDir === dir)
|
|
1295
1414
|
throw new Error(`biome.json not found from ${dir}`);
|
|
1296
1415
|
return this.#findBiomeRootPath(parentDir);
|
|
1297
1416
|
}
|
|
1298
1417
|
#toBiomePath(filePath) {
|
|
1299
|
-
const relativePath =
|
|
1300
|
-
if (!relativePath.startsWith("..") && !
|
|
1418
|
+
const relativePath = path6.relative(this.lintRoot, filePath);
|
|
1419
|
+
if (!relativePath.startsWith("..") && !path6.isAbsolute(relativePath))
|
|
1301
1420
|
return relativePath;
|
|
1302
1421
|
return filePath;
|
|
1303
1422
|
}
|
|
1304
1423
|
#resolveFilePath(filePath) {
|
|
1305
|
-
return
|
|
1424
|
+
return path6.isAbsolute(filePath) ? filePath : path6.join(this.lintRoot, filePath);
|
|
1306
1425
|
}
|
|
1307
1426
|
async#runBiome(args, input) {
|
|
1308
1427
|
return await new Promise((resolve, reject) => {
|
|
@@ -1327,7 +1446,7 @@ class Linter {
|
|
|
1327
1446
|
const diagnosticPath = diagnostic.location?.path;
|
|
1328
1447
|
if (!diagnosticPath)
|
|
1329
1448
|
return fallbackFilePath;
|
|
1330
|
-
return
|
|
1449
|
+
return path6.isAbsolute(diagnosticPath) ? diagnosticPath : path6.join(this.lintRoot, diagnosticPath);
|
|
1331
1450
|
}
|
|
1332
1451
|
#createLintMessage(diagnostic) {
|
|
1333
1452
|
const start = diagnostic.location?.start;
|
|
@@ -1535,7 +1654,7 @@ ${errorText}, ${warningText} found`];
|
|
|
1535
1654
|
|
|
1536
1655
|
// pkgs/@akanjs/devkit/repoIdentity.ts
|
|
1537
1656
|
import { execFileSync } from "child_process";
|
|
1538
|
-
import
|
|
1657
|
+
import path7 from "path";
|
|
1539
1658
|
var resolved = new Map;
|
|
1540
1659
|
var readRemoteName = (workspaceRoot) => {
|
|
1541
1660
|
try {
|
|
@@ -1553,13 +1672,13 @@ var resolveRepoName = (workspaceRoot) => {
|
|
|
1553
1672
|
const cached = resolved.get(workspaceRoot);
|
|
1554
1673
|
if (cached)
|
|
1555
1674
|
return cached;
|
|
1556
|
-
const repoName = readRemoteName(workspaceRoot) ??
|
|
1675
|
+
const repoName = readRemoteName(workspaceRoot) ?? path7.basename(workspaceRoot);
|
|
1557
1676
|
resolved.set(workspaceRoot, repoName);
|
|
1558
1677
|
return repoName;
|
|
1559
1678
|
};
|
|
1560
1679
|
|
|
1561
1680
|
// pkgs/@akanjs/devkit/scanInfo.ts
|
|
1562
|
-
import
|
|
1681
|
+
import path8 from "path";
|
|
1563
1682
|
|
|
1564
1683
|
// pkgs/@akanjs/devkit/workspaceLayout.ts
|
|
1565
1684
|
var appRootAllowedFiles = new Set([
|
|
@@ -1579,6 +1698,7 @@ var appRootAllowedDirs = new Set([
|
|
|
1579
1698
|
"common",
|
|
1580
1699
|
"env",
|
|
1581
1700
|
"lib",
|
|
1701
|
+
"native",
|
|
1582
1702
|
"page",
|
|
1583
1703
|
"plugin",
|
|
1584
1704
|
"private",
|
|
@@ -1607,6 +1727,7 @@ var libRootAllowedDirs = new Set([
|
|
|
1607
1727
|
"common",
|
|
1608
1728
|
"env",
|
|
1609
1729
|
"lib",
|
|
1730
|
+
"native",
|
|
1610
1731
|
"page",
|
|
1611
1732
|
"plugin",
|
|
1612
1733
|
"private",
|
|
@@ -1668,9 +1789,9 @@ var moduleUiFileTypes = {
|
|
|
1668
1789
|
scalar: new Set(["Template", "Unit"])
|
|
1669
1790
|
};
|
|
1670
1791
|
var createDependencyScanner = async (exec) => (await import("./dependencyScanner-06z2dmrr.js")).TypeScriptDependencyScanner.from(exec);
|
|
1671
|
-
var getScanPath = (exec, relativePath) =>
|
|
1792
|
+
var getScanPath = (exec, relativePath) => path8.posix.join(`${exec.type}s`, exec.name, relativePath.split(path8.sep).join("/"));
|
|
1672
1793
|
var getModuleNameFromPath = (kind, modulePath) => {
|
|
1673
|
-
const dirname =
|
|
1794
|
+
const dirname = path8.basename(modulePath);
|
|
1674
1795
|
return kind === "service" ? dirname.replace(/^_+/, "") : dirname;
|
|
1675
1796
|
};
|
|
1676
1797
|
async function assertScanConvention(exec, libRoot) {
|
|
@@ -1692,17 +1813,17 @@ async function assertScanConvention(exec, libRoot) {
|
|
|
1692
1813
|
addViolation(relativePath, reason);
|
|
1693
1814
|
for (const filename of libRoot.files)
|
|
1694
1815
|
if (!isAllowedLibFacetRootFile(filename))
|
|
1695
|
-
addViolation(
|
|
1816
|
+
addViolation(path8.join("lib", filename), "unsupported lib facet root file");
|
|
1696
1817
|
for (const dirname of libRoot.dirs)
|
|
1697
1818
|
if (dirname.startsWith("__") && !internalLibDirs.has(dirname))
|
|
1698
|
-
addViolation(
|
|
1819
|
+
addViolation(path8.join("lib", dirname), "unsupported internal lib folder");
|
|
1699
1820
|
const databaseDirs = libRoot.dirs.filter((dirname) => !dirname.startsWith("_"));
|
|
1700
1821
|
const serviceDirs = libRoot.dirs.filter((dirname) => dirname.startsWith("_") && !dirname.startsWith("__"));
|
|
1701
1822
|
const scalarDirs = await exec.readdir("lib/__scalar");
|
|
1702
1823
|
await Promise.all([
|
|
1703
|
-
...databaseDirs.map((dirname) => validateModuleFiles(exec, violations, "database",
|
|
1704
|
-
...serviceDirs.map((dirname) => validateModuleFiles(exec, violations, "service",
|
|
1705
|
-
...scalarDirs.map((dirname) => validateModuleFiles(exec, violations, "scalar",
|
|
1824
|
+
...databaseDirs.map((dirname) => validateModuleFiles(exec, violations, "database", path8.join("lib", dirname))),
|
|
1825
|
+
...serviceDirs.map((dirname) => validateModuleFiles(exec, violations, "service", path8.join("lib", dirname))),
|
|
1826
|
+
...scalarDirs.map((dirname) => validateModuleFiles(exec, violations, "scalar", path8.join("lib/__scalar", dirname)))
|
|
1706
1827
|
]);
|
|
1707
1828
|
if (violations.length > 0) {
|
|
1708
1829
|
throw new Error(`[scan-convention]
|
|
@@ -1714,11 +1835,11 @@ async function validateModuleFiles(exec, violations, kind, modulePath) {
|
|
|
1714
1835
|
const { files, dirs } = await exec.getFilesAndDirs(modulePath);
|
|
1715
1836
|
const moduleName = getModuleNameFromPath(kind, modulePath);
|
|
1716
1837
|
dirs.forEach((dirname) => {
|
|
1717
|
-
violations.push(`${getScanPath(exec,
|
|
1838
|
+
violations.push(`${getScanPath(exec, path8.join(modulePath, dirname))}: unsupported module folder`);
|
|
1718
1839
|
});
|
|
1719
1840
|
const uiModuleName = moduleName[0].toUpperCase() + moduleName.slice(1);
|
|
1720
1841
|
for (const filename of files) {
|
|
1721
|
-
const scanPath = getScanPath(exec,
|
|
1842
|
+
const scanPath = getScanPath(exec, path8.join(modulePath, filename));
|
|
1722
1843
|
if (filename === "index.ts" || filename === "index.tsx" || /\.(test|spec)\.(ts|tsx)$/.test(filename))
|
|
1723
1844
|
continue;
|
|
1724
1845
|
if (filename === `${moduleName}.abstract.md`)
|
|
@@ -1791,16 +1912,16 @@ class ScanInfo {
|
|
|
1791
1912
|
}
|
|
1792
1913
|
};
|
|
1793
1914
|
await Promise.all([
|
|
1794
|
-
...databaseDirs.map((name) => collect(
|
|
1795
|
-
...serviceDirs.map((dirname) => collect(
|
|
1796
|
-
...scalarDirs.map((name) => collect(
|
|
1915
|
+
...databaseDirs.map((name) => collect(path8.join("lib", name), name, "databases")),
|
|
1916
|
+
...serviceDirs.map((dirname) => collect(path8.join("lib", dirname), dirname.slice(1), "services")),
|
|
1917
|
+
...scalarDirs.map((name) => collect(path8.join("lib/__scalar", name), name, "scalars"))
|
|
1797
1918
|
]);
|
|
1798
1919
|
const routes = exec.type === "lib" ? [] : await exec.getPageKeys();
|
|
1799
1920
|
const common = {
|
|
1800
1921
|
name: exec.name,
|
|
1801
1922
|
type: exec.type,
|
|
1802
1923
|
repoName: exec.workspace.repoName,
|
|
1803
|
-
serveDomain: WorkspaceExecutor.getBaseDevEnv(
|
|
1924
|
+
serveDomain: WorkspaceExecutor.getBaseDevEnv(path8.join(exec.workspace.workspaceRoot, ".env")).serveDomain,
|
|
1804
1925
|
files,
|
|
1805
1926
|
libDeps,
|
|
1806
1927
|
pkgDeps,
|
|
@@ -2182,10 +2303,10 @@ class Executor {
|
|
|
2182
2303
|
return this.#settle(proc, target, { redStderr: true }).then(({ code, signal }) => ({ code, signal }));
|
|
2183
2304
|
}
|
|
2184
2305
|
getPath(filePath) {
|
|
2185
|
-
if (
|
|
2306
|
+
if (path9.isAbsolute(filePath))
|
|
2186
2307
|
return filePath;
|
|
2187
2308
|
if (filePath.startsWith("."))
|
|
2188
|
-
return
|
|
2309
|
+
return path9.join(this.cwdPath, filePath);
|
|
2189
2310
|
const baseParts = this.cwdPath.split(/[\\/]/).filter(Boolean);
|
|
2190
2311
|
const targetParts = filePath.split(/[\\/]/).filter(Boolean);
|
|
2191
2312
|
let overlapLength = 0;
|
|
@@ -2199,7 +2320,7 @@ class Executor {
|
|
|
2199
2320
|
if (isOverlap)
|
|
2200
2321
|
overlapLength = i;
|
|
2201
2322
|
}
|
|
2202
|
-
return
|
|
2323
|
+
return path9.join(this.cwdPath, ...targetParts.slice(overlapLength));
|
|
2203
2324
|
}
|
|
2204
2325
|
async mkdir(dirPath) {
|
|
2205
2326
|
const writePath = this.getPath(dirPath);
|
|
@@ -2240,7 +2361,7 @@ class Executor {
|
|
|
2240
2361
|
return this;
|
|
2241
2362
|
}
|
|
2242
2363
|
async removeDir(dirPath) {
|
|
2243
|
-
const readPath =
|
|
2364
|
+
const readPath = path9.join(this.getPath(dirPath), ".");
|
|
2244
2365
|
if (await FileSys2.entryExists(readPath))
|
|
2245
2366
|
await rm3(readPath, { recursive: true, force: true });
|
|
2246
2367
|
this.logger.verbose(`Remove directory ${readPath}`);
|
|
@@ -2248,7 +2369,7 @@ class Executor {
|
|
|
2248
2369
|
}
|
|
2249
2370
|
async writeFile(filePath, content, { overwrite = true, silent = false } = {}) {
|
|
2250
2371
|
const writePath = this.getPath(filePath);
|
|
2251
|
-
const dir =
|
|
2372
|
+
const dir = path9.dirname(writePath);
|
|
2252
2373
|
if (!await FileSys2.dirExists(dir))
|
|
2253
2374
|
await mkdir2(dir, { recursive: true });
|
|
2254
2375
|
let contentStr = typeof content === "string" ? content : `${JSON.stringify(content, null, 2)}
|
|
@@ -2274,7 +2395,7 @@ class Executor {
|
|
|
2274
2395
|
await this.writeFile(filePath, content);
|
|
2275
2396
|
}
|
|
2276
2397
|
async getLocalFile(targetPath) {
|
|
2277
|
-
const filePath =
|
|
2398
|
+
const filePath = path9.isAbsolute(targetPath) ? targetPath : targetPath.replace(this.cwdPath, "");
|
|
2278
2399
|
const content = await this.readFile(filePath);
|
|
2279
2400
|
return { filePath, content };
|
|
2280
2401
|
}
|
|
@@ -2361,9 +2482,9 @@ class Executor {
|
|
|
2361
2482
|
const result = await getContent.default(scanInfo ?? null, dict, options);
|
|
2362
2483
|
if (result === null)
|
|
2363
2484
|
return null;
|
|
2364
|
-
const filename = typeof result === "object" ? result.filename :
|
|
2485
|
+
const filename = typeof result === "object" ? result.filename : path9.basename(targetPath).replace(".js", ".ts");
|
|
2365
2486
|
const content = typeof result === "object" ? result.content : result;
|
|
2366
|
-
const convertedTargetPath = convertPath(`${
|
|
2487
|
+
const convertedTargetPath = convertPath(`${path9.dirname(targetPath)}/${filename}`);
|
|
2367
2488
|
this.logger.verbose(`Apply template ${templatePath} to ${convertedTargetPath}`);
|
|
2368
2489
|
return this.writeFile(convertedTargetPath, content, { overwrite });
|
|
2369
2490
|
} else if (targetPath.endsWith(".template")) {
|
|
@@ -2372,10 +2493,10 @@ class Executor {
|
|
|
2372
2493
|
const convertedContent = Object.entries(dict).reduce((data, [key, value]) => data.replace(new RegExp(`<%= ${key} %>`, "g"), value), content);
|
|
2373
2494
|
this.logger.verbose(`Apply template ${templatePath} to ${convertedTargetPath}`);
|
|
2374
2495
|
return this.writeFile(convertedTargetPath, convertedContent, { overwrite });
|
|
2375
|
-
} else if (staticTemplateFileExtensions.has(
|
|
2496
|
+
} else if (staticTemplateFileExtensions.has(path9.extname(targetPath).toLowerCase())) {
|
|
2376
2497
|
const convertedTargetPath = convertPath(targetPath);
|
|
2377
2498
|
const writePath = this.getPath(convertedTargetPath);
|
|
2378
|
-
const dirname =
|
|
2499
|
+
const dirname = path9.dirname(writePath);
|
|
2379
2500
|
if (!await FileSys2.dirExists(dirname))
|
|
2380
2501
|
await mkdir2(dirname, { recursive: true });
|
|
2381
2502
|
await copyFile(templatePath, writePath);
|
|
@@ -2397,7 +2518,7 @@ class Executor {
|
|
|
2397
2518
|
if ((await stat2(templatePath)).isFile()) {
|
|
2398
2519
|
const fileContent = await this.#applyTemplateFile({
|
|
2399
2520
|
templatePath,
|
|
2400
|
-
targetPath:
|
|
2521
|
+
targetPath: path9.join(basePath, path9.basename(templatePath)),
|
|
2401
2522
|
scanInfo,
|
|
2402
2523
|
overwrite
|
|
2403
2524
|
}, dict, options);
|
|
@@ -2405,19 +2526,19 @@ class Executor {
|
|
|
2405
2526
|
} else {
|
|
2406
2527
|
const subdirs = await readDirEntries(templatePath);
|
|
2407
2528
|
const fileContents = (await Promise.all(subdirs.map(async (subdir) => {
|
|
2408
|
-
const subpath =
|
|
2529
|
+
const subpath = path9.join(templatePath, subdir);
|
|
2409
2530
|
if ((await stat2(subpath)).isFile()) {
|
|
2410
2531
|
const fileContent = await this.#applyTemplateFile({
|
|
2411
2532
|
templatePath: subpath,
|
|
2412
|
-
targetPath:
|
|
2533
|
+
targetPath: path9.join(basePath, subdir),
|
|
2413
2534
|
scanInfo,
|
|
2414
2535
|
overwrite
|
|
2415
2536
|
}, dict, options);
|
|
2416
2537
|
return fileContent ? [fileContent] : [];
|
|
2417
2538
|
} else
|
|
2418
2539
|
return await this._applyTemplate({
|
|
2419
|
-
basePath:
|
|
2420
|
-
template:
|
|
2540
|
+
basePath: path9.join(basePath, subdir),
|
|
2541
|
+
template: path9.join(template, subdir),
|
|
2421
2542
|
scanInfo,
|
|
2422
2543
|
dict,
|
|
2423
2544
|
overwrite,
|
|
@@ -2429,8 +2550,8 @@ class Executor {
|
|
|
2429
2550
|
}
|
|
2430
2551
|
async#resolveTemplateRoot() {
|
|
2431
2552
|
const candidates = [
|
|
2432
|
-
|
|
2433
|
-
|
|
2553
|
+
path9.resolve(getDirname2(import.meta.url), "templates"),
|
|
2554
|
+
path9.resolve(getDirname2(import.meta.url), "../cli/templates")
|
|
2434
2555
|
];
|
|
2435
2556
|
for (const candidate of candidates) {
|
|
2436
2557
|
if (await FileSys2.dirExists(candidate))
|
|
@@ -2498,11 +2619,11 @@ class Executor {
|
|
|
2498
2619
|
async#resolveTypecheckWorkerEntry() {
|
|
2499
2620
|
const dirname = getDirname2(import.meta.url);
|
|
2500
2621
|
const candidates = [
|
|
2501
|
-
|
|
2502
|
-
|
|
2503
|
-
|
|
2504
|
-
|
|
2505
|
-
|
|
2622
|
+
path9.join(process.cwd(), "pkgs/@akanjs/devkit/typecheck/typecheck.proc.ts"),
|
|
2623
|
+
path9.join(process.cwd(), "node_modules/@akanjs/devkit/typecheck/typecheck.proc.ts"),
|
|
2624
|
+
path9.join(dirname, "typecheck/typecheck.proc.ts"),
|
|
2625
|
+
path9.join(dirname, "typecheck.proc.js"),
|
|
2626
|
+
path9.join(dirname, "typecheck.proc.ts")
|
|
2506
2627
|
];
|
|
2507
2628
|
for (const candidate of candidates)
|
|
2508
2629
|
if (await Bun.file(candidate).exists())
|
|
@@ -2622,7 +2743,7 @@ class WorkspaceExecutor extends Executor {
|
|
|
2622
2743
|
await Promise.all(dirs.map(async (dir) => {
|
|
2623
2744
|
if (dir.includes("_") || AVOID_DIRS.includes(dir))
|
|
2624
2745
|
return;
|
|
2625
|
-
const dirPath =
|
|
2746
|
+
const dirPath = path9.join(dirname, dir);
|
|
2626
2747
|
if ((await stat2(dirPath)).isDirectory()) {
|
|
2627
2748
|
results.push(`${prefix}${dir}`);
|
|
2628
2749
|
if (maxDepth > 0)
|
|
@@ -2653,15 +2774,15 @@ class WorkspaceExecutor extends Executor {
|
|
|
2653
2774
|
async#getDirHasFile(basePath, targetFilename) {
|
|
2654
2775
|
if (!await FileSys2.dirExists(basePath))
|
|
2655
2776
|
return [];
|
|
2656
|
-
const AVOID_DIRS = ["node_modules", "dist", "public", "webkit"];
|
|
2777
|
+
const AVOID_DIRS = ["node_modules", "dist", "public", "webkit", "local"];
|
|
2657
2778
|
const getDirs = async (dirname, maxDepth = 3, results = [], prefix = "") => {
|
|
2658
2779
|
const dirs = await this.readdir(dirname);
|
|
2659
2780
|
await Promise.all(dirs.map(async (dir) => {
|
|
2660
2781
|
if (AVOID_DIRS.includes(dir))
|
|
2661
2782
|
return;
|
|
2662
|
-
const dirPath =
|
|
2783
|
+
const dirPath = path9.join(dirname, dir);
|
|
2663
2784
|
if (await FileSys2.dirExists(dirPath)) {
|
|
2664
|
-
const hasTargetFile = await FileSys2.fileExists(
|
|
2785
|
+
const hasTargetFile = await FileSys2.fileExists(path9.join(dirPath, targetFilename));
|
|
2665
2786
|
if (hasTargetFile)
|
|
2666
2787
|
results.push(`${prefix}${dir}`);
|
|
2667
2788
|
if (maxDepth > 0)
|
|
@@ -2721,7 +2842,7 @@ class SysExecutor extends Executor {
|
|
|
2721
2842
|
return [];
|
|
2722
2843
|
const violations = [];
|
|
2723
2844
|
for (const entry of await this.getAllFiles("**/*", { cwd: this.getPath("page") })) {
|
|
2724
|
-
const relativePath = entry.split(
|
|
2845
|
+
const relativePath = entry.split(path9.sep).join("/");
|
|
2725
2846
|
const reason = getPageSourceFileViolation(relativePath);
|
|
2726
2847
|
if (reason)
|
|
2727
2848
|
violations.push({ relativePath: `page/${relativePath}`, reason });
|
|
@@ -2818,7 +2939,7 @@ class SysExecutor extends Executor {
|
|
|
2818
2939
|
await this.setPackageJson(libPkgJsonWithDeps);
|
|
2819
2940
|
}
|
|
2820
2941
|
async getLocalFile(targetPath) {
|
|
2821
|
-
const filePath =
|
|
2942
|
+
const filePath = path9.isAbsolute(targetPath) ? targetPath : `${this.type}s/${this.name}/${targetPath}`;
|
|
2822
2943
|
const content = await this.workspace.readFile(filePath);
|
|
2823
2944
|
return { filePath, content };
|
|
2824
2945
|
}
|
|
@@ -2906,6 +3027,18 @@ class AppExecutor extends SysExecutor {
|
|
|
2906
3027
|
static from(executor, name) {
|
|
2907
3028
|
return new AppExecutor({ workspace: executor instanceof WorkspaceExecutor ? executor : executor.workspace, name });
|
|
2908
3029
|
}
|
|
3030
|
+
static #keptOnStart = [path9.join(".akan", "mobile"), path9.join(".akan", "cache", "bin")];
|
|
3031
|
+
async#removeDevOutput(dir = ".akan") {
|
|
3032
|
+
const entries = await readDirEntries(this.getPath(dir)).catch(() => []);
|
|
3033
|
+
await Promise.all(entries.map(async (name) => {
|
|
3034
|
+
const entry = path9.join(dir, name);
|
|
3035
|
+
if (AppExecutor.#keptOnStart.includes(entry))
|
|
3036
|
+
return;
|
|
3037
|
+
if (AppExecutor.#keptOnStart.some((kept) => kept.startsWith(`${entry}${path9.sep}`)))
|
|
3038
|
+
return await this.#removeDevOutput(entry);
|
|
3039
|
+
await this.removeDir(entry);
|
|
3040
|
+
}));
|
|
3041
|
+
}
|
|
2909
3042
|
getEnv() {
|
|
2910
3043
|
return WorkspaceExecutor.getBaseDevEnv().env;
|
|
2911
3044
|
}
|
|
@@ -2959,7 +3092,7 @@ class AppExecutor extends SysExecutor {
|
|
|
2959
3092
|
...akanConfig.web.ssr ? [this.cp("public", `${this.dist.cwdPath}/public`, { dereference: true })] : []
|
|
2960
3093
|
]);
|
|
2961
3094
|
} else {
|
|
2962
|
-
await this
|
|
3095
|
+
await this.#removeDevOutput();
|
|
2963
3096
|
if (!akanConfig.web.ssr || !akanConfig.web.csr)
|
|
2964
3097
|
this.logger.verbose(`akan.config.ts disables web.${!akanConfig.web.ssr ? "ssr" : "csr"}; \`akan start\` still serves it, \`akan build\` will not`);
|
|
2965
3098
|
}
|
|
@@ -3025,13 +3158,13 @@ class AppExecutor extends SysExecutor {
|
|
|
3025
3158
|
absolute: false,
|
|
3026
3159
|
onlyFiles: true
|
|
3027
3160
|
})) {
|
|
3028
|
-
const segments = rel.split(
|
|
3161
|
+
const segments = rel.split(path9.sep);
|
|
3029
3162
|
if (segments.some((s) => s === "node_modules"))
|
|
3030
3163
|
continue;
|
|
3031
3164
|
const posix = `${root.keyPrefix}${segments.join("/")}`;
|
|
3032
3165
|
if (!root.keyPrefix && libKeyPrefixes.some((prefix) => posix.startsWith(prefix)))
|
|
3033
3166
|
continue;
|
|
3034
|
-
const absPath =
|
|
3167
|
+
const absPath = path9.join(root.dir, ...segments);
|
|
3035
3168
|
validatePageSourceFile(posix, { filePath: absPath });
|
|
3036
3169
|
if (!isRouteSourceFile(posix))
|
|
3037
3170
|
continue;
|
|
@@ -3172,7 +3305,7 @@ class AppExecutor extends SysExecutor {
|
|
|
3172
3305
|
static async#linkLibAsset(targetPath, linkPath) {
|
|
3173
3306
|
const isWindows = process.platform === "win32";
|
|
3174
3307
|
try {
|
|
3175
|
-
const target = isWindows ? targetPath :
|
|
3308
|
+
const target = isWindows ? targetPath : path9.relative(path9.dirname(linkPath), targetPath);
|
|
3176
3309
|
await symlink(target, linkPath, isWindows ? "junction" : "dir");
|
|
3177
3310
|
} catch (error) {
|
|
3178
3311
|
if (!isWindows)
|
|
@@ -3215,7 +3348,7 @@ class AppExecutor extends SysExecutor {
|
|
|
3215
3348
|
await this.writeFile(rel, content, opts);
|
|
3216
3349
|
},
|
|
3217
3350
|
readEnvClient: async () => {
|
|
3218
|
-
const envClientPath =
|
|
3351
|
+
const envClientPath = path9.join(this.cwdPath, "env", "env.client.ts");
|
|
3219
3352
|
if (!await FileSys2.fileExists(envClientPath))
|
|
3220
3353
|
return null;
|
|
3221
3354
|
try {
|
|
@@ -3309,7 +3442,7 @@ class PkgExecutor extends Executor {
|
|
|
3309
3442
|
return overrideVersion;
|
|
3310
3443
|
try {
|
|
3311
3444
|
const packageJsonPath = `pkgs/${dep}/package.json`;
|
|
3312
|
-
if (!await Bun.file(
|
|
3445
|
+
if (!await Bun.file(path9.join(this.workspace.workspaceRoot, packageJsonPath)).exists())
|
|
3313
3446
|
return;
|
|
3314
3447
|
const packageJson = await this.workspace.readJson(packageJsonPath);
|
|
3315
3448
|
if (packageJson.name === dep)
|
|
@@ -3402,4 +3535,4 @@ class ModuleExecutor extends Executor {
|
|
|
3402
3535
|
}
|
|
3403
3536
|
}
|
|
3404
3537
|
|
|
3405
|
-
export { AGENT_BLOCK_START, AGENT_BLOCK_END, stampBlockVersion, extractBlockVersion, readDevkitVersion, upsertAgentBlock, extractAgentBlock, renderRecipeEntries, collectScopeRecipeSources, renderScopeAgentBlock, CLAUDE_COMMENT_RULE, AsyncDefaultExportDetector, resolveSsrPageEntriesForApp, CodegenLock, Linter, rootAllowedFiles, rootAllowedDirs, isAllowedLibFacetRootFile, rootEntryHintOf, isScannedRootEntry, AppInfo, Spinner, Executor, WorkspaceExecutor, SysExecutor, AppExecutor, LibExecutor, PkgExecutor, ModuleExecutor };
|
|
3538
|
+
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 };
|