akanjs 2.0.0-beta.0 → 2.0.0-beta.10

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 (52) hide show
  1. package/cli/application/application.command.ts +11 -3
  2. package/cli/guidelines/databaseModule/databaseModule.instruction.md +1 -1
  3. package/cli/guidelines/modelConstant/modelConstant.instruction.md +5 -5
  4. package/cli/guidelines/modelDocument/modelDocument.instruction.md +34 -61
  5. package/cli/guidelines/modelService/modelService.instruction.md +1 -1
  6. package/cli/index.js +160 -63
  7. package/cli/package/package.runner.ts +24 -7
  8. package/cli/package/package.script.ts +2 -2
  9. package/cli/templates/app/page/_index.tsx +200 -76
  10. package/cli/templates/app/page/_layout.tsx +0 -1
  11. package/cli/templates/module/__Model__.Zone.tsx +1 -1
  12. package/cli/templates/module/__model__.document.ts +1 -1
  13. package/cli/templates/workspaceRoot/.gitignore.template +1 -11
  14. package/cli/templates/workspaceRoot/biome.json.template +16 -0
  15. package/cli/workspace/workspace.command.ts +2 -7
  16. package/cli/workspace/workspace.runner.ts +1 -7
  17. package/cli/workspace/workspace.script.ts +14 -8
  18. package/client/csrTypes.ts +1 -1
  19. package/constant/fieldInfo.ts +1 -1
  20. package/devkit/capacitor.base.config.ts +1 -1
  21. package/devkit/capacitorApp.ts +5 -1
  22. package/devkit/commandDecorators/argMeta.ts +28 -14
  23. package/devkit/commandDecorators/command.ts +41 -15
  24. package/devkit/commandDecorators/commandBuilder.ts +78 -42
  25. package/devkit/commandDecorators/helpFormatter.ts +7 -4
  26. package/devkit/executors.ts +2 -3
  27. package/devkit/frontendBuild/cssCompiler.ts +9 -3
  28. package/devkit/incrementalBuilder/incrementalBuilder.proc.ts +2 -1
  29. package/devkit/lint/no-deep-internal-import.grit +25 -0
  30. package/devkit/mobile/mobileTarget.ts +48 -8
  31. package/devkit/src/capacitorApp.ts +277 -0
  32. package/devkit/transforms/barrelImportsPlugin.ts +6 -0
  33. package/package.json +3 -1
  34. package/server/hmr/clientScript.ts +8 -5
  35. package/server/resolver/resolver.contract.fixture.ts +1 -1
  36. package/ui/Field.tsx +0 -1
  37. package/ui/Portal.tsx +2 -0
  38. package/ui/System/CSR.tsx +6 -5
  39. package/ui/System/SSR.tsx +1 -1
  40. package/ui/System/SelectLanguage.tsx +1 -1
  41. package/webkit/bootCsr.tsx +8 -5
  42. package/cli/templates/app/common/commonLogic.ts +0 -12
  43. package/cli/templates/app/common/index.ts +0 -10
  44. package/cli/templates/app/srvkit/backendLogic.ts +0 -12
  45. package/cli/templates/app/srvkit/index.ts +0 -10
  46. package/cli/templates/app/ui/UiComponent.ts +0 -16
  47. package/cli/templates/app/ui/index.ts +0 -10
  48. package/cli/templates/app/webkit/frontendLogic.ts +0 -12
  49. package/cli/templates/app/webkit/index.ts +0 -10
  50. package/cli/templates/module/index.tsx +0 -44
  51. /package/cli/templates/app/public/{favicon.ico → favicon.ico.template} +0 -0
  52. /package/cli/templates/app/public/{logo.png → logo.png.template} +0 -0
package/cli/index.js CHANGED
@@ -867,7 +867,9 @@ import {
867
867
  import { readFileSync as readFileSync3 } from "fs";
868
868
  import { mkdir as mkdir2, readdir as readDirEntries, stat as stat2 } from "fs/promises";
869
869
  import path7 from "path";
870
+ var {$ } = globalThis.Bun;
870
871
  import chalk4 from "chalk";
872
+ import ts3 from "typescript";
871
873
 
872
874
  import fs from "fs";
873
875
  import path from "path";
@@ -1163,9 +1165,6 @@ var decreaseBuildNum = async (app) => {
1163
1165
  fs.writeFileSync(akanConfigPath, akanConfigContent);
1164
1166
  };
1165
1167
 
1166
- var {$ } = globalThis.Bun;
1167
- import ts3 from "typescript";
1168
-
1169
1168
  import path2 from "path";
1170
1169
  var getDirname = (url) => path2.dirname(new URL(url).pathname);
1171
1170
 
@@ -4817,6 +4816,9 @@ var rewriteSingleStatement = (stmt, map) => {
4817
4816
  return null;
4818
4817
  const lines = [];
4819
4818
  const tail = ";";
4819
+ if (shouldPreserveBarrelSideEffects(stmt.specifier)) {
4820
+ lines.push(`import "${stmt.specifier}"${tail}`);
4821
+ }
4820
4822
  if (clause.defaultImport || remaining.length > 0) {
4821
4823
  const parts = [];
4822
4824
  if (clause.defaultImport)
@@ -4832,6 +4834,7 @@ var rewriteSingleStatement = (stmt, map) => {
4832
4834
  return lines.join(`
4833
4835
  `);
4834
4836
  };
4837
+ var shouldPreserveBarrelSideEffects = (specifier) => /^@(apps|libs)\/[^/]+\/client$/.test(specifier);
4835
4838
  var serializeNamedItem = (item) => {
4836
4839
  const prefix = item.isType ? "type " : "";
4837
4840
  if (item.imported === item.local)
@@ -6049,6 +6052,8 @@ class CssImportResolver {
6049
6052
 
6050
6053
  var SOURCE_EXTS3 = [".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs"];
6051
6054
  var NON_SOURCE_EXT_RE3 = /\.(json|svg|png|jpe?g|webp|gif|avif|ico|woff2?|ttf|otf|mp3|mp4|wav)$/i;
6055
+ var NODE_MODULES_RE3 = /[\\/]node_modules[\\/]/;
6056
+ var AKANJS_NODE_MODULE_RE3 = /[\\/]node_modules[\\/]akanjs[\\/]/;
6052
6057
 
6053
6058
  class CssCompiler {
6054
6059
  #logger = new Logger("CssCompiler");
@@ -6116,7 +6121,7 @@ class CssCompiler {
6116
6121
  const akanConfig2 = await this.#app.getConfig({ refresh });
6117
6122
  while (queue.length > 0) {
6118
6123
  const filePath = queue.shift();
6119
- if (!filePath || sourceFiles.has(filePath) || filePath.includes("node_modules"))
6124
+ if (!filePath || sourceFiles.has(filePath) || isIgnoredNodeModuleSource(filePath))
6120
6125
  continue;
6121
6126
  sourceFiles.add(filePath);
6122
6127
  let content;
@@ -6152,7 +6157,7 @@ class CssCompiler {
6152
6157
  if (NON_SOURCE_EXT_RE3.test(spec))
6153
6158
  continue;
6154
6159
  const resolved = await this.#resolveSourceImport(spec, importerDir, resolvePackage);
6155
- if (!resolved || sourceFiles.has(resolved) || resolved.includes("node_modules"))
6160
+ if (!resolved || sourceFiles.has(resolved) || isIgnoredNodeModuleSource(resolved))
6156
6161
  continue;
6157
6162
  queue.push(resolved);
6158
6163
  }
@@ -6240,7 +6245,7 @@ class CssCompiler {
6240
6245
  const files = new Set(sourcePaths);
6241
6246
  await Promise.all(dirs.map(async (dir) => {
6242
6247
  for await (const file of glob.scan({ cwd: dir, absolute: true })) {
6243
- if (file.includes("node_modules"))
6248
+ if (isIgnoredNodeModuleSource(file))
6244
6249
  continue;
6245
6250
  files.add(file);
6246
6251
  }
@@ -6287,6 +6292,9 @@ function resolveSourceWithRequire(id, fromBase) {
6287
6292
  function isSourceFile(filePath) {
6288
6293
  return SOURCE_EXTS3.includes(path23.extname(filePath));
6289
6294
  }
6295
+ function isIgnoredNodeModuleSource(filePath) {
6296
+ return NODE_MODULES_RE3.test(filePath) && !AKANJS_NODE_MODULE_RE3.test(filePath);
6297
+ }
6290
6298
  function getPageKeyBasePath(pageKey, basePaths) {
6291
6299
  const normalized = pageKey.split(path23.sep).join("/").replace(/^\.\//, "");
6292
6300
  const segments = normalized.split("/");
@@ -7904,21 +7912,65 @@ var getMobileTargets = async (app) => {
7904
7912
  const config = await app.getConfig();
7905
7913
  return Object.entries(config.mobile.targets).map(([name, target]) => ({ name, config: target }));
7906
7914
  };
7915
+ var getMobileTargetChoices = async (app) => {
7916
+ const config = await app.getConfig();
7917
+ const targetNames = Object.keys(config.mobile.targets);
7918
+ if (targetNames.length > 1)
7919
+ return targetNames;
7920
+ const basePaths = [...config.basePaths];
7921
+ if (basePaths.length > 1)
7922
+ return basePaths;
7923
+ if (targetNames.length > 0)
7924
+ return targetNames;
7925
+ return basePaths;
7926
+ };
7927
+ var resolveMobileTargetByBasePath = (targets, basePath2) => {
7928
+ const normalizedBasePath = basePath2.replace(/^\/+|\/+$/g, "");
7929
+ const byBasePath = targets.find((target) => target.config.basePath?.replace(/^\/+|\/+$/g, "") === normalizedBasePath);
7930
+ if (byBasePath)
7931
+ return byBasePath;
7932
+ const [template] = targets;
7933
+ if (!template)
7934
+ return;
7935
+ return {
7936
+ name: template.name,
7937
+ config: {
7938
+ ...template.config,
7939
+ basePath: normalizedBasePath
7940
+ }
7941
+ };
7942
+ };
7907
7943
  var resolveMobileTargets = async (app, selection) => {
7944
+ const config = await app.getConfig();
7908
7945
  const targets = await getMobileTargets(app);
7909
7946
  if (targets.length === 0)
7910
7947
  throw new Error(`No mobile targets configured for ${app.name}`);
7911
7948
  if (!selection) {
7912
- if (targets.length === 1)
7913
- return targets;
7914
- throw new Error(`Multiple mobile targets found for ${app.name}. Pass --target <${targets.map((t) => t.name).join("|")}|all>.`);
7949
+ const choices2 = await getMobileTargetChoices(app);
7950
+ if (choices2.length === 1)
7951
+ return resolveMobileTargets(app, choices2[0]);
7952
+ throw new Error(`Multiple mobile targets found for ${app.name}. Pass --target <${choices2.join("|")}|all>.`);
7915
7953
  }
7916
- if (selection === "all")
7954
+ if (selection === "all") {
7955
+ if (Object.keys(config.mobile.targets).length > 1)
7956
+ return targets;
7957
+ const basePaths = [...config.basePaths];
7958
+ if (basePaths.length > 1) {
7959
+ return basePaths.flatMap((basePath2) => {
7960
+ const resolved = resolveMobileTargetByBasePath(targets, basePath2);
7961
+ return resolved ? [resolved] : [];
7962
+ });
7963
+ }
7917
7964
  return targets;
7965
+ }
7918
7966
  const target = targets.find((candidate) => candidate.name === selection);
7919
- if (!target)
7920
- throw new Error(`Mobile target '${selection}' was not found. Available: ${targets.map((t) => t.name).join(", ")}`);
7921
- return [target];
7967
+ if (target)
7968
+ return [target];
7969
+ const basePathTarget = resolveMobileTargetByBasePath(targets, selection);
7970
+ if (basePathTarget && config.basePaths.has(selection.replace(/^\/+|\/+$/g, "")))
7971
+ return [basePathTarget];
7972
+ const choices = await getMobileTargetChoices(app);
7973
+ throw new Error(`Mobile target '${selection}' was not found. Available: ${choices.join(", ")}`);
7922
7974
  };
7923
7975
  var resolveMobilePath = (target, pathname) => {
7924
7976
  const basePath2 = target.basePath?.replace(/^\/+|\/+$/g, "");
@@ -8115,7 +8167,8 @@ class CapacitorApp {
8115
8167
  async#writeCapacitorConfig() {
8116
8168
  await mkdir10(this.targetRoot, { recursive: true });
8117
8169
  const appInfoPath = path34.relative(this.targetRoot, path34.join(this.app.cwdPath, "akan.app.json")).split(path34.sep).join("/");
8118
- const content = `import { withBase } from "akanjs/devkit/capacitor.base.config";
8170
+ const baseConfigPath = path34.relative(this.targetRoot, path34.join(this.app.workspace.cwdPath, "pkgs/akanjs/devkit/capacitor.base.config")).split(path34.sep).join("/");
8171
+ const content = `import { withBase } from "${baseConfigPath.startsWith(".") ? baseConfigPath : `./${baseConfigPath}`}";
8119
8172
  import appInfo from "${appInfoPath}";
8120
8173
 
8121
8174
  export default withBase((config) => config, appInfo, "${this.target.name}");
@@ -8565,7 +8618,7 @@ var formatCommandHelp = (command, key) => {
8565
8618
  const optName = `${flag}--${kebabName}`;
8566
8619
  const optDesc = opt.desc ?? "";
8567
8620
  const defaultVal = opt.default !== undefined ? chalk5.gray(` [default: ${String(opt.default)}]`) : "";
8568
- const choices = opt.enum ? chalk5.gray(` (${opt.enum.map(formatChoice).join(", ")})`) : "";
8621
+ const choices = opt.enum ? chalk5.gray(typeof opt.enum === "function" ? " ([dynamic choices])" : ` (${opt.enum.map(formatChoice).join(", ")})`) : "";
8569
8622
  lines.push(` ${chalk5.green(optName)} ${chalk5.gray(optDesc)}${defaultVal}${choices}`);
8570
8623
  }
8571
8624
  lines.push("");
@@ -8585,7 +8638,7 @@ var handleOption = (programCommand, argMeta) => {
8585
8638
  ask
8586
8639
  } = argMeta.argsOption;
8587
8640
  const kebabName = camelToKebabCase2(argMeta.name);
8588
- const choices = enumChoices?.map((choice) => typeof choice === "object" ? { value: choice.value, name: choice.label } : { value: choice, name: choice.toString() });
8641
+ const choices = enumChoices && typeof enumChoices !== "function" ? normalizeEnumChoices(enumChoices) : null;
8589
8642
  programCommand.option(`-${flag}, --${kebabName}${type === "boolean" ? " [boolean]" : ` <${kebabName}>`}`, `${desc}${ask ? ` (${ask})` : ""}${example ? ` (example: ${example})` : ""}${choices ? ` (choices: ${choices.map((choice) => choice.name).join(", ")})` : ""}`);
8590
8643
  return programCommand;
8591
8644
  };
@@ -8602,7 +8655,16 @@ var convertArgValue = (value, type) => {
8602
8655
  else
8603
8656
  return value === true || value === "true";
8604
8657
  };
8605
- var getOptionValue = async (argMeta, opt) => {
8658
+ var normalizeEnumChoices = (enumChoices) => enumChoices.map((choice) => typeof choice === "object" ? { value: choice.value, name: choice.label } : { value: choice, name: choice.toString() });
8659
+ var resolveEnumChoices = async (argMeta, context) => {
8660
+ const enumChoices = argMeta.argsOption.enum;
8661
+ if (!enumChoices)
8662
+ return null;
8663
+ if (typeof enumChoices === "function")
8664
+ return await enumChoices(context);
8665
+ return enumChoices;
8666
+ };
8667
+ var getOptionValue = async (argMeta, opt, context) => {
8606
8668
  const {
8607
8669
  name,
8608
8670
  argsOption: { enum: enumChoices, default: defaultValue, type, desc, nullable, example, ask }
@@ -8611,13 +8673,13 @@ var getOptionValue = async (argMeta, opt) => {
8611
8673
  return convertArgValue(opt[argMeta.name], type ?? "string");
8612
8674
  else if (defaultValue !== undefined)
8613
8675
  return defaultValue;
8614
- else if (nullable)
8615
- return null;
8616
8676
  if (enumChoices) {
8617
- const choices = enumChoices.map((choice2) => typeof choice2 === "object" ? { value: choice2.value, name: choice2.label } : { value: choice2, name: choice2.toString() });
8677
+ const choices = normalizeEnumChoices(await resolveEnumChoices(argMeta, context) ?? []);
8618
8678
  const choice = await select2({ message: ask ?? desc ?? `Select the ${name} value`, choices });
8619
8679
  return choice;
8620
- } else if (type === "boolean") {
8680
+ } else if (nullable)
8681
+ return null;
8682
+ else if (type === "boolean") {
8621
8683
  const message = ask ?? desc ?? `Do you want to set ${name}? ${desc ? ` (${desc})` : ""}: `;
8622
8684
  return await confirm({ message });
8623
8685
  } else {
@@ -8642,6 +8704,22 @@ var getArgumentValue = async (argMeta, value) => {
8642
8704
  const message = ask ? `${ask}: ` : desc ? `${desc}: ` : `Enter the ${name} value${example ? ` (example: ${example})` : ""}: `;
8643
8705
  return convertArgValue(await input2({ message }), type ?? "string");
8644
8706
  };
8707
+ var assignCommandContext = (context, argMeta, value) => {
8708
+ if (value instanceof AppExecutor)
8709
+ context.app = value;
8710
+ else if (value instanceof LibExecutor)
8711
+ context.lib = value;
8712
+ else if (value instanceof PkgExecutor)
8713
+ context.pkg = value;
8714
+ else if (value instanceof ModuleExecutor)
8715
+ context.module = value;
8716
+ else if (value instanceof Executor)
8717
+ context.exec = value;
8718
+ if (argMeta.type === "Argument" || argMeta.type === "Option")
8719
+ context.values[argMeta.name] = value;
8720
+ else
8721
+ context.values[argMeta.type.toLowerCase()] = value;
8722
+ };
8645
8723
  var assertCurrentDirectoryIsWorkspaceRoot = async () => {
8646
8724
  const cwd = process.cwd();
8647
8725
  const [hasPackageJson, hasTsConfig, hasEnv] = await Promise.all([
@@ -8817,15 +8895,17 @@ It may cause unexpected behavior. Run \`akan update\` to update latest akanjs.`)
8817
8895
  if (targetMeta.targetOption.runsOnWorkspaceRoot)
8818
8896
  await assertCurrentDirectoryIsWorkspaceRoot();
8819
8897
  const workspace = WorkspaceExecutor.fromRoot();
8898
+ const commandContext = { values: {} };
8820
8899
  for (const argMeta of allArgMetas) {
8821
8900
  if (argMeta.type === "Option")
8822
- commandArgs[argMeta.idx] = await getOptionValue(argMeta, opt);
8901
+ commandArgs[argMeta.idx] = await getOptionValue(argMeta, opt, commandContext);
8823
8902
  else if (argMeta.type === "Argument")
8824
8903
  commandArgs[argMeta.idx] = await getArgumentValue(argMeta, cmdArgs[argMeta.idx]);
8825
8904
  else
8826
8905
  commandArgs[argMeta.idx] = await getInternalArgumentValue(argMeta, cmdArgs[argMeta.idx], workspace);
8827
8906
  if (commandArgs[argMeta.idx] instanceof AppExecutor)
8828
8907
  process.env.AKAN_PUBLIC_APP_NAME = commandArgs[argMeta.idx].name;
8908
+ assignCommandContext(commandContext, argMeta, commandArgs[argMeta.idx]);
8829
8909
  if (opt.verbose)
8830
8910
  Executor.setVerbose(true);
8831
8911
  }
@@ -9847,14 +9927,22 @@ class ApplicationCommand extends command("application", [ApplicationScript], ({
9847
9927
  test: target({ desc: "Prepare and test an app, library, or package" }).with(Exec).option("write", Boolean, { desc: "write code generation", default: true }).exec(async function(exec2, write) {
9848
9928
  await this.applicationScript.test(exec2, { write });
9849
9929
  }),
9850
- buildIos: target({ short: true, desc: "Build iOS app with Capacitor" }).with(App).option("target", String, { desc: "mobile target name or all" }).option("env", String, {
9930
+ buildIos: target({ short: true, desc: "Build iOS app with Capacitor" }).with(App).option("target", String, {
9931
+ desc: "mobile target name or all",
9932
+ ask: "Select mobile target",
9933
+ enum: async ({ app }) => await getMobileTargetChoices(app)
9934
+ }).option("env", String, {
9851
9935
  enum: ["local", "debug", "develop", "main"],
9852
9936
  desc: "backend environment",
9853
9937
  default: "debug"
9854
9938
  }).option("write", Boolean, { desc: "write code generation", default: true }).option("regenerate", Boolean, { flag: "g", desc: "delete and regenerate native project", default: false }).exec(async function(app, target2, env, write, regenerate) {
9855
9939
  await this.applicationScript.buildIos(app, { target: target2, env: asMobileEnv(env), write, regenerate });
9856
9940
  }),
9857
- buildAndroid: target({ short: true, desc: "Build Android app with Capacitor" }).with(App).option("target", String, { desc: "mobile target name or all" }).option("env", String, {
9941
+ buildAndroid: target({ short: true, desc: "Build Android app with Capacitor" }).with(App).option("target", String, {
9942
+ desc: "mobile target name or all",
9943
+ ask: "Select mobile target",
9944
+ enum: async ({ app }) => await getMobileTargetChoices(app)
9945
+ }).option("env", String, {
9858
9946
  enum: ["local", "debug", "develop", "main"],
9859
9947
  desc: "backend environment",
9860
9948
  default: "debug"
@@ -9947,13 +10035,16 @@ class ApplicationCommand extends command("application", [ApplicationScript], ({
9947
10035
  })) {
9948
10036
  }
9949
10037
 
10038
+ import path36 from "path";
9950
10039
  var {$: $2 } = globalThis.Bun;
9951
10040
 
9952
10041
  class PackageRunner extends runner("package") {
9953
- async version(workspace) {
9954
- const pkgJson = await FileSys.readJson("package.json");
10042
+ async version(workspace, { log = true } = {}) {
10043
+ const pkgJson = await FileSys.readJson(process.env.USE_AKANJS_PKGS === "true" ? `${workspace.workspaceRoot}/pkgs/akanjs/package.json` : `${path36.dirname(Bun.main)}/../package.json`);
9955
10044
  const version = pkgJson.version;
9956
- Logger.rawLog(`${pkgJson.name}@${version}`);
10045
+ if (log)
10046
+ Logger.rawLog(`${pkgJson.name}@${version}`);
10047
+ return version;
9957
10048
  }
9958
10049
  async createPackage(workspace, pkgName) {
9959
10050
  await workspace.applyTemplate({ basePath: `pkgs/${pkgName}`, template: "pkgRoot", dict: { pkgName } });
@@ -9972,15 +10063,26 @@ class PackageRunner extends runner("package") {
9972
10063
  await pkg.dist.mkdir(pkg.dist.cwdPath);
9973
10064
  const scanner = await TypeScriptDependencyScanner.from(pkg);
9974
10065
  const { npmDeps, npmDevDeps, missingDeps } = await scanner.getPackageBuildDependencies(pkg.name);
9975
- if (missingDeps.length > 0)
9976
- throw new Error(`Missing dependency versions in root package.json: ${missingDeps.join(", ")}`);
9977
- await pkg.updatePackageJsonDependencies(npmDeps, npmDevDeps);
10066
+ const packageRuntimeDependencies = { akanjs: ["daisyui"] };
10067
+ const packageRuntimeDevDependencies = { akanjs: ["@biomejs/biome"] };
10068
+ const forcedRuntimeDeps = packageRuntimeDependencies[pkg.name] ?? [];
10069
+ const forcedRuntimeDevDeps = packageRuntimeDevDependencies[pkg.name] ?? [];
10070
+ const packageRuntimeDeps = [...new Set([...npmDeps, ...forcedRuntimeDeps])];
10071
+ const packageRuntimeDevDeps = [...new Set([...npmDevDeps, ...forcedRuntimeDevDeps])];
10072
+ const rootPackageJson = await pkg.workspace.getPackageJson();
10073
+ const rootDeps = { ...rootPackageJson.dependencies, ...rootPackageJson.devDependencies };
10074
+ const missingForcedDeps = forcedRuntimeDeps.filter((dep) => !rootDeps[dep]);
10075
+ const missingForcedDevDeps = forcedRuntimeDevDeps.filter((dep) => !rootDeps[dep]);
10076
+ const allMissingDeps = [...new Set([...missingDeps, ...missingForcedDeps, ...missingForcedDevDeps])].sort();
10077
+ if (allMissingDeps.length > 0)
10078
+ throw new Error(`Missing dependency versions in root package.json: ${allMissingDeps.join(", ")}`);
10079
+ await pkg.updatePackageJsonDependencies(packageRuntimeDeps, packageRuntimeDevDeps);
9978
10080
  const hasBuildFile = await Bun.file(`${pkg.cwdPath}/build.ts`).exists();
9979
10081
  if (hasBuildFile) {
9980
10082
  await pkg.workspace.spawn(process.execPath, [`${pkg.cwdPath}/build.ts`], { env: process.env, stdio: "inherit" });
9981
10083
  } else {
9982
10084
  await $2`cp -r ${pkg.cwdPath}/. ${pkg.dist.cwdPath}`;
9983
- await Promise.all([pkg.generateDistPackageJson(npmDeps, npmDevDeps), pkg.generateTsconfigJson()]);
10085
+ await Promise.all([pkg.generateDistPackageJson(packageRuntimeDeps, packageRuntimeDevDeps), pkg.generateTsconfigJson()]);
9984
10086
  }
9985
10087
  }
9986
10088
  async updateWorskpaceRootPackageJson(workspace, rootPackageJson) {
@@ -9997,8 +10099,8 @@ class PackageRunner extends runner("package") {
9997
10099
  }
9998
10100
 
9999
10101
  class PackageScript extends script("package", [PackageRunner]) {
10000
- async version(workspace) {
10001
- await this.packageRunner.version(workspace);
10102
+ async version(workspace, { log = true } = {}) {
10103
+ return await this.packageRunner.version(workspace, { log });
10002
10104
  }
10003
10105
  async createPackage(workspace, pkgName) {
10004
10106
  const spinner2 = workspace.spinning(`Creating package in pkgs/${pkgName}...`);
@@ -10257,14 +10359,14 @@ class GuidelinePrompt extends Prompter {
10257
10359
  async#getScanFilePaths(matchPattern, { avoidDirs = ["node_modules", ".next"], filterText } = {}) {
10258
10360
  const glob = new Bun.Glob(matchPattern);
10259
10361
  const paths = [];
10260
- for await (const path36 of glob.scan({ cwd: this.workspace.workspaceRoot, absolute: true })) {
10261
- if (avoidDirs.some((dir) => path36.includes(dir)))
10362
+ for await (const path37 of glob.scan({ cwd: this.workspace.workspaceRoot, absolute: true })) {
10363
+ if (avoidDirs.some((dir) => path37.includes(dir)))
10262
10364
  continue;
10263
- const fileContent = await FileSys.readText(path36);
10365
+ const fileContent = await FileSys.readText(path37);
10264
10366
  const textFilter = filterText ? new RegExp(filterText) : null;
10265
10367
  if (filterText && !textFilter?.test(fileContent))
10266
10368
  continue;
10267
- paths.push(path36);
10369
+ paths.push(path37);
10268
10370
  }
10269
10371
  return paths;
10270
10372
  }
@@ -11250,18 +11352,13 @@ class ScalarCommand extends command("scalar", [ScalarScript], ({ public: target
11250
11352
  })) {
11251
11353
  }
11252
11354
 
11253
- import path37 from "path";
11254
-
11255
- import path36 from "path";
11256
- import latestVersion2 from "latest-version";
11355
+ import path38 from "path";
11257
11356
 
11357
+ import path37 from "path";
11258
11358
  class WorkspaceRunner extends runner("workspace") {
11259
- async#resolveAkanVersion(tag) {
11260
- return /^\d+\.\d+\.\d+(?:[-+][0-9A-Za-z.-]+)?$/.test(tag) ? tag : await latestVersion2("akanjs", { version: tag });
11261
- }
11262
- async createWorkspace(repoName, appName, { dirname: dirname3 = ".", tag = "latest", init = true }) {
11359
+ async createWorkspace(repoName, appName, { dirname: dirname3 = ".", init = true, akanVersion }) {
11263
11360
  const cwdPath = process.cwd();
11264
- const workspaceRoot = path36.join(cwdPath, dirname3, repoName);
11361
+ const workspaceRoot = path37.join(cwdPath, dirname3, repoName);
11265
11362
  const workspace = WorkspaceExecutor.fromRoot({ workspaceRoot, repoName });
11266
11363
  const templateSpinner = workspace.spinning(`Creating workspace template files in ${dirname3}/${repoName}...`);
11267
11364
  await workspace.applyTemplate({
@@ -11271,7 +11368,6 @@ class WorkspaceRunner extends runner("workspace") {
11271
11368
  });
11272
11369
  templateSpinner.succeed(`Workspace files created in ${dirname3}/${repoName}`);
11273
11370
  const rootPackageJson = await workspace.getPackageJson();
11274
- const akanVersion = await this.#resolveAkanVersion(tag);
11275
11371
  const packageJson = {
11276
11372
  ...rootPackageJson,
11277
11373
  dependencies: {
@@ -11300,14 +11396,19 @@ class WorkspaceRunner extends runner("workspace") {
11300
11396
  }
11301
11397
  }
11302
11398
 
11303
- class WorkspaceScript extends script("workspace", [WorkspaceRunner, ApplicationScript, LibraryScript]) {
11304
- async createWorkspace(repoName, appName, {
11305
- dirname: dirname3 = ".",
11306
- installLibs = false,
11307
- tag = "latest",
11308
- init = true
11309
- }) {
11310
- const workspace = await this.workspaceRunner.createWorkspace(repoName, appName, { dirname: dirname3, tag, init });
11399
+ class WorkspaceScript extends script("workspace", [
11400
+ WorkspaceRunner,
11401
+ ApplicationScript,
11402
+ LibraryScript,
11403
+ PackageScript
11404
+ ]) {
11405
+ async createWorkspace(repoName, appName, { dirname: dirname3 = ".", installLibs = false, init = true }) {
11406
+ const akanVersion = await this.packageScript.version({ log: false });
11407
+ const workspace = await this.workspaceRunner.createWorkspace(repoName, appName, {
11408
+ dirname: dirname3,
11409
+ init,
11410
+ akanVersion
11411
+ });
11311
11412
  if (installLibs) {
11312
11413
  await this.libraryScript.installLibrary(workspace, "util");
11313
11414
  await this.libraryScript.installLibrary(workspace, "shared");
@@ -11320,7 +11421,7 @@ class WorkspaceScript extends script("workspace", [WorkspaceRunner, ApplicationS
11320
11421
  } catch (_) {
11321
11422
  gitSpinner.fail("Git repository initialization failed. It's not fatal, you can commit manually");
11322
11423
  }
11323
- const workspacePath = path37.join(dirname3, repoName);
11424
+ const workspacePath = path38.join(dirname3, repoName);
11324
11425
  Logger.rawLog(`
11325
11426
  \uD83C\uDF89 Welcome aboard! Workspace created in ${dirname3}/${repoName}`);
11326
11427
  Logger.rawLog(`\uD83D\uDE80 Run \`cd ${workspacePath} && akan start ${appName}\` to start the development server.`);
@@ -11362,8 +11463,7 @@ class WorkspaceScript extends script("workspace", [WorkspaceRunner, ApplicationS
11362
11463
 
11363
11464
  class WorkspaceCommand extends command("workspace", [WorkspaceScript], ({ public: target }) => ({
11364
11465
  createWorkspace: target({ desc: "Create a new Akan.js workspace", runsOnWorkspaceRoot: false }).arg("workspaceName", String, { desc: "what is the name of your organization?" }).option("app", String, {
11365
- desc: "what is the codename of your first application? (e.g. myapp)",
11366
- default: "app"
11466
+ desc: "what is the codename of your first application? (e.g. myapp)"
11367
11467
  }).option("dir", String, {
11368
11468
  desc: "directory of workspace",
11369
11469
  default: process.env.USE_AKANJS_PKGS === "true" ? "local" : "."
@@ -11376,15 +11476,12 @@ class WorkspaceCommand extends command("workspace", [WorkspaceScript], ({ public
11376
11476
  value: true
11377
11477
  }
11378
11478
  ]
11379
- }).option("tag", String, {
11380
- desc: "tag of the update",
11381
- default: "latest"
11382
11479
  }).option("init", Boolean, {
11383
11480
  desc: "Do you want to initialize the workspace? (Recommended)",
11384
11481
  default: true
11385
- }).exec(async function(workspaceName, app, dir, libs, tag, init) {
11482
+ }).exec(async function(workspaceName, app, dir, libs, init) {
11386
11483
  const appName = app || "app";
11387
- await this.workspaceScript.createWorkspace(workspaceName.toLowerCase().replace(/ /g, "-"), appName.toLowerCase().replace(/ /g, "-"), { dirname: dir, installLibs: libs, tag, init });
11484
+ await this.workspaceScript.createWorkspace(workspaceName.toLowerCase().replace(/ /g, "-"), appName.toLowerCase().replace(/ /g, "-"), { dirname: dir, installLibs: libs, init });
11388
11485
  }),
11389
11486
  lint: target({ desc: "Lint and fix code in a specific app/lib/pkg" }).with(Exec).option("fix", Boolean, { default: true }).with(Workspace).exec(async function(exec2, fix, workspace) {
11390
11487
  await this.workspaceScript.lint(exec2, workspace, { fix });
@@ -1,3 +1,4 @@
1
+ import path from "node:path";
1
2
  import { Logger } from "akanjs/common";
2
3
  import {
3
4
  FileSys,
@@ -10,10 +11,15 @@ import {
10
11
  import { $ } from "bun";
11
12
 
12
13
  export class PackageRunner extends runner("package") {
13
- async version(workspace: Workspace) {
14
- const pkgJson = await FileSys.readJson<PackageJson>("package.json");
14
+ async version(workspace: Workspace, { log = true }: { log?: boolean } = {}) {
15
+ const pkgJson = await FileSys.readJson<PackageJson>(
16
+ process.env.USE_AKANJS_PKGS === "true"
17
+ ? `${workspace.workspaceRoot}/pkgs/akanjs/package.json`
18
+ : `${path.dirname(Bun.main)}/../package.json`,
19
+ );
15
20
  const version = pkgJson.version;
16
- Logger.rawLog(`${pkgJson.name}@${version}`);
21
+ if (log) Logger.rawLog(`${pkgJson.name}@${version}`);
22
+ return version;
17
23
  }
18
24
  async createPackage(workspace: Workspace, pkgName: string) {
19
25
  await workspace.applyTemplate({ basePath: `pkgs/${pkgName}`, template: "pkgRoot", dict: { pkgName } });
@@ -32,17 +38,28 @@ export class PackageRunner extends runner("package") {
32
38
  await pkg.dist.mkdir(pkg.dist.cwdPath);
33
39
  const scanner = await TypeScriptDependencyScanner.from(pkg);
34
40
  const { npmDeps, npmDevDeps, missingDeps } = await scanner.getPackageBuildDependencies(pkg.name);
35
- if (missingDeps.length > 0)
36
- throw new Error(`Missing dependency versions in root package.json: ${missingDeps.join(", ")}`);
41
+ const packageRuntimeDependencies: Record<string, string[]> = { akanjs: ["daisyui"] };
42
+ const packageRuntimeDevDependencies: Record<string, string[]> = { akanjs: ["@biomejs/biome"] };
43
+ const forcedRuntimeDeps = packageRuntimeDependencies[pkg.name] ?? [];
44
+ const forcedRuntimeDevDeps = packageRuntimeDevDependencies[pkg.name] ?? [];
45
+ const packageRuntimeDeps = [...new Set([...npmDeps, ...forcedRuntimeDeps])];
46
+ const packageRuntimeDevDeps = [...new Set([...npmDevDeps, ...forcedRuntimeDevDeps])];
47
+ const rootPackageJson = await pkg.workspace.getPackageJson();
48
+ const rootDeps = { ...rootPackageJson.dependencies, ...rootPackageJson.devDependencies };
49
+ const missingForcedDeps = forcedRuntimeDeps.filter((dep) => !rootDeps[dep]);
50
+ const missingForcedDevDeps = forcedRuntimeDevDeps.filter((dep) => !rootDeps[dep]);
51
+ const allMissingDeps = [...new Set([...missingDeps, ...missingForcedDeps, ...missingForcedDevDeps])].sort();
52
+ if (allMissingDeps.length > 0)
53
+ throw new Error(`Missing dependency versions in root package.json: ${allMissingDeps.join(", ")}`);
37
54
 
38
- await pkg.updatePackageJsonDependencies(npmDeps, npmDevDeps);
55
+ await pkg.updatePackageJsonDependencies(packageRuntimeDeps, packageRuntimeDevDeps);
39
56
 
40
57
  const hasBuildFile = await Bun.file(`${pkg.cwdPath}/build.ts`).exists();
41
58
  if (hasBuildFile) {
42
59
  await pkg.workspace.spawn(process.execPath, [`${pkg.cwdPath}/build.ts`], { env: process.env, stdio: "inherit" });
43
60
  } else {
44
61
  await $`cp -r ${pkg.cwdPath}/. ${pkg.dist.cwdPath}`;
45
- await Promise.all([pkg.generateDistPackageJson(npmDeps, npmDevDeps), pkg.generateTsconfigJson()]);
62
+ await Promise.all([pkg.generateDistPackageJson(packageRuntimeDeps, packageRuntimeDevDeps), pkg.generateTsconfigJson()]);
46
63
  }
47
64
  }
48
65
 
@@ -3,8 +3,8 @@ import { type Pkg, script, type Workspace } from "akanjs/devkit";
3
3
  import { PackageRunner } from "./package.runner";
4
4
 
5
5
  export class PackageScript extends script("package", [PackageRunner]) {
6
- async version(workspace: Workspace) {
7
- await this.packageRunner.version(workspace);
6
+ async version(workspace: Workspace, { log = true }: { log?: boolean } = {}) {
7
+ return await this.packageRunner.version(workspace, { log });
8
8
  }
9
9
  async createPackage(workspace: Workspace, pkgName: string) {
10
10
  const spinner = workspace.spinning(`Creating package in pkgs/${pkgName}...`);