@akanjs/cli 2.1.1 → 2.1.2-rc.1

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