@akanjs/cli 3.0.0-alpha.85 → 3.0.0-alpha.87

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