akanjs 2.0.6 → 2.0.7

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 (45) hide show
  1. package/README.ko.md +1 -1
  2. package/README.md +1 -1
  3. package/cli/application/application.command.ts +4 -1
  4. package/cli/application/application.runner.ts +5 -7
  5. package/cli/build.ts +1 -0
  6. package/cli/index.js +114 -74
  7. package/constant/serialize.ts +1 -1
  8. package/devkit/capacitor.base.config.ts +18 -4
  9. package/devkit/capacitorApp.ts +118 -64
  10. package/devkit/mobile/mobileTarget.ts +2 -1
  11. package/devkit/scanInfo.ts +1 -0
  12. package/package.json +1 -1
  13. package/server/akanApp.ts +53 -12
  14. package/server/processMetricsCollector.ts +79 -1
  15. package/server/resolver/database.resolver.ts +82 -31
  16. package/server/resolver/signal.resolver.ts +67 -28
  17. package/service/ipcTypes.ts +5 -0
  18. package/service/predefinedAdaptor/database.adaptor.ts +95 -27
  19. package/service/predefinedAdaptor/solidSqlite.ts +7 -7
  20. package/service/predefinedAdaptor/storage.adaptor.ts +35 -9
  21. package/signal/index.ts +1 -0
  22. package/signal/middleware.ts +5 -1
  23. package/signal/signalContext.ts +85 -31
  24. package/signal/trace.ts +279 -0
  25. package/types/devkit/capacitorApp.d.ts +14 -5
  26. package/types/server/processMetricsCollector.d.ts +2 -0
  27. package/types/service/ipcTypes.d.ts +5 -0
  28. package/types/service/predefinedAdaptor/database.adaptor.d.ts +26 -32
  29. package/types/service/predefinedAdaptor/solidSqlite.d.ts +3 -3
  30. package/types/service/predefinedAdaptor/storage.adaptor.d.ts +8 -2
  31. package/types/signal/index.d.ts +1 -0
  32. package/types/signal/signalContext.d.ts +4 -1
  33. package/types/signal/trace.d.ts +97 -0
  34. package/types/ui/Signal/style.d.ts +15 -0
  35. package/ui/Signal/Arg.tsx +22 -15
  36. package/ui/Signal/Doc.tsx +28 -21
  37. package/ui/Signal/Listener.tsx +15 -39
  38. package/ui/Signal/Message.tsx +32 -50
  39. package/ui/Signal/Object.tsx +16 -13
  40. package/ui/Signal/PubSub.tsx +29 -47
  41. package/ui/Signal/Response.tsx +7 -17
  42. package/ui/Signal/RestApi.tsx +41 -57
  43. package/ui/Signal/WebSocket.tsx +1 -1
  44. package/ui/Signal/style.ts +36 -0
  45. package/webkit/useCsrValues.ts +147 -37
package/README.ko.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Akan.js
2
2
 
3
- [English](./README.md) | [Docs](https://akanjs.com/docs) | [npm](https://www.npmjs.com/package/akanjs)
3
+ [English](https://unpkg.com/akanjs@latest/README.md) | [Docs](https://akanjs.com/docs) | [npm](https://www.npmjs.com/package/akanjs)
4
4
 
5
5
  **코드가 아니라, 비즈니스를 씁니다.**
6
6
  **Write the business, not the plumbing.**
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Akan.js
2
2
 
3
- [한국어](./README.ko.md) | [Docs](https://akanjs.com/docs) | [npm](https://www.npmjs.com/package/akanjs)
3
+ [한국어](https://unpkg.com/akanjs@latest/README.ko.md) | [Docs](https://akanjs.com/docs) | [npm](https://www.npmjs.com/package/akanjs)
4
4
 
5
5
  **Write the business, not the plumbing.**
6
6
 
@@ -94,7 +94,10 @@ export class ApplicationCommand extends command("application", [ApplicationScrip
94
94
  }),
95
95
  startIos: target({ short: true, desc: "Start iOS app in simulator or device" })
96
96
  .with(App)
97
- .option("target", String, { desc: "mobile target name or all" })
97
+ .option("target", String, {
98
+ ask: "Select mobile target",
99
+ enum: async ({ app }) => await getMobileTargetChoices(app),
100
+ })
98
101
  .option("env", String, {
99
102
  enum: ["local", "debug", "develop", "main"],
100
103
  desc: "backend environment",
@@ -117,7 +117,7 @@ export class ApplicationRunner extends runner("application") {
117
117
  const targets = await resolveMobileTargets(app, target);
118
118
  await this.#buildMobileCsr(app, env);
119
119
  await this.#runMobileTargets(targets, async (mobileTarget) => {
120
- await new CapacitorApp(app, mobileTarget.config).buildIos({ regenerate });
120
+ await new CapacitorApp(app, mobileTarget.config).buildIos({ env, regenerate });
121
121
  });
122
122
  }
123
123
  async startIos(
@@ -152,7 +152,7 @@ export class ApplicationRunner extends runner("application") {
152
152
  const targets = await resolveMobileTargets(app, target);
153
153
  await this.#buildMobileCsr(app, env);
154
154
  for (const mobileTarget of targets) {
155
- await new CapacitorApp(app, mobileTarget.config).buildIos({ regenerate });
155
+ await new CapacitorApp(app, mobileTarget.config).buildIos({ env, regenerate });
156
156
  }
157
157
  }
158
158
 
@@ -163,7 +163,7 @@ export class ApplicationRunner extends runner("application") {
163
163
  const targets = await resolveMobileTargets(app, target);
164
164
  await this.#buildMobileCsr(app, env);
165
165
  await this.#runMobileTargets(targets, async (mobileTarget) => {
166
- await new CapacitorApp(app, mobileTarget.config).buildAndroid("apk", { regenerate });
166
+ await new CapacitorApp(app, mobileTarget.config).buildAndroid("apk", { env, regenerate });
167
167
  });
168
168
  }
169
169
 
@@ -201,11 +201,9 @@ export class ApplicationRunner extends runner("application") {
201
201
  const targets = await resolveMobileTargets(app, target);
202
202
  await this.#buildMobileCsr(app, env);
203
203
  for (const mobileTarget of targets) {
204
- await new CapacitorApp(app, mobileTarget.config).buildAndroid(assembleType, { regenerate });
204
+ await new CapacitorApp(app, mobileTarget.config).buildAndroid(assembleType, { env, regenerate });
205
205
  app.log(`Release Android ${app.name}/${mobileTarget.name} ${assembleType} Completed.`);
206
- app.log(
207
- `Path : ${app.cwdPath}/mobile/${mobileTarget.name}/android/app/build/outputs/${assembleType === "apk" ? "apk" : "bundle"}/release`,
208
- );
206
+ app.log(`Path : ${app.cwdPath}/android/app/build/outputs/${assembleType === "apk" ? "apk" : "bundle"}/release`);
209
207
  }
210
208
  }
211
209
 
package/cli/build.ts CHANGED
@@ -15,6 +15,7 @@ const build = async () => {
15
15
  target: "bun",
16
16
  outdir: `${OUT_DIR}/cli`,
17
17
  external: Object.keys({ ...packageJson.dependencies, ...packageJson.peerDependencies }),
18
+ plugins: [],
18
19
  });
19
20
  await $`cp -R ${CLI_DIR}/templates ${OUT_DIR}/cli/templates`;
20
21
  } catch (error) {
package/cli/index.js CHANGED
@@ -2203,7 +2203,7 @@ var require_source_map_support = __commonJS((exports, module) => {
2203
2203
  });
2204
2204
 
2205
2205
  var require_typescript = __commonJS((exports, module) => {
2206
- var __dirname = "/Users/kangminseon/Desktop/Mintaka_Github/bunkan/node_modules/typescript/lib", __filename = "/Users/kangminseon/Desktop/Mintaka_Github/bunkan/node_modules/typescript/lib/typescript.js";
2206
+ var __dirname = "/Users/kangminseon/github/Ieading-flight-guidance/node_modules/typescript/lib", __filename = "/Users/kangminseon/github/Ieading-flight-guidance/node_modules/typescript/lib/typescript.js";
2207
2207
 
2208
2208
  var ts = {};
2209
2209
  ((module2) => {
@@ -174321,6 +174321,7 @@ var appRootAllowedDirs = new Set([
174321
174321
  "env",
174322
174322
  "ios",
174323
174323
  "lib",
174324
+ "mobile",
174324
174325
  "page",
174325
174326
  "private",
174326
174327
  "public",
@@ -180781,9 +180782,10 @@ var resolveMobileTargetByBasePath = (targets, basePath2) => {
180781
180782
  if (!template)
180782
180783
  return;
180783
180784
  return {
180784
- name: template.name,
180785
+ name: normalizedBasePath,
180785
180786
  config: {
180786
180787
  ...template.config,
180788
+ name: normalizedBasePath,
180787
180789
  basePath: normalizedBasePath
180788
180790
  }
180789
180791
  };
@@ -180837,32 +180839,46 @@ class CapacitorApp {
180837
180839
  project;
180838
180840
  iosTargetName = "App";
180839
180841
  targetRoot;
180842
+ targetRootPath;
180843
+ targetWebRoot;
180844
+ targetAssetRoot;
180845
+ iosRootPath = "ios";
180846
+ iosProjectPath = "ios/App";
180847
+ androidRootPath = "android";
180840
180848
  constructor(app, target) {
180841
180849
  this.app = app;
180842
180850
  this.target = target;
180843
- this.targetRoot = path34.join(this.app.cwdPath, "mobile", this.target.name);
180844
- this.project = new MobileProject(this.targetRoot, {
180845
- android: { path: "android" },
180846
- ios: { path: "ios/App" }
180851
+ this.targetRootPath = path34.posix.join("mobile", this.target.name);
180852
+ this.targetRoot = path34.join(this.app.cwdPath, this.targetRootPath);
180853
+ this.targetWebRoot = path34.join(this.targetRoot, "www");
180854
+ this.targetAssetRoot = path34.join(this.targetRoot, "assets");
180855
+ this.project = new MobileProject(this.app.cwdPath, {
180856
+ android: { path: this.androidRootPath },
180857
+ ios: { path: this.iosProjectPath }
180847
180858
  });
180848
180859
  }
180849
- async init({ platform, regenerate = false } = {}) {
180860
+ async init({
180861
+ platform,
180862
+ operation = "release",
180863
+ env = "debug",
180864
+ regenerate = false
180865
+ } = {}) {
180850
180866
  await mkdir10(this.targetRoot, { recursive: true });
180851
180867
  await this.#writeCapacitorConfig();
180852
180868
  if (regenerate) {
180853
180869
  if (!platform || platform === "ios")
180854
- await rm4(path34.join(this.targetRoot, "ios"), { recursive: true, force: true });
180870
+ await rm4(path34.join(this.app.cwdPath, this.iosRootPath), { recursive: true, force: true });
180855
180871
  if (!platform || platform === "android")
180856
- await rm4(path34.join(this.targetRoot, "android"), { recursive: true, force: true });
180872
+ await rm4(path34.join(this.app.cwdPath, this.androidRootPath), { recursive: true, force: true });
180857
180873
  }
180858
180874
  const project = this.project;
180859
180875
  await this.project.load();
180860
180876
  if ((!platform || platform === "android") && !project.android) {
180861
- await this.#spawn("npx", ["cap", "add", "android"]);
180877
+ await this.#spawnMobile("npx", ["cap", "add", "android"], { operation, env });
180862
180878
  await this.project.load();
180863
180879
  }
180864
180880
  if ((!platform || platform === "ios") && !project.ios) {
180865
- await this.#spawn("npx", ["cap", "add", "ios"]);
180881
+ await this.#spawnMobile("npx", ["cap", "add", "ios"], { operation, env });
180866
180882
  await this.project.load();
180867
180883
  }
180868
180884
  return this;
@@ -180870,57 +180886,52 @@ class CapacitorApp {
180870
180886
  async save() {
180871
180887
  await this.project.commit();
180872
180888
  }
180873
- async#prepareIos({ regenerate = false } = {}) {
180874
- await this.init({ platform: "ios", regenerate });
180889
+ async#prepareIos({ operation, env, regenerate = false }) {
180890
+ await this.init({ platform: "ios", operation, env, regenerate });
180875
180891
  await this.#prepareTargetAssets();
180876
180892
  await this.#prepareExternalFiles("ios");
180877
180893
  await this.#applyIosMetadata();
180878
180894
  await this.#applyPermissions();
180879
180895
  await this.#applyLinks();
180880
180896
  await this.project.commit();
180881
- await this.#generateAssets();
180897
+ await this.#generateAssets({ operation, env });
180882
180898
  this.app.verbose(`syncing iOS`);
180883
- await this.#spawn("npx", ["cap", "sync", "ios"]);
180899
+ await this.#spawnMobile("npx", ["cap", "sync", "ios"], { operation, env });
180884
180900
  this.app.verbose(`sync completed.`);
180885
180901
  }
180886
- async buildIos(options = {}) {
180902
+ async buildIos({ env = "debug", regenerate = false } = {}) {
180887
180903
  await this.prepareWww();
180888
- await this.#prepareIos(options);
180889
- await this.#spawn("npx", ["cap", "build", "ios"], { stdio: "inherit" });
180904
+ await this.#prepareIos({ operation: "release", env, regenerate });
180905
+ await this.#spawnMobile("npx", ["cap", "build", "ios"], { operation: "release", env }, { stdio: "inherit" });
180890
180906
  this.app.verbose(`build completed iOS.`);
180891
180907
  return;
180892
180908
  }
180893
180909
  async syncIos() {
180894
- await this.#spawn("npx", ["cap", "sync", "ios"]);
180910
+ await this.#spawnMobile("npx", ["cap", "sync", "ios"], { operation: "local", env: "local" });
180895
180911
  }
180896
180912
  async openIos() {
180897
- await this.#spawn("npx", ["cap", "open", "ios"]);
180913
+ await this.#spawnMobile("npx", ["cap", "open", "ios"], { operation: "local", env: "local" });
180898
180914
  }
180899
180915
  async runIos({ operation, env, regenerate = false }) {
180900
180916
  if (operation === "release")
180901
180917
  await this.prepareWww();
180902
- await this.#prepareIos({ regenerate });
180918
+ await this.#prepareIos({ operation, env, regenerate });
180903
180919
  const args = ["cap", "run", "ios"];
180904
- if (operation !== "release")
180905
- args.push("--live-reload");
180906
- await this.#spawn("npx", args, {
180907
- env: this.#commandEnv(operation, env),
180908
- stdio: "inherit"
180909
- });
180920
+ await this.#spawnMobile("npx", args, { operation, env }, { stdio: "inherit" });
180910
180921
  }
180911
- async#prepareAndroid({ regenerate = false } = {}) {
180912
- await this.init({ platform: "android", regenerate });
180922
+ async#prepareAndroid({ operation, env, regenerate = false }) {
180923
+ await this.init({ platform: "android", operation, env, regenerate });
180913
180924
  await this.#prepareTargetAssets();
180914
180925
  await this.#prepareExternalFiles("android");
180915
180926
  await this.#applyAndroidMetadata();
180916
180927
  await this.#applyPermissions();
180917
180928
  await this.#applyLinks();
180918
180929
  await this.project.commit();
180919
- await this.#generateAssets();
180920
- await this.#spawn("npx", ["cap", "sync", "android"]);
180930
+ await this.#generateAssets({ operation, env });
180931
+ await this.#spawnMobile("npx", ["cap", "sync", "android"], { operation, env });
180921
180932
  }
180922
180933
  async#updateAndroidBuildTypes() {
180923
- const appGradle = await FileEditor.create(`${this.targetRoot}/android/app/build.gradle`);
180934
+ const appGradle = await FileEditor.create(path34.join(this.app.cwdPath, this.androidRootPath, "app/build.gradle"));
180924
180935
  const buildTypesBlock = `
180925
180936
  debug {
180926
180937
  applicationIdSuffix ".debug"
@@ -180955,54 +180966,49 @@ class CapacitorApp {
180955
180966
  }
180956
180967
  await appGradle.save();
180957
180968
  }
180958
- async buildAndroid(assembleType, options = {}) {
180969
+ async buildAndroid(assembleType, { env = "debug", regenerate = false } = {}) {
180959
180970
  await this.prepareWww();
180960
- await this.#prepareAndroid(options);
180971
+ await this.#prepareAndroid({ operation: "release", env, regenerate });
180961
180972
  await this.#updateAndroidBuildTypes();
180962
180973
  const isWindows = process.platform === "win32";
180963
180974
  const gradleCommand = isWindows ? "gradlew.bat" : "./gradlew";
180964
180975
  await this.app.spawn(gradleCommand, [assembleType === "apk" ? "assembleRelease" : "bundleRelease"], {
180965
180976
  stdio: "inherit",
180966
- cwd: `${this.targetRoot}/android`
180977
+ cwd: path34.join(this.app.cwdPath, this.androidRootPath),
180978
+ env: this.#commandEnv("release", env)
180967
180979
  });
180968
180980
  }
180969
180981
  async openAndroid() {
180970
- await this.#spawn("npx", ["cap", "open", "android"]);
180982
+ await this.#spawnMobile("npx", ["cap", "open", "android"], { operation: "local", env: "local" });
180971
180983
  }
180972
180984
  async syncAndroid(options = {}) {
180973
180985
  await this.prepareWww();
180974
- await this.#prepareAndroid(options);
180986
+ await this.#prepareAndroid({ operation: "release", env: "debug", ...options });
180975
180987
  this.app.log(`Sync Android Completed.`);
180976
180988
  }
180977
180989
  async runAndroid({ operation, env, regenerate = false }) {
180978
180990
  if (operation === "release")
180979
180991
  await this.prepareWww();
180980
- await this.#prepareAndroid({ regenerate });
180992
+ await this.#prepareAndroid({ operation, env, regenerate });
180981
180993
  this.app.logger.info(`Running Android in ${operation} mode on ${env} env`);
180982
180994
  const args = ["cap", "run", "android"];
180983
- if (operation !== "release")
180984
- args.push("--live-reload");
180985
- await this.#spawn("npx", args, {
180986
- env: this.#commandEnv(operation, env),
180987
- stdio: "inherit"
180988
- });
180995
+ await this.#spawnMobile("npx", args, { operation, env }, { stdio: "inherit" });
180989
180996
  }
180990
180997
  async releaseIos() {
180991
180998
  await this.prepareWww();
180992
- await this.#prepareIos();
180999
+ await this.#prepareIos({ operation: "release", env: "main" });
180993
181000
  }
180994
181001
  async releaseAndroid() {
180995
181002
  await this.prepareWww();
180996
- await this.#prepareAndroid();
181003
+ await this.#prepareAndroid({ operation: "release", env: "main" });
180997
181004
  }
180998
181005
  async prepareWww() {
180999
181006
  const htmlSource = path34.join(this.app.dist.cwdPath, "csr", targetHtmlFilename(this.target));
181000
181007
  if (!await Bun.file(htmlSource).exists())
181001
181008
  throw new Error(`CSR html for mobile target '${this.target.name}' not found: ${htmlSource}`);
181002
- const wwwDir = path34.join(this.targetRoot, "www");
181003
- await rm4(wwwDir, { recursive: true, force: true });
181004
- await mkdir10(wwwDir, { recursive: true });
181005
- await Bun.write(path34.join(wwwDir, "index.html"), this.#injectMobileTargetMeta(await Bun.file(htmlSource).text()));
181009
+ await rm4(this.targetWebRoot, { recursive: true, force: true });
181010
+ await mkdir10(this.targetWebRoot, { recursive: true });
181011
+ await Bun.write(path34.join(this.targetWebRoot, "index.html"), this.#injectMobileTargetMeta(await Bun.file(htmlSource).text()));
181006
181012
  }
181007
181013
  #injectMobileTargetMeta(html) {
181008
181014
  const basePath2 = this.target.basePath?.replace(/^\/+|\/+$/g, "") ?? "";
@@ -181014,24 +181020,40 @@ class CapacitorApp {
181014
181020
  }
181015
181021
  async#writeCapacitorConfig() {
181016
181022
  await mkdir10(this.targetRoot, { recursive: true });
181017
- const appInfoPath = path34.relative(this.targetRoot, path34.join(this.app.cwdPath, "akan.app.json")).split(path34.sep).join("/");
181018
- const baseConfigPath = path34.relative(this.targetRoot, path34.join(this.app.workspace.cwdPath, "pkgs/akanjs/devkit/capacitor.base.config")).split(path34.sep).join("/");
181019
- const content = `import { withBase } from "${baseConfigPath.startsWith(".") ? baseConfigPath : `./${baseConfigPath}`}";
181020
- import appInfo from "${appInfoPath}";
181023
+ const appInfoPath = path34.relative(this.app.cwdPath, path34.join(this.app.cwdPath, "akan.app.json")).split(path34.sep).join("/");
181024
+ const baseConfigPath = path34.relative(this.app.cwdPath, path34.join(this.app.workspace.cwdPath, "pkgs/akanjs/devkit/capacitor.base.config")).split(path34.sep).join("/");
181025
+ const content = `import type { AppScanResult } from "akanjs/devkit";
181026
+ import { withBase } from "${baseConfigPath.startsWith(".") ? baseConfigPath : `./${baseConfigPath}`}";
181027
+ import appInfo from "${appInfoPath.startsWith(".") ? appInfoPath : `./${appInfoPath}`}";
181021
181028
 
181022
- export default withBase((config) => config, appInfo, "${this.target.name}");
181029
+ export default withBase(
181030
+ (config, target) => ({
181031
+ ...config,
181032
+ webDir: \`mobile/\${target.name}/www\`,
181033
+ android: {
181034
+ ...config.android,
181035
+ path: "android",
181036
+ },
181037
+ ios: {
181038
+ ...config.ios,
181039
+ path: "ios",
181040
+ },
181041
+ }),
181042
+ appInfo as AppScanResult,
181043
+ );
181023
181044
  `;
181024
- await Bun.write(path34.join(this.targetRoot, "capacitor.config.ts"), content);
181045
+ await Bun.write(path34.join(this.app.cwdPath, "capacitor.config.ts"), content);
181025
181046
  }
181026
181047
  async#prepareTargetAssets() {
181027
181048
  if (!this.target.assets)
181028
181049
  return;
181029
- const assetsDir = path34.join(this.targetRoot, "assets");
181030
- await mkdir10(assetsDir, { recursive: true });
181050
+ await mkdir10(this.targetAssetRoot, { recursive: true });
181031
181051
  if (this.target.assets.icon)
181032
- await cp2(path34.join(this.app.cwdPath, this.target.assets.icon), path34.join(assetsDir, "icon.png"), { force: true });
181052
+ await cp2(path34.join(this.app.cwdPath, this.target.assets.icon), path34.join(this.targetAssetRoot, "icon.png"), {
181053
+ force: true
181054
+ });
181033
181055
  if (this.target.assets.splash)
181034
- await cp2(path34.join(this.app.cwdPath, this.target.assets.splash), path34.join(assetsDir, "splash.png"), {
181056
+ await cp2(path34.join(this.app.cwdPath, this.target.assets.splash), path34.join(this.targetAssetRoot, "splash.png"), {
181035
181057
  force: true
181036
181058
  });
181037
181059
  }
@@ -181039,16 +181061,26 @@ export default withBase((config) => config, appInfo, "${this.target.name}");
181039
181061
  const files = this.target.files?.[platform];
181040
181062
  if (!files)
181041
181063
  return;
181064
+ const platformRoot = path34.join(this.app.cwdPath, platform === "ios" ? this.iosRootPath : this.androidRootPath);
181042
181065
  await Promise.all(Object.entries(files).map(async ([to, from]) => {
181043
- const targetPath = path34.join(this.targetRoot, platform, to);
181066
+ const targetPath = path34.join(platformRoot, to);
181044
181067
  await mkdir10(path34.dirname(targetPath), { recursive: true });
181045
181068
  await cp2(path34.join(this.app.cwdPath, from), targetPath, { force: true });
181046
181069
  }));
181047
181070
  }
181048
- async#generateAssets() {
181071
+ async#generateAssets({ operation, env }) {
181049
181072
  if (!this.target.assets)
181050
181073
  return;
181051
- await this.#spawn("npx", ["@capacitor/assets", "generate"]);
181074
+ await this.#spawnMobile("npx", [
181075
+ "@capacitor/assets",
181076
+ "generate",
181077
+ "--assetPath",
181078
+ path34.posix.join(this.targetRootPath, "assets"),
181079
+ "--iosProject",
181080
+ this.iosProjectPath,
181081
+ "--androidProject",
181082
+ this.androidRootPath
181083
+ ], { operation, env });
181052
181084
  }
181053
181085
  async#applyIosMetadata() {
181054
181086
  this.project.ios.setBundleId("App", "Debug", this.target.appId);
@@ -181098,16 +181130,21 @@ export default withBase((config) => config, appInfo, "${this.target.name}");
181098
181130
  }
181099
181131
  }
181100
181132
  #commandEnv(operation, env) {
181101
- return {
181102
- ...process.env,
181133
+ return this.app.getCommandEnv({
181103
181134
  APP_OPERATION_MODE: operation,
181104
- AKAN_PUBLIC_OPERATION_MODE: operation,
181135
+ AKAN_PUBLIC_OPERATION_MODE: env === "local" ? "local" : "cloud",
181105
181136
  AKAN_PUBLIC_ENV: env,
181106
181137
  AKAN_MOBILE_TARGET: this.target.name
181107
- };
181138
+ });
181108
181139
  }
181109
181140
  async#spawn(command, args = [], options = {}) {
181110
- return await this.app.spawn(command, args, { cwd: this.targetRoot, ...options });
181141
+ return await this.app.spawn(command, args, { cwd: this.app.cwdPath, ...options });
181142
+ }
181143
+ async#spawnMobile(command, args = [], { operation, env }, options = {}) {
181144
+ return await this.#spawn(command, args, {
181145
+ ...options,
181146
+ env: { ...this.#commandEnv(operation, env), ...options.env }
181147
+ });
181111
181148
  }
181112
181149
  async addCamera() {
181113
181150
  await this.#setPermissionInIos({
@@ -182385,7 +182422,7 @@ class ApplicationRunner extends runner("application") {
182385
182422
  const targets = await resolveMobileTargets(app, target);
182386
182423
  await this.#buildMobileCsr(app, env);
182387
182424
  await this.#runMobileTargets(targets, async (mobileTarget2) => {
182388
- await new CapacitorApp(app, mobileTarget2.config).buildIos({ regenerate });
182425
+ await new CapacitorApp(app, mobileTarget2.config).buildIos({ env, regenerate });
182389
182426
  });
182390
182427
  }
182391
182428
  async startIos(app, {
@@ -182411,14 +182448,14 @@ class ApplicationRunner extends runner("application") {
182411
182448
  const targets = await resolveMobileTargets(app, target);
182412
182449
  await this.#buildMobileCsr(app, env);
182413
182450
  for (const mobileTarget2 of targets) {
182414
- await new CapacitorApp(app, mobileTarget2.config).buildIos({ regenerate });
182451
+ await new CapacitorApp(app, mobileTarget2.config).buildIos({ env, regenerate });
182415
182452
  }
182416
182453
  }
182417
182454
  async buildAndroid(app, { target, env = "debug", regenerate = false } = {}) {
182418
182455
  const targets = await resolveMobileTargets(app, target);
182419
182456
  await this.#buildMobileCsr(app, env);
182420
182457
  await this.#runMobileTargets(targets, async (mobileTarget2) => {
182421
- await new CapacitorApp(app, mobileTarget2.config).buildAndroid("apk", { regenerate });
182458
+ await new CapacitorApp(app, mobileTarget2.config).buildAndroid("apk", { env, regenerate });
182422
182459
  });
182423
182460
  }
182424
182461
  async startAndroid(app, {
@@ -182444,9 +182481,9 @@ class ApplicationRunner extends runner("application") {
182444
182481
  const targets = await resolveMobileTargets(app, target);
182445
182482
  await this.#buildMobileCsr(app, env);
182446
182483
  for (const mobileTarget2 of targets) {
182447
- await new CapacitorApp(app, mobileTarget2.config).buildAndroid(assembleType, { regenerate });
182484
+ await new CapacitorApp(app, mobileTarget2.config).buildAndroid(assembleType, { env, regenerate });
182448
182485
  app.log(`Release Android ${app.name}/${mobileTarget2.name} ${assembleType} Completed.`);
182449
- app.log(`Path : ${app.cwdPath}/mobile/${mobileTarget2.name}/android/app/build/outputs/${assembleType === "apk" ? "apk" : "bundle"}/release`);
182486
+ app.log(`Path : ${app.cwdPath}/android/app/build/outputs/${assembleType === "apk" ? "apk" : "bundle"}/release`);
182450
182487
  }
182451
182488
  }
182452
182489
  async#buildMobileCsr(app, env) {
@@ -182816,7 +182853,10 @@ class ApplicationCommand extends command("application", [ApplicationScript], ({
182816
182853
  start: target({ short: true, desc: "Start development server (frontend SSR + backend)" }).with(App).option("open", Boolean, { desc: "open web browser?", default: false }).option("write", Boolean, { desc: "write code generation", default: true }).exec(async function(app, open, write) {
182817
182854
  await this.applicationScript.start(app, { open, write });
182818
182855
  }),
182819
- startIos: target({ short: true, desc: "Start iOS app in simulator or device" }).with(App).option("target", String, { desc: "mobile target name or all" }).option("env", String, {
182856
+ startIos: target({ short: true, desc: "Start iOS app in simulator or device" }).with(App).option("target", String, {
182857
+ ask: "Select mobile target",
182858
+ enum: async ({ app }) => await getMobileTargetChoices(app)
182859
+ }).option("env", String, {
182820
182860
  enum: ["local", "debug", "develop", "main"],
182821
182861
  desc: "backend environment",
182822
182862
  default: "local"
@@ -53,7 +53,7 @@ const serializeInput = <Input = unknown>(
53
53
  return Object.fromEntries(
54
54
  Object.entries(modelRef[FIELD_META]).map(([key, field]) => [
55
55
  key,
56
- field.isClass && !field.isScalar
56
+ serializeType === "input" && field.isClass && !field.isScalar
57
57
  ? serialize(ID, field.arrDepth, getRelationId((value as Record<string, unknown>)?.[key]), serializeType, {
58
58
  nullable: field.nullable,
59
59
  key,
@@ -16,12 +16,25 @@ const getLocalIP = () => {
16
16
 
17
17
  const normalizeBasePath = (basePath: string | undefined) => basePath?.replace(/^\/+|\/+$/g, "");
18
18
 
19
+ const routeBasePaths = (appInfo: AppScanResult) =>
20
+ new Set(
21
+ appInfo.routes
22
+ .map((route) => route.replace(/^\.\//, "").split("/")[0])
23
+ .filter((segment): segment is string => !!segment && !segment.startsWith("_") && !segment.startsWith("(")),
24
+ );
25
+
19
26
  const resolveTarget = (appInfo: AppScanResult, targetName = process.env.AKAN_MOBILE_TARGET) => {
20
27
  const targets = appInfo.akanConfig.mobile.targets;
21
28
  if (!targets || Object.keys(targets).length === 0) throw new Error("Akan mobile target metadata is missing.");
22
29
  if (targetName) {
23
30
  const target = targets[targetName];
24
- if (!target) throw new Error(`Akan mobile target '${targetName}' was not found.`);
31
+ if (!target) {
32
+ const basePath = normalizeBasePath(targetName);
33
+ const [template] = Object.values(targets);
34
+ if (basePath && template && routeBasePaths(appInfo).has(basePath))
35
+ return { ...template, name: basePath, basePath };
36
+ throw new Error(`Akan mobile target '${targetName}' was not found.`);
37
+ }
25
38
  return target;
26
39
  }
27
40
  const entries = Object.entries(targets);
@@ -31,7 +44,8 @@ const resolveTarget = (appInfo: AppScanResult, targetName = process.env.AKAN_MOB
31
44
 
32
45
  const localCsrUrl = (ip: string, target: AkanMobileTargetConfig) => {
33
46
  const basePath = normalizeBasePath(target.basePath);
34
- return `http://${ip}:8282/${basePath ? `${basePath}` : ""}?csr=true`;
47
+ const port = process.env.AKAN_PUBLIC_CLIENT_PORT ?? process.env.PORT ?? "8282";
48
+ return `http://${ip}:${port}/${basePath ? `${basePath}` : ""}?csr=true`;
35
49
  };
36
50
 
37
51
  export const withBase = (
@@ -44,9 +58,10 @@ export const withBase = (
44
58
  if (!appInfo) throw new Error("withBase requires apps/<app>/akan.app.json metadata.");
45
59
  const target = resolveTarget(appInfo, targetName);
46
60
  const baseConfig: CapacitorConfig = {
61
+ ...target,
47
62
  appId: target.appId,
48
63
  appName: target.appName,
49
- webDir: "www",
64
+ webDir: "dist",
50
65
  server:
51
66
  process.env.APP_OPERATION_MODE !== "release"
52
67
  ? {
@@ -62,7 +77,6 @@ export const withBase = (
62
77
  CapacitorCookies: { enabled: true },
63
78
  ...target.plugins,
64
79
  },
65
- ...target,
66
80
  android: {
67
81
  ...target.android,
68
82
  },