@akanjs/cli 2.3.13 → 2.4.0-rc.1
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/guidelines/componentRule/componentRule.instruction.md +8 -0
- package/guidelines/cssRule/cssRule.instruction.md +18 -0
- package/guidelines/framework/framework.instruction.md +6 -0
- package/incrementalBuilder.proc.js +926 -329
- package/index.js +961 -362
- package/package.json +2 -2
- package/templates/app/page/styles.css.template +22 -0
- package/templates/facetIndex/index.ts +3 -9
- package/templates/workspaceRoot/biome.json.template +1 -0
package/index.js
CHANGED
|
@@ -4285,9 +4285,10 @@ class IncrementalBuilderHost {
|
|
|
4285
4285
|
// pkgs/@akanjs/devkit/akanApp/akanApp.host.ts
|
|
4286
4286
|
var backendMsgTypeSet = new Set(["build-route"]);
|
|
4287
4287
|
var BACKEND_RESTART_DEBOUNCE_MS = 120;
|
|
4288
|
-
var BACKEND_GRACEFUL_TIMEOUT_MS =
|
|
4288
|
+
var BACKEND_GRACEFUL_TIMEOUT_MS = 8000;
|
|
4289
4289
|
var BACKEND_RECOVERY_BASE_DELAY_MS = 1000;
|
|
4290
4290
|
var BACKEND_RECOVERY_MAX_DELAY_MS = 30000;
|
|
4291
|
+
var BACKEND_RECOVERY_MAX_ATTEMPTS = 5;
|
|
4291
4292
|
var BACKEND_STDERR_TAIL_LIMIT = 40;
|
|
4292
4293
|
var BUILDER_READY_TIMEOUT_MS = 150000;
|
|
4293
4294
|
var BUILDER_START_MAX_ATTEMPTS = 3;
|
|
@@ -4312,6 +4313,8 @@ var shouldRestartBackendByDevPlan = (message) => {
|
|
|
4312
4313
|
return message.devPlan.actions.includes("restart-backend");
|
|
4313
4314
|
};
|
|
4314
4315
|
var shouldRestartBuilderByDevPlan = (message) => message.devPlan?.actions.includes("restart-builder") ?? false;
|
|
4316
|
+
var shouldAbandonBackendRecovery = (attempts, maxAttempts = BACKEND_RECOVERY_MAX_ATTEMPTS) => attempts >= maxAttempts;
|
|
4317
|
+
var normalizeBackendReportedGeneration = (generation) => generation >= 0 ? generation : undefined;
|
|
4315
4318
|
var shouldRestartDevHostByDevPlan = (message) => message.devPlan?.actions.includes("restart-dev-host") ?? message.kinds.includes("config");
|
|
4316
4319
|
var RESTART_ROLE_ORDER = ["server", "shared", "barrel", "config"];
|
|
4317
4320
|
var generationValue = (generation) => generation ?? -1;
|
|
@@ -4560,6 +4563,16 @@ class AkanAppHost {
|
|
|
4560
4563
|
this.#replayBuilderState();
|
|
4561
4564
|
return;
|
|
4562
4565
|
}
|
|
4566
|
+
if (msg.type === "build-status") {
|
|
4567
|
+
const status = this.#recordBackendBuildStatus({
|
|
4568
|
+
generation: normalizeBackendReportedGeneration(msg.data.generation),
|
|
4569
|
+
ok: msg.data.ok,
|
|
4570
|
+
files: msg.data.files,
|
|
4571
|
+
message: msg.data.message
|
|
4572
|
+
});
|
|
4573
|
+
this.#sendOrQueueBuildStatus(status);
|
|
4574
|
+
return;
|
|
4575
|
+
}
|
|
4563
4576
|
if (backendMsgTypeSet.has(msg.type))
|
|
4564
4577
|
this.#sendToBuilder(msg);
|
|
4565
4578
|
},
|
|
@@ -4721,6 +4734,19 @@ class AkanAppHost {
|
|
|
4721
4734
|
#scheduleBackendRecovery(reason) {
|
|
4722
4735
|
if (this.#backendRecoveryTimer || this.#backend)
|
|
4723
4736
|
return;
|
|
4737
|
+
if (shouldAbandonBackendRecovery(this.#backendRecoveryAttempts)) {
|
|
4738
|
+
const message = `Backend exited ${this.#backendRecoveryAttempts} times in a row (${reason}); waiting for a server-side edit to retry.`;
|
|
4739
|
+
this.#setBackendLifecycleState("stopped", `gave up after ${this.#backendRecoveryAttempts} recovery attempts`);
|
|
4740
|
+
this.logger.error(`[backend-recovery] ${message}`);
|
|
4741
|
+
if (this.#backendStderrTail.length > 0) {
|
|
4742
|
+
this.logger.error(`[backend-recovery] recent backend stderr:
|
|
4743
|
+
${this.#backendStderrTail.join(`
|
|
4744
|
+
`)}`);
|
|
4745
|
+
}
|
|
4746
|
+
const abandonedStatus = this.#recordBackendBuildStatus({ ok: false, files: [], message });
|
|
4747
|
+
this.#sendOrQueueBuildStatus(abandonedStatus);
|
|
4748
|
+
return;
|
|
4749
|
+
}
|
|
4724
4750
|
this.#setBackendLifecycleState("recovering", reason);
|
|
4725
4751
|
const attempt = this.#backendRecoveryAttempts;
|
|
4726
4752
|
const delay = Math.min(BACKEND_RECOVERY_BASE_DELAY_MS * 2 ** attempt, BACKEND_RECOVERY_MAX_DELAY_MS);
|
|
@@ -4769,6 +4795,7 @@ ${this.#backendStderrTail.join(`
|
|
|
4769
4795
|
this.#sendToBackend(message);
|
|
4770
4796
|
}
|
|
4771
4797
|
async#handleInvalidate(message) {
|
|
4798
|
+
this.#logDevPlan(message);
|
|
4772
4799
|
if (shouldRestartBuilderByDevPlan(message)) {
|
|
4773
4800
|
try {
|
|
4774
4801
|
await this.#restartDevChildren(message);
|
|
@@ -4880,12 +4907,16 @@ ${this.#backendStderrTail.join(`
|
|
|
4880
4907
|
this.#sendToBackend({ type: "build-status", data: status });
|
|
4881
4908
|
}
|
|
4882
4909
|
}
|
|
4910
|
+
#logDevPlan(message) {
|
|
4911
|
+
if (!message.devPlan)
|
|
4912
|
+
return;
|
|
4913
|
+
const { generation, roles, actions, reasonByFile } = message.devPlan;
|
|
4914
|
+
this.logger.verbose(`[dev-plan] generation=${generation} roles=${roles.join(",") || "(none)"} actions=${actions.join(",") || "(none)"} reasons=${Object.keys(reasonByFile).length}`);
|
|
4915
|
+
}
|
|
4883
4916
|
async#shouldRestartBackend(message) {
|
|
4884
4917
|
if (message.kinds.length === 1 && message.kinds[0] === "css")
|
|
4885
4918
|
return false;
|
|
4886
4919
|
if (message.devPlan) {
|
|
4887
|
-
const { generation, roles, actions, reasonByFile } = message.devPlan;
|
|
4888
|
-
this.logger.verbose(`[dev-plan] generation=${generation} roles=${roles.join(",") || "(none)"} actions=${actions.join(",") || "(none)"} reasons=${Object.keys(reasonByFile).length}`);
|
|
4889
4920
|
const shouldRestart = shouldRestartBackendByDevPlan(message) ?? false;
|
|
4890
4921
|
if (shouldRestart && message.kinds.includes("code"))
|
|
4891
4922
|
await this.#backendGraph.refresh();
|
|
@@ -8835,7 +8866,7 @@ Caused by: ${ApplicationBuildReporter.formatError(error.cause)}` : "";
|
|
|
8835
8866
|
}
|
|
8836
8867
|
// pkgs/@akanjs/devkit/applicationBuildRunner.ts
|
|
8837
8868
|
import { mkdir as mkdir8, rm as rm4 } from "fs/promises";
|
|
8838
|
-
import
|
|
8869
|
+
import path38 from "path";
|
|
8839
8870
|
|
|
8840
8871
|
// pkgs/@akanjs/devkit/frontendBuild/allRoutesBuilder.ts
|
|
8841
8872
|
import path22 from "path";
|
|
@@ -10618,14 +10649,538 @@ class AllRoutesBuilder {
|
|
|
10618
10649
|
this.#routeIds.push(routeId);
|
|
10619
10650
|
}
|
|
10620
10651
|
}
|
|
10652
|
+
// pkgs/@akanjs/devkit/frontendBuild/autoImportSync.ts
|
|
10653
|
+
import { readdir as readdir2, readFile, stat as stat3, writeFile } from "fs/promises";
|
|
10654
|
+
import path23 from "path";
|
|
10655
|
+
import ts8 from "typescript";
|
|
10656
|
+
var TEST_FILE_RE = /\.(test|spec)\.(ts|tsx)$/;
|
|
10657
|
+
var AKAN_BASE = {
|
|
10658
|
+
names: ["Int", "Float", "ID", "Any", "Upload", "enumOf", "dayjs"],
|
|
10659
|
+
specifier: "akanjs/base",
|
|
10660
|
+
kind: "named"
|
|
10661
|
+
};
|
|
10662
|
+
var AKAN_BASE_TYPES = { names: ["Dayjs"], specifier: "akanjs/base", kind: "named", typeOnly: true };
|
|
10663
|
+
var CNST_NS = { names: ["cnst"], specifier: "../cnst", kind: "namespace" };
|
|
10664
|
+
var DB_NS = { names: ["db"], specifier: "../db", kind: "namespace" };
|
|
10665
|
+
var SRV_NS = { names: ["srv"], specifier: "../srv", kind: "namespace" };
|
|
10666
|
+
var ERR_DICT = { names: ["Err"], specifier: "../dict", kind: "named" };
|
|
10667
|
+
var RULES = {
|
|
10668
|
+
constant: [AKAN_BASE, AKAN_BASE_TYPES, { names: ["via"], specifier: "akanjs/constant", kind: "named" }],
|
|
10669
|
+
document: [
|
|
10670
|
+
AKAN_BASE,
|
|
10671
|
+
AKAN_BASE_TYPES,
|
|
10672
|
+
CNST_NS,
|
|
10673
|
+
DB_NS,
|
|
10674
|
+
ERR_DICT,
|
|
10675
|
+
{
|
|
10676
|
+
names: ["by", "from", "into", "SchemaOf", "DataInputOf", "DocumentUpdateHelper", "documentQueryHelper", "Mdl"],
|
|
10677
|
+
specifier: "akanjs/document",
|
|
10678
|
+
kind: "named"
|
|
10679
|
+
}
|
|
10680
|
+
],
|
|
10681
|
+
service: [
|
|
10682
|
+
AKAN_BASE,
|
|
10683
|
+
AKAN_BASE_TYPES,
|
|
10684
|
+
DB_NS,
|
|
10685
|
+
SRV_NS,
|
|
10686
|
+
CNST_NS,
|
|
10687
|
+
ERR_DICT,
|
|
10688
|
+
{ names: ["serve"], specifier: "akanjs/service", kind: "named" },
|
|
10689
|
+
{
|
|
10690
|
+
names: ["DataInputOf", "ListQueryOption", "DatabaseRegistry", "getFilterInfoByKey"],
|
|
10691
|
+
specifier: "akanjs/document",
|
|
10692
|
+
kind: "named"
|
|
10693
|
+
}
|
|
10694
|
+
],
|
|
10695
|
+
signal: [
|
|
10696
|
+
AKAN_BASE,
|
|
10697
|
+
AKAN_BASE_TYPES,
|
|
10698
|
+
SRV_NS,
|
|
10699
|
+
CNST_NS,
|
|
10700
|
+
ERR_DICT,
|
|
10701
|
+
{
|
|
10702
|
+
names: ["endpoint", "internal", "slice", "Public", "Req", "Ws", "None", "Res"],
|
|
10703
|
+
specifier: "akanjs/signal",
|
|
10704
|
+
kind: "named"
|
|
10705
|
+
}
|
|
10706
|
+
],
|
|
10707
|
+
dictionary: [
|
|
10708
|
+
{
|
|
10709
|
+
names: ["modelDictionary", "scalarDictionary", "serviceDictionary"],
|
|
10710
|
+
specifier: "akanjs/dictionary",
|
|
10711
|
+
kind: "named"
|
|
10712
|
+
}
|
|
10713
|
+
],
|
|
10714
|
+
srvkit: [
|
|
10715
|
+
AKAN_BASE,
|
|
10716
|
+
AKAN_BASE_TYPES,
|
|
10717
|
+
{ names: ["Logger", "HttpClient", "sleep"], specifier: "akanjs/common", kind: "named" },
|
|
10718
|
+
{ names: ["adapt"], specifier: "akanjs/service", kind: "named" },
|
|
10719
|
+
{ names: ["SignalContext", "Guard", "InternalArg", "Middleware"], specifier: "akanjs/signal", kind: "named" }
|
|
10720
|
+
],
|
|
10721
|
+
common: [AKAN_BASE, AKAN_BASE_TYPES],
|
|
10722
|
+
store: [
|
|
10723
|
+
CNST_NS,
|
|
10724
|
+
{ names: ["store"], specifier: "akanjs/store", kind: "named" },
|
|
10725
|
+
{ names: ["fetch", "usePage", "sig"], specifier: "../useClient", kind: "named" },
|
|
10726
|
+
{ names: ["st"], specifier: "../st", kind: "named" },
|
|
10727
|
+
{ names: ["RootStore"], specifier: "../st", kind: "named", typeOnly: true }
|
|
10728
|
+
],
|
|
10729
|
+
client: [
|
|
10730
|
+
{
|
|
10731
|
+
names: ["cnst", "fetch", "st", "usePage"],
|
|
10732
|
+
specifier: (ctx) => `@${ctx.scope}/${ctx.project}/client`,
|
|
10733
|
+
kind: "named"
|
|
10734
|
+
}
|
|
10735
|
+
]
|
|
10736
|
+
};
|
|
10737
|
+
var PASCAL_CASE_RE = /^[A-Z][A-Za-z0-9]*$/;
|
|
10738
|
+
var DOMAIN_ROLE_KINDS = {
|
|
10739
|
+
constant: ["constant"],
|
|
10740
|
+
dictionary: ["constant", "document", "signal"],
|
|
10741
|
+
common: ["constant"]
|
|
10742
|
+
};
|
|
10743
|
+
var LIB_BARRELS = {
|
|
10744
|
+
Err: { barrel: "dict", kind: "named" },
|
|
10745
|
+
db: { barrel: "db", kind: "namespace" },
|
|
10746
|
+
cnst: { barrel: "cnst", kind: "namespace" },
|
|
10747
|
+
srv: { barrel: "srv", kind: "namespace" }
|
|
10748
|
+
};
|
|
10749
|
+
var DOMAIN_DENYLIST = new Set([
|
|
10750
|
+
"Map",
|
|
10751
|
+
"Set",
|
|
10752
|
+
"WeakMap",
|
|
10753
|
+
"WeakSet",
|
|
10754
|
+
"Date",
|
|
10755
|
+
"Promise",
|
|
10756
|
+
"Array",
|
|
10757
|
+
"Object",
|
|
10758
|
+
"Error",
|
|
10759
|
+
"TypeError",
|
|
10760
|
+
"RangeError",
|
|
10761
|
+
"RegExp",
|
|
10762
|
+
"Symbol",
|
|
10763
|
+
"Proxy",
|
|
10764
|
+
"Reflect",
|
|
10765
|
+
"JSON",
|
|
10766
|
+
"Math",
|
|
10767
|
+
"Number",
|
|
10768
|
+
"BigInt",
|
|
10769
|
+
"Function",
|
|
10770
|
+
"Boolean",
|
|
10771
|
+
"String",
|
|
10772
|
+
"Record",
|
|
10773
|
+
"Partial",
|
|
10774
|
+
"Required",
|
|
10775
|
+
"Readonly",
|
|
10776
|
+
"Pick",
|
|
10777
|
+
"Omit",
|
|
10778
|
+
"Exclude",
|
|
10779
|
+
"Extract",
|
|
10780
|
+
"NonNullable",
|
|
10781
|
+
"ReturnType",
|
|
10782
|
+
"Parameters",
|
|
10783
|
+
"Awaited",
|
|
10784
|
+
"InstanceType"
|
|
10785
|
+
]);
|
|
10786
|
+
|
|
10787
|
+
class AutoImportSync {
|
|
10788
|
+
#workspaceRoot;
|
|
10789
|
+
#domainCache = new Map;
|
|
10790
|
+
constructor({ workspaceRoot }) {
|
|
10791
|
+
this.#workspaceRoot = path23.resolve(workspaceRoot);
|
|
10792
|
+
}
|
|
10793
|
+
async syncForBatch(files) {
|
|
10794
|
+
const changedFiles = [];
|
|
10795
|
+
const errors = [];
|
|
10796
|
+
const seen = new Set;
|
|
10797
|
+
for (const file of files) {
|
|
10798
|
+
const pkgRoot = this.#domainPkgRootOf(file);
|
|
10799
|
+
if (pkgRoot)
|
|
10800
|
+
this.#domainCache.delete(pkgRoot);
|
|
10801
|
+
}
|
|
10802
|
+
for (const file of files) {
|
|
10803
|
+
const abs = path23.resolve(file);
|
|
10804
|
+
if (seen.has(abs))
|
|
10805
|
+
continue;
|
|
10806
|
+
seen.add(abs);
|
|
10807
|
+
const ctx = this.#contextFor(abs);
|
|
10808
|
+
if (!ctx)
|
|
10809
|
+
continue;
|
|
10810
|
+
try {
|
|
10811
|
+
const changed = await this.#syncFile(abs, ctx);
|
|
10812
|
+
if (changed)
|
|
10813
|
+
changedFiles.push(abs);
|
|
10814
|
+
} catch (err) {
|
|
10815
|
+
errors.push(`[auto-import] sync failed for ${file}: ${formatError(err)}`);
|
|
10816
|
+
}
|
|
10817
|
+
}
|
|
10818
|
+
return { changedFiles, errors };
|
|
10819
|
+
}
|
|
10820
|
+
#contextFor(abs) {
|
|
10821
|
+
const rel = path23.relative(this.#workspaceRoot, abs);
|
|
10822
|
+
if (rel.startsWith("..") || path23.isAbsolute(rel))
|
|
10823
|
+
return null;
|
|
10824
|
+
const base = path23.basename(abs);
|
|
10825
|
+
if (TEST_FILE_RE.test(base) || base === "index.ts" || base === "index.tsx" || base.endsWith(".d.ts"))
|
|
10826
|
+
return null;
|
|
10827
|
+
const parts = rel.split(path23.sep).filter(Boolean);
|
|
10828
|
+
const [scope, project, facet] = parts;
|
|
10829
|
+
if (scope !== "apps" && scope !== "libs" || !project || !facet)
|
|
10830
|
+
return null;
|
|
10831
|
+
const role = roleFor(facet, base);
|
|
10832
|
+
if (!role)
|
|
10833
|
+
return null;
|
|
10834
|
+
return { role, scope, project };
|
|
10835
|
+
}
|
|
10836
|
+
async#syncFile(abs, ctx) {
|
|
10837
|
+
const stats = await stat3(abs).catch(() => null);
|
|
10838
|
+
if (!stats?.isFile())
|
|
10839
|
+
return false;
|
|
10840
|
+
const source2 = await readFile(abs, "utf8");
|
|
10841
|
+
const resolveExtra = await this.#extraResolverFor(abs, ctx);
|
|
10842
|
+
const next = transformSource(source2, abs, ctx, resolveExtra);
|
|
10843
|
+
if (next === null || next === source2)
|
|
10844
|
+
return false;
|
|
10845
|
+
await writeFile(abs, next);
|
|
10846
|
+
return true;
|
|
10847
|
+
}
|
|
10848
|
+
async#extraResolverFor(abs, ctx) {
|
|
10849
|
+
const resolvers = [];
|
|
10850
|
+
if (ctx.role === "srvkit" || ctx.role === "common")
|
|
10851
|
+
resolvers.push(await this.#libBarrelResolver(abs, ctx));
|
|
10852
|
+
const kinds = DOMAIN_ROLE_KINDS[ctx.role];
|
|
10853
|
+
if (kinds)
|
|
10854
|
+
resolvers.push(await this.#domainResolver(abs, ctx, kinds));
|
|
10855
|
+
if (resolvers.length === 0)
|
|
10856
|
+
return;
|
|
10857
|
+
return (symbol) => {
|
|
10858
|
+
for (const resolve of resolvers) {
|
|
10859
|
+
const target = resolve(symbol);
|
|
10860
|
+
if (target)
|
|
10861
|
+
return target;
|
|
10862
|
+
}
|
|
10863
|
+
return null;
|
|
10864
|
+
};
|
|
10865
|
+
}
|
|
10866
|
+
async#domainResolver(abs, ctx, kinds) {
|
|
10867
|
+
const index = await this.#domainIndex(path23.join(this.#workspaceRoot, ctx.scope, ctx.project));
|
|
10868
|
+
const fileDir = path23.dirname(abs);
|
|
10869
|
+
return (symbol) => {
|
|
10870
|
+
if (!PASCAL_CASE_RE.test(symbol) || DOMAIN_DENYLIST.has(symbol))
|
|
10871
|
+
return null;
|
|
10872
|
+
const entries = (index.get(symbol) ?? []).filter((entry) => kinds.includes(entry.kind));
|
|
10873
|
+
if (entries.length !== 1)
|
|
10874
|
+
return null;
|
|
10875
|
+
return { specifier: relativeSpecifier(fileDir, entries[0].file), kind: "named" };
|
|
10876
|
+
};
|
|
10877
|
+
}
|
|
10878
|
+
async#libBarrelResolver(abs, ctx) {
|
|
10879
|
+
const fileDir = path23.dirname(abs);
|
|
10880
|
+
const libDir = path23.join(this.#workspaceRoot, ctx.scope, ctx.project, "lib");
|
|
10881
|
+
const available = new Map;
|
|
10882
|
+
for (const [symbol, { barrel, kind }] of Object.entries(LIB_BARRELS)) {
|
|
10883
|
+
if (await fileExists2(path23.join(libDir, `${barrel}.ts`)))
|
|
10884
|
+
available.set(symbol, { specifier: relativeSpecifier(fileDir, path23.join(libDir, barrel)), kind });
|
|
10885
|
+
}
|
|
10886
|
+
return (symbol) => available.get(symbol) ?? null;
|
|
10887
|
+
}
|
|
10888
|
+
async#domainIndex(pkgRoot) {
|
|
10889
|
+
const cached = this.#domainCache.get(pkgRoot);
|
|
10890
|
+
if (cached)
|
|
10891
|
+
return cached;
|
|
10892
|
+
const index = await buildDomainIndex(path23.join(pkgRoot, "lib"));
|
|
10893
|
+
this.#domainCache.set(pkgRoot, index);
|
|
10894
|
+
return index;
|
|
10895
|
+
}
|
|
10896
|
+
#domainPkgRootOf(file) {
|
|
10897
|
+
const rel = path23.relative(this.#workspaceRoot, path23.resolve(file));
|
|
10898
|
+
if (rel.startsWith("..") || path23.isAbsolute(rel))
|
|
10899
|
+
return null;
|
|
10900
|
+
const [scope, project, facet] = rel.split(path23.sep).filter(Boolean);
|
|
10901
|
+
if (scope !== "apps" && scope !== "libs" || !project || facet !== "lib")
|
|
10902
|
+
return null;
|
|
10903
|
+
if (!domainKindOf(path23.basename(file)))
|
|
10904
|
+
return null;
|
|
10905
|
+
return path23.join(this.#workspaceRoot, scope, project);
|
|
10906
|
+
}
|
|
10907
|
+
}
|
|
10908
|
+
var roleFor = (facet, base) => {
|
|
10909
|
+
if (facet === "lib") {
|
|
10910
|
+
if (base.endsWith(".constant.ts"))
|
|
10911
|
+
return "constant";
|
|
10912
|
+
if (base.endsWith(".document.ts"))
|
|
10913
|
+
return "document";
|
|
10914
|
+
if (base.endsWith(".service.ts"))
|
|
10915
|
+
return "service";
|
|
10916
|
+
if (base.endsWith(".signal.ts"))
|
|
10917
|
+
return "signal";
|
|
10918
|
+
if (base.endsWith(".dictionary.ts"))
|
|
10919
|
+
return "dictionary";
|
|
10920
|
+
if (base.endsWith(".store.ts"))
|
|
10921
|
+
return "store";
|
|
10922
|
+
if (base.endsWith(".tsx"))
|
|
10923
|
+
return "client";
|
|
10924
|
+
return null;
|
|
10925
|
+
}
|
|
10926
|
+
if (facet === "ui" || facet === "page")
|
|
10927
|
+
return base.endsWith(".tsx") ? "client" : null;
|
|
10928
|
+
if (facet === "webkit")
|
|
10929
|
+
return base.endsWith(".ts") || base.endsWith(".tsx") ? "client" : null;
|
|
10930
|
+
if (facet === "srvkit")
|
|
10931
|
+
return base.endsWith(".ts") ? "srvkit" : null;
|
|
10932
|
+
if (facet === "common")
|
|
10933
|
+
return base.endsWith(".ts") || base.endsWith(".tsx") ? "common" : null;
|
|
10934
|
+
return null;
|
|
10935
|
+
};
|
|
10936
|
+
var targetFor = (symbol, ctx) => {
|
|
10937
|
+
for (const rule of RULES[ctx.role]) {
|
|
10938
|
+
if (!rule.names.includes(symbol))
|
|
10939
|
+
continue;
|
|
10940
|
+
const specifier = typeof rule.specifier === "function" ? rule.specifier(ctx) : rule.specifier;
|
|
10941
|
+
return { specifier, kind: rule.kind, typeOnly: rule.typeOnly };
|
|
10942
|
+
}
|
|
10943
|
+
return null;
|
|
10944
|
+
};
|
|
10945
|
+
var transformSource = (source2, fileName, ctx, resolveExtra) => {
|
|
10946
|
+
const sf = ts8.createSourceFile(fileName, source2, ts8.ScriptTarget.Latest, true, scriptKindFor(fileName));
|
|
10947
|
+
const bound = collectBoundNames(sf);
|
|
10948
|
+
const used = collectUsedReferences(sf);
|
|
10949
|
+
const namedBySpecifier = new Map;
|
|
10950
|
+
const namespaceImports = [];
|
|
10951
|
+
for (const name of used) {
|
|
10952
|
+
if (bound.has(name))
|
|
10953
|
+
continue;
|
|
10954
|
+
const target = targetFor(name, ctx) ?? resolveExtra?.(name) ?? null;
|
|
10955
|
+
if (!target)
|
|
10956
|
+
continue;
|
|
10957
|
+
if (target.kind === "namespace")
|
|
10958
|
+
namespaceImports.push({ name, specifier: target.specifier });
|
|
10959
|
+
else {
|
|
10960
|
+
const names = namedBySpecifier.get(target.specifier) ?? new Map;
|
|
10961
|
+
names.set(name, target.typeOnly ?? false);
|
|
10962
|
+
namedBySpecifier.set(target.specifier, names);
|
|
10963
|
+
}
|
|
10964
|
+
}
|
|
10965
|
+
if (namedBySpecifier.size === 0 && namespaceImports.length === 0)
|
|
10966
|
+
return null;
|
|
10967
|
+
const importDecls = sf.statements.filter(ts8.isImportDeclaration);
|
|
10968
|
+
const anchor = importDecls.at(-1) ?? null;
|
|
10969
|
+
const namedImportsBySpecifier = collectExistingNamedImports(importDecls);
|
|
10970
|
+
const edits = [];
|
|
10971
|
+
const newStatements = [];
|
|
10972
|
+
for (const [specifier, names] of namedBySpecifier) {
|
|
10973
|
+
const existing = namedImportsBySpecifier.get(specifier);
|
|
10974
|
+
if (existing) {
|
|
10975
|
+
const merged = new Map(existing.names);
|
|
10976
|
+
for (const [name, isType] of names)
|
|
10977
|
+
if (!merged.has(name))
|
|
10978
|
+
merged.set(name, isType);
|
|
10979
|
+
edits.push({
|
|
10980
|
+
start: existing.decl.getStart(sf),
|
|
10981
|
+
end: existing.decl.getEnd(),
|
|
10982
|
+
text: formatNamedImport(specifier, merged)
|
|
10983
|
+
});
|
|
10984
|
+
} else
|
|
10985
|
+
newStatements.push(formatNamedImport(specifier, names));
|
|
10986
|
+
}
|
|
10987
|
+
for (const ns of namespaceImports)
|
|
10988
|
+
newStatements.push(`import * as ${ns.name} from "${ns.specifier}";`);
|
|
10989
|
+
if (newStatements.length > 0) {
|
|
10990
|
+
const anchorEdit = anchor ? edits.find((edit) => edit.start === anchor.getStart(sf)) : undefined;
|
|
10991
|
+
if (anchorEdit)
|
|
10992
|
+
anchorEdit.text = `${anchorEdit.text}
|
|
10993
|
+
${newStatements.join(`
|
|
10994
|
+
`)}`;
|
|
10995
|
+
else if (anchor)
|
|
10996
|
+
edits.push({ start: anchor.getEnd(), end: anchor.getEnd(), text: `
|
|
10997
|
+
${newStatements.join(`
|
|
10998
|
+
`)}` });
|
|
10999
|
+
else {
|
|
11000
|
+
const prologueEnd = directivePrologueEnd(sf);
|
|
11001
|
+
if (prologueEnd >= 0)
|
|
11002
|
+
edits.push({ start: prologueEnd, end: prologueEnd, text: `
|
|
11003
|
+
${newStatements.join(`
|
|
11004
|
+
`)}` });
|
|
11005
|
+
else
|
|
11006
|
+
edits.push({ start: 0, end: 0, text: `${newStatements.join(`
|
|
11007
|
+
`)}
|
|
11008
|
+
|
|
11009
|
+
` });
|
|
11010
|
+
}
|
|
11011
|
+
}
|
|
11012
|
+
if (edits.length === 0)
|
|
11013
|
+
return null;
|
|
11014
|
+
edits.sort((a, b) => b.start - a.start);
|
|
11015
|
+
let out = source2;
|
|
11016
|
+
for (const edit of edits)
|
|
11017
|
+
out = out.slice(0, edit.start) + edit.text + out.slice(edit.end);
|
|
11018
|
+
return out === source2 ? null : out;
|
|
11019
|
+
};
|
|
11020
|
+
var collectBoundNames = (sf) => {
|
|
11021
|
+
const names = new Set;
|
|
11022
|
+
const visit = (node) => {
|
|
11023
|
+
if (ts8.isImportClause(node)) {
|
|
11024
|
+
if (node.name)
|
|
11025
|
+
names.add(node.name.text);
|
|
11026
|
+
const bindings = node.namedBindings;
|
|
11027
|
+
if (bindings && ts8.isNamespaceImport(bindings))
|
|
11028
|
+
names.add(bindings.name.text);
|
|
11029
|
+
if (bindings && ts8.isNamedImports(bindings))
|
|
11030
|
+
for (const el of bindings.elements)
|
|
11031
|
+
names.add(el.name.text);
|
|
11032
|
+
}
|
|
11033
|
+
if ((ts8.isVariableDeclaration(node) || ts8.isFunctionDeclaration(node) || ts8.isClassDeclaration(node) || ts8.isParameter(node) || ts8.isBindingElement(node) || ts8.isEnumDeclaration(node) || ts8.isTypeAliasDeclaration(node) || ts8.isInterfaceDeclaration(node)) && node.name && ts8.isIdentifier(node.name))
|
|
11034
|
+
names.add(node.name.text);
|
|
11035
|
+
ts8.forEachChild(node, visit);
|
|
11036
|
+
};
|
|
11037
|
+
ts8.forEachChild(sf, visit);
|
|
11038
|
+
return names;
|
|
11039
|
+
};
|
|
11040
|
+
var collectUsedReferences = (sf) => {
|
|
11041
|
+
const used = new Set;
|
|
11042
|
+
const visit = (node) => {
|
|
11043
|
+
if (ts8.isIdentifier(node) && isReferencePosition(node))
|
|
11044
|
+
used.add(node.text);
|
|
11045
|
+
ts8.forEachChild(node, visit);
|
|
11046
|
+
};
|
|
11047
|
+
ts8.forEachChild(sf, visit);
|
|
11048
|
+
return used;
|
|
11049
|
+
};
|
|
11050
|
+
var isReferencePosition = (node) => {
|
|
11051
|
+
const parent = node.parent;
|
|
11052
|
+
if (!parent)
|
|
11053
|
+
return true;
|
|
11054
|
+
if (ts8.isPropertyAccessExpression(parent) && parent.name === node)
|
|
11055
|
+
return false;
|
|
11056
|
+
if (ts8.isQualifiedName(parent) && parent.right === node)
|
|
11057
|
+
return false;
|
|
11058
|
+
if (ts8.isPropertyAssignment(parent) && parent.name === node)
|
|
11059
|
+
return false;
|
|
11060
|
+
if (ts8.isPropertySignature(parent) && parent.name === node)
|
|
11061
|
+
return false;
|
|
11062
|
+
if (ts8.isBindingElement(parent) && parent.propertyName === node)
|
|
11063
|
+
return false;
|
|
11064
|
+
if (ts8.isImportSpecifier(parent) || ts8.isExportSpecifier(parent))
|
|
11065
|
+
return false;
|
|
11066
|
+
return true;
|
|
11067
|
+
};
|
|
11068
|
+
var collectExistingNamedImports = (importDecls) => {
|
|
11069
|
+
const map = new Map;
|
|
11070
|
+
for (const decl of importDecls) {
|
|
11071
|
+
const clause = decl.importClause;
|
|
11072
|
+
const bindings = clause?.namedBindings;
|
|
11073
|
+
if (!clause || !bindings || !ts8.isNamedImports(bindings))
|
|
11074
|
+
continue;
|
|
11075
|
+
if (!ts8.isStringLiteral(decl.moduleSpecifier))
|
|
11076
|
+
continue;
|
|
11077
|
+
const specifier = decl.moduleSpecifier.text;
|
|
11078
|
+
if (map.has(specifier))
|
|
11079
|
+
continue;
|
|
11080
|
+
const names = new Map;
|
|
11081
|
+
for (const el of bindings.elements)
|
|
11082
|
+
names.set(el.name.text, clause.isTypeOnly || el.isTypeOnly);
|
|
11083
|
+
map.set(specifier, { decl, names });
|
|
11084
|
+
}
|
|
11085
|
+
return map;
|
|
11086
|
+
};
|
|
11087
|
+
var formatNamedImport = (specifier, names) => {
|
|
11088
|
+
const entries = [...names.entries()].sort((a, b) => compareNames(a[0], b[0]));
|
|
11089
|
+
if (entries.every(([, isType]) => isType))
|
|
11090
|
+
return `import type { ${entries.map(([name]) => name).join(", ")} } from "${specifier}";`;
|
|
11091
|
+
const parts = entries.map(([name, isType]) => isType ? `type ${name}` : name);
|
|
11092
|
+
return `import { ${parts.join(", ")} } from "${specifier}";`;
|
|
11093
|
+
};
|
|
11094
|
+
var directivePrologueEnd = (sf) => {
|
|
11095
|
+
let end = -1;
|
|
11096
|
+
for (const stmt of sf.statements) {
|
|
11097
|
+
if (ts8.isExpressionStatement(stmt) && ts8.isStringLiteral(stmt.expression))
|
|
11098
|
+
end = stmt.getEnd();
|
|
11099
|
+
else
|
|
11100
|
+
break;
|
|
11101
|
+
}
|
|
11102
|
+
return end;
|
|
11103
|
+
};
|
|
11104
|
+
var scriptKindFor = (fileName) => fileName.endsWith(".tsx") ? ts8.ScriptKind.TSX : ts8.ScriptKind.TS;
|
|
11105
|
+
var compareNames = (a, b) => {
|
|
11106
|
+
const [la, lb] = [a.toLowerCase(), b.toLowerCase()];
|
|
11107
|
+
if (la !== lb)
|
|
11108
|
+
return la < lb ? -1 : 1;
|
|
11109
|
+
return a < b ? -1 : a > b ? 1 : 0;
|
|
11110
|
+
};
|
|
11111
|
+
var formatError = (err) => err instanceof Error ? err.message : String(err);
|
|
11112
|
+
var fileExists2 = async (file) => stat3(file).then((s) => s.isFile()).catch(() => false);
|
|
11113
|
+
var domainKindOf = (base) => {
|
|
11114
|
+
if (base.endsWith(".constant.ts"))
|
|
11115
|
+
return "constant";
|
|
11116
|
+
if (base.endsWith(".document.ts"))
|
|
11117
|
+
return "document";
|
|
11118
|
+
if (base.endsWith(".signal.ts"))
|
|
11119
|
+
return "signal";
|
|
11120
|
+
return null;
|
|
11121
|
+
};
|
|
11122
|
+
var buildDomainIndex = async (libDir) => {
|
|
11123
|
+
const index = new Map;
|
|
11124
|
+
for (const file of await collectDomainFiles(libDir)) {
|
|
11125
|
+
const kind = domainKindOf(path23.basename(file));
|
|
11126
|
+
if (!kind)
|
|
11127
|
+
continue;
|
|
11128
|
+
const src = await readFile(file, "utf8").catch(() => null);
|
|
11129
|
+
if (src === null)
|
|
11130
|
+
continue;
|
|
11131
|
+
for (const name of exportedPascalNames(src, file)) {
|
|
11132
|
+
const entries = index.get(name) ?? [];
|
|
11133
|
+
entries.push({ file, kind });
|
|
11134
|
+
index.set(name, entries);
|
|
11135
|
+
}
|
|
11136
|
+
}
|
|
11137
|
+
return index;
|
|
11138
|
+
};
|
|
11139
|
+
var collectDomainFiles = async (dir) => {
|
|
11140
|
+
const entries = await readdir2(dir, { withFileTypes: true }).catch(() => []);
|
|
11141
|
+
const files = [];
|
|
11142
|
+
for (const entry of entries) {
|
|
11143
|
+
if (entry.name.startsWith(".") || entry.name === "node_modules")
|
|
11144
|
+
continue;
|
|
11145
|
+
const full = path23.join(dir, entry.name);
|
|
11146
|
+
if (entry.isDirectory())
|
|
11147
|
+
files.push(...await collectDomainFiles(full));
|
|
11148
|
+
else if (domainKindOf(entry.name) && !TEST_FILE_RE.test(entry.name))
|
|
11149
|
+
files.push(full);
|
|
11150
|
+
}
|
|
11151
|
+
return files;
|
|
11152
|
+
};
|
|
11153
|
+
var exportedPascalNames = (source2, fileName) => {
|
|
11154
|
+
const sf = ts8.createSourceFile(fileName, source2, ts8.ScriptTarget.Latest, true);
|
|
11155
|
+
const isExported = (node) => ts8.canHaveModifiers(node) && (ts8.getModifiers(node) ?? []).some((m) => m.kind === ts8.SyntaxKind.ExportKeyword);
|
|
11156
|
+
const names = [];
|
|
11157
|
+
for (const stmt of sf.statements) {
|
|
11158
|
+
if ((ts8.isClassDeclaration(stmt) || ts8.isFunctionDeclaration(stmt) || ts8.isEnumDeclaration(stmt)) && stmt.name) {
|
|
11159
|
+
if (isExported(stmt))
|
|
11160
|
+
names.push(stmt.name.text);
|
|
11161
|
+
} else if (ts8.isVariableStatement(stmt) && isExported(stmt)) {
|
|
11162
|
+
for (const decl of stmt.declarationList.declarations)
|
|
11163
|
+
if (ts8.isIdentifier(decl.name))
|
|
11164
|
+
names.push(decl.name.text);
|
|
11165
|
+
} else if (ts8.isExportDeclaration(stmt) && stmt.exportClause && ts8.isNamedExports(stmt.exportClause)) {
|
|
11166
|
+
for (const el of stmt.exportClause.elements)
|
|
11167
|
+
names.push(el.name.text);
|
|
11168
|
+
}
|
|
11169
|
+
}
|
|
11170
|
+
return names.filter((name) => PASCAL_CASE_RE.test(name));
|
|
11171
|
+
};
|
|
11172
|
+
var relativeSpecifier = (fromDir, toFile) => {
|
|
11173
|
+
const rel = path23.relative(fromDir, toFile).replace(/\.tsx?$/, "").split(path23.sep).join("/");
|
|
11174
|
+
return rel.startsWith(".") ? rel : `./${rel}`;
|
|
11175
|
+
};
|
|
10621
11176
|
// pkgs/@akanjs/devkit/frontendBuild/csrArtifactBuilder.ts
|
|
10622
11177
|
import { mkdir as mkdir5, rm as rm2, unlink } from "fs/promises";
|
|
10623
|
-
import
|
|
11178
|
+
import path25 from "path";
|
|
10624
11179
|
|
|
10625
11180
|
// pkgs/@akanjs/devkit/frontendBuild/pagesEntrySourceGenerator.ts
|
|
10626
11181
|
import fs3 from "fs";
|
|
10627
|
-
import
|
|
10628
|
-
import
|
|
11182
|
+
import path24 from "path";
|
|
11183
|
+
import ts9 from "typescript";
|
|
10629
11184
|
|
|
10630
11185
|
class PagesEntrySourceGenerator {
|
|
10631
11186
|
#pageEntries;
|
|
@@ -10667,12 +11222,12 @@ ${entries.join(`
|
|
|
10667
11222
|
`;
|
|
10668
11223
|
}
|
|
10669
11224
|
static #toImportSpecifier(moduleAbsPath) {
|
|
10670
|
-
return
|
|
11225
|
+
return path24.resolve(moduleAbsPath).split(path24.sep).join("/");
|
|
10671
11226
|
}
|
|
10672
11227
|
static #hasAsyncDefaultExport(moduleAbsPath) {
|
|
10673
11228
|
try {
|
|
10674
|
-
const source2 = fs3.readFileSync(
|
|
10675
|
-
const sourceFile2 =
|
|
11229
|
+
const source2 = fs3.readFileSync(path24.resolve(moduleAbsPath), "utf8");
|
|
11230
|
+
const sourceFile2 = ts9.createSourceFile(moduleAbsPath, source2, ts9.ScriptTarget.Latest, true, PagesEntrySourceGenerator.#scriptKind(moduleAbsPath));
|
|
10676
11231
|
return PagesEntrySourceGenerator.#sourceFileHasAsyncDefaultExport(sourceFile2);
|
|
10677
11232
|
} catch {
|
|
10678
11233
|
return false;
|
|
@@ -10682,31 +11237,31 @@ ${entries.join(`
|
|
|
10682
11237
|
const asyncBindings = new Map;
|
|
10683
11238
|
let defaultIdentifier = null;
|
|
10684
11239
|
for (const statement of sourceFile2.statements) {
|
|
10685
|
-
if (
|
|
10686
|
-
if (PagesEntrySourceGenerator.#hasModifier(statement,
|
|
10687
|
-
return PagesEntrySourceGenerator.#hasModifier(statement,
|
|
11240
|
+
if (ts9.isFunctionDeclaration(statement)) {
|
|
11241
|
+
if (PagesEntrySourceGenerator.#hasModifier(statement, ts9.SyntaxKind.DefaultKeyword)) {
|
|
11242
|
+
return PagesEntrySourceGenerator.#hasModifier(statement, ts9.SyntaxKind.AsyncKeyword);
|
|
10688
11243
|
}
|
|
10689
11244
|
if (statement.name) {
|
|
10690
|
-
asyncBindings.set(statement.name.text, PagesEntrySourceGenerator.#hasModifier(statement,
|
|
11245
|
+
asyncBindings.set(statement.name.text, PagesEntrySourceGenerator.#hasModifier(statement, ts9.SyntaxKind.AsyncKeyword));
|
|
10691
11246
|
}
|
|
10692
11247
|
continue;
|
|
10693
11248
|
}
|
|
10694
|
-
if (
|
|
11249
|
+
if (ts9.isVariableStatement(statement)) {
|
|
10695
11250
|
for (const declaration of statement.declarationList.declarations) {
|
|
10696
|
-
if (!
|
|
11251
|
+
if (!ts9.isIdentifier(declaration.name))
|
|
10697
11252
|
continue;
|
|
10698
11253
|
asyncBindings.set(declaration.name.text, PagesEntrySourceGenerator.#isAsyncFunctionExpression(declaration.initializer));
|
|
10699
11254
|
}
|
|
10700
11255
|
continue;
|
|
10701
11256
|
}
|
|
10702
|
-
if (
|
|
11257
|
+
if (ts9.isExportAssignment(statement)) {
|
|
10703
11258
|
if (PagesEntrySourceGenerator.#isAsyncFunctionExpression(statement.expression))
|
|
10704
11259
|
return true;
|
|
10705
|
-
if (
|
|
11260
|
+
if (ts9.isIdentifier(statement.expression))
|
|
10706
11261
|
defaultIdentifier = statement.expression.text;
|
|
10707
11262
|
continue;
|
|
10708
11263
|
}
|
|
10709
|
-
if (
|
|
11264
|
+
if (ts9.isExportDeclaration(statement) && statement.exportClause && ts9.isNamedExports(statement.exportClause)) {
|
|
10710
11265
|
const exportClause = statement.exportClause;
|
|
10711
11266
|
for (const specifier of exportClause.elements) {
|
|
10712
11267
|
if (specifier.name.text !== "default")
|
|
@@ -10718,13 +11273,13 @@ ${entries.join(`
|
|
|
10718
11273
|
return defaultIdentifier ? asyncBindings.get(defaultIdentifier) === true : false;
|
|
10719
11274
|
}
|
|
10720
11275
|
static #hasModifier(node, kind) {
|
|
10721
|
-
return
|
|
11276
|
+
return ts9.canHaveModifiers(node) && (ts9.getModifiers(node)?.some((modifier) => modifier.kind === kind) ?? false);
|
|
10722
11277
|
}
|
|
10723
11278
|
static #isAsyncFunctionExpression(node) {
|
|
10724
|
-
return Boolean(node && (
|
|
11279
|
+
return Boolean(node && (ts9.isArrowFunction(node) || ts9.isFunctionExpression(node)) && PagesEntrySourceGenerator.#hasModifier(node, ts9.SyntaxKind.AsyncKeyword));
|
|
10725
11280
|
}
|
|
10726
11281
|
static #scriptKind(moduleAbsPath) {
|
|
10727
|
-
return moduleAbsPath.endsWith(".tsx") || moduleAbsPath.endsWith(".jsx") ?
|
|
11282
|
+
return moduleAbsPath.endsWith(".tsx") || moduleAbsPath.endsWith(".jsx") ? ts9.ScriptKind.TSX : ts9.ScriptKind.TS;
|
|
10728
11283
|
}
|
|
10729
11284
|
}
|
|
10730
11285
|
|
|
@@ -10750,7 +11305,7 @@ class CsrArtifactBuilder {
|
|
|
10750
11305
|
const csrBasePaths = [...akanConfig2.basePaths];
|
|
10751
11306
|
const htmlEntries = csrBasePaths.length > 0 ? csrBasePaths : ["index"];
|
|
10752
11307
|
await rm2(this.#outputDir, { recursive: true, force: true });
|
|
10753
|
-
await mkdir5(
|
|
11308
|
+
await mkdir5(path25.join(this.#app.cwdPath, ".akan/generated/csr"), { recursive: true });
|
|
10754
11309
|
const generatedHtmlFiles = Object.fromEntries(htmlEntries.map((basePath2) => this.#createHtmlFile(basePath2)));
|
|
10755
11310
|
const result = await Bun.build({
|
|
10756
11311
|
target: "browser",
|
|
@@ -10782,7 +11337,7 @@ ${logs}` : ""}`);
|
|
|
10782
11337
|
return { outputDir: this.#outputDir };
|
|
10783
11338
|
}
|
|
10784
11339
|
get #outputDir() {
|
|
10785
|
-
return
|
|
11340
|
+
return path25.join(this.#command === "build" ? this.#app.dist.cwdPath : this.#app.cwdPath, this.#command === "build" ? "csr" : ".akan/artifact/csr");
|
|
10786
11341
|
}
|
|
10787
11342
|
#define() {
|
|
10788
11343
|
const nodeEnv = this.#command === "build" ? "production" : "development";
|
|
@@ -10813,8 +11368,8 @@ ${logs}` : ""}`);
|
|
|
10813
11368
|
];
|
|
10814
11369
|
}
|
|
10815
11370
|
async#loadCsrArtifact() {
|
|
10816
|
-
const artifactDir =
|
|
10817
|
-
const artifactFile = Bun.file(
|
|
11371
|
+
const artifactDir = path25.join(this.#command === "build" ? this.#app.dist.cwdPath : this.#app.cwdPath, ".akan/artifact");
|
|
11372
|
+
const artifactFile = Bun.file(path25.join(artifactDir, "base-artifact.json"));
|
|
10818
11373
|
if (!await artifactFile.exists())
|
|
10819
11374
|
return { cssAssets: {} };
|
|
10820
11375
|
const artifact = await artifactFile.json();
|
|
@@ -10827,7 +11382,7 @@ ${logs}` : ""}`);
|
|
|
10827
11382
|
const htmlFile = Bun.file(htmlPath);
|
|
10828
11383
|
if (!await htmlFile.exists())
|
|
10829
11384
|
continue;
|
|
10830
|
-
const basePath2 =
|
|
11385
|
+
const basePath2 = path25.basename(htmlPath, ".html") === "index" ? "" : path25.basename(htmlPath, ".html");
|
|
10831
11386
|
const inlined = await this.#inlineHtmlAssets(await htmlFile.text(), htmlPath, cssAssets[basePath2]);
|
|
10832
11387
|
for (const filePath of inlined.jsFiles)
|
|
10833
11388
|
jsFiles.add(filePath);
|
|
@@ -10869,7 +11424,7 @@ ${remainingAssets.join(`
|
|
|
10869
11424
|
next = CsrArtifactBuilder.injectBeforeHeadEnd(next, style);
|
|
10870
11425
|
}
|
|
10871
11426
|
if (cssAsset) {
|
|
10872
|
-
const cssPath =
|
|
11427
|
+
const cssPath = path25.join(this.#command === "build" ? this.#app.dist.cwdPath : this.#app.cwdPath, ".akan/artifact", cssAsset.cssRelPath);
|
|
10873
11428
|
const css = await Bun.file(cssPath).text();
|
|
10874
11429
|
const style = CsrArtifactBuilder.createInlineStyle(css);
|
|
10875
11430
|
if (!next.includes(style))
|
|
@@ -10940,16 +11495,16 @@ ${CsrArtifactBuilder.escapeInlineScript(await loadScript(src))}
|
|
|
10940
11495
|
throw new Error(`[csr-build] cannot inline external script: ${src}`);
|
|
10941
11496
|
}
|
|
10942
11497
|
const normalized = src.startsWith("/") ? src.slice(1) : src;
|
|
10943
|
-
return
|
|
11498
|
+
return path25.resolve(path25.dirname(htmlPath), normalized);
|
|
10944
11499
|
}
|
|
10945
11500
|
}
|
|
10946
11501
|
// pkgs/@akanjs/devkit/frontendBuild/cssCompiler.ts
|
|
10947
|
-
import
|
|
11502
|
+
import path27 from "path";
|
|
10948
11503
|
import { Logger as Logger8 } from "akanjs/common";
|
|
10949
11504
|
import { compile } from "tailwindcss";
|
|
10950
11505
|
|
|
10951
11506
|
// pkgs/@akanjs/devkit/frontendBuild/cssImportResolver.ts
|
|
10952
|
-
import
|
|
11507
|
+
import path26 from "path";
|
|
10953
11508
|
var CSS_IMPORT_EXTS = ["", ".css", "/styles.css", "/index.css"];
|
|
10954
11509
|
|
|
10955
11510
|
class CssImportResolver {
|
|
@@ -11002,7 +11557,7 @@ class CssImportResolver {
|
|
|
11002
11557
|
const exact = this.#paths[id];
|
|
11003
11558
|
if (exact) {
|
|
11004
11559
|
for (const repl of exact) {
|
|
11005
|
-
const resolved = await this.#firstExisting(
|
|
11560
|
+
const resolved = await this.#firstExisting(path26.resolve(this.#workspaceRoot, repl));
|
|
11006
11561
|
if (resolved)
|
|
11007
11562
|
return resolved;
|
|
11008
11563
|
}
|
|
@@ -11013,7 +11568,7 @@ class CssImportResolver {
|
|
|
11013
11568
|
const suffix = id.slice(prefix.length);
|
|
11014
11569
|
for (const repl of replacements) {
|
|
11015
11570
|
const replPath = repl.endsWith("/*") ? repl.slice(0, -1) : repl;
|
|
11016
|
-
const resolved = await this.#firstExisting(
|
|
11571
|
+
const resolved = await this.#firstExisting(path26.resolve(this.#workspaceRoot, replPath + suffix));
|
|
11017
11572
|
if (resolved)
|
|
11018
11573
|
return resolved;
|
|
11019
11574
|
}
|
|
@@ -11043,25 +11598,25 @@ class CssImportResolver {
|
|
|
11043
11598
|
try {
|
|
11044
11599
|
if (!await Bun.file(pkgPath).exists())
|
|
11045
11600
|
return null;
|
|
11046
|
-
const pkgDir =
|
|
11601
|
+
const pkgDir = path26.dirname(pkgPath);
|
|
11047
11602
|
const pkg = await Bun.file(pkgPath).json();
|
|
11048
11603
|
const subpath = id === pkgName ? "." : `.${id.slice(pkgName.length)}`;
|
|
11049
11604
|
const exportValue = pkg.exports?.[subpath];
|
|
11050
11605
|
const styleEntry = (typeof exportValue === "string" ? exportValue : exportValue?.style || exportValue?.import || exportValue?.default) || pkg.exports?.["."]?.style || pkg.style || "index.css";
|
|
11051
|
-
return await this.#firstExisting(
|
|
11606
|
+
return await this.#firstExisting(path26.resolve(pkgDir, styleEntry));
|
|
11052
11607
|
} catch {
|
|
11053
11608
|
return null;
|
|
11054
11609
|
}
|
|
11055
11610
|
}
|
|
11056
11611
|
#resolutionBases(fromBase) {
|
|
11057
|
-
return [fromBase, this.#workspaceRoot,
|
|
11612
|
+
return [fromBase, this.#workspaceRoot, path26.dirname(Bun.main), path26.resolve(path26.dirname(Bun.main), "../..")];
|
|
11058
11613
|
}
|
|
11059
11614
|
#packageJsonCandidates(pkgName) {
|
|
11060
11615
|
return [
|
|
11061
|
-
|
|
11062
|
-
|
|
11063
|
-
|
|
11064
|
-
|
|
11616
|
+
path26.join(this.#workspaceRoot, "pkgs", pkgName, "package.json"),
|
|
11617
|
+
path26.join(this.#workspaceRoot, "node_modules", pkgName, "package.json"),
|
|
11618
|
+
path26.join(path26.dirname(Bun.main), "node_modules", pkgName, "package.json"),
|
|
11619
|
+
path26.join(path26.dirname(Bun.main), "../../", pkgName, "package.json")
|
|
11065
11620
|
];
|
|
11066
11621
|
}
|
|
11067
11622
|
async#firstExisting(basePath2) {
|
|
@@ -11079,7 +11634,7 @@ class CssImportResolver {
|
|
|
11079
11634
|
return parts[0] ?? null;
|
|
11080
11635
|
}
|
|
11081
11636
|
static isCssFile(filePath) {
|
|
11082
|
-
return
|
|
11637
|
+
return path26.extname(filePath) === ".css";
|
|
11083
11638
|
}
|
|
11084
11639
|
}
|
|
11085
11640
|
|
|
@@ -11146,7 +11701,7 @@ class CssCompiler {
|
|
|
11146
11701
|
pageKeys
|
|
11147
11702
|
} = {}) {
|
|
11148
11703
|
pageKeys ??= await this.#app.getPageKeys({ refresh });
|
|
11149
|
-
const seeds = pageKeys.map((key) =>
|
|
11704
|
+
const seeds = pageKeys.map((key) => path27.resolve(this.#app.cwdPath, "page", key));
|
|
11150
11705
|
const cssFiles = new Set;
|
|
11151
11706
|
const sourceFiles = new Set;
|
|
11152
11707
|
const queue = [...seeds];
|
|
@@ -11178,7 +11733,7 @@ class CssCompiler {
|
|
|
11178
11733
|
} catch {
|
|
11179
11734
|
continue;
|
|
11180
11735
|
}
|
|
11181
|
-
const importerDir =
|
|
11736
|
+
const importerDir = path27.dirname(filePath);
|
|
11182
11737
|
for (const imp of imports) {
|
|
11183
11738
|
const spec = imp.path;
|
|
11184
11739
|
if (!spec)
|
|
@@ -11204,7 +11759,7 @@ class CssCompiler {
|
|
|
11204
11759
|
const compileStarted = Date.now();
|
|
11205
11760
|
const compilers = await Promise.all(cssPaths.map(async (cssPath) => {
|
|
11206
11761
|
const css = await Bun.file(cssPath).text();
|
|
11207
|
-
const base =
|
|
11762
|
+
const base = path27.dirname(cssPath);
|
|
11208
11763
|
const compiler = await compile(css, {
|
|
11209
11764
|
base,
|
|
11210
11765
|
loadStylesheet: (id, fromBase) => this.#loadStylesheet(id, fromBase),
|
|
@@ -11235,11 +11790,11 @@ class CssCompiler {
|
|
|
11235
11790
|
async#loadStylesheet(id, fromBase) {
|
|
11236
11791
|
const p = await this.#resolveCssImport(id, fromBase);
|
|
11237
11792
|
const content = await Bun.file(p).text();
|
|
11238
|
-
return { path: p, base:
|
|
11793
|
+
return { path: p, base: path27.dirname(p), content };
|
|
11239
11794
|
}
|
|
11240
11795
|
async#resolveCssImport(id, fromBase) {
|
|
11241
11796
|
if (id.startsWith(".") || id.startsWith("/"))
|
|
11242
|
-
return
|
|
11797
|
+
return path27.resolve(fromBase, id);
|
|
11243
11798
|
const resolver = await this.#getCssImportResolver();
|
|
11244
11799
|
const resolved = await resolver.resolve(id, fromBase);
|
|
11245
11800
|
if (resolved)
|
|
@@ -11255,11 +11810,11 @@ class CssCompiler {
|
|
|
11255
11810
|
async#loadModule(id, fromBase) {
|
|
11256
11811
|
const p = __require.resolve(id, { paths: [fromBase] });
|
|
11257
11812
|
const mod = await import(p);
|
|
11258
|
-
return { path: p, base:
|
|
11813
|
+
return { path: p, base: path27.dirname(p), module: mod.default ?? mod };
|
|
11259
11814
|
}
|
|
11260
11815
|
async#resolveSourceImport(id, fromBase, resolvePackage) {
|
|
11261
11816
|
if (id.startsWith(".") || id.startsWith("/")) {
|
|
11262
|
-
const abs = id.startsWith("/") ? id :
|
|
11817
|
+
const abs = id.startsWith("/") ? id : path27.resolve(fromBase, id);
|
|
11263
11818
|
return resolveSourceFileCandidate(abs);
|
|
11264
11819
|
}
|
|
11265
11820
|
const pkg = await resolvePackage(id);
|
|
@@ -11301,7 +11856,7 @@ async function resolveSourceFileCandidate(absPathNoExt) {
|
|
|
11301
11856
|
return filePath;
|
|
11302
11857
|
}
|
|
11303
11858
|
for (const ext of SOURCE_EXTS3) {
|
|
11304
|
-
const filePath =
|
|
11859
|
+
const filePath = path27.join(absPathNoExt, `index${ext}`);
|
|
11305
11860
|
if (await Bun.file(filePath).exists())
|
|
11306
11861
|
return filePath;
|
|
11307
11862
|
}
|
|
@@ -11324,19 +11879,19 @@ function resolveSourceWithRequire(id, fromBase) {
|
|
|
11324
11879
|
}
|
|
11325
11880
|
}
|
|
11326
11881
|
function isSourceFile(filePath) {
|
|
11327
|
-
return SOURCE_EXTS3.includes(
|
|
11882
|
+
return SOURCE_EXTS3.includes(path27.extname(filePath));
|
|
11328
11883
|
}
|
|
11329
11884
|
function isIgnoredNodeModuleSource(filePath) {
|
|
11330
11885
|
return NODE_MODULES_RE3.test(filePath) && !AKANJS_NODE_MODULE_RE3.test(filePath);
|
|
11331
11886
|
}
|
|
11332
11887
|
function getPageKeyBasePath(pageKey, basePaths) {
|
|
11333
|
-
const normalized = pageKey.split(
|
|
11888
|
+
const normalized = pageKey.split(path27.sep).join("/").replace(/^\.\//, "");
|
|
11334
11889
|
const segments = normalized.split("/");
|
|
11335
11890
|
const firstPublicSegment = segments.find((segment) => segment !== "[lang]" && !/^\(.+\)$/.test(segment));
|
|
11336
11891
|
return firstPublicSegment && basePaths.includes(firstPublicSegment) ? firstPublicSegment : null;
|
|
11337
11892
|
}
|
|
11338
11893
|
// pkgs/@akanjs/devkit/frontendBuild/devChangePlanner.ts
|
|
11339
|
-
import
|
|
11894
|
+
import path28 from "path";
|
|
11340
11895
|
var SOURCE_EXTS4 = new Set([".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs"]);
|
|
11341
11896
|
var CONFIG_BASENAMES = new Set(["akan.config.ts", "bunfig.toml", "tsconfig.json", "package.json"]);
|
|
11342
11897
|
var BARREL_FACETS = new Set(["common", "srvkit", "ui", "webkit", "plugin"]);
|
|
@@ -11348,11 +11903,11 @@ var RUNTIME_METADATA_BASENAMES2 = new Set(["dict.ts", "sig.ts", "useClient.ts",
|
|
|
11348
11903
|
class DevChangePlanner {
|
|
11349
11904
|
#workspaceRoot;
|
|
11350
11905
|
constructor({ workspaceRoot }) {
|
|
11351
|
-
this.#workspaceRoot =
|
|
11906
|
+
this.#workspaceRoot = path28.resolve(workspaceRoot);
|
|
11352
11907
|
}
|
|
11353
11908
|
plan({ generation, files, kinds, generatedFiles: generatedFiles2 = [] }) {
|
|
11354
11909
|
const fileList = uniqueResolved([...files, ...generatedFiles2]);
|
|
11355
|
-
const generatedSet = new Set(generatedFiles2.map((file) =>
|
|
11910
|
+
const generatedSet = new Set(generatedFiles2.map((file) => path28.resolve(file)));
|
|
11356
11911
|
const kindSet = new Set(kinds);
|
|
11357
11912
|
const roles = new Set;
|
|
11358
11913
|
const actions = new Set;
|
|
@@ -11369,13 +11924,13 @@ class DevChangePlanner {
|
|
|
11369
11924
|
}
|
|
11370
11925
|
for (const file of fileList) {
|
|
11371
11926
|
const reasons = new Set;
|
|
11372
|
-
const fileRoles = this.#rolesForFile(file, { isGenerated: generatedSet.has(
|
|
11927
|
+
const fileRoles = this.#rolesForFile(file, { isGenerated: generatedSet.has(path28.resolve(file)), reasons });
|
|
11373
11928
|
for (const role of fileRoles)
|
|
11374
11929
|
roles.add(role);
|
|
11375
11930
|
if (reasons.has("runtime-metadata"))
|
|
11376
11931
|
actions.add("restart-builder");
|
|
11377
11932
|
if (reasons.size > 0)
|
|
11378
|
-
reasonByFile[
|
|
11933
|
+
reasonByFile[path28.resolve(file)] = [...reasons].sort();
|
|
11379
11934
|
}
|
|
11380
11935
|
if (roles.has("barrel"))
|
|
11381
11936
|
actions.add("sync-generated");
|
|
@@ -11396,12 +11951,12 @@ class DevChangePlanner {
|
|
|
11396
11951
|
}
|
|
11397
11952
|
#rolesForFile(file, { isGenerated, reasons }) {
|
|
11398
11953
|
const roles = new Set;
|
|
11399
|
-
const abs =
|
|
11400
|
-
const base =
|
|
11401
|
-
const ext =
|
|
11954
|
+
const abs = path28.resolve(file);
|
|
11955
|
+
const base = path28.basename(abs);
|
|
11956
|
+
const ext = path28.extname(abs).toLowerCase();
|
|
11402
11957
|
const isSource = SOURCE_EXTS4.has(ext);
|
|
11403
|
-
const rel =
|
|
11404
|
-
const parts = rel.split(
|
|
11958
|
+
const rel = path28.relative(this.#workspaceRoot, abs);
|
|
11959
|
+
const parts = rel.split(path28.sep).filter(Boolean);
|
|
11405
11960
|
if (CONFIG_BASENAMES.has(base)) {
|
|
11406
11961
|
roles.add("config");
|
|
11407
11962
|
reasons.add("config-file");
|
|
@@ -11442,15 +11997,15 @@ class DevChangePlanner {
|
|
|
11442
11997
|
return roles;
|
|
11443
11998
|
}
|
|
11444
11999
|
#isServerBiased(abs, parts) {
|
|
11445
|
-
const base =
|
|
12000
|
+
const base = path28.basename(abs);
|
|
11446
12001
|
return parts.includes("srvkit") || SERVER_SUFFIXES2.some((suffix) => base.endsWith(suffix)) || base === "main.ts" || base === "server.ts";
|
|
11447
12002
|
}
|
|
11448
12003
|
#isClientBiased(abs, parts) {
|
|
11449
|
-
const base =
|
|
12004
|
+
const base = path28.basename(abs);
|
|
11450
12005
|
return parts.includes("ui") || parts.includes("webkit") || parts.includes("page") || CLIENT_SUFFIXES.some((suffix) => base.endsWith(suffix));
|
|
11451
12006
|
}
|
|
11452
12007
|
#isSharedBiased(abs, parts) {
|
|
11453
|
-
const base =
|
|
12008
|
+
const base = path28.basename(abs);
|
|
11454
12009
|
return parts.includes("common") || SHARED_SUFFIXES2.some((suffix) => base.endsWith(suffix)) || RUNTIME_METADATA_BASENAMES2.has(base);
|
|
11455
12010
|
}
|
|
11456
12011
|
#isRuntimeMetadataFile(parts, base) {
|
|
@@ -11475,16 +12030,16 @@ class DevChangePlanner {
|
|
|
11475
12030
|
return true;
|
|
11476
12031
|
}
|
|
11477
12032
|
#isWorkspaceSource(rel) {
|
|
11478
|
-
if (!rel || rel.startsWith("..") ||
|
|
12033
|
+
if (!rel || rel.startsWith("..") || path28.isAbsolute(rel))
|
|
11479
12034
|
return false;
|
|
11480
|
-
const [scope] = rel.split(
|
|
12035
|
+
const [scope] = rel.split(path28.sep);
|
|
11481
12036
|
return scope === "apps" || scope === "libs" || scope === "pkgs";
|
|
11482
12037
|
}
|
|
11483
12038
|
}
|
|
11484
|
-
var uniqueResolved = (files) => [...new Set(files.map((file) =>
|
|
12039
|
+
var uniqueResolved = (files) => [...new Set(files.map((file) => path28.resolve(file)))].sort();
|
|
11485
12040
|
// pkgs/@akanjs/devkit/frontendBuild/devGeneratedIndexSync.ts
|
|
11486
|
-
import { mkdir as mkdir6, readdir as
|
|
11487
|
-
import
|
|
12041
|
+
import { mkdir as mkdir6, readdir as readdir3, readFile as readFile2, rm as rm3, stat as stat4, writeFile as writeFile2 } from "fs/promises";
|
|
12042
|
+
import path29 from "path";
|
|
11488
12043
|
var BARREL_FACETS2 = new Set(["common", "srvkit", "ui", "webkit", "plugin"]);
|
|
11489
12044
|
var FACET_SOURCE_FILE_RE = /\.(ts|tsx)$/;
|
|
11490
12045
|
var FACET_EXCLUDED_FILE_RE = /(^index\.tsx?$|\.d\.ts$|\.(test|spec)\.(ts|tsx)$|\.css$|\.scss$|\.sass$)/;
|
|
@@ -11497,7 +12052,7 @@ var SCALAR_UI_TYPES = ["Template", "Unit"];
|
|
|
11497
12052
|
class DevGeneratedIndexSync {
|
|
11498
12053
|
#workspaceRoot;
|
|
11499
12054
|
constructor({ workspaceRoot }) {
|
|
11500
|
-
this.#workspaceRoot =
|
|
12055
|
+
this.#workspaceRoot = path29.resolve(workspaceRoot);
|
|
11501
12056
|
}
|
|
11502
12057
|
async syncForBatch(files) {
|
|
11503
12058
|
const indexPaths = new Set;
|
|
@@ -11507,7 +12062,7 @@ class DevGeneratedIndexSync {
|
|
|
11507
12062
|
if (facetIndex)
|
|
11508
12063
|
indexPaths.add(facetIndex);
|
|
11509
12064
|
const moduleIndex2 = await this.#moduleIndexForDirectoryEvent(file).catch((err) => {
|
|
11510
|
-
errors.push(`[generated-index] module detection failed for ${file}: ${
|
|
12065
|
+
errors.push(`[generated-index] module detection failed for ${file}: ${formatError2(err)}`);
|
|
11511
12066
|
return null;
|
|
11512
12067
|
});
|
|
11513
12068
|
if (moduleIndex2)
|
|
@@ -11520,17 +12075,17 @@ class DevGeneratedIndexSync {
|
|
|
11520
12075
|
if (changed)
|
|
11521
12076
|
changedFiles.push(indexPath);
|
|
11522
12077
|
} catch (err) {
|
|
11523
|
-
errors.push(`[generated-index] sync failed for ${indexPath}: ${
|
|
12078
|
+
errors.push(`[generated-index] sync failed for ${indexPath}: ${formatError2(err)}`);
|
|
11524
12079
|
}
|
|
11525
12080
|
}
|
|
11526
12081
|
return { changedFiles, errors };
|
|
11527
12082
|
}
|
|
11528
12083
|
#facetIndexFor(file) {
|
|
11529
|
-
const abs =
|
|
11530
|
-
const rel =
|
|
11531
|
-
if (rel.startsWith("..") ||
|
|
12084
|
+
const abs = path29.resolve(file);
|
|
12085
|
+
const rel = path29.relative(this.#workspaceRoot, abs);
|
|
12086
|
+
if (rel.startsWith("..") || path29.isAbsolute(rel))
|
|
11532
12087
|
return null;
|
|
11533
|
-
const parts = rel.split(
|
|
12088
|
+
const parts = rel.split(path29.sep).filter(Boolean);
|
|
11534
12089
|
if (parts.length < 4)
|
|
11535
12090
|
return null;
|
|
11536
12091
|
const [scope, project, facet, child] = parts;
|
|
@@ -11538,32 +12093,32 @@ class DevGeneratedIndexSync {
|
|
|
11538
12093
|
return null;
|
|
11539
12094
|
if (!child || child.startsWith(".") || child === "index.ts" || child === "index.tsx")
|
|
11540
12095
|
return null;
|
|
11541
|
-
return
|
|
12096
|
+
return path29.join(this.#workspaceRoot, scope, project, facet, "index.ts");
|
|
11542
12097
|
}
|
|
11543
12098
|
async#moduleIndexForDirectoryEvent(file) {
|
|
11544
|
-
const abs =
|
|
11545
|
-
const rel =
|
|
11546
|
-
if (rel.startsWith("..") ||
|
|
12099
|
+
const abs = path29.resolve(file);
|
|
12100
|
+
const rel = path29.relative(this.#workspaceRoot, abs);
|
|
12101
|
+
if (rel.startsWith("..") || path29.isAbsolute(rel))
|
|
11547
12102
|
return null;
|
|
11548
|
-
const parts = rel.split(
|
|
12103
|
+
const parts = rel.split(path29.sep).filter(Boolean);
|
|
11549
12104
|
if (parts.length !== 4 && parts.length !== 5)
|
|
11550
12105
|
return null;
|
|
11551
12106
|
const [scope, project, libSegment, moduleSegment, scalarSegment] = parts;
|
|
11552
12107
|
if (scope !== "apps" && scope !== "libs" || !project || libSegment !== "lib")
|
|
11553
12108
|
return null;
|
|
11554
|
-
const isExistingDirectory = await
|
|
11555
|
-
const looksLikeDeletedDirectory = !
|
|
12109
|
+
const isExistingDirectory = await stat4(abs).then((s) => s.isDirectory()).catch(() => false);
|
|
12110
|
+
const looksLikeDeletedDirectory = !path29.extname(abs);
|
|
11556
12111
|
if (!isExistingDirectory && !looksLikeDeletedDirectory)
|
|
11557
12112
|
return null;
|
|
11558
12113
|
if (moduleSegment === "__scalar" && scalarSegment) {
|
|
11559
|
-
return
|
|
12114
|
+
return path29.join(this.#workspaceRoot, scope, project, "lib", "__scalar", scalarSegment, "index.ts");
|
|
11560
12115
|
}
|
|
11561
12116
|
if (!moduleSegment || moduleSegment === "__scalar")
|
|
11562
12117
|
return null;
|
|
11563
|
-
return
|
|
12118
|
+
return path29.join(this.#workspaceRoot, scope, project, "lib", moduleSegment, "index.ts");
|
|
11564
12119
|
}
|
|
11565
12120
|
async#syncIndex(indexPath) {
|
|
11566
|
-
const dir =
|
|
12121
|
+
const dir = path29.dirname(indexPath);
|
|
11567
12122
|
const content = await this.#contentForIndex(indexPath);
|
|
11568
12123
|
if (content === null) {
|
|
11569
12124
|
if (!await exists(indexPath))
|
|
@@ -11571,23 +12126,23 @@ class DevGeneratedIndexSync {
|
|
|
11571
12126
|
await rm3(indexPath, { force: true });
|
|
11572
12127
|
return true;
|
|
11573
12128
|
}
|
|
11574
|
-
const current = await
|
|
12129
|
+
const current = await readFile2(indexPath, "utf8").catch(() => null);
|
|
11575
12130
|
if (current === content)
|
|
11576
12131
|
return false;
|
|
11577
12132
|
await mkdir6(dir, { recursive: true });
|
|
11578
|
-
await
|
|
12133
|
+
await writeFile2(indexPath, content);
|
|
11579
12134
|
return true;
|
|
11580
12135
|
}
|
|
11581
12136
|
async#contentForIndex(indexPath) {
|
|
11582
|
-
const parts =
|
|
12137
|
+
const parts = path29.relative(this.#workspaceRoot, indexPath).split(path29.sep).filter(Boolean);
|
|
11583
12138
|
const facet = parts.at(-2);
|
|
11584
12139
|
if (facet && BARREL_FACETS2.has(facet))
|
|
11585
|
-
return this.#facetContent(
|
|
11586
|
-
return this.#moduleContent(
|
|
12140
|
+
return this.#facetContent(path29.dirname(indexPath));
|
|
12141
|
+
return this.#moduleContent(path29.dirname(indexPath));
|
|
11587
12142
|
}
|
|
11588
12143
|
async#facetContent(dir) {
|
|
11589
|
-
const nameCasePattern =
|
|
11590
|
-
const entries = await
|
|
12144
|
+
const nameCasePattern = path29.basename(dir) === "ui" ? FACET_PASCAL_CASE_RE : FACET_CAMEL_CASE_RE;
|
|
12145
|
+
const entries = await readdir3(dir, { withFileTypes: true }).catch(() => []);
|
|
11591
12146
|
const exportNames = entries.flatMap((entry) => {
|
|
11592
12147
|
const name = entry.name;
|
|
11593
12148
|
if (name.startsWith("."))
|
|
@@ -11608,8 +12163,8 @@ class DevGeneratedIndexSync {
|
|
|
11608
12163
|
`;
|
|
11609
12164
|
}
|
|
11610
12165
|
async#moduleContent(dir) {
|
|
11611
|
-
const rel =
|
|
11612
|
-
const parts = rel.split(
|
|
12166
|
+
const rel = path29.relative(this.#workspaceRoot, dir);
|
|
12167
|
+
const parts = rel.split(path29.sep).filter(Boolean);
|
|
11613
12168
|
const moduleSegment = parts.at(-1);
|
|
11614
12169
|
if (!moduleSegment)
|
|
11615
12170
|
return null;
|
|
@@ -11621,7 +12176,7 @@ class DevGeneratedIndexSync {
|
|
|
11621
12176
|
const allowedTypes = isScalar ? SCALAR_UI_TYPES : moduleSegment.startsWith("_") ? SERVICE_UI_TYPES : MODULE_UI_TYPES;
|
|
11622
12177
|
const fileTypes = [];
|
|
11623
12178
|
for (const type of allowedTypes) {
|
|
11624
|
-
if (await exists(
|
|
12179
|
+
if (await exists(path29.join(dir, `${modelName}.${type}.tsx`)))
|
|
11625
12180
|
fileTypes.push(type);
|
|
11626
12181
|
}
|
|
11627
12182
|
if (fileTypes.length === 0)
|
|
@@ -11633,12 +12188,12 @@ ${fileTypes.map((type) => `import * as ${type} from "./${modelName}.${type}";`).
|
|
|
11633
12188
|
export const ${modelName} = { ${fileTypes.join(", ")} };`;
|
|
11634
12189
|
}
|
|
11635
12190
|
}
|
|
11636
|
-
var exists = async (file) =>
|
|
12191
|
+
var exists = async (file) => stat4(file).then(() => true).catch(() => false);
|
|
11637
12192
|
var capitalize4 = (value) => `${value.charAt(0).toUpperCase()}${value.slice(1)}`;
|
|
11638
|
-
var
|
|
12193
|
+
var formatError2 = (err) => err instanceof Error ? err.message : String(err);
|
|
11639
12194
|
// pkgs/@akanjs/devkit/frontendBuild/fontOptimizer.ts
|
|
11640
12195
|
import { mkdir as mkdir7 } from "fs/promises";
|
|
11641
|
-
import
|
|
12196
|
+
import path30 from "path";
|
|
11642
12197
|
import {
|
|
11643
12198
|
generateFontFace,
|
|
11644
12199
|
getMetricsForFamily,
|
|
@@ -11647,7 +12202,7 @@ import {
|
|
|
11647
12202
|
} from "fontaine";
|
|
11648
12203
|
import { createFont, woff2 } from "fonteditor-core";
|
|
11649
12204
|
import subsetFont from "subset-font";
|
|
11650
|
-
import
|
|
12205
|
+
import ts10 from "typescript";
|
|
11651
12206
|
var FONT_URL_PREFIX = "/_akan/fonts";
|
|
11652
12207
|
var DEFAULT_FONT_SUBSETS = ["latin"];
|
|
11653
12208
|
|
|
@@ -11662,7 +12217,7 @@ class FontOptimizer {
|
|
|
11662
12217
|
constructor(app, command = "start") {
|
|
11663
12218
|
this.#app = app;
|
|
11664
12219
|
this.#command = command;
|
|
11665
|
-
this.#artifactRoot =
|
|
12220
|
+
this.#artifactRoot = path30.join(command === "build" ? app.dist.cwdPath : app.cwdPath, ".akan/artifact");
|
|
11666
12221
|
}
|
|
11667
12222
|
async optimize() {
|
|
11668
12223
|
const fonts = await this.discoverFonts();
|
|
@@ -11681,7 +12236,7 @@ class FontOptimizer {
|
|
|
11681
12236
|
const pageKeys = await this.#app.getPageKeys();
|
|
11682
12237
|
const fonts = [];
|
|
11683
12238
|
await Promise.all(pageKeys.map(async (key) => {
|
|
11684
|
-
const filePath =
|
|
12239
|
+
const filePath = path30.resolve(this.#app.cwdPath, "page", key);
|
|
11685
12240
|
const file = Bun.file(filePath);
|
|
11686
12241
|
if (!await file.exists())
|
|
11687
12242
|
return;
|
|
@@ -11697,8 +12252,8 @@ class FontOptimizer {
|
|
|
11697
12252
|
this.#app.logger.warn(`[font] source not found: ${face.src}`);
|
|
11698
12253
|
continue;
|
|
11699
12254
|
}
|
|
11700
|
-
const outputPath =
|
|
11701
|
-
await mkdir7(
|
|
12255
|
+
const outputPath = path30.join(this.#artifactRoot, face.optimizedSrc.replace(/^\/_akan\//, ""));
|
|
12256
|
+
await mkdir7(path30.dirname(outputPath), { recursive: true });
|
|
11702
12257
|
const sourceBuffer = Buffer.from(await Bun.file(sourcePath).arrayBuffer());
|
|
11703
12258
|
const outputBuffer = font.subset === false ? await this.#convertToWoff2(sourceBuffer, sourcePath) : await subsetFont(sourceBuffer, await this.#getSubsetText(font), { targetFormat: "woff2" });
|
|
11704
12259
|
await Bun.write(outputPath, outputBuffer);
|
|
@@ -11712,17 +12267,17 @@ class FontOptimizer {
|
|
|
11712
12267
|
this.#cssParts.push(...faceCss, this.#buildRootVariableRule(font));
|
|
11713
12268
|
}
|
|
11714
12269
|
#extractFontsExport(source2, filePath) {
|
|
11715
|
-
const sourceFile2 =
|
|
12270
|
+
const sourceFile2 = ts10.createSourceFile(filePath, source2, ts10.ScriptTarget.Latest, true, ts10.ScriptKind.TSX);
|
|
11716
12271
|
const fonts = [];
|
|
11717
12272
|
for (const statement of sourceFile2.statements) {
|
|
11718
|
-
if (!
|
|
12273
|
+
if (!ts10.isVariableStatement(statement))
|
|
11719
12274
|
continue;
|
|
11720
|
-
const modifiers =
|
|
11721
|
-
const isExported = modifiers?.some((modifier) => modifier.kind ===
|
|
12275
|
+
const modifiers = ts10.canHaveModifiers(statement) ? ts10.getModifiers(statement) : undefined;
|
|
12276
|
+
const isExported = modifiers?.some((modifier) => modifier.kind === ts10.SyntaxKind.ExportKeyword) ?? false;
|
|
11722
12277
|
if (!isExported)
|
|
11723
12278
|
continue;
|
|
11724
12279
|
for (const declaration of statement.declarationList.declarations) {
|
|
11725
|
-
if (!
|
|
12280
|
+
if (!ts10.isIdentifier(declaration.name) || declaration.name.text !== "fonts")
|
|
11726
12281
|
continue;
|
|
11727
12282
|
const value = declaration.initializer ? this.#literalToValue(declaration.initializer) : null;
|
|
11728
12283
|
if (Array.isArray(value)) {
|
|
@@ -11733,20 +12288,20 @@ class FontOptimizer {
|
|
|
11733
12288
|
return fonts;
|
|
11734
12289
|
}
|
|
11735
12290
|
#literalToValue(node) {
|
|
11736
|
-
if (
|
|
12291
|
+
if (ts10.isStringLiteralLike(node))
|
|
11737
12292
|
return node.text;
|
|
11738
|
-
if (
|
|
12293
|
+
if (ts10.isNumericLiteral(node))
|
|
11739
12294
|
return Number(node.text);
|
|
11740
|
-
if (node.kind ===
|
|
12295
|
+
if (node.kind === ts10.SyntaxKind.TrueKeyword)
|
|
11741
12296
|
return true;
|
|
11742
|
-
if (node.kind ===
|
|
12297
|
+
if (node.kind === ts10.SyntaxKind.FalseKeyword)
|
|
11743
12298
|
return false;
|
|
11744
|
-
if (
|
|
12299
|
+
if (ts10.isArrayLiteralExpression(node))
|
|
11745
12300
|
return node.elements.map((element) => this.#literalToValue(element));
|
|
11746
|
-
if (
|
|
12301
|
+
if (ts10.isObjectLiteralExpression(node)) {
|
|
11747
12302
|
const obj = {};
|
|
11748
12303
|
for (const prop of node.properties) {
|
|
11749
|
-
if (!
|
|
12304
|
+
if (!ts10.isPropertyAssignment(prop))
|
|
11750
12305
|
continue;
|
|
11751
12306
|
const name = this.#getPropertyName(prop.name);
|
|
11752
12307
|
if (!name)
|
|
@@ -11755,13 +12310,13 @@ class FontOptimizer {
|
|
|
11755
12310
|
}
|
|
11756
12311
|
return obj;
|
|
11757
12312
|
}
|
|
11758
|
-
if (
|
|
12313
|
+
if (ts10.isAsExpression(node) || ts10.isSatisfiesExpression(node) || ts10.isParenthesizedExpression(node)) {
|
|
11759
12314
|
return this.#literalToValue(node.expression);
|
|
11760
12315
|
}
|
|
11761
12316
|
return;
|
|
11762
12317
|
}
|
|
11763
12318
|
#getPropertyName(name) {
|
|
11764
|
-
if (
|
|
12319
|
+
if (ts10.isIdentifier(name) || ts10.isStringLiteral(name) || ts10.isNumericLiteral(name))
|
|
11765
12320
|
return name.text;
|
|
11766
12321
|
return null;
|
|
11767
12322
|
}
|
|
@@ -11845,8 +12400,8 @@ class FontOptimizer {
|
|
|
11845
12400
|
return null;
|
|
11846
12401
|
const rel = src.replace(/^\//, "");
|
|
11847
12402
|
const candidates = [
|
|
11848
|
-
this.#command === "build" ?
|
|
11849
|
-
|
|
12403
|
+
this.#command === "build" ? path30.join(this.#app.dist.cwdPath, "public", rel) : null,
|
|
12404
|
+
path30.join(this.#app.cwdPath, "public", rel),
|
|
11850
12405
|
this.#resolveWorkspacePublicPath(rel)
|
|
11851
12406
|
].filter(Boolean);
|
|
11852
12407
|
for (const candidate of candidates) {
|
|
@@ -11874,7 +12429,7 @@ class FontOptimizer {
|
|
|
11874
12429
|
return "woff2";
|
|
11875
12430
|
if (signature === "OTTO")
|
|
11876
12431
|
return "otf";
|
|
11877
|
-
const ext =
|
|
12432
|
+
const ext = path30.extname(sourcePath).slice(1).toLowerCase();
|
|
11878
12433
|
if (ext === "otf" || ext === "woff" || ext === "woff2")
|
|
11879
12434
|
return ext;
|
|
11880
12435
|
return "ttf";
|
|
@@ -11883,7 +12438,7 @@ class FontOptimizer {
|
|
|
11883
12438
|
const [root, dep, ...rest] = rel.split("/");
|
|
11884
12439
|
if (root !== "libs" || !dep || rest.length === 0)
|
|
11885
12440
|
return null;
|
|
11886
|
-
return
|
|
12441
|
+
return path30.join(this.#app.workspace.workspaceRoot, "libs", dep, "public", ...rest);
|
|
11887
12442
|
}
|
|
11888
12443
|
async#getSubsetText(font) {
|
|
11889
12444
|
const parts = new Set;
|
|
@@ -11893,7 +12448,7 @@ class FontOptimizer {
|
|
|
11893
12448
|
if (font.subsetText)
|
|
11894
12449
|
parts.add(font.subsetText);
|
|
11895
12450
|
for (const filePath of font.subsetFiles ?? []) {
|
|
11896
|
-
const abs =
|
|
12451
|
+
const abs = path30.isAbsolute(filePath) ? filePath : path30.join(this.#app.cwdPath, filePath);
|
|
11897
12452
|
const file = Bun.file(abs);
|
|
11898
12453
|
if (await file.exists())
|
|
11899
12454
|
parts.add(await file.text());
|
|
@@ -11912,7 +12467,7 @@ class FontOptimizer {
|
|
|
11912
12467
|
return "";
|
|
11913
12468
|
}
|
|
11914
12469
|
async#collectAutoSubsetText() {
|
|
11915
|
-
const roots = ["page", "ui"].map((dir) =>
|
|
12470
|
+
const roots = ["page", "ui"].map((dir) => path30.join(this.#app.cwdPath, dir));
|
|
11916
12471
|
const glob = new Bun.Glob("**/*.{ts,tsx,js,jsx,html,md}");
|
|
11917
12472
|
const parts = [];
|
|
11918
12473
|
await Promise.all(roots.map(async (root) => {
|
|
@@ -12026,7 +12581,7 @@ ${declarations.map(([prop, value]) => ` ${prop}: ${value};`).join(`
|
|
|
12026
12581
|
}
|
|
12027
12582
|
}
|
|
12028
12583
|
// pkgs/@akanjs/devkit/frontendBuild/hmrChangeClassifier.ts
|
|
12029
|
-
import
|
|
12584
|
+
import path31 from "path";
|
|
12030
12585
|
var SOURCE_EXTS5 = new Set([".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs"]);
|
|
12031
12586
|
var CSS_EXTS = new Set([".css"]);
|
|
12032
12587
|
var CONFIG_BASENAMES2 = new Set(["akan.config.ts", "bunfig.toml", "tsconfig.json", "package.json"]);
|
|
@@ -12035,10 +12590,10 @@ class HmrChangeClassifier {
|
|
|
12035
12590
|
classify(abs) {
|
|
12036
12591
|
if (this.#isUninteresting(abs))
|
|
12037
12592
|
return "ignore";
|
|
12038
|
-
const base =
|
|
12593
|
+
const base = path31.basename(abs);
|
|
12039
12594
|
if (CONFIG_BASENAMES2.has(base))
|
|
12040
12595
|
return "config";
|
|
12041
|
-
const ext =
|
|
12596
|
+
const ext = path31.extname(abs).toLowerCase();
|
|
12042
12597
|
if (CSS_EXTS.has(ext))
|
|
12043
12598
|
return "css";
|
|
12044
12599
|
if (SOURCE_EXTS5.has(ext))
|
|
@@ -12046,23 +12601,23 @@ class HmrChangeClassifier {
|
|
|
12046
12601
|
return "ignore";
|
|
12047
12602
|
}
|
|
12048
12603
|
#isUninteresting(abs) {
|
|
12049
|
-
const base =
|
|
12604
|
+
const base = path31.basename(abs);
|
|
12050
12605
|
if (!base)
|
|
12051
12606
|
return true;
|
|
12052
12607
|
if (base.startsWith("."))
|
|
12053
12608
|
return true;
|
|
12054
12609
|
if (base.endsWith("~") || base.endsWith(".swp") || base.endsWith(".swx") || base.endsWith(".tmp"))
|
|
12055
12610
|
return true;
|
|
12056
|
-
if (abs.includes(`${
|
|
12611
|
+
if (abs.includes(`${path31.sep}node_modules${path31.sep}`))
|
|
12057
12612
|
return true;
|
|
12058
|
-
if (abs.includes(`${
|
|
12613
|
+
if (abs.includes(`${path31.sep}.akan${path31.sep}`))
|
|
12059
12614
|
return true;
|
|
12060
12615
|
return false;
|
|
12061
12616
|
}
|
|
12062
12617
|
}
|
|
12063
12618
|
// pkgs/@akanjs/devkit/frontendBuild/hmrWatcher.ts
|
|
12064
12619
|
import fs4 from "fs";
|
|
12065
|
-
import
|
|
12620
|
+
import path32 from "path";
|
|
12066
12621
|
class HmrWatcher {
|
|
12067
12622
|
#roots;
|
|
12068
12623
|
#debounceMs;
|
|
@@ -12075,7 +12630,7 @@ class HmrWatcher {
|
|
|
12075
12630
|
#stopped = false;
|
|
12076
12631
|
#flushing = false;
|
|
12077
12632
|
constructor(opts) {
|
|
12078
|
-
this.#roots = [...new Set(opts.roots.map((r) =>
|
|
12633
|
+
this.#roots = [...new Set(opts.roots.map((r) => path32.resolve(r)))];
|
|
12079
12634
|
this.#debounceMs = opts.debounceMs ?? 80;
|
|
12080
12635
|
this.#onBatch = opts.onBatch;
|
|
12081
12636
|
this.#logger = opts.logger;
|
|
@@ -12086,7 +12641,7 @@ class HmrWatcher {
|
|
|
12086
12641
|
const w = fs4.watch(root, { recursive: true, persistent: false }, (_event, filename) => {
|
|
12087
12642
|
if (!filename)
|
|
12088
12643
|
return;
|
|
12089
|
-
const abs =
|
|
12644
|
+
const abs = path32.resolve(root, filename.toString());
|
|
12090
12645
|
this.#queue(abs);
|
|
12091
12646
|
});
|
|
12092
12647
|
this.#watchers.push(w);
|
|
@@ -12144,10 +12699,10 @@ class HmrWatcher {
|
|
|
12144
12699
|
}
|
|
12145
12700
|
}
|
|
12146
12701
|
// pkgs/@akanjs/devkit/frontendBuild/pagesBundleBuilder.ts
|
|
12147
|
-
import
|
|
12702
|
+
import path34 from "path";
|
|
12148
12703
|
|
|
12149
12704
|
// pkgs/@akanjs/devkit/transforms/externalizeFrameworkPlugin.ts
|
|
12150
|
-
import
|
|
12705
|
+
import path33 from "path";
|
|
12151
12706
|
var DEFAULT_INCLUDE = ["akanjs/", "@apps/", "@libs/"];
|
|
12152
12707
|
var DEFAULT_EXCLUDE_EXACT = new Set(["akanjs/webkit", "@akanjs/cli", "@akanjs/devkit"]);
|
|
12153
12708
|
var DEFAULT_EXCLUDE_PREFIX = ["@akanjs/cli/", "@akanjs/devkit/"];
|
|
@@ -12190,7 +12745,7 @@ async function createExternalizeFrameworkPlugin(options) {
|
|
|
12190
12745
|
const replPath = repl?.endsWith("/*") ? repl.slice(0, -1) : repl ?? "";
|
|
12191
12746
|
if (!replPath)
|
|
12192
12747
|
continue;
|
|
12193
|
-
const candidate =
|
|
12748
|
+
const candidate = path33.resolve(workspaceRoot, replPath + suffix);
|
|
12194
12749
|
const hit = await firstExisting(candidate);
|
|
12195
12750
|
if (hit)
|
|
12196
12751
|
return hit;
|
|
@@ -12202,8 +12757,8 @@ async function createExternalizeFrameworkPlugin(options) {
|
|
|
12202
12757
|
if (spec === pkg)
|
|
12203
12758
|
continue;
|
|
12204
12759
|
const suffix = spec.slice(pkg.length + 1);
|
|
12205
|
-
const pkgDir =
|
|
12206
|
-
const candidate =
|
|
12760
|
+
const pkgDir = path33.dirname(path33.resolve(workspaceRoot, entryFile));
|
|
12761
|
+
const candidate = path33.join(pkgDir, suffix);
|
|
12207
12762
|
const hit = await firstExisting(candidate);
|
|
12208
12763
|
if (hit)
|
|
12209
12764
|
return hit;
|
|
@@ -12253,7 +12808,7 @@ async function firstExisting(basePath2) {
|
|
|
12253
12808
|
return candidate;
|
|
12254
12809
|
}
|
|
12255
12810
|
for (const ext of CANDIDATE_EXTS3) {
|
|
12256
|
-
const candidate =
|
|
12811
|
+
const candidate = path33.join(basePath2, `index${ext}`);
|
|
12257
12812
|
if (await Bun.file(candidate).exists())
|
|
12258
12813
|
return candidate;
|
|
12259
12814
|
}
|
|
@@ -12344,11 +12899,11 @@ class PagesBundleBuilder {
|
|
|
12344
12899
|
const entryArtifact = result.outputs.find((a) => a.kind === "entry-point");
|
|
12345
12900
|
if (!entryArtifact)
|
|
12346
12901
|
throw new Error("[PagesBundleBuilder] Bun.build emitted no entry-point artifact");
|
|
12347
|
-
const bundlePath =
|
|
12902
|
+
const bundlePath = path34.resolve(entryArtifact.path);
|
|
12348
12903
|
const buildId = Date.now();
|
|
12349
12904
|
const outputBytes = result.outputs.reduce((sum, output) => sum + output.size, 0);
|
|
12350
12905
|
const chunkCount = result.outputs.filter((output) => output.kind === "chunk").length;
|
|
12351
|
-
this.#app.verbose(`[PagesBundleBuilder] ${
|
|
12906
|
+
this.#app.verbose(`[PagesBundleBuilder] ${path34.basename(bundlePath)} emitted in ${Date.now() - this.#started}ms splitting=${this.#splitting} entry=${entryArtifact.size} bytes outputs=${result.outputs.length} chunks=${chunkCount} total=${outputBytes} bytes`);
|
|
12352
12907
|
return {
|
|
12353
12908
|
bundlePath,
|
|
12354
12909
|
buildId,
|
|
@@ -12430,11 +12985,11 @@ function loaderFor4(absPath) {
|
|
|
12430
12985
|
}
|
|
12431
12986
|
// pkgs/@akanjs/devkit/frontendBuild/precompressArtifacts.ts
|
|
12432
12987
|
import fs5 from "fs";
|
|
12433
|
-
import
|
|
12988
|
+
import path35 from "path";
|
|
12434
12989
|
var COMPRESSIBLE_EXTS = new Set([".css", ".html", ".js", ".json", ".svg"]);
|
|
12435
12990
|
var MIN_COMPRESS_BYTES = 1024;
|
|
12436
12991
|
async function precompressArtifacts(app) {
|
|
12437
|
-
const roots = [
|
|
12992
|
+
const roots = [path35.join(app.dist.cwdPath, ".akan/artifact/client")];
|
|
12438
12993
|
const result = { files: 0, inputBytes: 0, outputBytes: 0 };
|
|
12439
12994
|
await Promise.all(roots.map((root) => precompressRoot(root, result)));
|
|
12440
12995
|
if (result.files > 0) {
|
|
@@ -12460,7 +13015,7 @@ async function precompressRoot(root, result) {
|
|
|
12460
13015
|
async function shouldPrecompress(filePath) {
|
|
12461
13016
|
if (filePath.endsWith(".gz"))
|
|
12462
13017
|
return false;
|
|
12463
|
-
if (!COMPRESSIBLE_EXTS.has(
|
|
13018
|
+
if (!COMPRESSIBLE_EXTS.has(path35.extname(filePath).toLowerCase()))
|
|
12464
13019
|
return false;
|
|
12465
13020
|
const file = Bun.file(filePath);
|
|
12466
13021
|
if (!await file.exists())
|
|
@@ -12478,7 +13033,7 @@ function formatBytes(bytes) {
|
|
|
12478
13033
|
return `${(bytes / 1024 / 1024).toFixed(1)}MB`;
|
|
12479
13034
|
}
|
|
12480
13035
|
// pkgs/@akanjs/devkit/frontendBuild/ssrBaseArtifactBuilder.ts
|
|
12481
|
-
import
|
|
13036
|
+
import path36 from "path";
|
|
12482
13037
|
import { optimize } from "@tailwindcss/node";
|
|
12483
13038
|
function prepareCssAsset(command, basePath2, cssText) {
|
|
12484
13039
|
return optimize(cssText, { file: `${basePath2 || "root"}.css`, minify: command === "build" }).code;
|
|
@@ -12494,7 +13049,7 @@ class SsrBaseArtifactBuilder {
|
|
|
12494
13049
|
this.#app = app;
|
|
12495
13050
|
this.#command = command;
|
|
12496
13051
|
this.#artifactDir = `${command === "build" ? app.dist.cwdPath : app.cwdPath}/.akan/artifact`;
|
|
12497
|
-
this.#absArtifactDir =
|
|
13052
|
+
this.#absArtifactDir = path36.resolve(this.#artifactDir);
|
|
12498
13053
|
}
|
|
12499
13054
|
async build() {
|
|
12500
13055
|
const akanConfig2 = await this.#app.getConfig();
|
|
@@ -12516,7 +13071,7 @@ class SsrBaseArtifactBuilder {
|
|
|
12516
13071
|
rscRuntimeSsrManifest,
|
|
12517
13072
|
vendorMap,
|
|
12518
13073
|
cssAssets,
|
|
12519
|
-
pagesBundlePath: this.#command === "build" ?
|
|
13074
|
+
pagesBundlePath: this.#command === "build" ? path36.relative(this.#absArtifactDir, pagesBundle.bundlePath) : pagesBundle.bundlePath,
|
|
12520
13075
|
pagesBundleBuildId: pagesBundle.buildId,
|
|
12521
13076
|
domains: [...akanConfig2.domains],
|
|
12522
13077
|
subRoutes: Object.fromEntries(Array.from(akanConfig2.subRoutes.entries()).map(([basePath2, domains]) => [basePath2, [...domains]])),
|
|
@@ -12532,18 +13087,18 @@ class SsrBaseArtifactBuilder {
|
|
|
12532
13087
|
androidSha256CertFingerprints: target.deepLinks?.android?.sha256CertFingerprints
|
|
12533
13088
|
}))
|
|
12534
13089
|
};
|
|
12535
|
-
await Bun.write(
|
|
13090
|
+
await Bun.write(path36.join(this.#absArtifactDir, "base-artifact.json"), `${JSON.stringify(artifact, null, 2)}
|
|
12536
13091
|
`);
|
|
12537
13092
|
this.#app.verbose(`[base-artifact] complete in ${Date.now() - this.#started}ms`);
|
|
12538
13093
|
return { artifact, seedIndex, cssCompiler, optimizedFonts };
|
|
12539
13094
|
}
|
|
12540
13095
|
async#buildRuntimeClientEntries() {
|
|
12541
13096
|
const akanServerPath = await this.#resolveAkanServerPath();
|
|
12542
|
-
const rscClientEntry =
|
|
12543
|
-
const rscSegmentOutletEntry =
|
|
13097
|
+
const rscClientEntry = path36.resolve(akanServerPath, "rscClient.tsx");
|
|
13098
|
+
const rscSegmentOutletEntry = path36.resolve(akanServerPath, "rscSegmentOutlet.tsx");
|
|
12544
13099
|
const vendorEntries = VENDOR_SPECIFIERS.map((specifier) => ({
|
|
12545
13100
|
specifier,
|
|
12546
|
-
absPath:
|
|
13101
|
+
absPath: path36.resolve(akanServerPath, "vendor", `${specifier.replaceAll("/", "-").replaceAll(".", "-")}.ts`)
|
|
12547
13102
|
}));
|
|
12548
13103
|
const entries = [rscClientEntry, rscSegmentOutletEntry, ...vendorEntries.map((v) => v.absPath)];
|
|
12549
13104
|
const clientBundle = await new ClientEntriesBundler({ app: this.#app, entries, command: this.#command }).bundle();
|
|
@@ -12580,15 +13135,15 @@ class SsrBaseArtifactBuilder {
|
|
|
12580
13135
|
async#resolveAkanServerPath() {
|
|
12581
13136
|
const candidates = [];
|
|
12582
13137
|
try {
|
|
12583
|
-
candidates.push(
|
|
13138
|
+
candidates.push(path36.dirname(Bun.resolveSync("akanjs/server", this.#app.workspace.workspaceRoot)));
|
|
12584
13139
|
} catch {}
|
|
12585
|
-
candidates.push(
|
|
13140
|
+
candidates.push(path36.join(this.#app.workspace.workspaceRoot, "pkgs/akanjs/server"), path36.join(this.#app.workspace.workspaceRoot, "node_modules/akanjs/server"));
|
|
12586
13141
|
try {
|
|
12587
|
-
candidates.push(
|
|
13142
|
+
candidates.push(path36.dirname(Bun.resolveSync("akanjs/server", path36.dirname(Bun.main))));
|
|
12588
13143
|
} catch {}
|
|
12589
|
-
candidates.push(
|
|
13144
|
+
candidates.push(path36.join(path36.dirname(Bun.main), "node_modules/akanjs/server"), path36.join(path36.dirname(Bun.main), "../../akanjs/server"), path36.resolve(import.meta.dir, "../../server"), path36.resolve(import.meta.dir, "../server"));
|
|
12590
13145
|
for (const candidate of candidates) {
|
|
12591
|
-
if (await Bun.file(
|
|
13146
|
+
if (await Bun.file(path36.join(candidate, "rscClient.tsx")).exists())
|
|
12592
13147
|
return candidate;
|
|
12593
13148
|
}
|
|
12594
13149
|
throw new Error(`[base-artifact] failed to locate akanjs/server; looked in: ${candidates.join(", ")}`);
|
|
@@ -12617,14 +13172,14 @@ ${preparedCssText}`).toString(36);
|
|
|
12617
13172
|
`styles/${cssAssetName}-${cssHash}.css`,
|
|
12618
13173
|
`/_akan/styles/${cssAssetName}-${cssHash}.css`
|
|
12619
13174
|
];
|
|
12620
|
-
await Bun.write(
|
|
13175
|
+
await Bun.write(path36.join(this.#absArtifactDir, cssRelPath), preparedCssText);
|
|
12621
13176
|
this.#app.verbose(`[base-artifact] wrote ${preparedCssText.length} bytes of CSS for ${basePath2} -> ${cssRelPath}`);
|
|
12622
13177
|
return [basePath2, { cssUrl, cssRelPath }];
|
|
12623
13178
|
}
|
|
12624
13179
|
}
|
|
12625
13180
|
// pkgs/@akanjs/devkit/frontendBuild/watchRootResolver.ts
|
|
12626
13181
|
import fs6 from "fs";
|
|
12627
|
-
import
|
|
13182
|
+
import path37 from "path";
|
|
12628
13183
|
|
|
12629
13184
|
class WatchRootResolver {
|
|
12630
13185
|
#app;
|
|
@@ -12634,15 +13189,15 @@ class WatchRootResolver {
|
|
|
12634
13189
|
async resolve() {
|
|
12635
13190
|
const tsconfig = await this.#app.getTsConfig();
|
|
12636
13191
|
const set = new Set;
|
|
12637
|
-
set.add(
|
|
13192
|
+
set.add(path37.resolve(`${this.#app.cwdPath}/page`));
|
|
12638
13193
|
for (const targets of Object.values(tsconfig.compilerOptions.paths ?? {})) {
|
|
12639
13194
|
for (const target of targets) {
|
|
12640
13195
|
if (!target)
|
|
12641
13196
|
continue;
|
|
12642
|
-
if (
|
|
13197
|
+
if (path37.isAbsolute(target))
|
|
12643
13198
|
continue;
|
|
12644
13199
|
const cleaned = target.replace(/\/?\*+.*$/, "").replace(/\/[^/]+\.[^/]+$/, "");
|
|
12645
|
-
const resolved =
|
|
13200
|
+
const resolved = path37.resolve(this.#app.workspace.workspaceRoot, cleaned);
|
|
12646
13201
|
if (fs6.existsSync(resolved))
|
|
12647
13202
|
set.add(resolved);
|
|
12648
13203
|
}
|
|
@@ -12709,7 +13264,7 @@ class ApplicationBuildRunner {
|
|
|
12709
13264
|
phases: this.#phases,
|
|
12710
13265
|
durationMs: Date.now() - this.#startedAt,
|
|
12711
13266
|
outputDir: this.#app.dist.cwdPath,
|
|
12712
|
-
artifactDir:
|
|
13267
|
+
artifactDir: path38.join(this.#app.dist.cwdPath, ".akan/artifact")
|
|
12713
13268
|
};
|
|
12714
13269
|
}
|
|
12715
13270
|
async typecheck(options = {}) {
|
|
@@ -12717,7 +13272,7 @@ class ApplicationBuildRunner {
|
|
|
12717
13272
|
await this.#app.getPageKeys({ refresh: true });
|
|
12718
13273
|
const { typecheckDir, tsconfigPath } = await this.#writeTypecheckTsconfig({ incremental });
|
|
12719
13274
|
if (clean)
|
|
12720
|
-
await rm4(
|
|
13275
|
+
await rm4(path38.join(typecheckDir, "tsconfig.tsbuildinfo"), { force: true });
|
|
12721
13276
|
await this.#checkProjectInChildProcess(tsconfigPath);
|
|
12722
13277
|
}
|
|
12723
13278
|
async#runPhase(id, label, task, summarize, options = {}) {
|
|
@@ -12789,7 +13344,7 @@ class ApplicationBuildRunner {
|
|
|
12789
13344
|
};
|
|
12790
13345
|
}
|
|
12791
13346
|
async#writeConsoleShim() {
|
|
12792
|
-
await Bun.write(
|
|
13347
|
+
await Bun.write(path38.join(this.#app.dist.cwdPath, "console.js"), `import { cnst, db, dict, option, server, sig, srv } from "./server.js";
|
|
12793
13348
|
import { assertAkanConsoleAllowed, startAkanConsole } from "./console-runtime.js";
|
|
12794
13349
|
|
|
12795
13350
|
const run = async () => {
|
|
@@ -12812,14 +13367,14 @@ void run().catch((error) => {
|
|
|
12812
13367
|
try {
|
|
12813
13368
|
return Bun.resolveSync("akanjs/server/rsc-worker", import.meta.dir);
|
|
12814
13369
|
} catch {
|
|
12815
|
-
return
|
|
13370
|
+
return path38.join(this.#app.workspace.workspaceRoot, "pkgs/akanjs/server/rscWorker.tsx");
|
|
12816
13371
|
}
|
|
12817
13372
|
}
|
|
12818
13373
|
#resolveConsoleRuntimeBuildEntry() {
|
|
12819
13374
|
try {
|
|
12820
|
-
return
|
|
13375
|
+
return path38.join(path38.dirname(Bun.resolveSync("akanjs/server", import.meta.dir)), "console.ts");
|
|
12821
13376
|
} catch {
|
|
12822
|
-
return
|
|
13377
|
+
return path38.join(this.#app.workspace.workspaceRoot, "pkgs/akanjs/server/console.ts");
|
|
12823
13378
|
}
|
|
12824
13379
|
}
|
|
12825
13380
|
async#buildCsr() {
|
|
@@ -12836,7 +13391,7 @@ void run().catch((error) => {
|
|
|
12836
13391
|
return { base, allRoutes };
|
|
12837
13392
|
}
|
|
12838
13393
|
async#writeTypecheckTsconfig({ incremental = true } = {}) {
|
|
12839
|
-
const typecheckDir =
|
|
13394
|
+
const typecheckDir = path38.join(this.#app.cwdPath, ".akan", "typecheck");
|
|
12840
13395
|
await mkdir8(typecheckDir, { recursive: true });
|
|
12841
13396
|
const tsconfig = {
|
|
12842
13397
|
extends: "../../tsconfig.json",
|
|
@@ -12855,7 +13410,7 @@ void run().catch((error) => {
|
|
|
12855
13410
|
],
|
|
12856
13411
|
references: []
|
|
12857
13412
|
};
|
|
12858
|
-
const tsconfigPath =
|
|
13413
|
+
const tsconfigPath = path38.join(typecheckDir, "tsconfig.json");
|
|
12859
13414
|
await Bun.write(tsconfigPath, `${JSON.stringify(tsconfig, null, 2)}
|
|
12860
13415
|
`);
|
|
12861
13416
|
return { typecheckDir, tsconfigPath };
|
|
@@ -12881,10 +13436,10 @@ void run().catch((error) => {
|
|
|
12881
13436
|
}
|
|
12882
13437
|
async#resolveTypecheckWorkerEntry() {
|
|
12883
13438
|
const candidates = [
|
|
12884
|
-
|
|
12885
|
-
|
|
12886
|
-
|
|
12887
|
-
|
|
13439
|
+
path38.join(this.#app.workspace.workspaceRoot, "pkgs/@akanjs/devkit/typecheck/typecheck.proc.ts"),
|
|
13440
|
+
path38.join(this.#app.workspace.workspaceRoot, "node_modules/@akanjs/devkit/typecheck/typecheck.proc.ts"),
|
|
13441
|
+
path38.join(import.meta.dir, "typecheck.proc.js"),
|
|
13442
|
+
path38.join(import.meta.dir, "typecheck.proc.ts")
|
|
12888
13443
|
];
|
|
12889
13444
|
for (const candidate of candidates)
|
|
12890
13445
|
if (await Bun.file(candidate).exists())
|
|
@@ -12918,7 +13473,7 @@ void run().catch((error) => {
|
|
|
12918
13473
|
}
|
|
12919
13474
|
// pkgs/@akanjs/devkit/applicationReleasePackager.ts
|
|
12920
13475
|
import { cp, mkdir as mkdir9, rm as rm5 } from "fs/promises";
|
|
12921
|
-
import
|
|
13476
|
+
import path39 from "path";
|
|
12922
13477
|
|
|
12923
13478
|
// pkgs/@akanjs/devkit/uploadRelease.ts
|
|
12924
13479
|
import { HttpClient as HttpClient2, Logger as Logger9 } from "akanjs/common";
|
|
@@ -13035,7 +13590,7 @@ class ApplicationReleasePackager {
|
|
|
13035
13590
|
await cp(this.#app.dist.cwdPath, buildRoot, { recursive: true });
|
|
13036
13591
|
await rm5(`${buildRoot}/frontend/.next`, { recursive: true, force: true });
|
|
13037
13592
|
const releaseRoot = this.#app.workspace.workspaceRoot;
|
|
13038
|
-
const releaseArchivePath =
|
|
13593
|
+
const releaseArchivePath = path39.relative(releaseRoot, `${releaseRoot}/releases/builds/${this.#app.name}-release.tar.gz`).split(path39.sep).join("/");
|
|
13039
13594
|
await this.#app.workspace.spawn("tar", ["-zcf", releaseArchivePath, "-C", buildRoot, "./"], { cwd: releaseRoot });
|
|
13040
13595
|
await this.#writeCsrZipIfPresent();
|
|
13041
13596
|
return { platformVersion };
|
|
@@ -13057,17 +13612,17 @@ class ApplicationReleasePackager {
|
|
|
13057
13612
|
await cp(this.#app.dist.cwdPath, `${sourceRoot}/apps/${this.#app.name}`, { recursive: true });
|
|
13058
13613
|
const libDeps = ["social", "shared", "platform", "util"];
|
|
13059
13614
|
await Promise.all(libDeps.map((lib) => cp(`${this.#app.workspace.cwdPath}/libs/${lib}`, `${sourceRoot}/libs/${lib}`, { recursive: true })));
|
|
13060
|
-
await Promise.all([".next", "ios", "android", "public/libs"].map(async (
|
|
13061
|
-
const targetPath = `${sourceRoot}/apps/${this.#app.name}/${
|
|
13615
|
+
await Promise.all([".next", "ios", "android", "public/libs"].map(async (path40) => {
|
|
13616
|
+
const targetPath = `${sourceRoot}/apps/${this.#app.name}/${path40}`;
|
|
13062
13617
|
if (await FileSys.dirExists(targetPath))
|
|
13063
13618
|
await rm5(targetPath, { recursive: true, force: true });
|
|
13064
13619
|
}));
|
|
13065
13620
|
const syncPaths = [".husky", ".gitignore", "package.json"];
|
|
13066
|
-
await Promise.all(syncPaths.map((
|
|
13621
|
+
await Promise.all(syncPaths.map((path40) => cp(`${this.#app.workspace.cwdPath}/${path40}`, `${sourceRoot}/${path40}`, { recursive: true })));
|
|
13067
13622
|
await this.#writeSourceTsconfig(sourceRoot, libDeps);
|
|
13068
13623
|
await Bun.write(`${sourceRoot}/README.md`, readme);
|
|
13069
13624
|
const sourceCwd = this.#app.workspace.cwdPath;
|
|
13070
|
-
const sourceArchivePath =
|
|
13625
|
+
const sourceArchivePath = path39.relative(sourceCwd, `${sourceCwd}/releases/sources/${this.#app.name}-source.tar.gz`).split(path39.sep).join("/");
|
|
13071
13626
|
await this.#app.workspace.spawn("tar", ["-zcf", sourceArchivePath, "-C", sourceRoot, "./"], { cwd: sourceCwd });
|
|
13072
13627
|
}
|
|
13073
13628
|
async#resetSourceRoot(sourceRoot) {
|
|
@@ -13150,20 +13705,20 @@ class ApplicationReleasePackager {
|
|
|
13150
13705
|
}
|
|
13151
13706
|
}
|
|
13152
13707
|
// pkgs/@akanjs/devkit/applicationTestPreload.ts
|
|
13153
|
-
import
|
|
13708
|
+
import path40 from "path";
|
|
13154
13709
|
var SIGNAL_TEST_PRELOAD_PATH = "test/signalTest.preload.ts";
|
|
13155
13710
|
async function resolveSignalTestPreloadPath(target) {
|
|
13156
13711
|
const candidates = [];
|
|
13157
13712
|
const addResolvedPackageCandidate = (basePath2) => {
|
|
13158
13713
|
try {
|
|
13159
|
-
candidates.push(
|
|
13714
|
+
candidates.push(path40.join(path40.dirname(Bun.resolveSync("akanjs/package.json", basePath2)), SIGNAL_TEST_PRELOAD_PATH));
|
|
13160
13715
|
} catch {}
|
|
13161
13716
|
};
|
|
13162
13717
|
addResolvedPackageCandidate(target.cwdPath);
|
|
13163
13718
|
addResolvedPackageCandidate(process.cwd());
|
|
13164
|
-
addResolvedPackageCandidate(
|
|
13719
|
+
addResolvedPackageCandidate(path40.dirname(Bun.main));
|
|
13165
13720
|
addResolvedPackageCandidate(import.meta.dir);
|
|
13166
|
-
candidates.push(
|
|
13721
|
+
candidates.push(path40.join(target.cwdPath, "../../node_modules/akanjs", SIGNAL_TEST_PRELOAD_PATH), path40.join(target.cwdPath, "../../pkgs/akanjs", SIGNAL_TEST_PRELOAD_PATH), path40.join(process.cwd(), "node_modules/akanjs", SIGNAL_TEST_PRELOAD_PATH), path40.join(process.cwd(), "pkgs/akanjs", SIGNAL_TEST_PRELOAD_PATH), path40.join(path40.dirname(Bun.main), "../../akanjs", SIGNAL_TEST_PRELOAD_PATH), path40.resolve(import.meta.dir, "../../akanjs", SIGNAL_TEST_PRELOAD_PATH));
|
|
13167
13722
|
const uniqueCandidates = [...new Set(candidates)];
|
|
13168
13723
|
for (const candidate of uniqueCandidates) {
|
|
13169
13724
|
if (await Bun.file(candidate).exists())
|
|
@@ -13177,7 +13732,7 @@ ${uniqueCandidates.map((candidate) => ` - ${candidate}`).join(`
|
|
|
13177
13732
|
// pkgs/@akanjs/devkit/builder.ts
|
|
13178
13733
|
import { existsSync as existsSync2 } from "fs";
|
|
13179
13734
|
import { mkdir as mkdir10 } from "fs/promises";
|
|
13180
|
-
import
|
|
13735
|
+
import path41 from "path";
|
|
13181
13736
|
var SKIP_ENTRY_DIR_SET = new Set(["node_modules", "dist", "build", ".git", ".next"]);
|
|
13182
13737
|
var assetExtensions = [".css", ".md", ".js", ".png", ".ico", ".svg", ".json", ".template"];
|
|
13183
13738
|
var assetLoader = Object.fromEntries(assetExtensions.map((ext) => [ext, "file"]));
|
|
@@ -13194,14 +13749,14 @@ class Builder {
|
|
|
13194
13749
|
#globEntrypoints(cwd, pattern) {
|
|
13195
13750
|
const glob = new Bun.Glob(pattern);
|
|
13196
13751
|
return Array.from(glob.scanSync({ cwd, onlyFiles: true })).filter((relativePath) => {
|
|
13197
|
-
const segments = relativePath.split(
|
|
13752
|
+
const segments = relativePath.split(path41.sep);
|
|
13198
13753
|
return !segments.some((segment) => SKIP_ENTRY_DIR_SET.has(segment));
|
|
13199
|
-
}).map((rel) =>
|
|
13754
|
+
}).map((rel) => path41.join(cwd, rel));
|
|
13200
13755
|
}
|
|
13201
13756
|
#globFiles(cwd, pattern = "**/*.*") {
|
|
13202
13757
|
const glob = new Bun.Glob(pattern);
|
|
13203
13758
|
return Array.from(glob.scanSync({ cwd, onlyFiles: true })).filter((relativePath) => {
|
|
13204
|
-
const segments = relativePath.split(
|
|
13759
|
+
const segments = relativePath.split(path41.sep);
|
|
13205
13760
|
return !segments.some((segment) => SKIP_ENTRY_DIR_SET.has(segment));
|
|
13206
13761
|
});
|
|
13207
13762
|
}
|
|
@@ -13209,17 +13764,17 @@ class Builder {
|
|
|
13209
13764
|
const out = [];
|
|
13210
13765
|
for (const p of additionalEntryPoints) {
|
|
13211
13766
|
if (p.includes("*")) {
|
|
13212
|
-
const rel = p.startsWith(`${cwd}/`) || p.startsWith(`${cwd}${
|
|
13767
|
+
const rel = p.startsWith(`${cwd}/`) || p.startsWith(`${cwd}${path41.sep}`) ? p.slice(cwd.length + 1) : p;
|
|
13213
13768
|
out.push(...this.#globEntrypoints(cwd, rel));
|
|
13214
13769
|
} else
|
|
13215
|
-
out.push(
|
|
13770
|
+
out.push(path41.isAbsolute(p) ? p : path41.join(cwd, p));
|
|
13216
13771
|
}
|
|
13217
13772
|
return out;
|
|
13218
13773
|
}
|
|
13219
13774
|
#getBuildOptions({ bundle = false, additionalEntryPoints = [] } = {}) {
|
|
13220
13775
|
const cwd = this.#executor.cwdPath;
|
|
13221
13776
|
const entrypoints = [
|
|
13222
|
-
...bundle ? [
|
|
13777
|
+
...bundle ? [path41.join(cwd, "index.ts")] : this.#globEntrypoints(cwd, "**/*.{ts,tsx}"),
|
|
13223
13778
|
...this.#resolveAdditionalEntrypoints(cwd, additionalEntryPoints)
|
|
13224
13779
|
];
|
|
13225
13780
|
return {
|
|
@@ -13240,9 +13795,9 @@ class Builder {
|
|
|
13240
13795
|
for (const relativePath of this.#globFiles(cwd)) {
|
|
13241
13796
|
if (relativePath === "package.json")
|
|
13242
13797
|
continue;
|
|
13243
|
-
const sourcePath =
|
|
13244
|
-
const targetPath =
|
|
13245
|
-
await mkdir10(
|
|
13798
|
+
const sourcePath = path41.join(cwd, relativePath);
|
|
13799
|
+
const targetPath = path41.join(this.#distExecutor.cwdPath, relativePath);
|
|
13800
|
+
await mkdir10(path41.dirname(targetPath), { recursive: true });
|
|
13246
13801
|
await Bun.write(targetPath, Bun.file(sourcePath));
|
|
13247
13802
|
}
|
|
13248
13803
|
}
|
|
@@ -13253,13 +13808,13 @@ class Builder {
|
|
|
13253
13808
|
return withoutFormatDir;
|
|
13254
13809
|
if (!hasDotSlash && withoutFormatDir === publishedPath)
|
|
13255
13810
|
return publishedPath;
|
|
13256
|
-
const parsed =
|
|
13811
|
+
const parsed = path41.posix.parse(withoutFormatDir);
|
|
13257
13812
|
if (![".js", ".mjs", ".cjs"].includes(parsed.ext))
|
|
13258
13813
|
return withoutFormatDir;
|
|
13259
|
-
const withoutExt =
|
|
13814
|
+
const withoutExt = path41.posix.join(parsed.dir, parsed.name);
|
|
13260
13815
|
const sourcePath = withoutExt.startsWith("./") ? withoutExt.slice(2) : withoutExt;
|
|
13261
13816
|
const sourceCandidates = [`${sourcePath}.ts`, `${sourcePath}.tsx`];
|
|
13262
|
-
const matchedSource = sourceCandidates.find((candidate) => existsSync2(
|
|
13817
|
+
const matchedSource = sourceCandidates.find((candidate) => existsSync2(path41.join(this.#executor.cwdPath, candidate)));
|
|
13263
13818
|
if (!matchedSource)
|
|
13264
13819
|
return withoutFormatDir;
|
|
13265
13820
|
return hasDotSlash ? `./${matchedSource}` : matchedSource;
|
|
@@ -13308,9 +13863,9 @@ class Builder {
|
|
|
13308
13863
|
}
|
|
13309
13864
|
}
|
|
13310
13865
|
// pkgs/@akanjs/devkit/capacitorApp.ts
|
|
13311
|
-
import { cp as cp2, mkdir as mkdir11, readFile as
|
|
13866
|
+
import { cp as cp2, mkdir as mkdir11, readFile as readFile3, rm as rm6, writeFile as writeFile3 } from "fs/promises";
|
|
13312
13867
|
import os from "os";
|
|
13313
|
-
import
|
|
13868
|
+
import path42 from "path";
|
|
13314
13869
|
import { select as select2 } from "@inquirer/prompts";
|
|
13315
13870
|
import { MobileProject } from "@trapezedev/project";
|
|
13316
13871
|
import { capitalize as capitalize5 } from "akanjs/common";
|
|
@@ -13517,13 +14072,13 @@ var rootCapacitorConfigFilenames = [
|
|
|
13517
14072
|
"capacitor.config.js",
|
|
13518
14073
|
"capacitor.config.json"
|
|
13519
14074
|
];
|
|
13520
|
-
var rootCapacitorConfigPaths = (appRoot) => rootCapacitorConfigFilenames.map((file) =>
|
|
14075
|
+
var rootCapacitorConfigPaths = (appRoot) => rootCapacitorConfigFilenames.map((file) => path42.join(appRoot, file));
|
|
13521
14076
|
async function clearRootCapacitorConfigs(appRoot) {
|
|
13522
14077
|
await Promise.all(rootCapacitorConfigPaths(appRoot).map((file) => rm6(file, { force: true })));
|
|
13523
14078
|
}
|
|
13524
14079
|
async function writeRootCapacitorConfig(appRoot, content) {
|
|
13525
14080
|
await clearRootCapacitorConfigs(appRoot);
|
|
13526
|
-
await Bun.write(
|
|
14081
|
+
await Bun.write(path42.join(appRoot, "capacitor.config.json"), content);
|
|
13527
14082
|
}
|
|
13528
14083
|
var getLocalIP = () => {
|
|
13529
14084
|
const interfaces = os.networkInterfaces();
|
|
@@ -13632,13 +14187,13 @@ function buildIosNativeRunCommand({
|
|
|
13632
14187
|
scheme = "App",
|
|
13633
14188
|
configuration = "Debug"
|
|
13634
14189
|
}) {
|
|
13635
|
-
const derivedDataPath =
|
|
14190
|
+
const derivedDataPath = path42.join(appRoot, "ios/DerivedData", device.id);
|
|
13636
14191
|
const productPlatform = device.kind === "device" ? "iphoneos" : "iphonesimulator";
|
|
13637
14192
|
const destination = device.kind === "device" ? `id=${device.xcodebuildId ?? device.id}` : `platform=iOS Simulator,id=${device.id}`;
|
|
13638
14193
|
return {
|
|
13639
14194
|
configuration,
|
|
13640
14195
|
derivedDataPath,
|
|
13641
|
-
appPath:
|
|
14196
|
+
appPath: path42.join(derivedDataPath, "Build/Products", `${configuration}-${productPlatform}`, "App.app"),
|
|
13642
14197
|
xcodebuildArgs: [
|
|
13643
14198
|
"-project",
|
|
13644
14199
|
"App.xcodeproj",
|
|
@@ -13851,7 +14406,7 @@ function materializeCapacitorConfig(target, { operation, localServerUrl, localIp
|
|
|
13851
14406
|
...capacitorConfig,
|
|
13852
14407
|
appId,
|
|
13853
14408
|
appName,
|
|
13854
|
-
webDir:
|
|
14409
|
+
webDir: path42.posix.join(".akan", "mobile", name, "www"),
|
|
13855
14410
|
plugins: {
|
|
13856
14411
|
CapacitorCookies: { enabled: true },
|
|
13857
14412
|
...pluginsConfig,
|
|
@@ -13915,10 +14470,10 @@ class CapacitorApp {
|
|
|
13915
14470
|
constructor(app, target) {
|
|
13916
14471
|
this.app = app;
|
|
13917
14472
|
this.target = target;
|
|
13918
|
-
this.targetRootPath =
|
|
13919
|
-
this.targetRoot =
|
|
13920
|
-
this.targetWebRoot =
|
|
13921
|
-
this.targetAssetRoot =
|
|
14473
|
+
this.targetRootPath = path42.posix.join(".akan", "mobile", this.target.name);
|
|
14474
|
+
this.targetRoot = path42.join(this.app.cwdPath, this.targetRootPath);
|
|
14475
|
+
this.targetWebRoot = path42.join(this.targetRoot, "www");
|
|
14476
|
+
this.targetAssetRoot = path42.join(this.targetRoot, "assets");
|
|
13922
14477
|
this.project = new MobileProject(this.app.cwdPath, {
|
|
13923
14478
|
android: { path: this.androidRootPath },
|
|
13924
14479
|
ios: { path: this.iosProjectPath }
|
|
@@ -13933,9 +14488,9 @@ class CapacitorApp {
|
|
|
13933
14488
|
await mkdir11(this.targetRoot, { recursive: true });
|
|
13934
14489
|
if (regenerate) {
|
|
13935
14490
|
if (!platform || platform === "ios")
|
|
13936
|
-
await rm6(
|
|
14491
|
+
await rm6(path42.join(this.app.cwdPath, this.iosRootPath), { recursive: true, force: true });
|
|
13937
14492
|
if (!platform || platform === "android")
|
|
13938
|
-
await rm6(
|
|
14493
|
+
await rm6(path42.join(this.app.cwdPath, this.androidRootPath), { recursive: true, force: true });
|
|
13939
14494
|
}
|
|
13940
14495
|
const project = this.project;
|
|
13941
14496
|
await this.project.load();
|
|
@@ -14059,7 +14614,7 @@ ${textError instanceof Error ? textError.message : ""}`);
|
|
|
14059
14614
|
const xcodebuildArgs = noAllowProvisioningUpdates ? command.xcodebuildArgs : [...command.xcodebuildArgs.slice(0, -1), "-allowProvisioningUpdates", ...command.xcodebuildArgs.slice(-1)];
|
|
14060
14615
|
try {
|
|
14061
14616
|
await this.#spawn("xcodebuild", xcodebuildArgs, {
|
|
14062
|
-
cwd:
|
|
14617
|
+
cwd: path42.join(this.app.cwdPath, this.iosProjectPath),
|
|
14063
14618
|
env: mobileEnv
|
|
14064
14619
|
});
|
|
14065
14620
|
const devicectlId = runTarget.devicectlId ?? runTarget.id;
|
|
@@ -14084,7 +14639,7 @@ ${textError instanceof Error ? textError.message : ""}`);
|
|
|
14084
14639
|
return isRecord2(this.target.ios) && typeof this.target.ios.scheme === "string" ? this.target.ios.scheme : "App";
|
|
14085
14640
|
}
|
|
14086
14641
|
async#getIosDevelopmentTeam() {
|
|
14087
|
-
const pbxprojPath =
|
|
14642
|
+
const pbxprojPath = path42.join(this.app.cwdPath, this.iosProjectPath, "App.xcodeproj/project.pbxproj");
|
|
14088
14643
|
if (!await Bun.file(pbxprojPath).exists())
|
|
14089
14644
|
return;
|
|
14090
14645
|
return (await Bun.file(pbxprojPath).text()).match(/DEVELOPMENT_TEAM = ([^;]+);/)?.[1]?.trim();
|
|
@@ -14111,7 +14666,7 @@ ${error.message}`;
|
|
|
14111
14666
|
await this.#setDeepLinksInAndroid(this.target.deepLinks?.schemes ?? [], this.target.deepLinks?.domains ?? []);
|
|
14112
14667
|
}
|
|
14113
14668
|
async#updateAndroidBuildTypes() {
|
|
14114
|
-
const appGradle = await FileEditor.create(
|
|
14669
|
+
const appGradle = await FileEditor.create(path42.join(this.app.cwdPath, this.androidRootPath, "app/build.gradle"));
|
|
14115
14670
|
const buildTypesBlock = `
|
|
14116
14671
|
debug {
|
|
14117
14672
|
applicationIdSuffix ".debug"
|
|
@@ -14155,7 +14710,7 @@ ${error.message}`;
|
|
|
14155
14710
|
const gradleCommand = isWindows ? "gradlew.bat" : "./gradlew";
|
|
14156
14711
|
await this.app.spawn(gradleCommand, [assembleType === "apk" ? "assembleRelease" : "bundleRelease"], {
|
|
14157
14712
|
stdio: "inherit",
|
|
14158
|
-
cwd:
|
|
14713
|
+
cwd: path42.join(this.app.cwdPath, this.androidRootPath),
|
|
14159
14714
|
env: await this.#commandEnv("release", env)
|
|
14160
14715
|
});
|
|
14161
14716
|
}
|
|
@@ -14163,10 +14718,10 @@ ${error.message}`;
|
|
|
14163
14718
|
await this.#spawnMobile("npx", ["cap", "open", "android"], { operation: "local", env: "local" });
|
|
14164
14719
|
}
|
|
14165
14720
|
async#ensureAndroidAssetsDir() {
|
|
14166
|
-
await mkdir11(
|
|
14721
|
+
await mkdir11(path42.join(this.app.cwdPath, this.androidAssetsPath), { recursive: true });
|
|
14167
14722
|
}
|
|
14168
14723
|
async#ensureAndroidDebugKeystore() {
|
|
14169
|
-
const keystorePath =
|
|
14724
|
+
const keystorePath = path42.join(this.app.cwdPath, this.androidRootPath, "app/debug.keystore");
|
|
14170
14725
|
if (await Bun.file(keystorePath).exists())
|
|
14171
14726
|
return;
|
|
14172
14727
|
await this.#spawn("keytool", [
|
|
@@ -14205,7 +14760,7 @@ ${error.message}`;
|
|
|
14205
14760
|
await this.#spawnMobile("npx", args, { operation, env }, { stdio: "inherit" });
|
|
14206
14761
|
}
|
|
14207
14762
|
async#assertAndroidReleaseSigningConfig() {
|
|
14208
|
-
const gradlePropertiesPath =
|
|
14763
|
+
const gradlePropertiesPath = path42.join(this.app.cwdPath, this.androidRootPath, "gradle.properties");
|
|
14209
14764
|
const gradleProperties = await Bun.file(gradlePropertiesPath).exists() ? await Bun.file(gradlePropertiesPath).text() : "";
|
|
14210
14765
|
const missingKeys = getMissingAndroidReleaseSigningKeys({ gradleProperties });
|
|
14211
14766
|
if (missingKeys.length > 0)
|
|
@@ -14232,12 +14787,12 @@ ${error.message}`;
|
|
|
14232
14787
|
await this.#prepareAndroid({ operation: "release", env: "main" });
|
|
14233
14788
|
}
|
|
14234
14789
|
async prepareWww() {
|
|
14235
|
-
const htmlSource =
|
|
14790
|
+
const htmlSource = path42.join(this.app.dist.cwdPath, "csr", targetHtmlFilename(this.target));
|
|
14236
14791
|
if (!await Bun.file(htmlSource).exists())
|
|
14237
14792
|
throw new Error(`CSR html for mobile target '${this.target.name}' not found: ${htmlSource}`);
|
|
14238
14793
|
await rm6(this.targetWebRoot, { recursive: true, force: true });
|
|
14239
14794
|
await mkdir11(this.targetWebRoot, { recursive: true });
|
|
14240
|
-
await Bun.write(
|
|
14795
|
+
await Bun.write(path42.join(this.targetWebRoot, "index.html"), this.#injectMobileTargetMeta(await Bun.file(htmlSource).text()));
|
|
14241
14796
|
}
|
|
14242
14797
|
#injectMobileTargetMeta(html) {
|
|
14243
14798
|
const basePath2 = this.target.basePath?.replace(/^\/+|\/+$/g, "") ?? "";
|
|
@@ -14261,7 +14816,7 @@ ${error.message}`;
|
|
|
14261
14816
|
});
|
|
14262
14817
|
const content = `${JSON.stringify(config, null, 2)}
|
|
14263
14818
|
`;
|
|
14264
|
-
await Bun.write(
|
|
14819
|
+
await Bun.write(path42.join(this.targetRoot, "capacitor.config.json"), content);
|
|
14265
14820
|
return content;
|
|
14266
14821
|
}
|
|
14267
14822
|
async#prepareTargetAssets() {
|
|
@@ -14269,11 +14824,11 @@ ${error.message}`;
|
|
|
14269
14824
|
return;
|
|
14270
14825
|
await mkdir11(this.targetAssetRoot, { recursive: true });
|
|
14271
14826
|
if (this.target.assets.icon)
|
|
14272
|
-
await cp2(
|
|
14827
|
+
await cp2(path42.join(this.app.cwdPath, this.target.assets.icon), path42.join(this.targetAssetRoot, "icon.png"), {
|
|
14273
14828
|
force: true
|
|
14274
14829
|
});
|
|
14275
14830
|
if (this.target.assets.splash)
|
|
14276
|
-
await cp2(
|
|
14831
|
+
await cp2(path42.join(this.app.cwdPath, this.target.assets.splash), path42.join(this.targetAssetRoot, "splash.png"), {
|
|
14277
14832
|
force: true
|
|
14278
14833
|
});
|
|
14279
14834
|
}
|
|
@@ -14281,11 +14836,11 @@ ${error.message}`;
|
|
|
14281
14836
|
const files = this.target.files?.[platform];
|
|
14282
14837
|
if (!files)
|
|
14283
14838
|
return;
|
|
14284
|
-
const platformRoot =
|
|
14839
|
+
const platformRoot = path42.join(this.app.cwdPath, platform === "ios" ? this.iosRootPath : this.androidRootPath);
|
|
14285
14840
|
await Promise.all(Object.entries(files).map(async ([to, from]) => {
|
|
14286
|
-
const targetPath =
|
|
14287
|
-
await mkdir11(
|
|
14288
|
-
await cp2(
|
|
14841
|
+
const targetPath = path42.join(platformRoot, to);
|
|
14842
|
+
await mkdir11(path42.dirname(targetPath), { recursive: true });
|
|
14843
|
+
await cp2(path42.join(this.app.cwdPath, from), targetPath, { force: true });
|
|
14289
14844
|
}));
|
|
14290
14845
|
}
|
|
14291
14846
|
async#generateAssets({ operation, env }) {
|
|
@@ -14295,7 +14850,7 @@ ${error.message}`;
|
|
|
14295
14850
|
"@capacitor/assets",
|
|
14296
14851
|
"generate",
|
|
14297
14852
|
"--assetPath",
|
|
14298
|
-
|
|
14853
|
+
path42.posix.join(this.targetRootPath, "assets"),
|
|
14299
14854
|
"--iosProject",
|
|
14300
14855
|
this.iosProjectPath,
|
|
14301
14856
|
"--androidProject",
|
|
@@ -14329,13 +14884,18 @@ ${error.message}`;
|
|
|
14329
14884
|
}
|
|
14330
14885
|
for (const permission of this.target.permissions ?? []) {
|
|
14331
14886
|
const claimants = nativePlugins.get(permission);
|
|
14332
|
-
if (
|
|
14333
|
-
|
|
14887
|
+
if (claimants?.length) {
|
|
14888
|
+
const ctx = this.#makeNativeContext({ operation, env });
|
|
14889
|
+
for (const plugin of claimants)
|
|
14890
|
+
await plugin.capacitor?.configureNative?.(ctx);
|
|
14334
14891
|
continue;
|
|
14335
14892
|
}
|
|
14336
|
-
|
|
14337
|
-
|
|
14338
|
-
|
|
14893
|
+
if (permission === "camera")
|
|
14894
|
+
await this.addCamera();
|
|
14895
|
+
else if (permission === "contacts")
|
|
14896
|
+
await this.addContact();
|
|
14897
|
+
else if (permission === "location")
|
|
14898
|
+
await this.addLocation();
|
|
14339
14899
|
}
|
|
14340
14900
|
}
|
|
14341
14901
|
#makeNativeContext({ operation, env }) {
|
|
@@ -14452,11 +15012,33 @@ ${error.message}`;
|
|
|
14452
15012
|
await this.#clearRootCapacitorConfigs();
|
|
14453
15013
|
}
|
|
14454
15014
|
}
|
|
15015
|
+
async addCamera() {
|
|
15016
|
+
await this.#setPermissionInIos({
|
|
15017
|
+
cameraUsageDescription: "$(PRODUCT_NAME) requires access to the camera to take photos.",
|
|
15018
|
+
photoAddUsageDescription: "$(PRODUCT_NAME) requires access to the photo library to take photos.",
|
|
15019
|
+
photoUsageDescription: "$(PRODUCT_NAME) requires access to the photo library to take photos."
|
|
15020
|
+
});
|
|
15021
|
+
this.#setPermissionsInAndroid(["READ_MEDIA_IMAGES", "READ_EXTERNAL_STORAGE", "WRITE_EXTERNAL_STORAGE"]);
|
|
15022
|
+
}
|
|
15023
|
+
async addContact() {
|
|
15024
|
+
await this.#setPermissionInIos({
|
|
15025
|
+
contactsUsageDescription: "$(PRODUCT_NAME) requires access to the contacts to add new contacts."
|
|
15026
|
+
});
|
|
15027
|
+
this.#setPermissionsInAndroid(["READ_CONTACTS", "WRITE_CONTACTS"]);
|
|
15028
|
+
}
|
|
15029
|
+
async addLocation() {
|
|
15030
|
+
await this.#setPermissionInIos({
|
|
15031
|
+
locationAlwaysUsageDescription: "$(PRODUCT_NAME) requires access to the location to get the user's location.",
|
|
15032
|
+
locationWhenInUseUsageDescription: "$(PRODUCT_NAME) requires access to the location to get the user's location."
|
|
15033
|
+
});
|
|
15034
|
+
this.#setPermissionsInAndroid(["ACCESS_COARSE_LOCATION", "ACCESS_FINE_LOCATION"]);
|
|
15035
|
+
this.#setFeaturesInAndroid(["android.hardware.location.gps"]);
|
|
15036
|
+
}
|
|
14455
15037
|
#addIosEntitlements(entitlements) {
|
|
14456
15038
|
Object.assign(this.#iosEntitlements, entitlements);
|
|
14457
15039
|
}
|
|
14458
15040
|
async#editIosAppDelegate(transform) {
|
|
14459
|
-
const appDelegatePath =
|
|
15041
|
+
const appDelegatePath = path42.join(this.app.cwdPath, this.iosProjectPath, "App/AppDelegate.swift");
|
|
14460
15042
|
if (!await Bun.file(appDelegatePath).exists())
|
|
14461
15043
|
return;
|
|
14462
15044
|
const editor = await FileEditor.create(appDelegatePath);
|
|
@@ -14498,7 +15080,7 @@ ${error.message}`;
|
|
|
14498
15080
|
if (Object.keys(this.#iosEntitlements).length === 0)
|
|
14499
15081
|
return;
|
|
14500
15082
|
const entitlementsRelPath = "App/App.entitlements";
|
|
14501
|
-
const entitlementsPath =
|
|
15083
|
+
const entitlementsPath = path42.join(this.app.cwdPath, this.iosProjectPath, entitlementsRelPath);
|
|
14502
15084
|
const body = [
|
|
14503
15085
|
'<?xml version="1.0" encoding="UTF-8"?>',
|
|
14504
15086
|
'<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">',
|
|
@@ -14512,12 +15094,12 @@ ${error.message}`;
|
|
|
14512
15094
|
`);
|
|
14513
15095
|
const currentBody = await Bun.file(entitlementsPath).exists() ? await Bun.file(entitlementsPath).text() : undefined;
|
|
14514
15096
|
if (currentBody !== body)
|
|
14515
|
-
await
|
|
15097
|
+
await writeFile3(entitlementsPath, body);
|
|
14516
15098
|
await this.#setCodeSignEntitlementsInIos(entitlementsRelPath);
|
|
14517
15099
|
}
|
|
14518
15100
|
async#setCodeSignEntitlementsInIos(entitlementsRelPath) {
|
|
14519
|
-
const pbxprojPath =
|
|
14520
|
-
const lines = (await
|
|
15101
|
+
const pbxprojPath = path42.join(this.app.cwdPath, this.iosProjectPath, "App.xcodeproj/project.pbxproj");
|
|
15102
|
+
const lines = (await readFile3(pbxprojPath, "utf8")).split(`
|
|
14521
15103
|
`);
|
|
14522
15104
|
let changed = false;
|
|
14523
15105
|
for (let index = 0;index < lines.length; index++) {
|
|
@@ -14539,12 +15121,12 @@ ${error.message}`;
|
|
|
14539
15121
|
changed = true;
|
|
14540
15122
|
}
|
|
14541
15123
|
if (changed)
|
|
14542
|
-
await
|
|
15124
|
+
await writeFile3(pbxprojPath, lines.join(`
|
|
14543
15125
|
`));
|
|
14544
15126
|
}
|
|
14545
15127
|
async#setUrlSchemesInAndroid(schemes) {
|
|
14546
|
-
const manifestPath =
|
|
14547
|
-
let manifest = await
|
|
15128
|
+
const manifestPath = path42.join(this.app.cwdPath, this.androidRootPath, "app/src/main/AndroidManifest.xml");
|
|
15129
|
+
let manifest = await readFile3(manifestPath, "utf8");
|
|
14548
15130
|
let changed = false;
|
|
14549
15131
|
for (const scheme of schemes) {
|
|
14550
15132
|
if (manifest.includes(`android:scheme="${scheme}"`))
|
|
@@ -14563,12 +15145,12 @@ ${filter}$1`);
|
|
|
14563
15145
|
changed = true;
|
|
14564
15146
|
}
|
|
14565
15147
|
if (changed)
|
|
14566
|
-
await
|
|
15148
|
+
await writeFile3(manifestPath, manifest);
|
|
14567
15149
|
}
|
|
14568
15150
|
async#setDeepLinksInAndroid(schemes, domains) {
|
|
14569
15151
|
await this.#setUrlSchemesInAndroid(schemes);
|
|
14570
|
-
const manifestPath =
|
|
14571
|
-
let manifest = await
|
|
15152
|
+
const manifestPath = path42.join(this.app.cwdPath, this.androidRootPath, "app/src/main/AndroidManifest.xml");
|
|
15153
|
+
let manifest = await readFile3(manifestPath, "utf8");
|
|
14572
15154
|
let changed = false;
|
|
14573
15155
|
const pathPrefix = resolveMobilePath(this.target, "/");
|
|
14574
15156
|
for (const domain of domains) {
|
|
@@ -14588,7 +15170,7 @@ ${filter}$1`);
|
|
|
14588
15170
|
changed = true;
|
|
14589
15171
|
}
|
|
14590
15172
|
if (changed)
|
|
14591
|
-
await
|
|
15173
|
+
await writeFile3(manifestPath, manifest);
|
|
14592
15174
|
}
|
|
14593
15175
|
#setFeaturesInAndroid(features) {
|
|
14594
15176
|
for (const feature of features) {
|
|
@@ -14669,7 +15251,7 @@ var Pkg = createInternalArgToken("Pkg");
|
|
|
14669
15251
|
var Module = createInternalArgToken("Module");
|
|
14670
15252
|
var Workspace = createInternalArgToken("Workspace");
|
|
14671
15253
|
// pkgs/@akanjs/devkit/commandDecorators/command.ts
|
|
14672
|
-
import
|
|
15254
|
+
import path43 from "path";
|
|
14673
15255
|
import { confirm, input as input2, select as select3 } from "@inquirer/prompts";
|
|
14674
15256
|
import { Logger as Logger10 } from "akanjs/common";
|
|
14675
15257
|
import chalk6 from "chalk";
|
|
@@ -15173,7 +15755,7 @@ var runCommands = async (...commands) => {
|
|
|
15173
15755
|
process.exit(1);
|
|
15174
15756
|
});
|
|
15175
15757
|
const __dirname2 = getDirname(import.meta.url);
|
|
15176
|
-
const packageJsonCandidates = [`${
|
|
15758
|
+
const packageJsonCandidates = [`${path43.dirname(Bun.main)}/package.json`, `${__dirname2}/../package.json`];
|
|
15177
15759
|
let cliPackageJson = null;
|
|
15178
15760
|
for (const packageJsonPath of packageJsonCandidates) {
|
|
15179
15761
|
if (!await FileSys.fileExists(packageJsonPath))
|
|
@@ -15420,7 +16002,7 @@ import { capitalize as capitalize7 } from "akanjs/common";
|
|
|
15420
16002
|
// pkgs/@akanjs/devkit/getRelatedCnsts.ts
|
|
15421
16003
|
import { readFileSync as readFileSync4, realpathSync } from "fs";
|
|
15422
16004
|
import ora2 from "ora";
|
|
15423
|
-
import * as
|
|
16005
|
+
import * as ts11 from "typescript";
|
|
15424
16006
|
var tsTranspiler = new Bun.Transpiler({ loader: "ts" });
|
|
15425
16007
|
var tsxTranspiler = new Bun.Transpiler({ loader: "tsx" });
|
|
15426
16008
|
var getTranspiler = (filePath) => filePath.endsWith(".tsx") ? tsxTranspiler : tsTranspiler;
|
|
@@ -15453,10 +16035,10 @@ var scanModuleSpecifiers = (source2, filePath, includeExports) => {
|
|
|
15453
16035
|
return importSpecifiers;
|
|
15454
16036
|
};
|
|
15455
16037
|
var parseTsConfig = (tsConfigPath = "./tsconfig.json") => {
|
|
15456
|
-
const configFile =
|
|
15457
|
-
return
|
|
16038
|
+
const configFile = ts11.readConfigFile(tsConfigPath, (path44) => {
|
|
16039
|
+
return ts11.sys.readFile(path44);
|
|
15458
16040
|
});
|
|
15459
|
-
return
|
|
16041
|
+
return ts11.parseJsonConfigFileContent(configFile.config, ts11.sys, realpathSync(tsConfigPath).replace(/[^/\\]+$/, ""));
|
|
15460
16042
|
};
|
|
15461
16043
|
var collectImportedFiles = (constantFilePath, parsedConfig) => {
|
|
15462
16044
|
const allFilesToAnalyze = new Set([constantFilePath]);
|
|
@@ -15471,7 +16053,7 @@ var collectImportedFiles = (constantFilePath, parsedConfig) => {
|
|
|
15471
16053
|
for (const importPath of scanModuleSpecifiers(source2, filePath, false)) {
|
|
15472
16054
|
if (!importPath.startsWith("."))
|
|
15473
16055
|
continue;
|
|
15474
|
-
const resolved =
|
|
16056
|
+
const resolved = ts11.resolveModuleName(importPath, filePath, parsedConfig.options, ts11.sys).resolvedModule?.resolvedFileName;
|
|
15475
16057
|
if (resolved && !allFilesToAnalyze.has(resolved)) {
|
|
15476
16058
|
allFilesToAnalyze.add(resolved);
|
|
15477
16059
|
collectImported(resolved);
|
|
@@ -15488,7 +16070,7 @@ var collectImportedFiles = (constantFilePath, parsedConfig) => {
|
|
|
15488
16070
|
var createTsProgram = (filePaths, options) => {
|
|
15489
16071
|
const spinner = ora2("Creating TypeScript program for all files...");
|
|
15490
16072
|
spinner.start();
|
|
15491
|
-
const program2 =
|
|
16073
|
+
const program2 = ts11.createProgram(Array.from(filePaths), options);
|
|
15492
16074
|
const checker = program2.getTypeChecker();
|
|
15493
16075
|
spinner.succeed("TypeScript program created.");
|
|
15494
16076
|
return {
|
|
@@ -15528,17 +16110,17 @@ var analyzeProperties = (filesToAnalyze, program2, checker) => {
|
|
|
15528
16110
|
function visit(node) {
|
|
15529
16111
|
if (!source2)
|
|
15530
16112
|
return;
|
|
15531
|
-
if (
|
|
16113
|
+
if (ts11.isPropertyAccessExpression(node)) {
|
|
15532
16114
|
const left = node.expression;
|
|
15533
16115
|
const right = node.name;
|
|
15534
|
-
const { line } =
|
|
15535
|
-
if (
|
|
16116
|
+
const { line } = ts11.getLineAndCharacterOfPosition(source2, node.getStart());
|
|
16117
|
+
if (ts11.isIdentifier(left) && sourceLines && sourceLines.length > line && sourceLines[line] && (sourceLines[line]?.includes(`@Field.Prop(() => ${left.text}.${right.text}`) || sourceLines[line].includes(`base.Filter(${left.text}.${right.text},`))) {
|
|
15536
16118
|
const symbol = getCachedSymbol(right);
|
|
15537
16119
|
if (symbol?.declarations && symbol.declarations.length > 0) {
|
|
15538
16120
|
const key = symbol.declarations[0]?.getSourceFile().fileName.split("/").pop()?.split(".")[0] ?? "";
|
|
15539
16121
|
const property = propertyMap.get(key);
|
|
15540
16122
|
const isScalar = symbol.declarations[0]?.getSourceFile().fileName.includes("_") ?? false;
|
|
15541
|
-
const symbolFilePath = symbol.declarations[0]?.getSourceFile().fileName.replace(`${
|
|
16123
|
+
const symbolFilePath = symbol.declarations[0]?.getSourceFile().fileName.replace(`${ts11.sys.getCurrentDirectory()}/`, "");
|
|
15542
16124
|
if (!symbolFilePath)
|
|
15543
16125
|
throw new Error(`No symbol file path found for ${left.text}.${right.text}`);
|
|
15544
16126
|
if (property) {
|
|
@@ -15562,10 +16144,10 @@ var analyzeProperties = (filesToAnalyze, program2, checker) => {
|
|
|
15562
16144
|
}
|
|
15563
16145
|
}
|
|
15564
16146
|
}
|
|
15565
|
-
} else if (
|
|
16147
|
+
} else if (ts11.isImportDeclaration(node) && ts11.isStringLiteral(node.moduleSpecifier)) {
|
|
15566
16148
|
const importPath = node.moduleSpecifier.text;
|
|
15567
16149
|
if (importPath.startsWith(".")) {
|
|
15568
|
-
const resolved =
|
|
16150
|
+
const resolved = ts11.resolveModuleName(importPath, filePath, program2.getCompilerOptions(), ts11.sys).resolvedModule?.resolvedFileName;
|
|
15569
16151
|
const moduleName = importPath.split("/").pop()?.split(".")[0] ?? "";
|
|
15570
16152
|
const property = propertyMap.get(moduleName);
|
|
15571
16153
|
const isScalar = importPath.includes("_");
|
|
@@ -15580,7 +16162,7 @@ var analyzeProperties = (filesToAnalyze, program2, checker) => {
|
|
|
15580
16162
|
}
|
|
15581
16163
|
}
|
|
15582
16164
|
}
|
|
15583
|
-
|
|
16165
|
+
ts11.forEachChild(node, visit);
|
|
15584
16166
|
}
|
|
15585
16167
|
visit(source2);
|
|
15586
16168
|
}
|
|
@@ -15672,10 +16254,10 @@ ${document}
|
|
|
15672
16254
|
}
|
|
15673
16255
|
// pkgs/@akanjs/devkit/qualityScanner.ts
|
|
15674
16256
|
import { createHash } from "crypto";
|
|
15675
|
-
import { readdir as
|
|
15676
|
-
import
|
|
16257
|
+
import { readdir as readdir4, readFile as readFile4, stat as stat5 } from "fs/promises";
|
|
16258
|
+
import path44 from "path";
|
|
15677
16259
|
import ignore2 from "ignore";
|
|
15678
|
-
import
|
|
16260
|
+
import ts12 from "typescript";
|
|
15679
16261
|
var MAX_FILE_LINES = 2000;
|
|
15680
16262
|
var PLACEHOLDER_EXPORT_NAMES = new Set([
|
|
15681
16263
|
"aa",
|
|
@@ -15787,7 +16369,7 @@ class AkanQualityScanner {
|
|
|
15787
16369
|
const ignoreFilter = ignore2().add(await this.#readGitIgnore(workspaceRoot));
|
|
15788
16370
|
const files = [];
|
|
15789
16371
|
for (const targetRoot of ["apps", "libs"]) {
|
|
15790
|
-
const absoluteTargetRoot =
|
|
16372
|
+
const absoluteTargetRoot = path44.join(workspaceRoot, targetRoot);
|
|
15791
16373
|
if (!await isDirectory(absoluteTargetRoot))
|
|
15792
16374
|
continue;
|
|
15793
16375
|
await this.#walkTargetFiles(workspaceRoot, absoluteTargetRoot, ignoreFilter, files);
|
|
@@ -15795,16 +16377,16 @@ class AkanQualityScanner {
|
|
|
15795
16377
|
return files.sort();
|
|
15796
16378
|
}
|
|
15797
16379
|
async#readGitIgnore(workspaceRoot) {
|
|
15798
|
-
const gitIgnorePath =
|
|
16380
|
+
const gitIgnorePath = path44.join(workspaceRoot, ".gitignore");
|
|
15799
16381
|
if (!await Bun.file(gitIgnorePath).exists())
|
|
15800
16382
|
return [];
|
|
15801
|
-
return (await
|
|
16383
|
+
return (await readFile4(gitIgnorePath, "utf8")).split(/\r?\n/);
|
|
15802
16384
|
}
|
|
15803
16385
|
async#walkTargetFiles(workspaceRoot, currentPath, ignoreFilter, files) {
|
|
15804
|
-
const entries = await
|
|
16386
|
+
const entries = await readdir4(currentPath, { withFileTypes: true });
|
|
15805
16387
|
for (const entry of entries) {
|
|
15806
|
-
const absolutePath =
|
|
15807
|
-
const relativePath = toPosix(
|
|
16388
|
+
const absolutePath = path44.join(currentPath, entry.name);
|
|
16389
|
+
const relativePath = toPosix(path44.relative(workspaceRoot, absolutePath));
|
|
15808
16390
|
if (shouldSkipPath(relativePath, entry.isDirectory(), ignoreFilter))
|
|
15809
16391
|
continue;
|
|
15810
16392
|
if (entry.isDirectory()) {
|
|
@@ -15817,13 +16399,13 @@ class AkanQualityScanner {
|
|
|
15817
16399
|
}
|
|
15818
16400
|
}
|
|
15819
16401
|
async#readSourceFile(workspaceRoot, file) {
|
|
15820
|
-
const absolutePath =
|
|
15821
|
-
const content = await
|
|
16402
|
+
const absolutePath = path44.join(workspaceRoot, file);
|
|
16403
|
+
const content = await readFile4(absolutePath, "utf8");
|
|
15822
16404
|
return {
|
|
15823
16405
|
file,
|
|
15824
16406
|
absolutePath,
|
|
15825
16407
|
content,
|
|
15826
|
-
sourceFile:
|
|
16408
|
+
sourceFile: ts12.createSourceFile(file, content, ts12.ScriptTarget.Latest, true, getScriptKind(file))
|
|
15827
16409
|
};
|
|
15828
16410
|
}
|
|
15829
16411
|
#scanGlobalQuality(sourceFiles) {
|
|
@@ -15948,7 +16530,7 @@ class AkanQualityScanner {
|
|
|
15948
16530
|
const suffix = CONVENTION_SUFFIXES.find((candidate) => sourceFile2.file.endsWith(candidate));
|
|
15949
16531
|
if (!suffix)
|
|
15950
16532
|
return [];
|
|
15951
|
-
const modelName = toPascalCase(
|
|
16533
|
+
const modelName = toPascalCase(path44.basename(sourceFile2.file, suffix));
|
|
15952
16534
|
const warnings = [];
|
|
15953
16535
|
for (const declaration of getTopLevelDeclarations(sourceFile2)) {
|
|
15954
16536
|
if (isAllowedConventionDeclaration(suffix, modelName, declaration))
|
|
@@ -15959,7 +16541,7 @@ class AkanQualityScanner {
|
|
|
15959
16541
|
severity: "warning",
|
|
15960
16542
|
file: sourceFile2.file,
|
|
15961
16543
|
line: declaration.line,
|
|
15962
|
-
message: `${
|
|
16544
|
+
message: `${path44.basename(sourceFile2.file)} should not declare top-level ${declaration.kind} "${declaration.name}". Allowed declarations: ${getConventionDescription(suffix, modelName)}.`
|
|
15963
16545
|
});
|
|
15964
16546
|
}
|
|
15965
16547
|
return warnings;
|
|
@@ -16031,7 +16613,7 @@ function getExportedFunctionLikes(sourceFile2) {
|
|
|
16031
16613
|
const declarations = [];
|
|
16032
16614
|
const nameExempt = isPageRouteFile(sourceFile2.file) || isUiComponentFile(sourceFile2.file);
|
|
16033
16615
|
for (const statement of sourceFile2.sourceFile.statements) {
|
|
16034
|
-
if (
|
|
16616
|
+
if (ts12.isFunctionDeclaration(statement) && statement.name && isExported(statement)) {
|
|
16035
16617
|
declarations.push({
|
|
16036
16618
|
name: statement.name.text,
|
|
16037
16619
|
kind: "function",
|
|
@@ -16041,7 +16623,7 @@ function getExportedFunctionLikes(sourceFile2) {
|
|
|
16041
16623
|
duplicateNameExempt: nameExempt || isConventionDuplicateNameExempt(sourceFile2.file, false)
|
|
16042
16624
|
});
|
|
16043
16625
|
}
|
|
16044
|
-
if (
|
|
16626
|
+
if (ts12.isClassDeclaration(statement) && statement.name && isExported(statement)) {
|
|
16045
16627
|
declarations.push({
|
|
16046
16628
|
name: statement.name.text,
|
|
16047
16629
|
kind: "class",
|
|
@@ -16051,9 +16633,9 @@ function getExportedFunctionLikes(sourceFile2) {
|
|
|
16051
16633
|
duplicateNameExempt: nameExempt || isConventionDuplicateNameExempt(sourceFile2.file, isEnumClassStatement(sourceFile2.sourceFile, statement))
|
|
16052
16634
|
});
|
|
16053
16635
|
}
|
|
16054
|
-
if (
|
|
16636
|
+
if (ts12.isVariableStatement(statement) && isExported(statement)) {
|
|
16055
16637
|
for (const declaration of statement.declarationList.declarations) {
|
|
16056
|
-
if (!
|
|
16638
|
+
if (!ts12.isIdentifier(declaration.name) || !isFunctionLikeInitializer(declaration.initializer))
|
|
16057
16639
|
continue;
|
|
16058
16640
|
declarations.push({
|
|
16059
16641
|
name: declaration.name.text,
|
|
@@ -16092,14 +16674,14 @@ function isInLibModule(file) {
|
|
|
16092
16674
|
return (segments[0] === "apps" || segments[0] === "libs") && segments.includes("lib");
|
|
16093
16675
|
}
|
|
16094
16676
|
function isEnumClassStatement(sourceFile2, statement) {
|
|
16095
|
-
if (!
|
|
16677
|
+
if (!ts12.isClassDeclaration(statement))
|
|
16096
16678
|
return false;
|
|
16097
|
-
const heritageClause = statement.heritageClauses?.find((clause) => clause.token ===
|
|
16679
|
+
const heritageClause = statement.heritageClauses?.find((clause) => clause.token === ts12.SyntaxKind.ExtendsKeyword);
|
|
16098
16680
|
const expression = heritageClause?.types[0]?.expression;
|
|
16099
16681
|
return !!expression && expression.getText(sourceFile2).startsWith("enumOf(");
|
|
16100
16682
|
}
|
|
16101
16683
|
function getExportedClassNames(sourceFile2) {
|
|
16102
|
-
return sourceFile2.statements.filter((statement) =>
|
|
16684
|
+
return sourceFile2.statements.filter((statement) => ts12.isClassDeclaration(statement) && !!statement.name).filter((statement) => isExported(statement)).map((statement) => statement.name.text);
|
|
16103
16685
|
}
|
|
16104
16686
|
function isComponentDeclarationFile(file) {
|
|
16105
16687
|
if (!file.endsWith(".tsx"))
|
|
@@ -16115,7 +16697,7 @@ function isComponentDeclarationFile(file) {
|
|
|
16115
16697
|
function getComponentFileDeclarations(sourceFile2) {
|
|
16116
16698
|
const reExportedNames = new Set;
|
|
16117
16699
|
for (const statement of sourceFile2.statements) {
|
|
16118
|
-
if (
|
|
16700
|
+
if (ts12.isExportDeclaration(statement) && statement.exportClause && ts12.isNamedExports(statement.exportClause)) {
|
|
16119
16701
|
for (const element of statement.exportClause.elements)
|
|
16120
16702
|
reExportedNames.add((element.propertyName ?? element.name).text);
|
|
16121
16703
|
}
|
|
@@ -16125,19 +16707,19 @@ function getComponentFileDeclarations(sourceFile2) {
|
|
|
16125
16707
|
const isDefaultExport = isDefaultExportStatement(statement);
|
|
16126
16708
|
const inlineExported = isExported(statement);
|
|
16127
16709
|
const add = (name, kind, line) => declarations.push({ name, kind, line, exported: inlineExported || reExportedNames.has(name), isDefaultExport });
|
|
16128
|
-
if (
|
|
16710
|
+
if (ts12.isInterfaceDeclaration(statement))
|
|
16129
16711
|
add(statement.name.text, "interface", getLine(sourceFile2, statement));
|
|
16130
|
-
else if (
|
|
16712
|
+
else if (ts12.isTypeAliasDeclaration(statement))
|
|
16131
16713
|
add(statement.name.text, "type", getLine(sourceFile2, statement));
|
|
16132
|
-
else if (
|
|
16714
|
+
else if (ts12.isEnumDeclaration(statement))
|
|
16133
16715
|
add(statement.name.text, "enum", getLine(sourceFile2, statement));
|
|
16134
|
-
else if (
|
|
16716
|
+
else if (ts12.isFunctionDeclaration(statement) && statement.name)
|
|
16135
16717
|
add(statement.name.text, "function", getLine(sourceFile2, statement));
|
|
16136
|
-
else if (
|
|
16718
|
+
else if (ts12.isClassDeclaration(statement) && statement.name)
|
|
16137
16719
|
add(statement.name.text, "class", getLine(sourceFile2, statement));
|
|
16138
|
-
else if (
|
|
16720
|
+
else if (ts12.isVariableStatement(statement)) {
|
|
16139
16721
|
for (const declaration of statement.declarationList.declarations) {
|
|
16140
|
-
if (!
|
|
16722
|
+
if (!ts12.isIdentifier(declaration.name))
|
|
16141
16723
|
continue;
|
|
16142
16724
|
const kind = isFunctionLikeInitializer(declaration.initializer) ? "function" : "variable";
|
|
16143
16725
|
add(declaration.name.text, kind, getLine(sourceFile2, declaration));
|
|
@@ -16149,15 +16731,15 @@ function getComponentFileDeclarations(sourceFile2) {
|
|
|
16149
16731
|
function getCompoundComponentNames(sourceFile2) {
|
|
16150
16732
|
const names = new Set;
|
|
16151
16733
|
for (const statement of sourceFile2.statements) {
|
|
16152
|
-
if (!
|
|
16734
|
+
if (!ts12.isExpressionStatement(statement))
|
|
16153
16735
|
continue;
|
|
16154
16736
|
const { expression } = statement;
|
|
16155
|
-
if (!
|
|
16737
|
+
if (!ts12.isBinaryExpression(expression) || expression.operatorToken.kind !== ts12.SyntaxKind.EqualsToken)
|
|
16156
16738
|
continue;
|
|
16157
|
-
if (!
|
|
16739
|
+
if (!ts12.isPropertyAccessExpression(expression.left) || !isPascalCaseName(expression.left.name.text))
|
|
16158
16740
|
continue;
|
|
16159
16741
|
names.add(expression.left.name.text);
|
|
16160
|
-
if (
|
|
16742
|
+
if (ts12.isIdentifier(expression.right) && isPascalCaseName(expression.right.text))
|
|
16161
16743
|
names.add(expression.right.text);
|
|
16162
16744
|
}
|
|
16163
16745
|
return names;
|
|
@@ -16177,9 +16759,9 @@ function isPascalCaseName(name) {
|
|
|
16177
16759
|
return /^[A-Z]/.test(name) && !/^[A-Z0-9_]+$/.test(name);
|
|
16178
16760
|
}
|
|
16179
16761
|
function isDefaultExportStatement(statement) {
|
|
16180
|
-
if (
|
|
16762
|
+
if (ts12.isExportAssignment(statement))
|
|
16181
16763
|
return !statement.isExportEquals;
|
|
16182
|
-
return !!(
|
|
16764
|
+
return !!(ts12.getCombinedModifierFlags(statement) & ts12.ModifierFlags.Default);
|
|
16183
16765
|
}
|
|
16184
16766
|
function getPlaceholderExportWarnings(sourceFile2) {
|
|
16185
16767
|
if (!sourceFile2.file.endsWith("/index.ts") && !sourceFile2.file.endsWith("/index.tsx"))
|
|
@@ -16209,7 +16791,7 @@ function getDictionaryTextWarnings(sourceFile2) {
|
|
|
16209
16791
|
function getGlobalMutationWarnings(sourceFile2) {
|
|
16210
16792
|
const warnings = [];
|
|
16211
16793
|
for (const statement of sourceFile2.sourceFile.statements) {
|
|
16212
|
-
if (
|
|
16794
|
+
if (ts12.isModuleDeclaration(statement) && statement.name.getText(sourceFile2.sourceFile) === "global") {
|
|
16213
16795
|
warnings.push({
|
|
16214
16796
|
rule: "akan.file.global-declaration",
|
|
16215
16797
|
scope: "file",
|
|
@@ -16219,7 +16801,7 @@ function getGlobalMutationWarnings(sourceFile2) {
|
|
|
16219
16801
|
message: "Global declarations require an explicit low-level integration allowlist."
|
|
16220
16802
|
});
|
|
16221
16803
|
}
|
|
16222
|
-
if (
|
|
16804
|
+
if (ts12.isInterfaceDeclaration(statement) && statement.name.text === "Window") {
|
|
16223
16805
|
warnings.push({
|
|
16224
16806
|
rule: "akan.file.window-augmentation",
|
|
16225
16807
|
scope: "file",
|
|
@@ -16229,7 +16811,7 @@ function getGlobalMutationWarnings(sourceFile2) {
|
|
|
16229
16811
|
message: "Window augmentation should be isolated to approved browser integration files."
|
|
16230
16812
|
});
|
|
16231
16813
|
}
|
|
16232
|
-
if (
|
|
16814
|
+
if (ts12.isExpressionStatement(statement) && statement.expression.getText(sourceFile2.sourceFile).includes(".prototype.")) {
|
|
16233
16815
|
warnings.push({
|
|
16234
16816
|
rule: "akan.file.prototype-mutation",
|
|
16235
16817
|
scope: "file",
|
|
@@ -16247,23 +16829,23 @@ function getTopLevelDeclarations(sourceFile2) {
|
|
|
16247
16829
|
}
|
|
16248
16830
|
function getTopLevelDeclaration(sourceFile2, statement) {
|
|
16249
16831
|
const line = getLine(sourceFile2, statement);
|
|
16250
|
-
if (
|
|
16832
|
+
if (ts12.isClassDeclaration(statement) && statement.name) {
|
|
16251
16833
|
return [{ name: statement.name.text, kind: "class", line, exported: isExported(statement), node: statement }];
|
|
16252
16834
|
}
|
|
16253
|
-
if (
|
|
16835
|
+
if (ts12.isFunctionDeclaration(statement) && statement.name) {
|
|
16254
16836
|
return [{ name: statement.name.text, kind: "function", line, exported: isExported(statement), node: statement }];
|
|
16255
16837
|
}
|
|
16256
|
-
if (
|
|
16838
|
+
if (ts12.isInterfaceDeclaration(statement)) {
|
|
16257
16839
|
return [{ name: statement.name.text, kind: "interface", line, exported: isExported(statement), node: statement }];
|
|
16258
16840
|
}
|
|
16259
|
-
if (
|
|
16841
|
+
if (ts12.isTypeAliasDeclaration(statement)) {
|
|
16260
16842
|
return [{ name: statement.name.text, kind: "type", line, exported: isExported(statement), node: statement }];
|
|
16261
16843
|
}
|
|
16262
|
-
if (
|
|
16844
|
+
if (ts12.isEnumDeclaration(statement)) {
|
|
16263
16845
|
return [{ name: statement.name.text, kind: "enum", line, exported: isExported(statement), node: statement }];
|
|
16264
16846
|
}
|
|
16265
|
-
if (
|
|
16266
|
-
return statement.declarationList.declarations.filter((declaration) =>
|
|
16847
|
+
if (ts12.isVariableStatement(statement)) {
|
|
16848
|
+
return statement.declarationList.declarations.filter((declaration) => ts12.isIdentifier(declaration.name)).map((declaration) => ({
|
|
16267
16849
|
name: declaration.name.text,
|
|
16268
16850
|
kind: "variable",
|
|
16269
16851
|
line: getLine(sourceFile2, declaration),
|
|
@@ -16271,7 +16853,7 @@ function getTopLevelDeclaration(sourceFile2, statement) {
|
|
|
16271
16853
|
node: statement
|
|
16272
16854
|
}));
|
|
16273
16855
|
}
|
|
16274
|
-
if (
|
|
16856
|
+
if (ts12.isExportDeclaration(statement)) {
|
|
16275
16857
|
return [{ name: "export declaration", kind: "export", line, exported: true, node: statement }];
|
|
16276
16858
|
}
|
|
16277
16859
|
return [];
|
|
@@ -16296,9 +16878,9 @@ function isAllowedConstantDeclaration(modelName, declaration) {
|
|
|
16296
16878
|
return false;
|
|
16297
16879
|
if ([`${modelName}Input`, `${modelName}Object`, modelName, `Light${modelName}`, `${modelName}Insight`].includes(declaration.name))
|
|
16298
16880
|
return true;
|
|
16299
|
-
if (!
|
|
16881
|
+
if (!ts12.isClassDeclaration(declaration.node))
|
|
16300
16882
|
return false;
|
|
16301
|
-
const heritageClause = declaration.node.heritageClauses?.find((clause) => clause.token ===
|
|
16883
|
+
const heritageClause = declaration.node.heritageClauses?.find((clause) => clause.token === ts12.SyntaxKind.ExtendsKeyword);
|
|
16302
16884
|
const expression = heritageClause?.types[0]?.expression;
|
|
16303
16885
|
return !!expression && expression.getText().startsWith("enumOf(");
|
|
16304
16886
|
}
|
|
@@ -16364,13 +16946,13 @@ function getModuleInfo(file) {
|
|
|
16364
16946
|
return { moduleName, fileName, kind: "database" };
|
|
16365
16947
|
}
|
|
16366
16948
|
function isExportedConst(declaration) {
|
|
16367
|
-
return declaration.exported &&
|
|
16949
|
+
return declaration.exported && ts12.isVariableStatement(declaration.node) && (declaration.node.declarationList.flags & ts12.NodeFlags.Const) !== 0;
|
|
16368
16950
|
}
|
|
16369
16951
|
function isExported(node) {
|
|
16370
|
-
return !!
|
|
16952
|
+
return !!ts12.getCombinedModifierFlags(node) && !!(ts12.getCombinedModifierFlags(node) & ts12.ModifierFlags.Export);
|
|
16371
16953
|
}
|
|
16372
16954
|
function isFunctionLikeInitializer(node) {
|
|
16373
|
-
return !!node && (
|
|
16955
|
+
return !!node && (ts12.isArrowFunction(node) || ts12.isFunctionExpression(node));
|
|
16374
16956
|
}
|
|
16375
16957
|
function getBodyFingerprint(sourceFile2, node) {
|
|
16376
16958
|
if (!node)
|
|
@@ -16386,13 +16968,13 @@ function shouldSkipPath(relativePath, isDirectory, ignoreFilter) {
|
|
|
16386
16968
|
}
|
|
16387
16969
|
async function isDirectory(absolutePath) {
|
|
16388
16970
|
try {
|
|
16389
|
-
return (await
|
|
16971
|
+
return (await stat5(absolutePath)).isDirectory();
|
|
16390
16972
|
} catch {
|
|
16391
16973
|
return false;
|
|
16392
16974
|
}
|
|
16393
16975
|
}
|
|
16394
16976
|
function getScriptKind(file) {
|
|
16395
|
-
return file.endsWith(".tsx") ?
|
|
16977
|
+
return file.endsWith(".tsx") ? ts12.ScriptKind.TSX : ts12.ScriptKind.TS;
|
|
16396
16978
|
}
|
|
16397
16979
|
function getLine(sourceFile2, node) {
|
|
16398
16980
|
return sourceFile2.getLineAndCharacterOfPosition(node.getStart(sourceFile2)).line + 1;
|
|
@@ -16413,7 +16995,7 @@ function toPascalCase(value) {
|
|
|
16413
16995
|
return value.replace(/(^|[-_./])([a-zA-Z0-9])/g, (_, __, char) => char.toUpperCase()).replace(/[-_./]/g, "");
|
|
16414
16996
|
}
|
|
16415
16997
|
function toPosix(value) {
|
|
16416
|
-
return value.split(
|
|
16998
|
+
return value.split(path44.sep).join("/");
|
|
16417
16999
|
}
|
|
16418
17000
|
function groupBy(items, getKey) {
|
|
16419
17001
|
const grouped = new Map;
|
|
@@ -17505,7 +18087,7 @@ class ApplicationCommand extends command("application", [ApplicationScript], ({
|
|
|
17505
18087
|
import { Logger as Logger16 } from "akanjs/common";
|
|
17506
18088
|
|
|
17507
18089
|
// pkgs/@akanjs/cli/package/package.runner.ts
|
|
17508
|
-
import
|
|
18090
|
+
import path45 from "path";
|
|
17509
18091
|
import { Logger as Logger14 } from "akanjs/common";
|
|
17510
18092
|
var {$: $2 } = globalThis.Bun;
|
|
17511
18093
|
|
|
@@ -17525,11 +18107,11 @@ class PackageRunner extends runner("package") {
|
|
|
17525
18107
|
}
|
|
17526
18108
|
async#getInstalledPackageJson() {
|
|
17527
18109
|
const packageJsonCandidates = [
|
|
17528
|
-
`${
|
|
18110
|
+
`${path45.dirname(Bun.main)}/package.json`,
|
|
17529
18111
|
`${process.cwd()}/node_modules/akanjs/package.json`
|
|
17530
18112
|
];
|
|
17531
18113
|
try {
|
|
17532
|
-
packageJsonCandidates.unshift(Bun.resolveSync("akanjs/package.json",
|
|
18114
|
+
packageJsonCandidates.unshift(Bun.resolveSync("akanjs/package.json", path45.dirname(Bun.main)));
|
|
17533
18115
|
} catch {}
|
|
17534
18116
|
for (const packageJsonPath of packageJsonCandidates) {
|
|
17535
18117
|
if (!await Bun.file(packageJsonPath).exists())
|
|
@@ -17538,7 +18120,7 @@ class PackageRunner extends runner("package") {
|
|
|
17538
18120
|
if (packageJson.name === "akanjs" || packageJson.name === "@akanjs/cli")
|
|
17539
18121
|
return packageJson;
|
|
17540
18122
|
}
|
|
17541
|
-
throw new Error(`[package] failed to locate akanjs package.json from ${
|
|
18123
|
+
throw new Error(`[package] failed to locate akanjs package.json from ${path45.dirname(Bun.main)}`);
|
|
17542
18124
|
}
|
|
17543
18125
|
async createPackage(workspace, pkgName) {
|
|
17544
18126
|
await workspace.applyTemplate({ basePath: `pkgs/${pkgName}`, template: "pkgRoot", dict: { pkgName } });
|
|
@@ -17713,7 +18295,7 @@ class PackageScript extends script("package", [PackageRunner]) {
|
|
|
17713
18295
|
}
|
|
17714
18296
|
|
|
17715
18297
|
// pkgs/@akanjs/cli/cloud/cloud.runner.ts
|
|
17716
|
-
import
|
|
18298
|
+
import path46 from "path";
|
|
17717
18299
|
import { confirm as confirm4, input as input5, select as select8 } from "@inquirer/prompts";
|
|
17718
18300
|
import { Logger as Logger15, sleep } from "akanjs/common";
|
|
17719
18301
|
import chalk7 from "chalk";
|
|
@@ -17984,7 +18566,7 @@ ${chalk7.green("\u27A4")} Authentication Required`));
|
|
|
17984
18566
|
await Promise.all(akanPkgs.map(async (library) => {
|
|
17985
18567
|
Logger15.info(`Publishing ${library}@${nextVersion} to ${registry ?? "npm"}...`);
|
|
17986
18568
|
await workspace.spawn("npm", ["publish", "--tag", tag, ...this.#getRegistryArgs(registry), ...this.#getLocalRegistryAuthArgs(registry)], {
|
|
17987
|
-
cwd:
|
|
18569
|
+
cwd: path46.join(workspace.workspaceRoot, "dist/pkgs", library),
|
|
17988
18570
|
env: this.#getRegistryEnv(registry),
|
|
17989
18571
|
stdio: "inherit"
|
|
17990
18572
|
});
|
|
@@ -18038,12 +18620,12 @@ ${chalk7.green("\u27A4")} Authentication Required`));
|
|
|
18038
18620
|
async downloadEnv(cloudApi2, workspace, workspaceId) {
|
|
18039
18621
|
await workspace.mkdir("local");
|
|
18040
18622
|
const localPath = await cloudApi2.downloadEnv(workspaceId);
|
|
18041
|
-
const relativePath =
|
|
18623
|
+
const relativePath = path46.relative(workspace.workspaceRoot, localPath).split(path46.sep).join("/");
|
|
18042
18624
|
await workspace.spawn("tar", ["-xf", relativePath], { cwd: workspace.workspaceRoot });
|
|
18043
18625
|
await workspace.remove(localPath);
|
|
18044
18626
|
}
|
|
18045
18627
|
async uploadEnv(cloudApi2, workspaceId, filePath) {
|
|
18046
|
-
const file = new File([Bun.file(filePath)],
|
|
18628
|
+
const file = new File([Bun.file(filePath)], path46.basename(filePath));
|
|
18047
18629
|
await cloudApi2.uploadEnv(workspaceId, file);
|
|
18048
18630
|
}
|
|
18049
18631
|
async downloadEnvByScp(workspace) {
|
|
@@ -18113,8 +18695,8 @@ ${chalk7.green("\u27A4")} Authentication Required`));
|
|
|
18113
18695
|
const secretGlobs = config.secrets ?? [];
|
|
18114
18696
|
if (secretGlobs.length === 0)
|
|
18115
18697
|
return [];
|
|
18116
|
-
const appDir =
|
|
18117
|
-
return secretGlobs.flatMap((pattern) => Array.from(new Bun.Glob(pattern).scanSync({ cwd: appDir, onlyFiles: true })).map((match) => `apps/${appName}/${match.split(
|
|
18698
|
+
const appDir = path46.join(workspace.workspaceRoot, "apps", appName);
|
|
18699
|
+
return secretGlobs.flatMap((pattern) => Array.from(new Bun.Glob(pattern).scanSync({ cwd: appDir, onlyFiles: true })).map((match) => `apps/${appName}/${match.split(path46.sep).join("/")}`));
|
|
18118
18700
|
}));
|
|
18119
18701
|
return secretPaths.flat();
|
|
18120
18702
|
}
|
|
@@ -18184,14 +18766,14 @@ class CloudScript extends script("cloud", [CloudRunner, ApplicationScript, Packa
|
|
|
18184
18766
|
}
|
|
18185
18767
|
async uploadEnv(workspace, { host = GlobalConfig.akanCloudHost } = {}) {
|
|
18186
18768
|
const workspaceId = workspace.getWorkspaceId({ allowEmpty: true });
|
|
18187
|
-
const { path:
|
|
18769
|
+
const { path: path47 } = await this.cloudRunner.gatherEnvFiles(workspace);
|
|
18188
18770
|
if (workspaceId) {
|
|
18189
18771
|
await this.login(workspace, host);
|
|
18190
18772
|
const cloudApi2 = await CloudApi.fromHost(workspace, host);
|
|
18191
|
-
await this.cloudRunner.uploadEnv(cloudApi2, workspaceId,
|
|
18773
|
+
await this.cloudRunner.uploadEnv(cloudApi2, workspaceId, path47);
|
|
18192
18774
|
return;
|
|
18193
18775
|
}
|
|
18194
|
-
await this.cloudRunner.uploadEnvByScp(workspace,
|
|
18776
|
+
await this.cloudRunner.uploadEnvByScp(workspace, path47);
|
|
18195
18777
|
}
|
|
18196
18778
|
async deployAkan(workspace, { test = true, registryUrl } = {}) {
|
|
18197
18779
|
const akanPkgs = await this.cloudRunner.getAkanPkgs(workspace);
|
|
@@ -18432,8 +19014,8 @@ class RepairRunner extends runner("repair") {
|
|
|
18432
19014
|
}
|
|
18433
19015
|
|
|
18434
19016
|
// pkgs/@akanjs/cli/workflow/workflow.runner.ts
|
|
18435
|
-
import { mkdir as mkdir12, readFile as
|
|
18436
|
-
import
|
|
19017
|
+
import { mkdir as mkdir12, readFile as readFile5, writeFile as writeFile4 } from "fs/promises";
|
|
19018
|
+
import path47 from "path";
|
|
18437
19019
|
import { capitalize as capitalize8 } from "akanjs/common";
|
|
18438
19020
|
|
|
18439
19021
|
// pkgs/@akanjs/cli/workflows/shared.ts
|
|
@@ -18999,7 +19581,7 @@ var workflowSpecs = [
|
|
|
18999
19581
|
];
|
|
19000
19582
|
|
|
19001
19583
|
// pkgs/@akanjs/cli/workflow/workflow.runner.ts
|
|
19002
|
-
var resolvePath = (filePath) =>
|
|
19584
|
+
var resolvePath = (filePath) => path47.isAbsolute(filePath) ? filePath : path47.join(process.cwd(), filePath);
|
|
19003
19585
|
var isRecord3 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
19004
19586
|
var isWorkflowPlan2 = (value) => {
|
|
19005
19587
|
if (!isRecord3(value))
|
|
@@ -19097,7 +19679,7 @@ var defaultValidationExecutor = (workspace) => async (command3) => {
|
|
|
19097
19679
|
};
|
|
19098
19680
|
}
|
|
19099
19681
|
};
|
|
19100
|
-
var readJsonFile = async (filePath) => JSON.parse(await
|
|
19682
|
+
var readJsonFile = async (filePath) => JSON.parse(await readFile5(resolvePath(filePath), "utf8"));
|
|
19101
19683
|
var planInputString2 = (plan2, key) => {
|
|
19102
19684
|
const value = plan2.inputs[key];
|
|
19103
19685
|
return typeof value === "string" ? value : "";
|
|
@@ -19193,8 +19775,8 @@ class WorkflowRunner extends runner("workflow") {
|
|
|
19193
19775
|
const plan2 = createWorkflowPlan(spec, compactWorkflowInputs(inputs));
|
|
19194
19776
|
if (out) {
|
|
19195
19777
|
const outPath = resolvePath(out);
|
|
19196
|
-
await mkdir12(
|
|
19197
|
-
await
|
|
19778
|
+
await mkdir12(path47.dirname(outPath), { recursive: true });
|
|
19779
|
+
await writeFile4(outPath, jsonText(plan2));
|
|
19198
19780
|
}
|
|
19199
19781
|
return format === "json" ? jsonText(plan2) : renderWorkflowPlan(plan2);
|
|
19200
19782
|
}
|
|
@@ -19212,7 +19794,7 @@ class WorkflowRunner extends runner("workflow") {
|
|
|
19212
19794
|
};
|
|
19213
19795
|
let plan2;
|
|
19214
19796
|
try {
|
|
19215
|
-
const parsed = JSON.parse(await
|
|
19797
|
+
const parsed = JSON.parse(await readFile5(resolvePath(planPath), "utf8"));
|
|
19216
19798
|
if (!isWorkflowPlan2(parsed)) {
|
|
19217
19799
|
const report = failedApplyReport("unknown", [
|
|
19218
19800
|
{
|
|
@@ -21145,7 +21727,7 @@ class ContextScript extends script("context", [ContextRunner]) {
|
|
|
21145
21727
|
async doctor(workspace, options = {}) {
|
|
21146
21728
|
Logger17.rawLog(await this.contextRunner.doctor(workspace, options));
|
|
21147
21729
|
}
|
|
21148
|
-
async mcpInstall(workspace, target, { force = false, mode = "
|
|
21730
|
+
async mcpInstall(workspace, target, { force = false, mode = "apply" } = {}) {
|
|
21149
21731
|
const targets = resolveMcpInstallTargets(target);
|
|
21150
21732
|
const written = [];
|
|
21151
21733
|
for (const t of targets) {
|
|
@@ -21156,7 +21738,7 @@ class ContextScript extends script("context", [ContextRunner]) {
|
|
|
21156
21738
|
${written.map((line) => `- ${line}`).join(`
|
|
21157
21739
|
`)}`);
|
|
21158
21740
|
}
|
|
21159
|
-
async mcp(workspace, { mode = "
|
|
21741
|
+
async mcp(workspace, { mode = "apply" } = {}) {
|
|
21160
21742
|
await this.contextRunner.runMcp(workspace, { mode });
|
|
21161
21743
|
}
|
|
21162
21744
|
async mcpCall(workspace, tool, {
|
|
@@ -21195,7 +21777,7 @@ class ContextCommand extends command("context", [ContextScript], ({ public: targ
|
|
|
21195
21777
|
}),
|
|
21196
21778
|
mcpInstall: target({ desc: "Install the Akan MCP server config for Cursor, Claude Code, and Codex" }).arg("target", String, { desc: "cursor, claude, codex, or all", nullable: true }).option("force", Boolean, { desc: "overwrite an existing Akan MCP server entry", default: false }).option("mode", String, {
|
|
21197
21779
|
desc: "MCP permission mode",
|
|
21198
|
-
default: "
|
|
21780
|
+
default: "apply",
|
|
21199
21781
|
enum: ["readonly", "plan", "apply"]
|
|
21200
21782
|
}).with(Workspace).exec(async function(targetName, force, mode, workspace) {
|
|
21201
21783
|
await this.contextScript.mcpInstall(workspace, targetName, {
|
|
@@ -21252,14 +21834,14 @@ class GuidelinePrompt extends Prompter {
|
|
|
21252
21834
|
async#getScanFilePaths(matchPattern, { avoidDirs = ["node_modules", ".next"], filterText } = {}) {
|
|
21253
21835
|
const glob = new Bun.Glob(matchPattern);
|
|
21254
21836
|
const paths = [];
|
|
21255
|
-
for await (const
|
|
21256
|
-
if (avoidDirs.some((dir) =>
|
|
21837
|
+
for await (const path48 of glob.scan({ cwd: this.workspace.workspaceRoot, absolute: true })) {
|
|
21838
|
+
if (avoidDirs.some((dir) => path48.includes(dir)))
|
|
21257
21839
|
continue;
|
|
21258
|
-
const fileContent = await FileSys.readText(
|
|
21840
|
+
const fileContent = await FileSys.readText(path48);
|
|
21259
21841
|
const textFilter = filterText ? new RegExp(filterText) : null;
|
|
21260
21842
|
if (filterText && !textFilter?.test(fileContent))
|
|
21261
21843
|
continue;
|
|
21262
|
-
paths.push(
|
|
21844
|
+
paths.push(path48);
|
|
21263
21845
|
}
|
|
21264
21846
|
return paths;
|
|
21265
21847
|
}
|
|
@@ -21579,7 +22161,7 @@ class LibraryCommand extends command("library", [LibraryScript], ({ public: targ
|
|
|
21579
22161
|
|
|
21580
22162
|
// pkgs/@akanjs/cli/localRegistry/localRegistry.runner.ts
|
|
21581
22163
|
import { mkdir as mkdir13, rm as rm7 } from "fs/promises";
|
|
21582
|
-
import
|
|
22164
|
+
import path48 from "path";
|
|
21583
22165
|
import { Logger as Logger19 } from "akanjs/common";
|
|
21584
22166
|
var defaultLocalRegistryUrl = "http://127.0.0.1:4873";
|
|
21585
22167
|
var containerName = "akan-verdaccio";
|
|
@@ -21597,8 +22179,8 @@ class LocalRegistryRunner extends runner("localRegistry") {
|
|
|
21597
22179
|
Logger19.info(`Local registry is already running at ${registry}`);
|
|
21598
22180
|
return registry;
|
|
21599
22181
|
} catch {}
|
|
21600
|
-
const configPath2 =
|
|
21601
|
-
const storagePath =
|
|
22182
|
+
const configPath2 = path48.join(workspace.workspaceRoot, "pkgs/@akanjs/cli/localRegistry/verdaccio.yaml");
|
|
22183
|
+
const storagePath = path48.join(workspace.workspaceRoot, ".akan/verdaccio/storage");
|
|
21602
22184
|
await mkdir13(storagePath, { recursive: true });
|
|
21603
22185
|
await workspace.spawn("docker", [
|
|
21604
22186
|
"run",
|
|
@@ -21621,13 +22203,13 @@ class LocalRegistryRunner extends runner("localRegistry") {
|
|
|
21621
22203
|
try {
|
|
21622
22204
|
await workspace.spawn("docker", ["rm", "-f", containerName], { stdio: "inherit" });
|
|
21623
22205
|
} catch {}
|
|
21624
|
-
await rm7(
|
|
22206
|
+
await rm7(path48.join(workspace.workspaceRoot, ".akan/verdaccio"), { recursive: true, force: true });
|
|
21625
22207
|
Logger19.info("Local registry storage has been reset");
|
|
21626
22208
|
}
|
|
21627
22209
|
async smoke(workspace, { registryUrl } = {}) {
|
|
21628
22210
|
const registry = this.getRegistryUrl(registryUrl);
|
|
21629
|
-
const smokeRoot =
|
|
21630
|
-
await rm7(
|
|
22211
|
+
const smokeRoot = path48.join(workspace.workspaceRoot, ".akan/e2e");
|
|
22212
|
+
await rm7(path48.join(smokeRoot, smokeRepoName), { recursive: true, force: true });
|
|
21631
22213
|
await workspace.spawn(process.execPath, [
|
|
21632
22214
|
"dist/pkgs/create-akan-workspace/index.js",
|
|
21633
22215
|
smokeRepoName,
|
|
@@ -21644,12 +22226,12 @@ class LocalRegistryRunner extends runner("localRegistry") {
|
|
|
21644
22226
|
stdio: "inherit"
|
|
21645
22227
|
});
|
|
21646
22228
|
await workspace.spawn("akan", ["typecheck", smokeAppName], {
|
|
21647
|
-
cwd:
|
|
22229
|
+
cwd: path48.join(smokeRoot, smokeRepoName),
|
|
21648
22230
|
env: { ...process.env, AKAN_NPM_REGISTRY: registry, NPM_CONFIG_REGISTRY: registry },
|
|
21649
22231
|
stdio: "inherit"
|
|
21650
22232
|
});
|
|
21651
22233
|
await workspace.spawn("akan", ["build", smokeAppName], {
|
|
21652
|
-
cwd:
|
|
22234
|
+
cwd: path48.join(smokeRoot, smokeRepoName),
|
|
21653
22235
|
env: { ...process.env, AKAN_NPM_REGISTRY: registry, NPM_CONFIG_REGISTRY: registry },
|
|
21654
22236
|
stdio: "inherit"
|
|
21655
22237
|
});
|
|
@@ -22005,11 +22587,11 @@ class WorkflowCommand extends command("workflow", [WorkflowScript], ({ public: t
|
|
|
22005
22587
|
}
|
|
22006
22588
|
|
|
22007
22589
|
// pkgs/@akanjs/cli/workspace/workspace.script.ts
|
|
22008
|
-
import
|
|
22590
|
+
import path50 from "path";
|
|
22009
22591
|
import { Logger as Logger26 } from "akanjs/common";
|
|
22010
22592
|
|
|
22011
22593
|
// pkgs/@akanjs/cli/workspace/workspace.runner.ts
|
|
22012
|
-
import
|
|
22594
|
+
import path49 from "path";
|
|
22013
22595
|
var defaultWorkspacePeerDependencies = new Set([
|
|
22014
22596
|
"@react-spring/web",
|
|
22015
22597
|
"@use-gesture/react",
|
|
@@ -22067,7 +22649,7 @@ class WorkspaceRunner extends runner("workspace") {
|
|
|
22067
22649
|
owner = ""
|
|
22068
22650
|
}) {
|
|
22069
22651
|
const cwdPath = process.cwd();
|
|
22070
|
-
const workspaceRoot =
|
|
22652
|
+
const workspaceRoot = path49.join(cwdPath, dirname2, repoName);
|
|
22071
22653
|
const normalizedRegistryUrl = registryUrl ? getNpmRegistryUrl(registryUrl) : undefined;
|
|
22072
22654
|
const workspace = WorkspaceExecutor.fromRoot({ workspaceRoot, repoName });
|
|
22073
22655
|
const templateSpinner = workspace.spinning(`Creating workspace template files in ${dirname2}/${repoName}...`);
|
|
@@ -22123,9 +22705,9 @@ class WorkspaceRunner extends runner("workspace") {
|
|
|
22123
22705
|
}
|
|
22124
22706
|
async#getCliPackageJson() {
|
|
22125
22707
|
const packageJsonCandidates = [
|
|
22126
|
-
|
|
22127
|
-
|
|
22128
|
-
|
|
22708
|
+
path49.join(import.meta.dir, "../package.json"),
|
|
22709
|
+
path49.join(import.meta.dir, "package.json"),
|
|
22710
|
+
path49.join(path49.dirname(Bun.main), "package.json")
|
|
22129
22711
|
];
|
|
22130
22712
|
try {
|
|
22131
22713
|
packageJsonCandidates.unshift(Bun.resolveSync("@akanjs/cli/package.json", import.meta.dir));
|
|
@@ -22141,9 +22723,9 @@ class WorkspaceRunner extends runner("workspace") {
|
|
|
22141
22723
|
}
|
|
22142
22724
|
async#getAkanPackageJson() {
|
|
22143
22725
|
const packageJsonCandidates = [
|
|
22144
|
-
|
|
22145
|
-
|
|
22146
|
-
|
|
22726
|
+
path49.join(import.meta.dir, "../../../akanjs/package.json"),
|
|
22727
|
+
path49.join(process.cwd(), "pkgs/akanjs/package.json"),
|
|
22728
|
+
path49.join(path49.dirname(Bun.main), "node_modules/akanjs/package.json")
|
|
22147
22729
|
];
|
|
22148
22730
|
try {
|
|
22149
22731
|
packageJsonCandidates.unshift(Bun.resolveSync("akanjs/package.json", import.meta.dir));
|
|
@@ -22157,13 +22739,13 @@ class WorkspaceRunner extends runner("workspace") {
|
|
|
22157
22739
|
}
|
|
22158
22740
|
let current = import.meta.dir;
|
|
22159
22741
|
for (let depth = 0;depth < 6; depth++) {
|
|
22160
|
-
const packageJsonPath =
|
|
22742
|
+
const packageJsonPath = path49.join(current, "package.json");
|
|
22161
22743
|
if (await Bun.file(packageJsonPath).exists()) {
|
|
22162
22744
|
const packageJson = await FileSys.readJson(packageJsonPath);
|
|
22163
22745
|
if (packageJson.name === "akanjs")
|
|
22164
22746
|
return packageJson;
|
|
22165
22747
|
}
|
|
22166
|
-
const parent =
|
|
22748
|
+
const parent = path49.dirname(current);
|
|
22167
22749
|
if (parent === current)
|
|
22168
22750
|
break;
|
|
22169
22751
|
current = parent;
|
|
@@ -22205,14 +22787,18 @@ class WorkspaceScript extends script("workspace", [
|
|
|
22205
22787
|
ApplicationScript,
|
|
22206
22788
|
LibraryScript,
|
|
22207
22789
|
PackageScript,
|
|
22208
|
-
CloudScript
|
|
22790
|
+
CloudScript,
|
|
22791
|
+
ContextScript,
|
|
22792
|
+
AgentScript
|
|
22209
22793
|
]) {
|
|
22210
22794
|
async createWorkspace(repoName, appName, {
|
|
22211
22795
|
dirname: dirname2 = ".",
|
|
22212
22796
|
installLibs = false,
|
|
22213
22797
|
init = true,
|
|
22214
22798
|
registryUrl,
|
|
22215
|
-
owner
|
|
22799
|
+
owner,
|
|
22800
|
+
mcpInstall = true,
|
|
22801
|
+
agentInstall = true
|
|
22216
22802
|
}) {
|
|
22217
22803
|
const akanVersion = await this.packageScript.version(null, { log: false });
|
|
22218
22804
|
const workspace = await this.workspaceRunner.createWorkspace(repoName, appName, {
|
|
@@ -22233,6 +22819,10 @@ class WorkspaceScript extends script("workspace", [
|
|
|
22233
22819
|
dict: { appName },
|
|
22234
22820
|
options: { libs: installLibs ? ["util", "shared"] : [] }
|
|
22235
22821
|
});
|
|
22822
|
+
if (agentInstall)
|
|
22823
|
+
await this.agentScript.agent(workspace, "install", "all", { force: true });
|
|
22824
|
+
if (mcpInstall)
|
|
22825
|
+
await this.contextScript.mcpInstall(workspace, "all", { force: true });
|
|
22236
22826
|
const gitSpinner = workspace.spinning("Initializing git repository and commit...");
|
|
22237
22827
|
try {
|
|
22238
22828
|
await workspace.commit("Initial commit", { init: true });
|
|
@@ -22240,7 +22830,7 @@ class WorkspaceScript extends script("workspace", [
|
|
|
22240
22830
|
} catch (_) {
|
|
22241
22831
|
gitSpinner.fail("Git repository initialization failed. It's not fatal, you can commit manually");
|
|
22242
22832
|
}
|
|
22243
|
-
const workspacePath2 =
|
|
22833
|
+
const workspacePath2 = path50.join(dirname2, repoName);
|
|
22244
22834
|
Logger26.rawLog(`
|
|
22245
22835
|
\uD83C\uDF89 Welcome aboard! Workspace created in ${dirname2}/${repoName}`);
|
|
22246
22836
|
Logger26.rawLog(`\uD83D\uDE80 Run \`cd ${workspacePath2} && akan start ${appName}\` to start the development server.`);
|
|
@@ -22331,13 +22921,22 @@ class WorkspaceCommand extends command("workspace", [WorkspaceScript], ({ public
|
|
|
22331
22921
|
desc: "owner of the workspace",
|
|
22332
22922
|
default: process.env.GITHUB_OWNER,
|
|
22333
22923
|
nullable: true
|
|
22334
|
-
}).
|
|
22924
|
+
}).option("mcpInstall", Boolean, {
|
|
22925
|
+
desc: "Install the Akan MCP server config for Cursor, Claude Code, and Codex? (Recommended)",
|
|
22926
|
+
default: true
|
|
22927
|
+
}).option("agentInstall", Boolean, {
|
|
22928
|
+
flag: "A",
|
|
22929
|
+
desc: "Install Akan agent rules (AGENTS.md, CLAUDE.md, Cursor)? (Recommended)",
|
|
22930
|
+
default: true
|
|
22931
|
+
}).exec(async function(workspaceName, app, dir, libs, init, registry, owner, mcpInstall, agentInstall) {
|
|
22335
22932
|
const appName = app || "app";
|
|
22336
22933
|
await this.workspaceScript.createWorkspace(workspaceName.toLowerCase().replace(/ /g, "-"), appName.toLowerCase().replace(/ /g, "-"), {
|
|
22337
22934
|
dirname: dir,
|
|
22338
22935
|
installLibs: libs,
|
|
22339
22936
|
init,
|
|
22340
22937
|
owner,
|
|
22938
|
+
mcpInstall,
|
|
22939
|
+
agentInstall,
|
|
22341
22940
|
...registry ? { registryUrl: registry } : {}
|
|
22342
22941
|
});
|
|
22343
22942
|
}),
|