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

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
@@ -4,14 +4,14 @@ import {
4
4
  } from "./index-ayy5ecax.js";
5
5
  import {
6
6
  GlobalConfig
7
- } from "./index-mr9b7nkd.js";
7
+ } from "./index-wet2ytnr.js";
8
8
  import {
9
9
  Exec,
10
10
  Workspace,
11
11
  runner,
12
12
  script,
13
13
  command
14
- } from "./index-n0x82fhs.js";
14
+ } from "./index-ft1sfjz0.js";
15
15
  import {
16
16
  extractAgentBlock,
17
17
  collectScopeRecipeSources,
@@ -21,10 +21,8 @@ import {
21
21
  AppExecutor,
22
22
  LibExecutor,
23
23
  PkgExecutor
24
- } from "./index-c6rfvayh.js";
25
- import"./index-7nr23j55.js";
24
+ } from "./index-k1n0h7dk.js";
26
25
  import"./index-6wwzs1bc.js";
27
- import"./index-5es51p0n.js";
28
26
  import {
29
27
  countBlocking,
30
28
  formatStyleContract,
@@ -34,86 +32,48 @@ import {
34
32
  collectRecipeSources2,
35
33
  scanRecipes2
36
34
  } from "./index-by5gpp8x.js";
37
- import"./index-md3wv29p.js";
38
- import"./index-vfwdwq5c.js";
35
+ import"./index-saheq2bs.js";
36
+ import"./index-5y7qba1c.js";
39
37
  import"./index-h7yw2z9n.js";
40
38
  import {
41
39
  AgentScript
42
- } from "./index-rna7cj75.js";
40
+ } from "./index-5n0hf8r9.js";
43
41
  import {
44
42
  ApplicationScript
45
- } from "./index-yagad3ht.js";
43
+ } from "./index-a6c5pc4p.js";
46
44
  import {
47
45
  LibraryScript
48
- } from "./index-zp8y6zbb.js";
49
- import"./index-ctphds8v.js";
46
+ } from "./index-xxe90kqy.js";
47
+ import"./index-9wtbw98m.js";
50
48
  import"./index-mfm35dhh.js";
51
49
  import {
52
50
  PackageScript
53
- } from "./index-cnfawb2y.js";
51
+ } from "./index-a8h184wr.js";
54
52
  import {
55
53
  getNpmRegistryUrl,
56
54
  getLatestPackageVersion
57
- } from "./index-fqwtcy9j.js";
55
+ } from "./index-6c3ex9qw.js";
58
56
  import {
59
57
  CloudScript
60
- } from "./index-q2xqmbcq.js";
58
+ } from "./index-gz0c482j.js";
61
59
  import {
62
60
  ContextScript
63
- } from "./index-ktkm3ht3.js";
64
- import"./index-1q83gs77.js";
65
- import"./index-aknp5f6x.js";
66
- import"./index-y429w5m5.js";
67
- import"./index-azkj85kx.js";
68
- import"./index-ktnvnp7h.js";
69
- import"./index-nr8w8h7y.js";
70
- import"./index-nf4zam3r.js";
71
- import"./index-sc7s8927.js";
61
+ } from "./index-dq6wq1tv.js";
62
+ import"./index-b2nt0w0k.js";
63
+ import"./index-qcracvc9.js";
64
+ import"./index-j9vnq8tr.js";
65
+ import"./index-k86zc21w.js";
66
+ import"./index-1kzsn94d.js";
67
+ import"./index-cd5x18qh.js";
68
+ import"./index-v0s24t8j.js";
69
+ import"./index-m9c7k0gm.js";
72
70
 
73
71
  // pkgs/@akanjs/cli/workspace/workspace.runner.ts
74
- import path2 from "path";
72
+ import path from "path";
75
73
 
76
74
  // pkgs/@akanjs/devkit/biomeBase.ts
77
- var biomeBaseConfig = "@akanjs/devkit/biome.base.json";
78
- var biomeDomainsConfig = "@akanjs/devkit/biome.domains.json";
79
75
  var biomeVersion = "2.5.12";
80
76
 
81
- // pkgs/@akanjs/devkit/biomeStrictConfig.ts
82
- import { rm } from "fs/promises";
83
- import path from "path";
84
- class BiomeStrictConfig {
85
- static configFileNames = ["biome.json", "biome.jsonc"];
86
- static async resolveConfigName(workspaceRoot) {
87
- for (const fileName of BiomeStrictConfig.configFileNames) {
88
- if (await Bun.file(path.join(workspaceRoot, fileName)).exists())
89
- return fileName;
90
- }
91
- return null;
92
- }
93
- #filePath;
94
- #workspaceRoot;
95
- constructor(workspaceRoot, { id = process.pid } = {}) {
96
- this.#workspaceRoot = workspaceRoot;
97
- this.#filePath = path.join(workspaceRoot, `.biome.strict.${id}.json`);
98
- }
99
- get filePath() {
100
- return this.#filePath;
101
- }
102
- async write() {
103
- const configName = await BiomeStrictConfig.resolveConfigName(this.#workspaceRoot);
104
- if (!configName)
105
- return null;
106
- const config = { extends: [biomeBaseConfig, `./${configName}`, biomeDomainsConfig] };
107
- await Bun.write(this.#filePath, `${JSON.stringify(config, null, 2)}
108
- `);
109
- return this.#filePath;
110
- }
111
- async remove() {
112
- await rm(this.#filePath, { force: true });
113
- }
114
- }
115
- if (false) {}
116
-
117
77
  // pkgs/@akanjs/cli/workspace/workspace.runner.ts
118
78
  var defaultWorkspacePeerDependencies = new Set([
119
79
  "@react-spring/web",
@@ -168,7 +128,7 @@ class WorkspaceRunner extends runner("workspace") {
168
128
  owner = ""
169
129
  }) {
170
130
  const cwdPath = process.cwd();
171
- const workspaceRoot = path2.join(cwdPath, dirname, repoName);
131
+ const workspaceRoot = path.join(cwdPath, dirname, repoName);
172
132
  const normalizedRegistryUrl = registryUrl ? getNpmRegistryUrl(registryUrl) : undefined;
173
133
  const workspace = WorkspaceExecutor.fromRoot({ workspaceRoot, repoName });
174
134
  const templateSpinner = workspace.spinning(`Creating workspace template files in ${dirname}/${repoName}...`);
@@ -221,9 +181,9 @@ class WorkspaceRunner extends runner("workspace") {
221
181
  }
222
182
  async#getCliPackageJson() {
223
183
  const packageJsonCandidates = [
224
- path2.join(import.meta.dir, "../package.json"),
225
- path2.join(import.meta.dir, "package.json"),
226
- path2.join(path2.dirname(Bun.main), "package.json")
184
+ path.join(import.meta.dir, "../package.json"),
185
+ path.join(import.meta.dir, "package.json"),
186
+ path.join(path.dirname(Bun.main), "package.json")
227
187
  ];
228
188
  try {
229
189
  packageJsonCandidates.unshift(Bun.resolveSync("@akanjs/cli/package.json", import.meta.dir));
@@ -239,9 +199,9 @@ class WorkspaceRunner extends runner("workspace") {
239
199
  }
240
200
  async#getAkanPackageJson() {
241
201
  const packageJsonCandidates = [
242
- path2.join(import.meta.dir, "../../../akanjs/package.json"),
243
- path2.join(process.cwd(), "pkgs/akanjs/package.json"),
244
- path2.join(path2.dirname(Bun.main), "node_modules/akanjs/package.json")
202
+ path.join(import.meta.dir, "../../../akanjs/package.json"),
203
+ path.join(process.cwd(), "pkgs/akanjs/package.json"),
204
+ path.join(path.dirname(Bun.main), "node_modules/akanjs/package.json")
245
205
  ];
246
206
  try {
247
207
  packageJsonCandidates.unshift(Bun.resolveSync("akanjs/package.json", import.meta.dir));
@@ -255,13 +215,13 @@ class WorkspaceRunner extends runner("workspace") {
255
215
  }
256
216
  let current = import.meta.dir;
257
217
  for (let depth = 0;depth < 6; depth++) {
258
- const packageJsonPath = path2.join(current, "package.json");
218
+ const packageJsonPath = path.join(current, "package.json");
259
219
  if (await Bun.file(packageJsonPath).exists()) {
260
220
  const packageJson = await FileSys.readJson(packageJsonPath);
261
221
  if (packageJson.name === "akanjs")
262
222
  return packageJson;
263
223
  }
264
- const parent = path2.dirname(current);
224
+ const parent = path.dirname(current);
265
225
  if (parent === current)
266
226
  break;
267
227
  current = parent;
@@ -269,27 +229,26 @@ class WorkspaceRunner extends runner("workspace") {
269
229
  throw new Error(`[workspace] failed to locate akanjs package.json from ${import.meta.dir}`);
270
230
  }
271
231
  async lint(exec, workspace, { fix = true, maxDiagnostics = defaultMaxDiagnostics } = {}) {
272
- const strictConfig = new BiomeStrictConfig(workspace.workspaceRoot);
273
- const configPath = await strictConfig.write();
274
- try {
275
- await workspace.spawn("./node_modules/.bin/biome", [
276
- "check",
277
- ...fix ? ["--write"] : [],
278
- "--no-errors-on-unmatched",
279
- `--max-diagnostics=${maxDiagnostics > 0 ? maxDiagnostics : "none"}`,
280
- ...configPath ? ["--config-path", configPath] : [],
281
- exec.cwdPath
282
- ]);
283
- } finally {
284
- await strictConfig.remove();
285
- }
232
+ const configPath = await WorkspaceRunner.resolveBiomeConfigPath(workspace);
233
+ await workspace.spawn("./node_modules/.bin/biome", [
234
+ "check",
235
+ ...fix ? ["--write"] : [],
236
+ "--no-errors-on-unmatched",
237
+ `--max-diagnostics=${maxDiagnostics > 0 ? maxDiagnostics : "none"}`,
238
+ ...configPath ? ["--config-path", configPath] : [],
239
+ exec.cwdPath
240
+ ]);
286
241
  await this.#enforceStyleContract(exec);
287
242
  await this.#enforceRecipeGate(exec);
288
243
  await this.#enforceAgentsIndex(exec);
289
244
  }
290
245
  static async resolveBiomeConfigPath(workspace) {
291
- const fileName = await BiomeStrictConfig.resolveConfigName(workspace.workspaceRoot);
292
- return fileName ? path2.join(workspace.workspaceRoot, fileName) : null;
246
+ for (const fileName of ["biome.json", "biome.jsonc"]) {
247
+ const configPath = path.join(workspace.workspaceRoot, fileName);
248
+ if (await Bun.file(configPath).exists())
249
+ return configPath;
250
+ }
251
+ return null;
293
252
  }
294
253
  async#enforceAgentsIndex(exec) {
295
254
  if (!(exec instanceof SysExecutor))
@@ -308,7 +267,7 @@ class WorkspaceRunner extends runner("workspace") {
308
267
  const cwdPath = exec.cwdPath;
309
268
  if (!cwdPath)
310
269
  return;
311
- const uiDir = path2.join(cwdPath, "ui");
270
+ const uiDir = path.join(cwdPath, "ui");
312
271
  const sources = [
313
272
  ...await collectRecipeSources2(uiDir, "ui/Recipe"),
314
273
  ...await collectRecipeSources2(uiDir, "ui/recipe", "recipe")
@@ -325,7 +284,7 @@ class WorkspaceRunner extends runner("workspace") {
325
284
  const cwdPath = exec.cwdPath;
326
285
  if (!cwdPath)
327
286
  return;
328
- const stylesCssPath = path2.join(cwdPath, "page", "styles.css");
287
+ const stylesCssPath = path.join(cwdPath, "page", "styles.css");
329
288
  if (!await Bun.file(stylesCssPath).exists())
330
289
  return;
331
290
  const violations = {
@@ -361,7 +320,7 @@ AKAN_PUBLIC_LOG_LEVEL=debug
361
320
  }
362
321
 
363
322
  // pkgs/@akanjs/cli/workspace/workspace.script.ts
364
- import path3 from "path";
323
+ import path2 from "path";
365
324
  import { Logger } from "akanjs/common";
366
325
  class WorkspaceScript extends script("workspace", [
367
326
  WorkspaceRunner,
@@ -411,7 +370,7 @@ class WorkspaceScript extends script("workspace", [
411
370
  } catch (_) {
412
371
  gitSpinner.fail("Git repository initialization failed. It's not fatal, you can commit manually");
413
372
  }
414
- const workspacePath = path3.join(dirname, repoName);
373
+ const workspacePath = path2.join(dirname, repoName);
415
374
  Logger.rawLog(`
416
375
  \uD83C\uDF89 Welcome aboard! Workspace created in ${dirname}/${repoName}`);
417
376
  Logger.rawLog(`\uD83D\uDE80 Run \`cd ${workspacePath} && akan start ${appName}\` to start the development server.`);
package/index-5es51p0n.js DELETED
@@ -1,66 +0,0 @@
1
- // @bun
2
- // pkgs/@akanjs/devkit/spinner.ts
3
- import ora from "ora";
4
-
5
- class Spinner {
6
- static padding = 12;
7
- static oraOptions = { discardStdin: false };
8
- static canAnimate(stream = process.stderr) {
9
- return !stream.isTTY || stream.columns > 0;
10
- }
11
- spinner;
12
- stopWatch = null;
13
- startAt = new Date;
14
- prefix;
15
- message;
16
- enableSpin;
17
- constructor(message, { prefix = "", indent = 0, enableSpin = true } = {}) {
18
- Spinner.padding = Math.max(Spinner.padding, prefix.length);
19
- this.prefix = prefix;
20
- this.message = message;
21
- this.spinner = ora({ ...Spinner.oraOptions, text: message });
22
- this.spinner.prefixText = prefix.padStart(Spinner.padding, " ");
23
- this.spinner.indent = indent;
24
- this.enableSpin = enableSpin && Spinner.canAnimate();
25
- }
26
- start() {
27
- this.startAt = new Date;
28
- if (this.enableSpin) {
29
- this.spinner.start();
30
- this.stopWatch = setInterval(() => {
31
- this.spinner.prefixText = this.prefix.padStart(Spinner.padding, " ");
32
- this.spinner.text = `${this.message} (${this.#getElapsedTimeStr({ floor: true })})`;
33
- }, 1000);
34
- } else
35
- this.spinner.info();
36
- return this;
37
- }
38
- succeed(message) {
39
- this.spinner.succeed(`${message} (${this.#getElapsedTimeStr()})`);
40
- this.#reset();
41
- }
42
- fail(message) {
43
- this.spinner.fail(`${message} (${this.#getElapsedTimeStr()})`);
44
- this.#reset();
45
- }
46
- isSpinning() {
47
- return this.spinner.isSpinning;
48
- }
49
- #reset() {
50
- if (this.stopWatch)
51
- clearInterval(this.stopWatch);
52
- this.stopWatch = null;
53
- }
54
- #getElapsedTimeStr({ floor = false } = {}) {
55
- const ms = Date.now() - this.startAt.getTime();
56
- if (ms < 1000)
57
- return `${ms}ms`;
58
- const s = Math.floor(ms / 1000);
59
- if (s < 60)
60
- return `${floor ? Math.floor(ms / 1000) : Math.floor(ms / 100) / 10}s`;
61
- const m = Math.floor(s / 60);
62
- return `${m}m ${s % 60}s`;
63
- }
64
- }
65
-
66
- export { Spinner };
package/index-7nr23j55.js DELETED
@@ -1,344 +0,0 @@
1
- // @bun
2
- // pkgs/@akanjs/devkit/artifact/implicitRootLayout.ts
3
- import { mkdir } from "fs/promises";
4
- import path2 from "path";
5
-
6
- // pkgs/@akanjs/devkit/transforms/asyncDefaultExportDetector.ts
7
- import fs from "fs";
8
- import path from "path";
9
-
10
- class AsyncDefaultExportDetector {
11
- static #typescriptLoad;
12
- static #loadTypescript() {
13
- AsyncDefaultExportDetector.#typescriptLoad ??= import("typescript").then((mod) => mod.default ?? mod);
14
- return AsyncDefaultExportDetector.#typescriptLoad;
15
- }
16
- static async detect(moduleAbsPath) {
17
- try {
18
- const typescript = await AsyncDefaultExportDetector.#loadTypescript();
19
- const source = fs.readFileSync(path.resolve(moduleAbsPath), "utf8");
20
- const sourceFile = typescript.createSourceFile(moduleAbsPath, source, typescript.ScriptTarget.Latest, true, AsyncDefaultExportDetector.#scriptKind(typescript, moduleAbsPath));
21
- return new AsyncDefaultExportDetector(typescript).detectInSourceFile(sourceFile);
22
- } catch {
23
- return false;
24
- }
25
- }
26
- #ts;
27
- constructor(typescript) {
28
- this.#ts = typescript;
29
- }
30
- detectInSourceFile(sourceFile) {
31
- const ts = this.#ts;
32
- const asyncBindings = new Map;
33
- let defaultIdentifier = null;
34
- for (const statement of sourceFile.statements) {
35
- if (ts.isFunctionDeclaration(statement)) {
36
- if (this.#hasModifier(statement, ts.SyntaxKind.DefaultKeyword)) {
37
- return this.#hasModifier(statement, ts.SyntaxKind.AsyncKeyword);
38
- }
39
- if (statement.name) {
40
- asyncBindings.set(statement.name.text, this.#hasModifier(statement, ts.SyntaxKind.AsyncKeyword));
41
- }
42
- continue;
43
- }
44
- if (ts.isVariableStatement(statement)) {
45
- for (const declaration of statement.declarationList.declarations) {
46
- if (!ts.isIdentifier(declaration.name))
47
- continue;
48
- asyncBindings.set(declaration.name.text, this.#isAsyncFunctionExpression(declaration.initializer));
49
- }
50
- continue;
51
- }
52
- if (ts.isExportAssignment(statement)) {
53
- if (this.#isAsyncFunctionExpression(statement.expression))
54
- return true;
55
- if (ts.isIdentifier(statement.expression))
56
- defaultIdentifier = statement.expression.text;
57
- continue;
58
- }
59
- if (ts.isExportDeclaration(statement) && statement.exportClause && ts.isNamedExports(statement.exportClause)) {
60
- const exportClause = statement.exportClause;
61
- for (const specifier of exportClause.elements) {
62
- if (specifier.name.text !== "default")
63
- continue;
64
- defaultIdentifier = specifier.propertyName?.text ?? specifier.name.text;
65
- }
66
- }
67
- }
68
- return defaultIdentifier ? asyncBindings.get(defaultIdentifier) === true : false;
69
- }
70
- #hasModifier(node, kind) {
71
- const ts = this.#ts;
72
- return ts.canHaveModifiers(node) && (ts.getModifiers(node)?.some((modifier) => modifier.kind === kind) ?? false);
73
- }
74
- #isAsyncFunctionExpression(node) {
75
- const ts = this.#ts;
76
- return Boolean(node && (ts.isArrowFunction(node) || ts.isFunctionExpression(node)) && this.#hasModifier(node, ts.SyntaxKind.AsyncKeyword));
77
- }
78
- static #scriptKind(typescript, moduleAbsPath) {
79
- return moduleAbsPath.endsWith(".tsx") || moduleAbsPath.endsWith(".jsx") ? typescript.ScriptKind.TSX : typescript.ScriptKind.TS;
80
- }
81
- }
82
-
83
- // pkgs/@akanjs/devkit/artifact/implicitRootLayout.ts
84
- var LAYOUT_KEY_RE = /^\.\/(.+\/)?_layout\.(tsx|ts|jsx|js)$/;
85
- async function appHasStModule(appCwdPath) {
86
- return Bun.file(path2.join(appCwdPath, "lib", "st.ts")).exists();
87
- }
88
- var IMPLICIT_LAYOUT_DIR = path2.join(".akan", "generated", "root-layouts");
89
- var IMPLICIT_DICT_DIR = path2.join(".akan", "generated", "dict");
90
- var IMPLICIT_OVERRIDES_DIR = path2.join(".akan", "generated", "overrides");
91
- var OVERRIDES_KEY_RE = /^\.\/(.+\/)?_overrides\.(tsx|ts|jsx|js)$/;
92
- async function writeGeneratedOverridesLayoutFile(opts) {
93
- const filename = `${opts.key.replace(/^\.\//, "").replace(/[^a-zA-Z0-9]+/g, "_")}.tsx`;
94
- const absPath = path2.join(path2.resolve(opts.appCwdPath), IMPLICIT_OVERRIDES_DIR, filename);
95
- const userRel = path2.relative(path2.dirname(absPath), opts.userAbsPath).split(path2.sep).join("/");
96
- const userSpecifier = userRel.startsWith(".") ? userRel : `./${userRel}`;
97
- const source = `"use client";
98
- import { UiOverrideProvider } from "akanjs/ui";
99
- import { createElement, type ReactNode } from "react";
100
- import value from ${JSON.stringify(userSpecifier)};
101
-
102
- export default function AkanUiOverridesLayout({ children }: { children?: ReactNode }) {
103
- return createElement(UiOverrideProvider, { value }, children);
104
- }
105
- `;
106
- await Bun.write(absPath, source);
107
- return absPath;
108
- }
109
- function getRootBoundarySegments(key) {
110
- const match = LAYOUT_KEY_RE.exec(key);
111
- if (!match)
112
- return null;
113
- const prefix = match[1]?.replace(/\/$/, "");
114
- if (!prefix)
115
- return [];
116
- return prefix.split("/").filter(Boolean);
117
- }
118
- function implicitRootLayoutKey(segments) {
119
- return `./${[...segments, "__root_layout"].join("/")}.tsx`;
120
- }
121
- function implicitRootLayoutAbsPath(appCwdPath, segments) {
122
- const filename = segments.length ? `${segments.join("__")}__root_layout.tsx` : "__root_layout.tsx";
123
- return path2.join(path2.resolve(appCwdPath), IMPLICIT_LAYOUT_DIR, filename);
124
- }
125
- function implicitDictionaryMacroAbsPath(appCwdPath) {
126
- return path2.join(path2.resolve(appCwdPath), IMPLICIT_DICT_DIR, "useDict.ts");
127
- }
128
- function isRootBoundarySegments(segments, basePaths) {
129
- const firstVisibleIndex = segments.findIndex((segment) => !/^\(.+\)$/.test(segment));
130
- if (firstVisibleIndex === -1)
131
- return segments.length <= 1;
132
- if (segments.slice(firstVisibleIndex + 1).some((segment) => /^\(.+\)$/.test(segment)))
133
- return false;
134
- const visible = segments.slice(firstVisibleIndex);
135
- const allowedBasePaths = new Set([...basePaths].map((basePath) => basePath.trim()).filter(Boolean));
136
- return visible.length === 1 && (firstVisibleIndex > 0 || allowedBasePaths.has(visible[0] ?? ""));
137
- }
138
- function findRootBoundaries(pageKeys, appCwdPath, basePaths) {
139
- const boundaries = new Map;
140
- for (const key of pageKeys) {
141
- const segments = getRootBoundarySegments(key);
142
- if (!segments)
143
- continue;
144
- if (!isRootBoundarySegments(segments, basePaths))
145
- continue;
146
- const id = segments.join("/");
147
- boundaries.set(id, {
148
- sourceKey: key,
149
- sourceAbsPath: path2.resolve(appCwdPath, "page", key.replace(/^\.\//, "")),
150
- segments
151
- });
152
- }
153
- const hasExplicitRootBoundary = [...boundaries.values()].some((boundary) => boundary.segments.length === 0);
154
- if (!hasExplicitRootBoundary && boundaries.size === 0) {
155
- boundaries.set("", { sourceKey: null, sourceAbsPath: null, segments: [] });
156
- }
157
- return [...boundaries.values()].sort((a, b) => a.segments.join("/").localeCompare(b.segments.join("/")));
158
- }
159
- function hasAncestorRootBoundary(boundary, boundaries) {
160
- return boundaries.some((candidate) => candidate !== boundary && candidate.segments.length < boundary.segments.length && candidate.segments.every((segment, index) => boundary.segments[index] === segment));
161
- }
162
- function findExplicitRootLayoutAbsPath(pageKeys, appCwdPath) {
163
- const rootLayoutKey = pageKeys.find((key) => {
164
- const segments = getRootBoundarySegments(key);
165
- return segments !== null && segments.length === 0;
166
- });
167
- return rootLayoutKey ? path2.resolve(appCwdPath, "page", rootLayoutKey.replace(/^\.\//, "")) : null;
168
- }
169
- function routePrefixForSegments(segments) {
170
- const visible = segments.filter((segment) => !/^\(.+\)$/.test(segment));
171
- return visible[0] ?? null;
172
- }
173
- async function assertEnvClientConvention(appCwdPath, appName) {
174
- const envPath = path2.join(appCwdPath, "env", "env.client.ts");
175
- if (!await Bun.file(envPath).exists()) {
176
- throw new Error(`[route-convention] app "${appName}" must provide env/env.client.ts exporting "env" for generated System.Provider`);
177
- }
178
- }
179
- async function writeGeneratedDictionaryMacroFile(appCwdPath, appName) {
180
- const absPath = implicitDictionaryMacroAbsPath(appCwdPath);
181
- await mkdir(path2.dirname(absPath), { recursive: true });
182
- await Bun.write(absPath, `import { getAllDictionary } from "@apps/${appName}/lib/dict" with { type: "macro" };
183
-
184
- export const allDictionary = getAllDictionary();
185
- `);
186
- return absPath;
187
- }
188
- async function writeGeneratedRootLayoutFile(opts) {
189
- await assertEnvClientConvention(opts.appCwdPath, opts.appName);
190
- const dictMacroAbsPath = opts.includeSystemProvider ? await writeGeneratedDictionaryMacroFile(opts.appCwdPath, opts.appName) : null;
191
- const absPath = implicitRootLayoutAbsPath(opts.appCwdPath, opts.boundary.segments);
192
- await mkdir(path2.dirname(absPath), { recursive: true });
193
- const dictMacroRel = dictMacroAbsPath ? path2.relative(path2.dirname(absPath), dictMacroAbsPath).split(path2.sep).join("/") : null;
194
- const dictMacroSpecifier = dictMacroRel ? dictMacroRel.startsWith(".") ? dictMacroRel : `./${dictMacroRel}` : null;
195
- const sourceRel = opts.boundary.sourceAbsPath ? path2.relative(path2.dirname(absPath), opts.boundary.sourceAbsPath).split(path2.sep).join("/") : null;
196
- const sourceSpecifier = sourceRel ? sourceRel.startsWith(".") ? sourceRel : `./${sourceRel}` : null;
197
- const inheritedSourceAbsPath = opts.rootSourceAbsPath && opts.rootSourceAbsPath !== opts.boundary.sourceAbsPath ? opts.rootSourceAbsPath : null;
198
- const inheritedSourceRel = inheritedSourceAbsPath ? path2.relative(path2.dirname(absPath), inheritedSourceAbsPath).split(path2.sep).join("/") : null;
199
- const inheritedSourceSpecifier = inheritedSourceRel ? inheritedSourceRel.startsWith(".") ? inheritedSourceRel : `./${inheritedSourceRel}` : null;
200
- const clientImport = opts.includeStInit ? `import { st } from "@apps/${opts.appName}/client";
201
- void st;
202
- ` : `import "@apps/${opts.appName}/client";
203
- `;
204
- const inheritedImport = inheritedSourceSpecifier ? `import * as inheritedLayout from ${JSON.stringify(inheritedSourceSpecifier)};
205
- ` : `const inheritedLayout = {};
206
- `;
207
- const prefix = routePrefixForSegments(opts.boundary.segments);
208
- const userImport = sourceSpecifier ? `import UserLayout, * as userLayout from ${JSON.stringify(sourceSpecifier)};
209
- ` : `const UserLayout = ({ children }) => children;
210
- const userLayout = {};
211
- `;
212
- const isAsyncUserLayout = opts.boundary.sourceAbsPath ? await AsyncDefaultExportDetector.detect(opts.boundary.sourceAbsPath) : false;
213
- const userLayoutElement = "<UserLayout params={params} searchParams={searchParams}>{children}</UserLayout>";
214
- const layoutSignature = isAsyncUserLayout ? "export default async function GeneratedLayout" : "export default function GeneratedLayout";
215
- const layoutBinding = isAsyncUserLayout ? ` const layout =
216
- process.env.AKAN_PUBLIC_RENDER_ENV === "csr"
217
- ? await UserLayout({ params, searchParams, children })
218
- : ${userLayoutElement};
219
- ` : "";
220
- const layoutChild = isAsyncUserLayout ? "{layout}" : userLayoutElement;
221
- const layoutReturn = isAsyncUserLayout ? "layout" : userLayoutElement;
222
- const source = opts.includeSystemProvider ? `import type { LayoutProps, PageProps } from "akanjs/client";
223
- import { loadFonts } from "akanjs/client";
224
- import { System } from "akanjs/ui";
225
- import { env } from "@apps/${opts.appName}/env/env.client";
226
- import { allDictionary } from ${JSON.stringify(dictMacroSpecifier)};
227
- ${clientImport}${inheritedImport}${userImport}
228
- const userFonts = userLayout.fonts ?? inheritedLayout.fonts ?? [];
229
- const defaultFonts = userFonts.filter((font) => font.default);
230
- if (defaultFonts.length > 1) throw new Error("[route-convention] only one default font is allowed per root layout");
231
- const defaultFont = defaultFonts[0];
232
- const defaultFontClassName = defaultFont ? (defaultFont.className ?? \`font-\${defaultFont.name}\`) : undefined;
233
-
234
- export async function generateHead(props: PageProps) {
235
- if (userLayout.generateHead) return userLayout.generateHead(props);
236
- if (userLayout.head !== undefined) return userLayout.head;
237
- if (inheritedLayout.generateHead) return inheritedLayout.generateHead(props);
238
- return inheritedLayout.head;
239
- }
240
-
241
- export async function generateMetadata(props: PageProps) {
242
- if (userLayout.generateMetadata) return userLayout.generateMetadata(props);
243
- if (userLayout.metadata !== undefined) return userLayout.metadata;
244
- if (inheritedLayout.generateMetadata) return inheritedLayout.generateMetadata(props);
245
- return inheritedLayout.metadata;
246
- }
247
-
248
- export const NotFound = userLayout.NotFound ?? inheritedLayout.NotFound;
249
- export const Error = userLayout.Error ?? inheritedLayout.Error;
250
- export const pageConfig = userLayout.pageConfig ?? inheritedLayout.pageConfig;
251
-
252
- ${layoutSignature}({ children, params, searchParams }: LayoutProps) {
253
- ${layoutBinding} return (
254
- <System.Provider
255
- of={GeneratedLayout as never}
256
- appName=${JSON.stringify(opts.appName)}
257
- ${prefix ? `prefix=${JSON.stringify(prefix)}
258
- ` : ""}params={params}
259
- manifest={userLayout.manifest ?? inheritedLayout.manifest}
260
- env={env}
261
- theme={userLayout.theme ?? inheritedLayout.theme}
262
- fonts={loadFonts(userFonts)}
263
- className={defaultFontClassName}
264
- gaTrackingId={userLayout.gaTrackingId ?? inheritedLayout.gaTrackingId}
265
- layoutStyle={userLayout.layoutStyle ?? inheritedLayout.layoutStyle}
266
- reconnect={userLayout.reconnect ?? inheritedLayout.reconnect ?? false}
267
- wsConnect={userLayout.wsConnect ?? inheritedLayout.wsConnect ?? true}
268
- allDictionary={process.env.AKAN_PUBLIC_RENDER_ENV === "ssr" ? allDictionary : undefined}
269
- >
270
- ${layoutChild}
271
- </System.Provider>
272
- );
273
- }
274
- ` : `import type { LayoutProps, PageProps } from "akanjs/client";
275
- ${inheritedImport}${userImport}
276
- export async function generateHead(props: PageProps) {
277
- if (userLayout.generateHead) return userLayout.generateHead(props);
278
- if (userLayout.head !== undefined) return userLayout.head;
279
- if (inheritedLayout.generateHead) return inheritedLayout.generateHead(props);
280
- return inheritedLayout.head;
281
- }
282
-
283
- export async function generateMetadata(props: PageProps) {
284
- if (userLayout.generateMetadata) return userLayout.generateMetadata(props);
285
- if (userLayout.metadata !== undefined) return userLayout.metadata;
286
- if (inheritedLayout.generateMetadata) return inheritedLayout.generateMetadata(props);
287
- return inheritedLayout.metadata;
288
- }
289
-
290
- export const NotFound = userLayout.NotFound ?? inheritedLayout.NotFound;
291
- export const Error = userLayout.Error ?? inheritedLayout.Error;
292
- export const pageConfig = userLayout.pageConfig ?? inheritedLayout.pageConfig;
293
-
294
- ${layoutSignature}({ children, params, searchParams }: LayoutProps) {
295
- ${layoutBinding} return ${layoutReturn};
296
- }
297
- `;
298
- await Bun.write(absPath, source);
299
- return absPath;
300
- }
301
- async function resolveSsrPageEntries(opts) {
302
- const absPageDir = path2.resolve(opts.appCwdPath, "page");
303
- const hasSt = await appHasStModule(opts.appCwdPath);
304
- const basePaths = opts.basePaths ?? [];
305
- const rootSourceAbsPath = findExplicitRootLayoutAbsPath(opts.pageKeys, opts.appCwdPath);
306
- const rootBoundaries = findRootBoundaries(opts.pageKeys, opts.appCwdPath, basePaths);
307
- const rootLayoutKeys = new Set(opts.pageKeys.filter((key) => {
308
- const segments = getRootBoundarySegments(key);
309
- return segments !== null && isRootBoundarySegments(segments, basePaths);
310
- }));
311
- const base = await Promise.all(opts.pageKeys.filter((key) => !rootLayoutKeys.has(key)).map(async (key) => {
312
- const userAbsPath = path2.resolve(absPageDir, key);
313
- if (OVERRIDES_KEY_RE.test(key)) {
314
- const moduleAbsPath = await writeGeneratedOverridesLayoutFile({
315
- appCwdPath: opts.appCwdPath,
316
- key,
317
- userAbsPath
318
- });
319
- return { key, moduleAbsPath, seedAbsPaths: [userAbsPath] };
320
- }
321
- return { key, moduleAbsPath: userAbsPath };
322
- }));
323
- const generated = await Promise.all(rootBoundaries.map(async (boundary) => ({
324
- key: implicitRootLayoutKey(boundary.segments),
325
- moduleAbsPath: await writeGeneratedRootLayoutFile({
326
- appCwdPath: opts.appCwdPath,
327
- appName: opts.appName,
328
- boundary,
329
- rootSourceAbsPath,
330
- includeStInit: hasSt && boundary.segments.length === 0,
331
- includeSystemProvider: !hasAncestorRootBoundary(boundary, rootBoundaries)
332
- }),
333
- seedAbsPaths: [...new Set([boundary.sourceAbsPath, rootSourceAbsPath].filter((absPath) => absPath !== null))]
334
- })));
335
- const entries = [...base, ...generated];
336
- entries.sort((a, b) => a.key.localeCompare(b.key));
337
- return entries;
338
- }
339
- async function resolveSsrPageEntriesForApp(app, pageKeys) {
340
- const config = await app.getConfig();
341
- return resolveSsrPageEntries({ appCwdPath: app.cwdPath, appName: app.name, pageKeys, basePaths: config.basePaths });
342
- }
343
-
344
- export { AsyncDefaultExportDetector, getRootBoundarySegments, isRootBoundarySegments, resolveSsrPageEntriesForApp };