@akanjs/cli 2.1.1 → 2.1.2-rc.0

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/index.js CHANGED
@@ -203,11 +203,13 @@ class HttpClient {
203
203
  class CloudApi {
204
204
  #api;
205
205
  #accessToken = null;
206
- static async fromHost(host) {
206
+ #workspace;
207
+ static async fromHost(workspace, host) {
207
208
  const hostConfig = await GlobalConfig.getHostConfig(host);
208
- return new CloudApi(hostConfig);
209
+ return new CloudApi(workspace, hostConfig);
209
210
  }
210
- constructor(hostConfig) {
211
+ constructor(workspace, hostConfig) {
212
+ this.#workspace = workspace;
211
213
  const host = akanCloudHost;
212
214
  this.#api = new HttpClient(`${host}/api`);
213
215
  this.#accessToken = hostConfig.auth?.accessToken ?? null;
@@ -223,16 +225,17 @@ class CloudApi {
223
225
  const data = await this.#api.post(`/uploadEnv/${devProjectId}`, formData);
224
226
  return data;
225
227
  }
226
- async downloadEnv(devProjectId, localPath) {
228
+ async downloadEnv(devProjectId) {
229
+ const localPath = `${this.#workspace.workspaceRoot}/local/env.tar`;
227
230
  await this.#api.getFile(`/downloadEnv/${devProjectId}`, localPath);
228
231
  }
229
232
  async getRemoteAuthToken(remoteId) {
230
233
  try {
231
234
  if (this.#accessToken) {
232
235
  if (GlobalConfig.needRefreshToken(this.#accessToken))
233
- return await this.refreshAuthToken();
236
+ return await this.#refreshAuthToken();
234
237
  else
235
- return await this.refreshAuthToken();
238
+ return await this.#refreshAuthToken();
236
239
  }
237
240
  const accessToken = await this.#api.get(`/getRemoteAuthToken/${remoteId}`);
238
241
  this.#accessToken = GlobalConfig.toAccessToken(accessToken);
@@ -244,10 +247,14 @@ class CloudApi {
244
247
  return null;
245
248
  }
246
249
  }
247
- async refreshAuthToken() {
248
- const response = await this.#api.post(`/refreshRemoteAuthToken`, {
249
- refreshToken: this.#accessToken?.refreshToken
250
- });
250
+ async#refreshAuthToken() {
251
+ const refreshToken = this.#accessToken?.refreshToken;
252
+ if (!refreshToken)
253
+ throw new Error("No refresh token");
254
+ return await this.refreshAuthToken(refreshToken);
255
+ }
256
+ async refreshAuthToken(refreshToken) {
257
+ const response = await this.#api.post(`/refreshRemoteAuthToken`, { refreshToken });
251
258
  this.#accessToken = GlobalConfig.toAccessToken(response);
252
259
  this.#api.setHeaders({ Authorization: `Bearer ${this.#accessToken.jwt}` });
253
260
  return this.#accessToken;
@@ -650,12 +657,7 @@ import {
650
657
  spawn as spawn2
651
658
  } from "child_process";
652
659
  import { readFileSync as readFileSync3 } from "fs";
653
- import {
654
- copyFile,
655
- mkdir as mkdir2,
656
- readdir as readDirEntries,
657
- stat as stat2
658
- } from "fs/promises";
660
+ import { copyFile, mkdir as mkdir2, readdir as readDirEntries, stat as stat2 } from "fs/promises";
659
661
  import path7 from "path";
660
662
  import {
661
663
  capitalize,
@@ -707,8 +709,18 @@ var DEFAULT_OPTIMIZE_IMPORTS = [
707
709
  "mui-core",
708
710
  "react-icons/*"
709
711
  ];
710
- var WORKSPACE_BARREL_FACETS = ["ui", "webkit", "common", "client", "server"];
711
- var SSR_RUNTIME_PACKAGES = ["react", "react-dom", "react-server-dom-webpack"];
712
+ var WORKSPACE_BARREL_FACETS = [
713
+ "ui",
714
+ "webkit",
715
+ "common",
716
+ "client",
717
+ "server"
718
+ ];
719
+ var SSR_RUNTIME_PACKAGES = [
720
+ "react",
721
+ "react-dom",
722
+ "react-server-dom-webpack"
723
+ ];
712
724
  var NATIVE_RUNTIME_PACKAGES = ["sharp"];
713
725
  var DEFAULT_BACKEND_RUNTIME_PACKAGES = ["croner"];
714
726
  var DATABASE_MODE_RUNTIME_PACKAGES = {
@@ -768,7 +780,12 @@ class AkanAppConfig {
768
780
  ...libs.flatMap((lib) => WORKSPACE_BARREL_FACETS.map((facet) => `@libs/${lib}/${facet}`)),
769
781
  ...config?.barrelImports ?? []
770
782
  ];
771
- this.optimizeImports = [...new Set([...DEFAULT_OPTIMIZE_IMPORTS, ...config?.optimizeImports ?? []])];
783
+ this.optimizeImports = [
784
+ ...new Set([
785
+ ...DEFAULT_OPTIMIZE_IMPORTS,
786
+ ...config?.optimizeImports ?? []
787
+ ])
788
+ ];
772
789
  this.images = mergeImageConfig(config?.images);
773
790
  this.i18n = resolveAkanI18nConfig(config?.i18n);
774
791
  process.env.AKAN_PUBLIC_DEFAULT_LOCALE = this.i18n.defaultLocale;
@@ -879,7 +896,13 @@ class AkanAppConfig {
879
896
  }
880
897
  #makeDockerContent(docker) {
881
898
  if (docker.content)
882
- return { content: docker.content, image: {}, preRuns: [], postRuns: [], command: [] };
899
+ return {
900
+ content: docker.content,
901
+ image: {},
902
+ preRuns: [],
903
+ postRuns: [],
904
+ command: []
905
+ };
883
906
  const preRunScripts = this.#getDockerRunScripts(docker.preRuns ?? []);
884
907
  const postRunScripts = this.#getDockerRunScripts(docker.postRuns ?? []);
885
908
  const imageScript = docker.image ? this.#getDockerImageScript(docker.image, "oven/bun:1-slim") : "FROM oven/bun:1-slim";
@@ -910,7 +933,13 @@ ENV AKAN_PUBLIC_LOCALES=${this.i18n.locales.join(",")}
910
933
  ENV AKAN_PUBLIC_OPERATION_MODE=cloud
911
934
 
912
935
  CMD [${command.map((c) => `"${c}"`).join(",")}]`;
913
- return { content, image: imageScript, preRuns: docker.preRuns ?? [], postRuns: docker.postRuns ?? [], command };
936
+ return {
937
+ content,
938
+ image: imageScript,
939
+ preRuns: docker.preRuns ?? [],
940
+ postRuns: docker.postRuns ?? [],
941
+ command
942
+ };
914
943
  }
915
944
  static async from(app) {
916
945
  const [configImp, baseDevEnv, libs, rootPackageJson] = await Promise.all([
@@ -936,9 +965,24 @@ CMD [${command.map((c) => `"${c}"`).join(",")}]`;
936
965
  ...SSR_RUNTIME_PACKAGES,
937
966
  ...NATIVE_RUNTIME_PACKAGES,
938
967
  ...DEFAULT_BACKEND_RUNTIME_PACKAGES,
939
- ...DATABASE_MODE_RUNTIME_PACKAGES[this.defaultDatabaseMode]
968
+ ...this.getDatabaseModeRuntimePackages()
940
969
  ];
941
970
  }
971
+ getDatabaseModeRuntimePackages(databaseMode = this.defaultDatabaseMode) {
972
+ return [...DATABASE_MODE_RUNTIME_PACKAGES[databaseMode]];
973
+ }
974
+ getMissingDatabaseModeDependencySpecs(databaseMode = this.defaultDatabaseMode) {
975
+ const rootDependencies = {
976
+ ...this.rootPackageJson.dependencies,
977
+ ...this.rootPackageJson.devDependencies
978
+ };
979
+ return this.getDatabaseModeRuntimePackages(databaseMode).filter((lib) => !rootDependencies[lib]).map((lib) => {
980
+ const version = this.#resolveProductionDependencyVersion(lib);
981
+ if (!version)
982
+ throw new Error(`Dependency ${lib} not found in package.json`);
983
+ return `${lib}@${version}`;
984
+ });
985
+ }
942
986
  getProductionPackageJson(data = {}) {
943
987
  return {
944
988
  name: this.app.name,
@@ -974,7 +1018,12 @@ function getAkanPackageJson() {
974
1018
  return akanPackageJson;
975
1019
  } catch {}
976
1020
  }
977
- akanPackageJson = { name: "akanjs", version: "0.0.0", description: "akanjs", dependencies: {} };
1021
+ akanPackageJson = {
1022
+ name: "akanjs",
1023
+ version: "0.0.0",
1024
+ description: "akanjs",
1025
+ dependencies: {}
1026
+ };
978
1027
  return akanPackageJson;
979
1028
  }
980
1029
  function mergeImageConfig(config = {}) {
@@ -998,7 +1047,9 @@ class AkanLibConfig {
998
1047
  this.externalLibs = config?.externalLibs ?? [];
999
1048
  }
1000
1049
  static async from(lib) {
1001
- const [configImp] = await Promise.all([import(`${lib.cwdPath}/akan.config.ts`).then((mod) => mod.default)]);
1050
+ const [configImp] = await Promise.all([
1051
+ import(`${lib.cwdPath}/akan.config.ts`).then((mod) => mod.default)
1052
+ ]);
1002
1053
  const config = typeof configImp === "function" ? configImp(lib) : configImp;
1003
1054
  return new AkanLibConfig(lib, config);
1004
1055
  }
@@ -2372,13 +2423,8 @@ class CommandExecutionError extends Error {
2372
2423
  const displayCommand = formatCommandForDisplay(command, args);
2373
2424
  const status = signal ? `signal: ${signal}` : `exit code: ${code ?? "unknown"}`;
2374
2425
  const output = (stderr || stdout).trim();
2375
- super([
2376
- `Command failed: ${displayCommand}`,
2377
- `cwd: ${cwd}`,
2378
- status,
2379
- output ? `
2380
- ${output}` : ""
2381
- ].join(`
2426
+ super([`Command failed: ${displayCommand}`, `cwd: ${cwd}`, status, output ? `
2427
+ ${output}` : ""].join(`
2382
2428
  `), {
2383
2429
  cause
2384
2430
  });
@@ -2427,13 +2473,7 @@ var parseEnvFile = (envPath) => {
2427
2473
  }
2428
2474
  return env;
2429
2475
  };
2430
- var PAGE_ROUTE_EXPORTS = new Set([
2431
- "default",
2432
- "pageConfig",
2433
- "head",
2434
- "generateHead",
2435
- "Loading"
2436
- ]);
2476
+ var PAGE_ROUTE_EXPORTS = new Set(["default", "pageConfig", "head", "generateHead", "Loading"]);
2437
2477
  var ROOT_LAYOUT_EXPORTS = new Set([
2438
2478
  "default",
2439
2479
  "head",
@@ -2444,14 +2484,11 @@ var ROOT_LAYOUT_EXPORTS = new Set([
2444
2484
  "reconnect",
2445
2485
  "layoutStyle",
2446
2486
  "gaTrackingId",
2447
- "Loading"
2448
- ]);
2449
- var LAYOUT_ROUTE_EXPORTS = new Set([
2450
- "default",
2451
- "head",
2452
- "generateHead",
2453
- "Loading"
2487
+ "Loading",
2488
+ "NotFound",
2489
+ "Error"
2454
2490
  ]);
2491
+ var LAYOUT_ROUTE_EXPORTS = new Set(["default", "head", "generateHead", "Loading", "NotFound", "Error"]);
2455
2492
  function validateRouteSourceExports(source, filePath, kind, options = {}) {
2456
2493
  const sourceFile = ts3.createSourceFile(filePath, source, ts3.ScriptTarget.Latest, true, ts3.ScriptKind.TSX);
2457
2494
  const allowed = kind === "page" ? PAGE_ROUTE_EXPORTS : options.rootLayout ? ROOT_LAYOUT_EXPORTS : LAYOUT_ROUTE_EXPORTS;
@@ -2798,11 +2835,7 @@ class Executor {
2798
2835
  this.logger.debug(msg);
2799
2836
  return this;
2800
2837
  }
2801
- spinning(msg, {
2802
- prefix = `${this.emoji}${this.name}`,
2803
- indent = 0,
2804
- enableSpin = !Executor.verbose
2805
- } = {}) {
2838
+ spinning(msg, { prefix = `${this.emoji}${this.name}`, indent = 0, enableSpin = !Executor.verbose } = {}) {
2806
2839
  return new Spinner(msg, { prefix, indent, enableSpin }).start();
2807
2840
  }
2808
2841
  #tsconfig = null;
@@ -2831,9 +2864,7 @@ class Executor {
2831
2864
  this.#tsconfig = tsconfig;
2832
2865
  }
2833
2866
  #packageJson = null;
2834
- async getPackageJson({
2835
- refresh
2836
- } = {}) {
2867
+ async getPackageJson({ refresh } = {}) {
2837
2868
  if (this.#packageJson && !refresh)
2838
2869
  return this.#packageJson;
2839
2870
  const packageJson = await this.readJson("package.json");
@@ -2949,10 +2980,7 @@ class Executor {
2949
2980
  async applyTemplate(options) {
2950
2981
  const dict = {
2951
2982
  ...options.dict ?? {},
2952
- ...Object.fromEntries(Object.entries(options.dict ?? {}).map(([key, value]) => [
2953
- capitalize(key),
2954
- capitalize(value)
2955
- ]))
2983
+ ...Object.fromEntries(Object.entries(options.dict ?? {}).map(([key, value]) => [capitalize(key), capitalize(value)]))
2956
2984
  };
2957
2985
  return this._applyTemplate({ ...options, dict });
2958
2986
  }
@@ -3088,10 +3116,7 @@ class WorkspaceExecutor extends Executor {
3088
3116
  return await this.#getDirHasFile(`${this.workspaceRoot}/libs`, "akan.config.ts");
3089
3117
  }
3090
3118
  async getSyss() {
3091
- const [appNames, libNames] = await Promise.all([
3092
- this.getApps(),
3093
- this.getLibs()
3094
- ]);
3119
+ const [appNames, libNames] = await Promise.all([this.getApps(), this.getLibs()]);
3095
3120
  return [appNames, libNames];
3096
3121
  }
3097
3122
  async getPkgs() {
@@ -3100,11 +3125,7 @@ class WorkspaceExecutor extends Executor {
3100
3125
  return await this.#getDirHasFile(`${this.workspaceRoot}/pkgs`, "package.json");
3101
3126
  }
3102
3127
  async getExecs() {
3103
- const [appNames, libNames, pkgNames] = await Promise.all([
3104
- this.getApps(),
3105
- this.getLibs(),
3106
- this.getPkgs()
3107
- ]);
3128
+ const [appNames, libNames, pkgNames] = await Promise.all([this.getApps(), this.getLibs(), this.getPkgs()]);
3108
3129
  return [appNames, libNames, pkgNames];
3109
3130
  }
3110
3131
  async setPkgTsPaths(name) {
@@ -3122,10 +3143,7 @@ class WorkspaceExecutor extends Executor {
3122
3143
  async unsetPkgTsPaths(name) {
3123
3144
  const rootTsConfig = await this.readJson("tsconfig.json");
3124
3145
  const filteredKeys = Object.keys(rootTsConfig.compilerOptions.paths ?? {}).filter((key) => key !== name && key !== `${name}/*`);
3125
- rootTsConfig.compilerOptions.paths = Object.fromEntries(filteredKeys.map((key) => [
3126
- key,
3127
- rootTsConfig.compilerOptions.paths?.[key] ?? []
3128
- ]));
3146
+ rootTsConfig.compilerOptions.paths = Object.fromEntries(filteredKeys.map((key) => [key, rootTsConfig.compilerOptions.paths?.[key] ?? []]));
3129
3147
  if (rootTsConfig.references) {
3130
3148
  rootTsConfig.references = rootTsConfig.references.filter((ref) => ref.path !== `./pkgs/${name}/tsconfig.json`);
3131
3149
  }
@@ -3217,11 +3235,7 @@ class SysExecutor extends Executor {
3217
3235
  name;
3218
3236
  type;
3219
3237
  emoji;
3220
- constructor({
3221
- workspace = WorkspaceExecutor.fromRoot(),
3222
- name,
3223
- type
3224
- }) {
3238
+ constructor({ workspace = WorkspaceExecutor.fromRoot(), name, type }) {
3225
3239
  super(name, `${workspace.workspaceRoot}/${type}s/${name}`);
3226
3240
  this.workspace = workspace;
3227
3241
  this.name = name;
@@ -3324,10 +3338,7 @@ class SysExecutor extends Executor {
3324
3338
  },
3325
3339
  devDependencies: {
3326
3340
  ...Object.fromEntries(Object.entries(libPackageJson.devDependencies ?? {}).filter(([dep]) => !dependencySet.has(dep))),
3327
- ...Object.fromEntries(devDependencies.filter((dep) => rootPackageJson.dependencies?.[dep] || rootPackageJson.devDependencies?.[dep]).sort().map((dep) => [
3328
- dep,
3329
- rootPackageJson.devDependencies?.[dep] ?? rootPackageJson.dependencies?.[dep]
3330
- ]))
3341
+ ...Object.fromEntries(devDependencies.filter((dep) => rootPackageJson.dependencies?.[dep] || rootPackageJson.devDependencies?.[dep]).sort().map((dep) => [dep, rootPackageJson.devDependencies?.[dep] ?? rootPackageJson.dependencies?.[dep]]))
3331
3342
  }
3332
3343
  };
3333
3344
  await this.setPackageJson(libPkgJsonWithDeps);
@@ -3394,11 +3405,7 @@ class SysExecutor extends Executor {
3394
3405
  ...await LibExecutor.from(this, lib).getConstantFiles(),
3395
3406
  ...await LibExecutor.from(this, lib).getScalarConstantFiles()
3396
3407
  ]));
3397
- return [
3398
- ...sysContantFiles,
3399
- ...sysScalarConstantFiles,
3400
- ...libConstantFiles.flat()
3401
- ];
3408
+ return [...sysContantFiles, ...sysScalarConstantFiles, ...libConstantFiles.flat()];
3402
3409
  }
3403
3410
  async getDictionaryFiles() {
3404
3411
  const modules = await this.getModules();
@@ -3407,10 +3414,7 @@ class SysExecutor extends Executor {
3407
3414
  async applyTemplate(options) {
3408
3415
  const dict = {
3409
3416
  ...options.dict ?? {},
3410
- ...Object.fromEntries(Object.entries(options.dict ?? {}).map(([key, value]) => [
3411
- capitalize(key),
3412
- capitalize(value)
3413
- ]))
3417
+ ...Object.fromEntries(Object.entries(options.dict ?? {}).map(([key, value]) => [capitalize(key), capitalize(value)]))
3414
3418
  };
3415
3419
  const scanInfo = await this.scan();
3416
3420
  const fileContents = await this._applyTemplate({
@@ -3443,6 +3447,13 @@ class AppExecutor extends SysExecutor {
3443
3447
  getEnv() {
3444
3448
  return WorkspaceExecutor.getBaseDevEnv().env;
3445
3449
  }
3450
+ async getDevPort() {
3451
+ const basePort = 8282;
3452
+ const appNames = (await this.workspace.getApps()).sort((a, b) => a.localeCompare(b));
3453
+ const appIndex = Math.max(appNames.indexOf(this.name), 0);
3454
+ const portOffset = WorkspaceExecutor.getBaseDevEnv().portOffset;
3455
+ return basePort + appIndex + portOffset;
3456
+ }
3446
3457
  getCommandEnv(env = {}) {
3447
3458
  const basePort = 8282;
3448
3459
  const portOffset = WorkspaceExecutor.getBaseDevEnv().portOffset;
@@ -3469,17 +3480,19 @@ class AppExecutor extends SysExecutor {
3469
3480
  if (type === "build") {
3470
3481
  if (await this.exists(this.dist.cwdPath))
3471
3482
  await this.dist.exec(`rm -rf ${this.dist.cwdPath}`);
3472
- await Promise.all([
3473
- this.dist.mkdir("private"),
3474
- this.dist.mkdir("public")
3475
- ]);
3483
+ await Promise.all([this.dist.mkdir("private"), this.dist.mkdir("public")]);
3476
3484
  await Promise.all([
3477
3485
  this.cp("private", `${this.dist.cwdPath}/private`),
3478
3486
  this.cp("public", `${this.dist.cwdPath}/public`)
3479
3487
  ]);
3480
3488
  } else
3481
3489
  await this.removeDir(".akan");
3482
- const env = this.getCommandEnv({ AKAN_COMMAND_TYPE: type, ...routeEnv });
3490
+ const devPort = type === "start" ? (await this.getDevPort()).toString() : undefined;
3491
+ const env = this.getCommandEnv({
3492
+ AKAN_COMMAND_TYPE: type,
3493
+ ...routeEnv,
3494
+ ...devPort ? { PORT: devPort, AKAN_PUBLIC_CLIENT_PORT: devPort, AKAN_PUBLIC_SERVER_PORT: devPort } : {}
3495
+ });
3483
3496
  return { env };
3484
3497
  }
3485
3498
  #publicEnv = null;
@@ -3515,9 +3528,7 @@ class AppExecutor extends SysExecutor {
3515
3528
  return this.#akanConfig;
3516
3529
  }
3517
3530
  #pageKeys = null;
3518
- async getPageKeys({
3519
- refresh
3520
- } = {}) {
3531
+ async getPageKeys({ refresh } = {}) {
3521
3532
  if (this.#pageKeys && !refresh)
3522
3533
  return this.#pageKeys;
3523
3534
  const akanConfig2 = await this.getConfig();
@@ -3566,10 +3577,7 @@ class AppExecutor extends SysExecutor {
3566
3577
  const projectAssetsPath = `${this.cwdPath}/private`;
3567
3578
  const projectPublicLibPath = `${projectPublicPath}/libs`;
3568
3579
  const projectAssetsLibPath = `${projectAssetsPath}/libs`;
3569
- await Promise.all([
3570
- this.removeDir(projectPublicLibPath),
3571
- this.removeDir(projectAssetsLibPath)
3572
- ]);
3580
+ await Promise.all([this.removeDir(projectPublicLibPath), this.removeDir(projectAssetsLibPath)]);
3573
3581
  const targetPublicDeps = [];
3574
3582
  for (const dep of libDeps) {
3575
3583
  if (await this.exists(`${this.workspace.workspaceRoot}/libs/${dep}/public`))
@@ -3587,10 +3595,7 @@ class AppExecutor extends SysExecutor {
3587
3595
  ...targetAssetsDeps.map((dep) => this.cp(`${this.workspace.workspaceRoot}/libs/${dep}/private`, `${projectAssetsLibPath}/${dep}`))
3588
3596
  ]);
3589
3597
  }
3590
- async scanSync({
3591
- refresh = false,
3592
- write = true
3593
- } = {}) {
3598
+ async scanSync({ refresh = false, write = true } = {}) {
3594
3599
  const scanInfo = await this.scan({
3595
3600
  refresh,
3596
3601
  write,
@@ -3639,10 +3644,7 @@ class PkgExecutor extends Executor {
3639
3644
  name;
3640
3645
  dist;
3641
3646
  emoji = execEmoji.pkg;
3642
- constructor({
3643
- workspace = WorkspaceExecutor.fromRoot(),
3644
- name
3645
- }) {
3647
+ constructor({ workspace = WorkspaceExecutor.fromRoot(), name }) {
3646
3648
  super(name, `${workspace.workspaceRoot}/pkgs/${name}`);
3647
3649
  this.workspace = workspace;
3648
3650
  this.name = name;
@@ -3706,10 +3708,7 @@ class PkgExecutor extends Executor {
3706
3708
  };
3707
3709
  }
3708
3710
  async updatePackageJsonDependencies(dependencies = [], devDependencies = []) {
3709
- const [rootPackageJson, pkgJson] = await Promise.all([
3710
- this.workspace.getPackageJson(),
3711
- this.getPackageJson()
3712
- ]);
3711
+ const [rootPackageJson, pkgJson] = await Promise.all([this.workspace.getPackageJson(), this.getPackageJson()]);
3713
3712
  const dependencyMaps = await this.#toDependencyMap(rootPackageJson, dependencies, devDependencies);
3714
3713
  const newPkgJson = {
3715
3714
  ...pkgJson,
@@ -3719,10 +3718,7 @@ class PkgExecutor extends Executor {
3719
3718
  return newPkgJson;
3720
3719
  }
3721
3720
  async generateDistPackageJson(dependencies = [], devDependencies = []) {
3722
- const [rootPackageJson, pkgJson] = await Promise.all([
3723
- this.workspace.getPackageJson(),
3724
- this.getPackageJson()
3725
- ]);
3721
+ const [rootPackageJson, pkgJson] = await Promise.all([this.workspace.getPackageJson(), this.getPackageJson()]);
3726
3722
  const dependencyMaps = await this.#toDependencyMap(rootPackageJson, dependencies, devDependencies);
3727
3723
  const distPkgJson = {
3728
3724
  ...pkgJson,
@@ -3738,10 +3734,7 @@ class PkgExecutor extends Executor {
3738
3734
  engines: { bun: ">=1.3.13" },
3739
3735
  ...dependencyMaps
3740
3736
  };
3741
- await Promise.all([
3742
- this.dist.writeJson("package.json", distPkgJson),
3743
- this.writeJson("package.json", distPkgJson)
3744
- ]);
3737
+ await Promise.all([this.dist.writeJson("package.json", distPkgJson), this.writeJson("package.json", distPkgJson)]);
3745
3738
  return distPkgJson;
3746
3739
  }
3747
3740
  async build() {
@@ -3754,10 +3747,7 @@ class PkgExecutor extends Executor {
3754
3747
  await this.cp(`${this.cwdPath}/dist`, this.dist.cwdPath);
3755
3748
  }
3756
3749
  async generateTsconfigJson() {
3757
- const [rootTsconfig, pkgTsconfig] = await Promise.all([
3758
- this.workspace.getTsConfig(),
3759
- this.getTsConfig()
3760
- ]);
3750
+ const [rootTsconfig, pkgTsconfig] = await Promise.all([this.workspace.getTsConfig(), this.getTsConfig()]);
3761
3751
  const tsconfig = {
3762
3752
  ...rootTsconfig,
3763
3753
  ...pkgTsconfig,
@@ -4628,6 +4618,9 @@ export async function generateHead(props: PageProps) {
4628
4618
  return inheritedLayout.head;
4629
4619
  }
4630
4620
 
4621
+ export const NotFound = userLayout.NotFound ?? inheritedLayout.NotFound;
4622
+ export const Error = userLayout.Error ?? inheritedLayout.Error;
4623
+
4631
4624
  export default function GeneratedLayout({ children, params, searchParams }: LayoutProps) {
4632
4625
  return (
4633
4626
  <System.Provider
@@ -4657,6 +4650,9 @@ export async function generateHead(props: PageProps) {
4657
4650
  return inheritedLayout.head;
4658
4651
  }
4659
4652
 
4653
+ export const NotFound = userLayout.NotFound ?? inheritedLayout.NotFound;
4654
+ export const Error = userLayout.Error ?? inheritedLayout.Error;
4655
+
4660
4656
  export default function GeneratedLayout({ children, params, searchParams }: LayoutProps) {
4661
4657
  return <UserLayout params={params} searchParams={searchParams}>{children}</UserLayout>;
4662
4658
  }
@@ -10051,6 +10047,7 @@ import { jsxDEV as jsxDEV2, Fragment as Fragment2 } from "react/jsx-dev-runtime"
10051
10047
  import { select as select6 } from "@inquirer/prompts";
10052
10048
 
10053
10049
  // pkgs/@akanjs/cli/application/application.script.ts
10050
+ import { confirm as confirm3 } from "@inquirer/prompts";
10054
10051
  import { Logger as Logger12 } from "akanjs/common";
10055
10052
 
10056
10053
  // pkgs/@akanjs/cli/semver.ts
@@ -10254,7 +10251,7 @@ class ApplicationRunner extends runner("application") {
10254
10251
  const appHost = await new AkanAppHost(app, { env, withInk }).start();
10255
10252
  onStart?.();
10256
10253
  if (open)
10257
- setTimeout(() => openBrowser("http://localhost:8282"), 3000);
10254
+ setTimeout(() => openBrowser(`http://localhost:${env.AKAN_PUBLIC_CLIENT_PORT ?? env.PORT ?? "8282"}`), 3000);
10258
10255
  return appHost;
10259
10256
  }
10260
10257
  async buildIos(app, { target, env = "debug", regenerate = false } = {}) {
@@ -10479,7 +10476,38 @@ ${detail}`
10479
10476
  }
10480
10477
 
10481
10478
  // pkgs/@akanjs/cli/application/application.script.ts
10482
- class ApplicationScript extends script("application", [ApplicationRunner, LibraryScript]) {
10479
+ class ApplicationScript extends script("application", [
10480
+ ApplicationRunner,
10481
+ LibraryScript
10482
+ ]) {
10483
+ async confirmDatabaseModeDependencyInstall(databaseMode, installSpecs) {
10484
+ return await confirm3({
10485
+ message: [
10486
+ `Database mode '${databaseMode}' requires missing dependencies: ${installSpecs.join(", ")}.`,
10487
+ "Install them now?"
10488
+ ].join(" "),
10489
+ default: true
10490
+ });
10491
+ }
10492
+ async syncDatabaseModeDependencies(app, akanConfig3, databaseMode) {
10493
+ const installSpecs = akanConfig3.getMissingDatabaseModeDependencySpecs(databaseMode);
10494
+ if (installSpecs.length === 0)
10495
+ return;
10496
+ const shouldInstall = await this.confirmDatabaseModeDependencyInstall(databaseMode, installSpecs);
10497
+ if (!shouldInstall)
10498
+ throw new Error(`Database mode '${databaseMode}' requires missing dependencies: ${installSpecs.join(", ")}.`);
10499
+ const spinner2 = app.workspace.spinning(`Installing database dependencies for ${databaseMode} mode...`);
10500
+ try {
10501
+ await app.workspace.spawn("bun", ["add", ...installSpecs], {
10502
+ stdio: "inherit"
10503
+ });
10504
+ await app.workspace.getPackageJson({ refresh: true });
10505
+ spinner2.succeed(`Installed database dependencies for ${databaseMode} mode`);
10506
+ } catch (error) {
10507
+ spinner2.fail(`Failed to install database dependencies for ${databaseMode} mode`);
10508
+ throw error;
10509
+ }
10510
+ }
10483
10511
  async createApplication(appName, workspace, { start = false, libs = [] } = {}) {
10484
10512
  const spinner2 = workspace.spinning("Creating application...");
10485
10513
  const app = await this.applicationRunner.createApplication(appName, workspace, libs);
@@ -10504,7 +10532,11 @@ class ApplicationScript extends script("application", [ApplicationRunner, Librar
10504
10532
  await app.scanSync();
10505
10533
  await this.applicationRunner.runScript(app, scriptFilename);
10506
10534
  }
10507
- async build(app, { write = true, fast = false, quiet = false } = {}) {
10535
+ async build(app, {
10536
+ write = true,
10537
+ fast = false,
10538
+ quiet = false
10539
+ } = {}) {
10508
10540
  await app.scanSync({ write });
10509
10541
  if (!quiet)
10510
10542
  Logger12.rawLog(`Creating an optimized production build for ${app.name}...`);
@@ -10522,7 +10554,11 @@ class ApplicationScript extends script("application", [ApplicationRunner, Librar
10522
10554
  throw error;
10523
10555
  }
10524
10556
  }
10525
- async typecheck(app, { write = true, clean = false, incremental = true } = {}) {
10557
+ async typecheck(app, {
10558
+ write = true,
10559
+ clean = false,
10560
+ incremental = true
10561
+ } = {}) {
10526
10562
  await app.scanSync({ write });
10527
10563
  const spinner2 = app.spinning(`Typechecking ${app.name}...`);
10528
10564
  try {
@@ -10564,6 +10600,7 @@ class ApplicationScript extends script("application", [ApplicationRunner, Librar
10564
10600
  await app.scanSync({ write });
10565
10601
  const akanConfig3 = await app.getConfig();
10566
10602
  const databaseMode = process.env.AKAN_DATABASE_MODE ?? akanConfig3.defaultDatabaseMode ?? "single";
10603
+ await this.syncDatabaseModeDependencies(app, akanConfig3, databaseMode);
10567
10604
  if (app.getEnv() === "local" && dbup && databaseMode !== "single") {
10568
10605
  const wasDbAlreadyUp = await this.dbup(app.workspace, databaseMode);
10569
10606
  if (!wasDbAlreadyUp)
@@ -10582,7 +10619,12 @@ class ApplicationScript extends script("application", [ApplicationRunner, Librar
10582
10619
  });
10583
10620
  return akanAppHost;
10584
10621
  }
10585
- async buildIos(app, { write = true, target, env = "debug", regenerate = false } = {}) {
10622
+ async buildIos(app, {
10623
+ write = true,
10624
+ target,
10625
+ env = "debug",
10626
+ regenerate = false
10627
+ } = {}) {
10586
10628
  await app.scanSync({ write });
10587
10629
  await this.applicationRunner.buildIos(app, { target, env, regenerate });
10588
10630
  }
@@ -10595,15 +10637,32 @@ class ApplicationScript extends script("application", [ApplicationRunner, Librar
10595
10637
  regenerate = false
10596
10638
  } = {}) {
10597
10639
  await app.scanSync({ write });
10598
- await this.applicationRunner.startIos(app, { open, operation, env, target, regenerate });
10640
+ await this.applicationRunner.startIos(app, {
10641
+ open,
10642
+ operation,
10643
+ env,
10644
+ target,
10645
+ regenerate
10646
+ });
10599
10647
  }
10600
- async releaseIos(app, { write = true, target, env = "main", regenerate = false, allowLocalRelease = false } = {}) {
10648
+ async releaseIos(app, {
10649
+ write = true,
10650
+ target,
10651
+ env = "main",
10652
+ regenerate = false,
10653
+ allowLocalRelease = false
10654
+ } = {}) {
10601
10655
  await app.scanSync({ write });
10602
10656
  if (env === "local" && !allowLocalRelease)
10603
10657
  throw new Error("releaseIos --env local is blocked. Pass allowLocalRelease only for explicit local release testing.");
10604
10658
  await this.applicationRunner.releaseIos(app, { target, env, regenerate });
10605
10659
  }
10606
- async buildAndroid(app, { write = true, target, env = "debug", regenerate = false } = {}) {
10660
+ async buildAndroid(app, {
10661
+ write = true,
10662
+ target,
10663
+ env = "debug",
10664
+ regenerate = false
10665
+ } = {}) {
10607
10666
  await app.scanSync({ write });
10608
10667
  await this.applicationRunner.buildAndroid(app, { target, env, regenerate });
10609
10668
  }
@@ -10616,13 +10675,29 @@ class ApplicationScript extends script("application", [ApplicationRunner, Librar
10616
10675
  regenerate = false
10617
10676
  } = {}) {
10618
10677
  await app.scanSync({ write });
10619
- await this.applicationRunner.startAndroid(app, { open, operation, env, target, regenerate });
10678
+ await this.applicationRunner.startAndroid(app, {
10679
+ open,
10680
+ operation,
10681
+ env,
10682
+ target,
10683
+ regenerate
10684
+ });
10620
10685
  }
10621
- async releaseAndroid(app, assembleType, { write = true, target, env = "main", regenerate = false, allowLocalRelease = false } = {}) {
10686
+ async releaseAndroid(app, assembleType, {
10687
+ write = true,
10688
+ target,
10689
+ env = "main",
10690
+ regenerate = false,
10691
+ allowLocalRelease = false
10692
+ } = {}) {
10622
10693
  await app.scanSync({ write });
10623
10694
  if (env === "local" && !allowLocalRelease)
10624
10695
  throw new Error("releaseAndroid --env local is blocked. Pass allowLocalRelease only for explicit local release testing.");
10625
- await this.applicationRunner.releaseAndroid(app, assembleType, { target, env, regenerate });
10696
+ await this.applicationRunner.releaseAndroid(app, assembleType, {
10697
+ target,
10698
+ env,
10699
+ regenerate
10700
+ });
10626
10701
  }
10627
10702
  async configureApp(app) {
10628
10703
  await this.applicationRunner.configureApp(app);
@@ -10933,7 +11008,7 @@ class PackageScript extends script("package", [PackageRunner]) {
10933
11008
 
10934
11009
  // pkgs/@akanjs/cli/cloud/cloud.runner.ts
10935
11010
  import path38 from "path";
10936
- import { confirm as confirm3, input as input5, select as select7 } from "@inquirer/prompts";
11011
+ import { confirm as confirm4, input as input5, select as select7 } from "@inquirer/prompts";
10937
11012
  import { Logger as Logger14, sleep } from "akanjs/common";
10938
11013
  import chalk7 from "chalk";
10939
11014
  import * as QRcode from "qrcode";
@@ -10959,12 +11034,7 @@ var addRemoteEnvServerValue = "__addRemoteEnvServer";
10959
11034
  var removeRemoteEnvServerValue = "__removeRemoteEnvServer";
10960
11035
 
10961
11036
  class CloudRunner extends runner("cloud") {
10962
- #akanFrameworkPackages = new Set([
10963
- "akanjs",
10964
- "@akanjs/devkit",
10965
- "@akanjs/cli",
10966
- "create-akan-workspace"
10967
- ]);
11037
+ #akanFrameworkPackages = new Set(["akanjs", "@akanjs/devkit", "@akanjs/cli", "create-akan-workspace"]);
10968
11038
  #getRegistryArgs(registryUrl) {
10969
11039
  return registryUrl ? ["--registry", getNpmRegistryUrl(registryUrl)] : [];
10970
11040
  }
@@ -11047,7 +11117,7 @@ class CloudRunner extends runner("cloud") {
11047
11117
  value: name
11048
11118
  }))
11049
11119
  });
11050
- const shouldRemove = await confirm3({
11120
+ const shouldRemove = await confirm4({
11051
11121
  message: `Remove remote env server "${selectedName}"?`,
11052
11122
  default: false
11053
11123
  });
@@ -11085,22 +11155,14 @@ class CloudRunner extends runner("cloud") {
11085
11155
  return `${config.username ? `${config.username}@` : ""}${config.host}`;
11086
11156
  }
11087
11157
  #getScpArgs(config, source, target) {
11088
- return [
11089
- ...config.port ? ["-P", config.port.toString()] : [],
11090
- source,
11091
- target
11092
- ];
11158
+ return [...config.port ? ["-P", config.port.toString()] : [], source, target];
11093
11159
  }
11094
11160
  #getSshArgs(config, command3) {
11095
- return [
11096
- ...config.port ? ["-p", config.port.toString()] : [],
11097
- this.#getSshTarget(config),
11098
- command3
11099
- ];
11161
+ return [...config.port ? ["-p", config.port.toString()] : [], this.#getSshTarget(config), command3];
11100
11162
  }
11101
- async login() {
11163
+ async login(workspace) {
11102
11164
  const config = await GlobalConfig.getHostConfig();
11103
- const cloudApi2 = new CloudApi(config);
11165
+ const cloudApi2 = new CloudApi(workspace, config);
11104
11166
  const self = config.auth ? await cloudApi2.getRemoteSelf() : null;
11105
11167
  if (self) {
11106
11168
  Logger14.rawLog(chalk7.green(`
@@ -11207,7 +11269,7 @@ ${chalk7.green("\u27A4")} Authentication Required`));
11207
11269
  await workspace.writeJson(`dist/pkgs/${library}/package.json`, newDistPackageJson);
11208
11270
  }
11209
11271
  if (confirmPublish) {
11210
- const isDeployConfirmed = await confirm3({
11272
+ const isDeployConfirmed = await confirm4({
11211
11273
  message: "Are you sure you want to deploy the libraries?"
11212
11274
  });
11213
11275
  if (!isDeployConfirmed) {
@@ -11217,13 +11279,7 @@ ${chalk7.green("\u27A4")} Authentication Required`));
11217
11279
  }
11218
11280
  await Promise.all(akanPkgs.map(async (library) => {
11219
11281
  Logger14.info(`Publishing ${library}@${nextVersion} to ${registry ?? "npm"}...`);
11220
- await workspace.spawn("npm", [
11221
- "publish",
11222
- "--tag",
11223
- tag,
11224
- ...this.#getRegistryArgs(registry),
11225
- ...this.#getLocalRegistryAuthArgs(registry)
11226
- ], {
11282
+ await workspace.spawn("npm", ["publish", "--tag", tag, ...this.#getRegistryArgs(registry), ...this.#getLocalRegistryAuthArgs(registry)], {
11227
11283
  cwd: path38.join(workspace.workspaceRoot, "dist/pkgs", library),
11228
11284
  env: this.#getRegistryEnv(registry),
11229
11285
  stdio: "inherit"
@@ -11240,14 +11296,7 @@ ${chalk7.green("\u27A4")} Authentication Required`));
11240
11296
  await workspace.spawn("bun", ["update", "-g", "akanjs", "--latest", `--tag=${tag}`, ...registryArgs], { env });
11241
11297
  else
11242
11298
  await Promise.all([
11243
- workspace.spawn("bun", [
11244
- "update",
11245
- "-g",
11246
- "akanjs",
11247
- "--latest",
11248
- `--tag=${tag}`,
11249
- ...registryArgs
11250
- ], { env }),
11299
+ workspace.spawn("bun", ["update", "-g", "akanjs", "--latest", `--tag=${tag}`, ...registryArgs], { env }),
11251
11300
  this.#updateAkanPkgs(workspace, tag, registry)
11252
11301
  ]);
11253
11302
  }
@@ -11271,12 +11320,7 @@ ${chalk7.green("\u27A4")} Authentication Required`));
11271
11320
  }
11272
11321
  #normalizeAkanPackageJson(packageJson, packageName, version) {
11273
11322
  const normalized = { ...packageJson, version };
11274
- for (const field of [
11275
- "dependencies",
11276
- "devDependencies",
11277
- "peerDependencies",
11278
- "optionalDependencies"
11279
- ]) {
11323
+ for (const field of ["dependencies", "devDependencies", "peerDependencies", "optionalDependencies"]) {
11280
11324
  const dependencies = normalized[field];
11281
11325
  if (!dependencies)
11282
11326
  continue;
@@ -11291,7 +11335,7 @@ ${chalk7.green("\u27A4")} Authentication Required`));
11291
11335
  const envArchivePath = "local/env.tar";
11292
11336
  await workspace.mkdir("local");
11293
11337
  await workspace.remove(envArchivePath);
11294
- await cloudApi2.downloadEnv(workspaceId, path38.join(workspace.workspaceRoot, envArchivePath));
11338
+ await cloudApi2.downloadEnv(workspaceId);
11295
11339
  await workspace.spawn("tar", ["-xf", envArchivePath], {
11296
11340
  cwd: workspace.workspaceRoot
11297
11341
  });
@@ -11362,13 +11406,9 @@ ${chalk7.green("\u27A4")} Authentication Required`));
11362
11406
  }
11363
11407
 
11364
11408
  // pkgs/@akanjs/cli/cloud/cloud.script.ts
11365
- class CloudScript extends script("cloud", [
11366
- CloudRunner,
11367
- ApplicationScript,
11368
- PackageScript
11369
- ]) {
11409
+ class CloudScript extends script("cloud", [CloudRunner, ApplicationScript, PackageScript]) {
11370
11410
  async login(workspace) {
11371
- await this.cloudRunner.login();
11411
+ await this.cloudRunner.login(workspace);
11372
11412
  }
11373
11413
  async logout(workspace) {
11374
11414
  await this.cloudRunner.logout();
@@ -11386,7 +11426,7 @@ class CloudScript extends script("cloud", [
11386
11426
  async downloadEnv(workspace) {
11387
11427
  const workspaceId = workspace.getWorkspaceId({ allowEmpty: true });
11388
11428
  if (workspaceId) {
11389
- const cloudApi2 = await CloudApi.fromHost();
11429
+ const cloudApi2 = await CloudApi.fromHost(workspace);
11390
11430
  await this.cloudRunner.downloadEnv(cloudApi2, workspace, workspaceId);
11391
11431
  return;
11392
11432
  }
@@ -11396,7 +11436,7 @@ class CloudScript extends script("cloud", [
11396
11436
  const workspaceId = workspace.getWorkspaceId({ allowEmpty: true });
11397
11437
  const { path: path39 } = await this.cloudRunner.gatherEnvFiles(workspace);
11398
11438
  if (workspaceId) {
11399
- const cloudApi2 = await CloudApi.fromHost();
11439
+ const cloudApi2 = await CloudApi.fromHost(workspace);
11400
11440
  await this.cloudRunner.uploadEnv(cloudApi2, workspaceId, path39);
11401
11441
  return;
11402
11442
  }
@@ -11471,7 +11511,8 @@ class CloudCommand extends command("cloud", [CloudScript], ({ public: target })
11471
11511
  enum: [
11472
11512
  { label: "npm", value: "npm" },
11473
11513
  { label: "local", value: "local" }
11474
- ]
11514
+ ],
11515
+ default: process.env.USE_AKANJS_PKGS === "true" ? undefined : "npm"
11475
11516
  }).exec(async function(workspace, tag, registry) {
11476
11517
  await this.cloudScript.update(workspace, tag, {
11477
11518
  registryUrl: resolveRegistryUrl(registry)