@akanjs/cli 2.1.0-rc.8 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.js CHANGED
@@ -484,7 +484,18 @@ var DEFAULT_OPTIMIZE_IMPORTS = [
484
484
  var WORKSPACE_BARREL_FACETS = ["ui", "webkit", "common", "client", "server"];
485
485
  var SSR_RUNTIME_PACKAGES = ["react", "react-dom", "react-server-dom-webpack"];
486
486
  var NATIVE_RUNTIME_PACKAGES = ["sharp"];
487
- var AKAN_RUNTIME_PACKAGES = new Set([...SSR_RUNTIME_PACKAGES, ...NATIVE_RUNTIME_PACKAGES]);
487
+ var DEFAULT_BACKEND_RUNTIME_PACKAGES = ["croner"];
488
+ var DATABASE_MODE_RUNTIME_PACKAGES = {
489
+ single: [],
490
+ multiple: ["@libsql/client", "bullmq", "ioredis", "protobufjs"],
491
+ cluster: ["bullmq", "ioredis", "postgres", "protobufjs"]
492
+ };
493
+ var AKAN_RUNTIME_PACKAGES = new Set([
494
+ ...SSR_RUNTIME_PACKAGES,
495
+ ...NATIVE_RUNTIME_PACKAGES,
496
+ ...DEFAULT_BACKEND_RUNTIME_PACKAGES,
497
+ ...Object.values(DATABASE_MODE_RUNTIME_PACKAGES).flat()
498
+ ]);
488
499
  var DEFAULT_AKAN_IMAGE_CONFIG = {
489
500
  deviceSizes: [640, 750, 828, 1080, 1200, 1920, 2048, 3840],
490
501
  imageSizes: [32, 48, 64, 96, 128, 256, 384],
@@ -693,13 +704,22 @@ CMD [${command.map((c) => `"${c}"`).join(",")}]`;
693
704
  if (AKAN_RUNTIME_PACKAGES.has(lib))
694
705
  return akanPackageJson.dependencies?.[lib] ?? akanPackageJson.peerDependencies?.[lib];
695
706
  }
707
+ #getProductionRuntimePackages() {
708
+ return [
709
+ ...this.externalLibs,
710
+ ...SSR_RUNTIME_PACKAGES,
711
+ ...NATIVE_RUNTIME_PACKAGES,
712
+ ...DEFAULT_BACKEND_RUNTIME_PACKAGES,
713
+ ...DATABASE_MODE_RUNTIME_PACKAGES[this.defaultDatabaseMode]
714
+ ];
715
+ }
696
716
  getProductionPackageJson(data = {}) {
697
717
  return {
698
718
  name: this.app.name,
699
719
  description: this.app.name,
700
720
  version: "1.0.0",
701
721
  main: "./main.js",
702
- dependencies: Object.fromEntries([...new Set([...this.externalLibs, ...SSR_RUNTIME_PACKAGES, ...NATIVE_RUNTIME_PACKAGES])].map((lib) => {
722
+ dependencies: Object.fromEntries([...new Set(this.#getProductionRuntimePackages())].map((lib) => {
703
723
  const version = this.#resolveProductionDependencyVersion(lib);
704
724
  if (!version)
705
725
  throw new Error(`Dependency ${lib} not found in package.json`);
@@ -7166,9 +7186,19 @@ var SSR_RENDER_EXTERNALS = [
7166
7186
  "react/jsx-dev-runtime",
7167
7187
  "react-dom",
7168
7188
  "react-dom/server.browser",
7189
+ "react-server-dom-webpack",
7190
+ "react-server-dom-webpack/server.node",
7169
7191
  "react-server-dom-webpack/client.node",
7170
7192
  "react-server-dom-webpack/client.browser"
7171
7193
  ];
7194
+ var AKAN_OPTIONAL_BACKEND_EXTERNALS = [
7195
+ "@libsql/client",
7196
+ "bullmq",
7197
+ "croner",
7198
+ "ioredis",
7199
+ "postgres",
7200
+ "protobufjs"
7201
+ ];
7172
7202
 
7173
7203
  class ApplicationBuildRunner {
7174
7204
  #app;
@@ -7237,7 +7267,9 @@ class ApplicationBuildRunner {
7237
7267
  }
7238
7268
  async#buildBackend() {
7239
7269
  const akanConfig2 = await this.#app.getConfig();
7240
- const backendExternals = [...new Set([...akanConfig2.externalLibs, ...SSR_RENDER_EXTERNALS])];
7270
+ const backendExternals = [
7271
+ ...new Set([...akanConfig2.externalLibs, ...SSR_RENDER_EXTERNALS, ...AKAN_OPTIONAL_BACKEND_EXTERNALS])
7272
+ ];
7241
7273
  const backendEntryPoints = [`${this.#app.cwdPath}/main.ts`, `${this.#app.cwdPath}/server.ts`];
7242
7274
  for (const entrypoint of backendEntryPoints) {
7243
7275
  if (!await Bun.file(entrypoint).exists())
@@ -7259,7 +7291,7 @@ class ApplicationBuildRunner {
7259
7291
  naming: { entry: "[name].[ext]", chunk: "chunk-[hash].[ext]" },
7260
7292
  conditions: ["react-server"],
7261
7293
  define: { "process.env.NODE_ENV": JSON.stringify("production") },
7262
- plugins: akanConfig2.externalLibs.length > 0 ? [this.#createExternalSpecifiersPlugin(akanConfig2.externalLibs)] : []
7294
+ plugins: backendExternals.length > 0 ? [this.#createExternalSpecifiersPlugin(backendExternals)] : []
7263
7295
  });
7264
7296
  return {
7265
7297
  entrypoints: backendEntryPoints.length + 1,
@@ -7607,10 +7639,31 @@ class ApplicationReleasePackager {
7607
7639
  `;
7608
7640
  }
7609
7641
  }
7642
+ // pkgs/@akanjs/devkit/applicationTestPreload.ts
7643
+ import path33 from "path";
7644
+ var SIGNAL_TEST_PRELOAD_PATH = "test/signalTest.preload.ts";
7645
+ async function resolveSignalTestPreloadPath(target) {
7646
+ const candidates = [];
7647
+ const addResolvedPackageCandidate = (basePath2) => {
7648
+ try {
7649
+ candidates.push(path33.join(path33.dirname(Bun.resolveSync("akanjs/package.json", basePath2)), SIGNAL_TEST_PRELOAD_PATH));
7650
+ } catch {}
7651
+ };
7652
+ addResolvedPackageCandidate(target.cwdPath);
7653
+ addResolvedPackageCandidate(process.cwd());
7654
+ addResolvedPackageCandidate(path33.dirname(Bun.main));
7655
+ addResolvedPackageCandidate(import.meta.dir);
7656
+ candidates.push(path33.join(target.cwdPath, "../../node_modules/akanjs", SIGNAL_TEST_PRELOAD_PATH), path33.join(target.cwdPath, "../../pkgs/akanjs", SIGNAL_TEST_PRELOAD_PATH), path33.join(process.cwd(), "node_modules/akanjs", SIGNAL_TEST_PRELOAD_PATH), path33.join(process.cwd(), "pkgs/akanjs", SIGNAL_TEST_PRELOAD_PATH), path33.join(path33.dirname(Bun.main), "../../akanjs", SIGNAL_TEST_PRELOAD_PATH), path33.resolve(import.meta.dir, "../../akanjs", SIGNAL_TEST_PRELOAD_PATH));
7657
+ for (const candidate of [...new Set(candidates)]) {
7658
+ if (await Bun.file(candidate).exists())
7659
+ return candidate;
7660
+ }
7661
+ throw new Error(`Failed to locate ${SIGNAL_TEST_PRELOAD_PATH} from ${target.cwdPath}`);
7662
+ }
7610
7663
  // pkgs/@akanjs/devkit/builder.ts
7611
7664
  import { existsSync as existsSync2 } from "fs";
7612
7665
  import { mkdir as mkdir9 } from "fs/promises";
7613
- import path33 from "path";
7666
+ import path34 from "path";
7614
7667
  var SKIP_ENTRY_DIR_SET = new Set(["node_modules", "dist", "build", ".git", ".next"]);
7615
7668
  var assetExtensions = [".css", ".md", ".js", ".png", ".ico", ".svg", ".json", ".template"];
7616
7669
  var assetLoader = Object.fromEntries(assetExtensions.map((ext) => [ext, "file"]));
@@ -7627,14 +7680,14 @@ class Builder {
7627
7680
  #globEntrypoints(cwd, pattern) {
7628
7681
  const glob = new Bun.Glob(pattern);
7629
7682
  return Array.from(glob.scanSync({ cwd, onlyFiles: true })).filter((relativePath) => {
7630
- const segments = relativePath.split(path33.sep);
7683
+ const segments = relativePath.split(path34.sep);
7631
7684
  return !segments.some((segment) => SKIP_ENTRY_DIR_SET.has(segment));
7632
- }).map((rel) => path33.join(cwd, rel));
7685
+ }).map((rel) => path34.join(cwd, rel));
7633
7686
  }
7634
7687
  #globFiles(cwd, pattern = "**/*.*") {
7635
7688
  const glob = new Bun.Glob(pattern);
7636
7689
  return Array.from(glob.scanSync({ cwd, onlyFiles: true })).filter((relativePath) => {
7637
- const segments = relativePath.split(path33.sep);
7690
+ const segments = relativePath.split(path34.sep);
7638
7691
  return !segments.some((segment) => SKIP_ENTRY_DIR_SET.has(segment));
7639
7692
  });
7640
7693
  }
@@ -7642,17 +7695,17 @@ class Builder {
7642
7695
  const out = [];
7643
7696
  for (const p of additionalEntryPoints) {
7644
7697
  if (p.includes("*")) {
7645
- const rel = p.startsWith(`${cwd}/`) || p.startsWith(`${cwd}${path33.sep}`) ? p.slice(cwd.length + 1) : p;
7698
+ const rel = p.startsWith(`${cwd}/`) || p.startsWith(`${cwd}${path34.sep}`) ? p.slice(cwd.length + 1) : p;
7646
7699
  out.push(...this.#globEntrypoints(cwd, rel));
7647
7700
  } else
7648
- out.push(path33.isAbsolute(p) ? p : path33.join(cwd, p));
7701
+ out.push(path34.isAbsolute(p) ? p : path34.join(cwd, p));
7649
7702
  }
7650
7703
  return out;
7651
7704
  }
7652
7705
  #getBuildOptions({ bundle = false, additionalEntryPoints = [] } = {}) {
7653
7706
  const cwd = this.#executor.cwdPath;
7654
7707
  const entrypoints = [
7655
- ...bundle ? [path33.join(cwd, "index.ts")] : this.#globEntrypoints(cwd, "**/*.{ts,tsx}"),
7708
+ ...bundle ? [path34.join(cwd, "index.ts")] : this.#globEntrypoints(cwd, "**/*.{ts,tsx}"),
7656
7709
  ...this.#resolveAdditionalEntrypoints(cwd, additionalEntryPoints)
7657
7710
  ];
7658
7711
  return {
@@ -7673,9 +7726,9 @@ class Builder {
7673
7726
  for (const relativePath of this.#globFiles(cwd)) {
7674
7727
  if (relativePath === "package.json")
7675
7728
  continue;
7676
- const sourcePath = path33.join(cwd, relativePath);
7677
- const targetPath = path33.join(this.#distExecutor.cwdPath, relativePath);
7678
- await mkdir9(path33.dirname(targetPath), { recursive: true });
7729
+ const sourcePath = path34.join(cwd, relativePath);
7730
+ const targetPath = path34.join(this.#distExecutor.cwdPath, relativePath);
7731
+ await mkdir9(path34.dirname(targetPath), { recursive: true });
7679
7732
  await Bun.write(targetPath, Bun.file(sourcePath));
7680
7733
  }
7681
7734
  }
@@ -7686,13 +7739,13 @@ class Builder {
7686
7739
  return withoutFormatDir;
7687
7740
  if (!hasDotSlash && withoutFormatDir === publishedPath)
7688
7741
  return publishedPath;
7689
- const parsed = path33.posix.parse(withoutFormatDir);
7742
+ const parsed = path34.posix.parse(withoutFormatDir);
7690
7743
  if (![".js", ".mjs", ".cjs"].includes(parsed.ext))
7691
7744
  return withoutFormatDir;
7692
- const withoutExt = path33.posix.join(parsed.dir, parsed.name);
7745
+ const withoutExt = path34.posix.join(parsed.dir, parsed.name);
7693
7746
  const sourcePath = withoutExt.startsWith("./") ? withoutExt.slice(2) : withoutExt;
7694
7747
  const sourceCandidates = [`${sourcePath}.ts`, `${sourcePath}.tsx`];
7695
- const matchedSource = sourceCandidates.find((candidate) => existsSync2(path33.join(this.#executor.cwdPath, candidate)));
7748
+ const matchedSource = sourceCandidates.find((candidate) => existsSync2(path34.join(this.#executor.cwdPath, candidate)));
7696
7749
  if (!matchedSource)
7697
7750
  return withoutFormatDir;
7698
7751
  return hasDotSlash ? `./${matchedSource}` : matchedSource;
@@ -7742,7 +7795,7 @@ class Builder {
7742
7795
  }
7743
7796
  // pkgs/@akanjs/devkit/capacitorApp.ts
7744
7797
  import { cp as cp2, mkdir as mkdir10, rm as rm4 } from "fs/promises";
7745
- import path34 from "path";
7798
+ import path35 from "path";
7746
7799
  import { MobileProject } from "@trapezedev/project";
7747
7800
  import { capitalize as capitalize2 } from "akanjs/common";
7748
7801
 
@@ -7936,10 +7989,10 @@ class CapacitorApp {
7936
7989
  constructor(app, target) {
7937
7990
  this.app = app;
7938
7991
  this.target = target;
7939
- this.targetRootPath = path34.posix.join("mobile", this.target.name);
7940
- this.targetRoot = path34.join(this.app.cwdPath, this.targetRootPath);
7941
- this.targetWebRoot = path34.join(this.targetRoot, "www");
7942
- this.targetAssetRoot = path34.join(this.targetRoot, "assets");
7992
+ this.targetRootPath = path35.posix.join("mobile", this.target.name);
7993
+ this.targetRoot = path35.join(this.app.cwdPath, this.targetRootPath);
7994
+ this.targetWebRoot = path35.join(this.targetRoot, "www");
7995
+ this.targetAssetRoot = path35.join(this.targetRoot, "assets");
7943
7996
  this.project = new MobileProject(this.app.cwdPath, {
7944
7997
  android: { path: this.androidRootPath },
7945
7998
  ios: { path: this.iosProjectPath }
@@ -7955,9 +8008,9 @@ class CapacitorApp {
7955
8008
  await this.#writeCapacitorConfig();
7956
8009
  if (regenerate) {
7957
8010
  if (!platform || platform === "ios")
7958
- await rm4(path34.join(this.app.cwdPath, this.iosRootPath), { recursive: true, force: true });
8011
+ await rm4(path35.join(this.app.cwdPath, this.iosRootPath), { recursive: true, force: true });
7959
8012
  if (!platform || platform === "android")
7960
- await rm4(path34.join(this.app.cwdPath, this.androidRootPath), { recursive: true, force: true });
8013
+ await rm4(path35.join(this.app.cwdPath, this.androidRootPath), { recursive: true, force: true });
7961
8014
  }
7962
8015
  const project = this.project;
7963
8016
  await this.project.load();
@@ -8019,7 +8072,7 @@ class CapacitorApp {
8019
8072
  await this.#spawnMobile("npx", ["cap", "sync", "android"], { operation, env });
8020
8073
  }
8021
8074
  async#updateAndroidBuildTypes() {
8022
- const appGradle = await FileEditor.create(path34.join(this.app.cwdPath, this.androidRootPath, "app/build.gradle"));
8075
+ const appGradle = await FileEditor.create(path35.join(this.app.cwdPath, this.androidRootPath, "app/build.gradle"));
8023
8076
  const buildTypesBlock = `
8024
8077
  debug {
8025
8078
  applicationIdSuffix ".debug"
@@ -8062,7 +8115,7 @@ class CapacitorApp {
8062
8115
  const gradleCommand = isWindows ? "gradlew.bat" : "./gradlew";
8063
8116
  await this.app.spawn(gradleCommand, [assembleType === "apk" ? "assembleRelease" : "bundleRelease"], {
8064
8117
  stdio: "inherit",
8065
- cwd: path34.join(this.app.cwdPath, this.androidRootPath),
8118
+ cwd: path35.join(this.app.cwdPath, this.androidRootPath),
8066
8119
  env: this.#commandEnv("release", env)
8067
8120
  });
8068
8121
  }
@@ -8091,12 +8144,12 @@ class CapacitorApp {
8091
8144
  await this.#prepareAndroid({ operation: "release", env: "main" });
8092
8145
  }
8093
8146
  async prepareWww() {
8094
- const htmlSource = path34.join(this.app.dist.cwdPath, "csr", targetHtmlFilename(this.target));
8147
+ const htmlSource = path35.join(this.app.dist.cwdPath, "csr", targetHtmlFilename(this.target));
8095
8148
  if (!await Bun.file(htmlSource).exists())
8096
8149
  throw new Error(`CSR html for mobile target '${this.target.name}' not found: ${htmlSource}`);
8097
8150
  await rm4(this.targetWebRoot, { recursive: true, force: true });
8098
8151
  await mkdir10(this.targetWebRoot, { recursive: true });
8099
- await Bun.write(path34.join(this.targetWebRoot, "index.html"), this.#injectMobileTargetMeta(await Bun.file(htmlSource).text()));
8152
+ await Bun.write(path35.join(this.targetWebRoot, "index.html"), this.#injectMobileTargetMeta(await Bun.file(htmlSource).text()));
8100
8153
  }
8101
8154
  #injectMobileTargetMeta(html) {
8102
8155
  const basePath2 = this.target.basePath?.replace(/^\/+|\/+$/g, "") ?? "";
@@ -8108,7 +8161,7 @@ class CapacitorApp {
8108
8161
  }
8109
8162
  async#writeCapacitorConfig() {
8110
8163
  await mkdir10(this.targetRoot, { recursive: true });
8111
- const appInfoPath = path34.relative(this.app.cwdPath, path34.join(this.app.cwdPath, "akan.app.json")).split(path34.sep).join("/");
8164
+ const appInfoPath = path35.relative(this.app.cwdPath, path35.join(this.app.cwdPath, "akan.app.json")).split(path35.sep).join("/");
8112
8165
  const content = `import type { AppScanResult } from "akanjs";
8113
8166
  import { withBase } from "akanjs/capacitor.base.config";
8114
8167
  import appInfo from "${appInfoPath.startsWith(".") ? appInfoPath : `./${appInfoPath}`}";
@@ -8129,18 +8182,18 @@ export default withBase(
8129
8182
  appInfo as AppScanResult,
8130
8183
  );
8131
8184
  `;
8132
- await Bun.write(path34.join(this.app.cwdPath, "capacitor.config.ts"), content);
8185
+ await Bun.write(path35.join(this.app.cwdPath, "capacitor.config.ts"), content);
8133
8186
  }
8134
8187
  async#prepareTargetAssets() {
8135
8188
  if (!this.target.assets)
8136
8189
  return;
8137
8190
  await mkdir10(this.targetAssetRoot, { recursive: true });
8138
8191
  if (this.target.assets.icon)
8139
- await cp2(path34.join(this.app.cwdPath, this.target.assets.icon), path34.join(this.targetAssetRoot, "icon.png"), {
8192
+ await cp2(path35.join(this.app.cwdPath, this.target.assets.icon), path35.join(this.targetAssetRoot, "icon.png"), {
8140
8193
  force: true
8141
8194
  });
8142
8195
  if (this.target.assets.splash)
8143
- await cp2(path34.join(this.app.cwdPath, this.target.assets.splash), path34.join(this.targetAssetRoot, "splash.png"), {
8196
+ await cp2(path35.join(this.app.cwdPath, this.target.assets.splash), path35.join(this.targetAssetRoot, "splash.png"), {
8144
8197
  force: true
8145
8198
  });
8146
8199
  }
@@ -8148,11 +8201,11 @@ export default withBase(
8148
8201
  const files = this.target.files?.[platform];
8149
8202
  if (!files)
8150
8203
  return;
8151
- const platformRoot = path34.join(this.app.cwdPath, platform === "ios" ? this.iosRootPath : this.androidRootPath);
8204
+ const platformRoot = path35.join(this.app.cwdPath, platform === "ios" ? this.iosRootPath : this.androidRootPath);
8152
8205
  await Promise.all(Object.entries(files).map(async ([to, from]) => {
8153
- const targetPath = path34.join(platformRoot, to);
8154
- await mkdir10(path34.dirname(targetPath), { recursive: true });
8155
- await cp2(path34.join(this.app.cwdPath, from), targetPath, { force: true });
8206
+ const targetPath = path35.join(platformRoot, to);
8207
+ await mkdir10(path35.dirname(targetPath), { recursive: true });
8208
+ await cp2(path35.join(this.app.cwdPath, from), targetPath, { force: true });
8156
8209
  }));
8157
8210
  }
8158
8211
  async#generateAssets({ operation, env }) {
@@ -8162,7 +8215,7 @@ export default withBase(
8162
8215
  "@capacitor/assets",
8163
8216
  "generate",
8164
8217
  "--assetPath",
8165
- path34.posix.join(this.targetRootPath, "assets"),
8218
+ path35.posix.join(this.targetRootPath, "assets"),
8166
8219
  "--iosProject",
8167
8220
  this.iosProjectPath,
8168
8221
  "--androidProject",
@@ -8347,7 +8400,7 @@ var Pkg = createInternalArgToken("Pkg");
8347
8400
  var Module = createInternalArgToken("Module");
8348
8401
  var Workspace = createInternalArgToken("Workspace");
8349
8402
  // pkgs/@akanjs/devkit/commandDecorators/command.ts
8350
- import path35 from "path";
8403
+ import path36 from "path";
8351
8404
  import { confirm, input as input2, select as select2 } from "@inquirer/prompts";
8352
8405
  import { Logger as Logger11 } from "akanjs/common";
8353
8406
  import chalk6 from "chalk";
@@ -8847,7 +8900,7 @@ var runCommands = async (...commands) => {
8847
8900
  process.exit(1);
8848
8901
  });
8849
8902
  const __dirname2 = getDirname(import.meta.url);
8850
- const packageJsonCandidates = [`${path35.dirname(Bun.main)}/package.json`, `${__dirname2}/../package.json`];
8903
+ const packageJsonCandidates = [`${path36.dirname(Bun.main)}/package.json`, `${__dirname2}/../package.json`];
8851
8904
  let cliPackageJson = null;
8852
8905
  for (const packageJsonPath of packageJsonCandidates) {
8853
8906
  if (!await FileSys.fileExists(packageJsonPath))
@@ -9123,8 +9176,8 @@ var scanModuleSpecifiers = (source, filePath, includeExports) => {
9123
9176
  return importSpecifiers;
9124
9177
  };
9125
9178
  var parseTsConfig = (tsConfigPath = "./tsconfig.json") => {
9126
- const configFile = ts6.readConfigFile(tsConfigPath, (path36) => {
9127
- return ts6.sys.readFile(path36);
9179
+ const configFile = ts6.readConfigFile(tsConfigPath, (path37) => {
9180
+ return ts6.sys.readFile(path37);
9128
9181
  });
9129
9182
  return ts6.parseJsonConfigFileContent(configFile.config, ts6.sys, realpathSync(tsConfigPath).replace(/[^/\\]+$/, ""));
9130
9183
  };
@@ -9469,7 +9522,6 @@ class LibraryScript extends script("library", [LibraryRunner]) {
9469
9522
  }
9470
9523
 
9471
9524
  // pkgs/@akanjs/cli/application/application.runner.ts
9472
- import path36 from "path";
9473
9525
  import { confirm as confirm2, input as input4, select as select5 } from "@inquirer/prompts";
9474
9526
  import { StringOutputParser } from "@langchain/core/output_parsers";
9475
9527
  import { PromptTemplate as PromptTemplate2 } from "@langchain/core/prompts";
@@ -9535,14 +9587,14 @@ class ApplicationRunner extends runner("application") {
9535
9587
  }
9536
9588
  async test(exec2) {
9537
9589
  const isSignalTarget = exec2 instanceof AppExecutor || exec2 instanceof LibExecutor;
9538
- const preloadPath = path36.join(exec2.cwdPath, "../../pkgs/akanjs/test/signalTest.preload.ts");
9590
+ const preloadPath = isSignalTarget ? await resolveSignalTestPreloadPath(exec2) : null;
9539
9591
  const env = isSignalTarget ? {
9540
9592
  AKAN_TEST_SIGNAL: "1",
9541
9593
  AKAN_TEST_TARGET_TYPE: exec2.type,
9542
9594
  AKAN_TEST_TARGET_NAME: exec2.name,
9543
9595
  AKAN_TEST_LIBS: exec2.getScanInfo({ allowEmpty: true })?.getLibs().join(",") ?? ""
9544
9596
  } : {};
9545
- const args = isSignalTarget ? ["test", "--isolate", "--preload", preloadPath] : ["test", "--isolate"];
9597
+ const args = preloadPath ? ["test", "--isolate", "--preload", preloadPath] : ["test", "--isolate"];
9546
9598
  await exec2.spawn("bun", args, {
9547
9599
  ...isSignalTarget ? { env: { ...process.env, ...env } } : {},
9548
9600
  stdio: "inherit"
@@ -9841,12 +9893,17 @@ class ApplicationScript extends script("application", [ApplicationRunner, Librar
9841
9893
  }
9842
9894
  }
9843
9895
  async test(exec2, { write = true } = {}) {
9896
+ if (exec2 instanceof LibExecutor) {
9897
+ await this.libraryScript.syncLibrary(exec2);
9898
+ const spinner3 = exec2.spinning(`Preparing ${exec2.name}...`);
9899
+ spinner3.succeed(`${exec2.name} prepared`);
9900
+ await this.applicationRunner.test(exec2);
9901
+ return;
9902
+ }
9844
9903
  const spinner2 = exec2.spinning(`Preparing ${exec2.name}...`);
9845
9904
  try {
9846
9905
  if (exec2 instanceof PkgExecutor)
9847
9906
  await exec2.scan({ refresh: true });
9848
- else if (exec2 instanceof LibExecutor)
9849
- await this.libraryScript.syncLibrary(exec2);
9850
9907
  else
9851
9908
  await exec2.scanSync({ write });
9852
9909
  spinner2.succeed(`${exec2.name} prepared`);
@@ -10229,17 +10286,21 @@ class PackageScript extends script("package", [PackageRunner]) {
10229
10286
  }
10230
10287
 
10231
10288
  // pkgs/@akanjs/cli/cloud/cloud.runner.ts
10289
+ import path38 from "path";
10232
10290
  import { confirm as confirm3 } from "@inquirer/prompts";
10233
10291
  import { Logger as Logger15, sleep } from "akanjs/common";
10234
10292
  import chalk7 from "chalk";
10235
10293
  import * as QRcode from "qrcode";
10236
10294
 
10237
10295
  // pkgs/@akanjs/cli/npmRegistry.ts
10238
- async function getLatestPackageVersion(packageName, tag = "latest") {
10239
- const url = `https://registry.npmjs.org/${encodeURIComponent(packageName).replace(/^%40/, "@")}`;
10296
+ var defaultNpmRegistry = "https://registry.npmjs.org";
10297
+ var getNpmRegistryUrl = (registryUrl = process.env.AKAN_NPM_REGISTRY ?? defaultNpmRegistry) => registryUrl.replace(/\/+$/, "");
10298
+ async function getLatestPackageVersion(packageName, tag = "latest", registryUrl) {
10299
+ const registry = getNpmRegistryUrl(registryUrl);
10300
+ const url = `${registry}/${encodeURIComponent(packageName).replace(/^%40/, "@")}`;
10240
10301
  const res = await fetch(url);
10241
10302
  if (!res.ok)
10242
- throw new Error(`Failed to fetch ${packageName} metadata from npm registry`);
10303
+ throw new Error(`Failed to fetch ${packageName} metadata from ${registry}`);
10243
10304
  const metadata = await res.json();
10244
10305
  const version = metadata["dist-tags"]?.[tag];
10245
10306
  if (!version)
@@ -10249,6 +10310,24 @@ async function getLatestPackageVersion(packageName, tag = "latest") {
10249
10310
 
10250
10311
  // pkgs/@akanjs/cli/cloud/cloud.runner.ts
10251
10312
  class CloudRunner extends runner("cloud") {
10313
+ #akanFrameworkPackages = new Set(["akanjs", "@akanjs/devkit", "@akanjs/cli", "create-akan-workspace"]);
10314
+ #getRegistryArgs(registryUrl) {
10315
+ return registryUrl ? ["--registry", getNpmRegistryUrl(registryUrl)] : [];
10316
+ }
10317
+ #getLocalRegistryAuthArgs(registryUrl) {
10318
+ if (!registryUrl)
10319
+ return [];
10320
+ const { host, pathname } = new URL(getNpmRegistryUrl(registryUrl));
10321
+ const registryPath = pathname === "/" ? "/" : `${pathname.replace(/\/+$/, "")}/`;
10322
+ return [`--//${host}${registryPath}:_authToken=akan-local-registry`];
10323
+ }
10324
+ #getRegistryEnv(registryUrl) {
10325
+ return registryUrl ? {
10326
+ ...process.env,
10327
+ AKAN_NPM_REGISTRY: getNpmRegistryUrl(registryUrl),
10328
+ NPM_CONFIG_REGISTRY: getNpmRegistryUrl(registryUrl)
10329
+ } : process.env;
10330
+ }
10252
10331
  async login() {
10253
10332
  const config = await getHostConfig();
10254
10333
  const self = config.auth ? await getSelf(config.auth.token) : null;
@@ -10327,15 +10406,16 @@ ${chalk7.green("\u27A4")} Authentication Required`));
10327
10406
  const pkgs = await workspace.getPkgs();
10328
10407
  return pkgs.filter((pkg) => pkg === "akanjs" || pkg === "create-akan-workspace" || pkg.startsWith("@akanjs/"));
10329
10408
  }
10330
- async deployAkan(workspace, akanPkgs) {
10409
+ async deployAkan(workspace, akanPkgs, { registryUrl, confirmPublish = true, tag: distTag } = {}) {
10410
+ const registry = registryUrl ? getNpmRegistryUrl(registryUrl) : undefined;
10331
10411
  const akanPackageJson2 = await workspace.readJson("pkgs/akanjs/package.json");
10332
10412
  const [majorVersion, minorVersion, patchVersion, devPatchVersion] = akanPackageJson2.version.split(".");
10333
10413
  const isOfficialRelease = !devPatchVersion;
10334
10414
  const targetVersionPrefix = isOfficialRelease ? `${majorVersion}.${minorVersion}` : `${majorVersion}.${minorVersion}.${patchVersion}`;
10335
- const tag = isOfficialRelease ? "latest" : patchVersion.split("-").at(1) ?? "dev";
10415
+ const tag = distTag ?? (isOfficialRelease ? "latest" : patchVersion.split("-").at(1) ?? "dev");
10336
10416
  const getNextVersion = async (prefix, tag2) => {
10337
10417
  try {
10338
- const latestPublishedVersion2 = await getLatestPackageVersion("akanjs", tag2);
10418
+ const latestPublishedVersion2 = await getLatestPackageVersion("akanjs", tag2, registry);
10339
10419
  const latestPatch = latestPublishedVersion2.startsWith(prefix) ? parseInt(latestPublishedVersion2.split(".").at(-1) ?? "-1") : -1;
10340
10420
  const nextVersion2 = `${prefix}.${latestPatch + 1}`;
10341
10421
  return { nextVersion: nextVersion2, latestPublishedVersion: latestPublishedVersion2 };
@@ -10348,37 +10428,46 @@ ${chalk7.green("\u27A4")} Authentication Required`));
10348
10428
  Logger15.info(`Next version of akanjs: ${nextVersion}`);
10349
10429
  for (const library of akanPkgs) {
10350
10430
  const packageJson = await workspace.readJson(`pkgs/${library}/package.json`);
10351
- const newPackageJsonStr = JSON.stringify({ ...packageJson, version: nextVersion }, null, 2);
10431
+ const newPackageJsonStr = JSON.stringify(this.#normalizeAkanPackageJson(packageJson, library, nextVersion), null, 2);
10352
10432
  await workspace.writeFile(`pkgs/${library}/package.json`, newPackageJsonStr);
10353
10433
  const distPackageJson = await workspace.readJson(`dist/pkgs/${library}/package.json`);
10354
- const newDistPackageJson = { ...distPackageJson, version: nextVersion };
10434
+ const newDistPackageJson = this.#normalizeAkanPackageJson(distPackageJson, library, nextVersion);
10355
10435
  await workspace.writeJson(`dist/pkgs/${library}/package.json`, newDistPackageJson);
10356
10436
  }
10357
- const isDeployConfirmed = await confirm3({
10358
- message: "Are you sure you want to deploy the libraries?"
10359
- });
10360
- if (!isDeployConfirmed) {
10361
- Logger15.error("Deployment cancelled");
10362
- return;
10437
+ if (confirmPublish) {
10438
+ const isDeployConfirmed = await confirm3({
10439
+ message: "Are you sure you want to deploy the libraries?"
10440
+ });
10441
+ if (!isDeployConfirmed) {
10442
+ Logger15.error("Deployment cancelled");
10443
+ return;
10444
+ }
10363
10445
  }
10364
10446
  await Promise.all(akanPkgs.map(async (library) => {
10365
- Logger15.info(`Publishing ${library}@${nextVersion} to npm...`);
10366
- await workspace.exec(`npm publish --tag ${tag}`, { cwd: `dist/pkgs/${library}` });
10367
- Logger15.info(`${library}@${nextVersion} is published to npm`);
10447
+ Logger15.info(`Publishing ${library}@${nextVersion} to ${registry ?? "npm"}...`);
10448
+ await workspace.spawn("npm", ["publish", "--tag", tag, ...this.#getRegistryArgs(registry), ...this.#getLocalRegistryAuthArgs(registry)], {
10449
+ cwd: path38.join(workspace.workspaceRoot, "dist/pkgs", library),
10450
+ env: this.#getRegistryEnv(registry),
10451
+ stdio: "inherit"
10452
+ });
10453
+ Logger15.info(`${library}@${nextVersion} is published to ${registry ?? "npm"}`);
10368
10454
  }));
10369
- Logger15.info("All libraries are published to npm");
10455
+ Logger15.info(`All libraries are published to ${registry ?? "npm"}`);
10370
10456
  }
10371
- async update(workspace, tag = "latest") {
10457
+ async update(workspace, tag = "latest", { registryUrl } = {}) {
10458
+ const registry = registryUrl ? getNpmRegistryUrl(registryUrl) : undefined;
10459
+ const registryArgs = this.#getRegistryArgs(registry);
10460
+ const env = this.#getRegistryEnv(registry);
10372
10461
  if (!await workspace.exists("package.json"))
10373
- await workspace.spawn("npm", ["update", "-g", "akanjs", "--latest", `--tag=${tag}`]);
10462
+ await workspace.spawn("bun", ["update", "-g", "akanjs", "--latest", `--tag=${tag}`, ...registryArgs], { env });
10374
10463
  else
10375
10464
  await Promise.all([
10376
- workspace.spawn("npm", ["update", "-g", "akanjs", "--latest", `--tag=${tag}`]),
10377
- this.#updateAkanPkgs(workspace, tag)
10465
+ workspace.spawn("bun", ["update", "-g", "akanjs", "--latest", `--tag=${tag}`, ...registryArgs], { env }),
10466
+ this.#updateAkanPkgs(workspace, tag, registry)
10378
10467
  ]);
10379
10468
  }
10380
- async#updateAkanPkgs(workspace, tag = "latest") {
10381
- const latestPublishedVersion = await getLatestPackageVersion("akanjs", tag);
10469
+ async#updateAkanPkgs(workspace, tag = "latest", registryUrl) {
10470
+ const latestPublishedVersion = await getLatestPackageVersion("akanjs", tag, registryUrl);
10382
10471
  const rootPackageJson = await workspace.getPackageJson();
10383
10472
  if (!rootPackageJson.dependencies)
10384
10473
  throw new Error("No dependencies found in package.json");
@@ -10386,8 +10475,27 @@ ${chalk7.green("\u27A4")} Authentication Required`));
10386
10475
  rootPackageJson.dependencies.akanjs = latestPublishedVersion;
10387
10476
  if (rootPackageJson.devDependencies?.akanjs)
10388
10477
  rootPackageJson.devDependencies.akanjs = latestPublishedVersion;
10389
- workspace.setPackageJson(rootPackageJson);
10390
- await workspace.spawn("bun", ["install"]);
10478
+ if (rootPackageJson.dependencies["@akanjs/devkit"])
10479
+ rootPackageJson.dependencies["@akanjs/devkit"] = latestPublishedVersion;
10480
+ if (rootPackageJson.devDependencies?.["@akanjs/devkit"])
10481
+ rootPackageJson.devDependencies["@akanjs/devkit"] = latestPublishedVersion;
10482
+ await workspace.setPackageJson(rootPackageJson);
10483
+ await workspace.spawn("bun", ["install", ...this.#getRegistryArgs(registryUrl)], {
10484
+ env: this.#getRegistryEnv(registryUrl)
10485
+ });
10486
+ }
10487
+ #normalizeAkanPackageJson(packageJson, packageName, version) {
10488
+ const normalized = { ...packageJson, version };
10489
+ for (const field of ["dependencies", "devDependencies", "peerDependencies", "optionalDependencies"]) {
10490
+ const dependencies = normalized[field];
10491
+ if (!dependencies)
10492
+ continue;
10493
+ normalized[field] = Object.fromEntries(Object.entries(dependencies).map(([dep, depVersion]) => [
10494
+ dep,
10495
+ dep !== packageName && this.#akanFrameworkPackages.has(dep) ? version : depVersion
10496
+ ]));
10497
+ }
10498
+ return normalized;
10391
10499
  }
10392
10500
  }
10393
10501
 
@@ -10409,7 +10517,7 @@ class CloudScript extends script("cloud", [CloudRunner, ApplicationScript, Packa
10409
10517
  const session = new AiSession("general", { workspace, isContinued: true });
10410
10518
  await session.ask(question);
10411
10519
  }
10412
- async deployAkan(workspace, { test = true } = {}) {
10520
+ async deployAkan(workspace, { test = true, registryUrl } = {}) {
10413
10521
  const akanPkgs = await this.cloudRunner.getAkanPkgs(workspace);
10414
10522
  await this.packageScript.updateWorskpaceRootPackageJson(workspace);
10415
10523
  const pkgs = akanPkgs.map((pkgName) => PkgExecutor.from(workspace, pkgName));
@@ -10418,11 +10526,11 @@ class CloudScript extends script("cloud", [CloudRunner, ApplicationScript, Packa
10418
10526
  await this.applicationScript.test(pkg);
10419
10527
  for (const pkg of pkgs)
10420
10528
  await this.packageScript.buildPackage(pkg);
10421
- await this.cloudRunner.deployAkan(workspace, akanPkgs);
10529
+ await this.cloudRunner.deployAkan(workspace, akanPkgs, { registryUrl });
10422
10530
  }
10423
- async update(workspace, tag = "latest") {
10531
+ async update(workspace, tag = "latest", { registryUrl } = {}) {
10424
10532
  const spinner2 = workspace.spinning("Updating Akan.js packages and CLI...");
10425
- await this.cloudRunner.update(workspace, tag);
10533
+ await this.cloudRunner.update(workspace, tag, { registryUrl });
10426
10534
  spinner2.succeed("Akan.js packages and CLI updated, global version is below");
10427
10535
  Logger16.raw("> Akan version: ");
10428
10536
  await workspace.spawn("akan", ["--version"], { stdio: "inherit" });
@@ -10430,6 +10538,9 @@ class CloudScript extends script("cloud", [CloudRunner, ApplicationScript, Packa
10430
10538
  }
10431
10539
 
10432
10540
  // pkgs/@akanjs/cli/cloud/cloud.command.ts
10541
+ var localRegistryUrl = () => process.env.AKAN_NPM_REGISTRY ?? "http://127.0.0.1:4873";
10542
+ var resolveRegistryUrl = (registry) => registry === "local" ? localRegistryUrl() : undefined;
10543
+
10433
10544
  class CloudCommand extends command("cloud", [CloudScript], ({ public: target }) => ({
10434
10545
  login: target({ desc: "Login to Akan Cloud services" }).with(Workspace).exec(async function(workspace) {
10435
10546
  await this.cloudScript.login(workspace);
@@ -10446,15 +10557,32 @@ class CloudCommand extends command("cloud", [CloudScript], ({ public: target })
10446
10557
  ask: target({ desc: "Ask AI assistant a question about your project" }).option("question", String, { ask: "question to ask" }).with(Workspace).exec(async function(question, workspace) {
10447
10558
  await this.cloudScript.ask(question, workspace);
10448
10559
  }),
10449
- deployAkan: target({ devOnly: true, desc: "Deploy Akan.js framework to cloud (internal use)" }).option("test", Boolean, { desc: "test the deployment", default: true }).with(Workspace).exec(async function(test, workspace) {
10450
- await this.cloudScript.deployAkan(workspace, { test });
10560
+ deployAkan: target({ devOnly: true, desc: "Deploy Akan.js framework to cloud (internal use)" }).option("test", Boolean, { desc: "test the deployment", default: true }).option("registry", String, {
10561
+ desc: "registry target for publishing Akan packages",
10562
+ ask: "Select a registry target",
10563
+ enum: [
10564
+ { label: "local", value: "local" },
10565
+ { label: "npm", value: "npm" }
10566
+ ]
10567
+ }).with(Workspace).exec(async function(test, registry, workspace) {
10568
+ await this.cloudScript.deployAkan(workspace, {
10569
+ test,
10570
+ registryUrl: resolveRegistryUrl(registry)
10571
+ });
10451
10572
  }),
10452
10573
  update: target({ desc: "Update Akan.js framework to the latest version" }).with(Workspace).option("tag", String, {
10453
10574
  desc: "tag of the update",
10454
10575
  default: "latest",
10455
10576
  enum: ["latest", "dev", "canary", "beta", "rc", "alpha"]
10456
- }).exec(async function(workspace, tag) {
10457
- await this.cloudScript.update(workspace, tag);
10577
+ }).option("registry", String, {
10578
+ desc: "registry target for resolving Akan packages",
10579
+ ask: "Select a registry target",
10580
+ enum: [
10581
+ { label: "npm", value: "npm" },
10582
+ { label: "local", value: "local" }
10583
+ ]
10584
+ }).exec(async function(workspace, tag, registry) {
10585
+ await this.cloudScript.update(workspace, tag, { registryUrl: resolveRegistryUrl(registry) });
10458
10586
  })
10459
10587
  })) {
10460
10588
  }
@@ -10480,14 +10608,14 @@ class GuidelinePrompt extends Prompter {
10480
10608
  async#getScanFilePaths(matchPattern, { avoidDirs = ["node_modules", ".next"], filterText } = {}) {
10481
10609
  const glob = new Bun.Glob(matchPattern);
10482
10610
  const paths = [];
10483
- for await (const path38 of glob.scan({ cwd: this.workspace.workspaceRoot, absolute: true })) {
10484
- if (avoidDirs.some((dir) => path38.includes(dir)))
10611
+ for await (const path39 of glob.scan({ cwd: this.workspace.workspaceRoot, absolute: true })) {
10612
+ if (avoidDirs.some((dir) => path39.includes(dir)))
10485
10613
  continue;
10486
- const fileContent = await FileSys.readText(path38);
10614
+ const fileContent = await FileSys.readText(path39);
10487
10615
  const textFilter = filterText ? new RegExp(filterText) : null;
10488
10616
  if (filterText && !textFilter?.test(fileContent))
10489
10617
  continue;
10490
- paths.push(path38);
10618
+ paths.push(path39);
10491
10619
  }
10492
10620
  return paths;
10493
10621
  }
@@ -10782,6 +10910,147 @@ class LibraryCommand extends command("library", [LibraryScript], ({ public: targ
10782
10910
  })) {
10783
10911
  }
10784
10912
 
10913
+ // pkgs/@akanjs/cli/localRegistry/localRegistry.runner.ts
10914
+ import { mkdir as mkdir11, rm as rm5 } from "fs/promises";
10915
+ import path39 from "path";
10916
+ import { Logger as Logger17 } from "akanjs/common";
10917
+ var defaultLocalRegistryUrl = "http://127.0.0.1:4873";
10918
+ var containerName = "akan-verdaccio";
10919
+ var smokeRepoName = "akan-local-smoke";
10920
+ var smokeAppName = "demo";
10921
+
10922
+ class LocalRegistryRunner extends runner("localRegistry") {
10923
+ getRegistryUrl(registryUrl = process.env.AKAN_NPM_REGISTRY ?? defaultLocalRegistryUrl) {
10924
+ return getNpmRegistryUrl(registryUrl);
10925
+ }
10926
+ async start(workspace, { registryUrl } = {}) {
10927
+ const registry = this.getRegistryUrl(registryUrl);
10928
+ try {
10929
+ await workspace.spawn("docker", ["inspect", containerName]);
10930
+ Logger17.info(`Local registry is already running at ${registry}`);
10931
+ return registry;
10932
+ } catch {}
10933
+ const configPath2 = path39.join(workspace.workspaceRoot, "pkgs/@akanjs/cli/localRegistry/verdaccio.yaml");
10934
+ const storagePath = path39.join(workspace.workspaceRoot, ".akan/verdaccio/storage");
10935
+ await mkdir11(storagePath, { recursive: true });
10936
+ await workspace.spawn("docker", [
10937
+ "run",
10938
+ "--rm",
10939
+ "-d",
10940
+ "--name",
10941
+ containerName,
10942
+ "-p",
10943
+ "4873:4873",
10944
+ "-v",
10945
+ `${configPath2}:/verdaccio/conf/config.yaml:ro`,
10946
+ "-v",
10947
+ `${storagePath}:/verdaccio/storage`,
10948
+ "verdaccio/verdaccio:6"
10949
+ ], { stdio: "inherit" });
10950
+ Logger17.info(`Local registry is running at ${registry}`);
10951
+ return registry;
10952
+ }
10953
+ async reset(workspace) {
10954
+ try {
10955
+ await workspace.spawn("docker", ["rm", "-f", containerName], { stdio: "inherit" });
10956
+ } catch {}
10957
+ await rm5(path39.join(workspace.workspaceRoot, ".akan/verdaccio"), { recursive: true, force: true });
10958
+ Logger17.info("Local registry storage has been reset");
10959
+ }
10960
+ async smoke(workspace, { registryUrl } = {}) {
10961
+ const registry = this.getRegistryUrl(registryUrl);
10962
+ const smokeRoot = path39.join(workspace.workspaceRoot, ".akan/e2e");
10963
+ await rm5(path39.join(smokeRoot, smokeRepoName), { recursive: true, force: true });
10964
+ await workspace.spawn(process.execPath, [
10965
+ "dist/pkgs/create-akan-workspace/index.js",
10966
+ smokeRepoName,
10967
+ "--app",
10968
+ smokeAppName,
10969
+ "--dir",
10970
+ ".akan/e2e",
10971
+ "--init",
10972
+ "true",
10973
+ "--registry",
10974
+ registry
10975
+ ], {
10976
+ env: { ...process.env, AKAN_NPM_REGISTRY: registry, NPM_CONFIG_REGISTRY: registry },
10977
+ stdio: "inherit"
10978
+ });
10979
+ await workspace.spawn("akan", ["build", smokeAppName], {
10980
+ cwd: path39.join(smokeRoot, smokeRepoName),
10981
+ env: { ...process.env, AKAN_NPM_REGISTRY: registry, NPM_CONFIG_REGISTRY: registry },
10982
+ stdio: "inherit"
10983
+ });
10984
+ Logger17.info(`Local registry smoke test completed for ${smokeRepoName}/${smokeAppName}`);
10985
+ }
10986
+ }
10987
+
10988
+ // pkgs/@akanjs/cli/localRegistry/localRegistry.script.ts
10989
+ class LocalRegistryScript extends script("localRegistry", [
10990
+ LocalRegistryRunner,
10991
+ CloudRunner,
10992
+ ApplicationScript,
10993
+ PackageScript
10994
+ ]) {
10995
+ async start(workspace, { registryUrl } = {}) {
10996
+ const spinner2 = workspace.spinning("Starting local npm registry...");
10997
+ const registry = await this.localRegistryRunner.start(workspace, { registryUrl });
10998
+ spinner2.succeed(`Local npm registry is ready at ${registry}`);
10999
+ }
11000
+ async reset(workspace) {
11001
+ const spinner2 = workspace.spinning("Resetting local npm registry...");
11002
+ await this.localRegistryRunner.reset(workspace);
11003
+ spinner2.succeed("Local npm registry reset");
11004
+ }
11005
+ async smoke(workspace, { tag = "rc", test = true, registryUrl } = {}) {
11006
+ const registry = await this.localRegistryRunner.start(workspace, { registryUrl });
11007
+ const akanPkgs = await this.cloudRunner.getAkanPkgs(workspace);
11008
+ await this.#preparePackages(workspace, akanPkgs, { test });
11009
+ await this.cloudRunner.deployAkan(workspace, akanPkgs, {
11010
+ registryUrl: registry,
11011
+ confirmPublish: false,
11012
+ tag
11013
+ });
11014
+ await this.localRegistryRunner.smoke(workspace, { registryUrl: registry });
11015
+ }
11016
+ async#preparePackages(workspace, akanPkgs, { test = true } = {}) {
11017
+ await this.packageScript.updateWorskpaceRootPackageJson(workspace);
11018
+ const pkgs = akanPkgs.map((pkgName) => PkgExecutor.from(workspace, pkgName));
11019
+ if (test)
11020
+ for (const pkg of pkgs)
11021
+ await this.applicationScript.test(pkg);
11022
+ for (const pkg of pkgs)
11023
+ await this.packageScript.buildPackage(pkg, { showSpinner: false });
11024
+ }
11025
+ }
11026
+
11027
+ // pkgs/@akanjs/cli/localRegistry/localRegistry.command.ts
11028
+ class LocalRegistryCommand extends command("local-registry", [LocalRegistryScript], ({ public: target }) => ({
11029
+ startRegistry: target({ devOnly: true, desc: "Start the local Verdaccio npm registry" }).with(Workspace).option("registry", String, {
11030
+ desc: "local npm registry URL",
11031
+ default: process.env.AKAN_NPM_REGISTRY ?? "http://127.0.0.1:4873"
11032
+ }).exec(async function(workspace, registry) {
11033
+ await this.localRegistryScript.start(workspace, { registryUrl: registry });
11034
+ }),
11035
+ resetRegistry: target({ devOnly: true, desc: "Stop and clear the local Verdaccio npm registry" }).with(Workspace).exec(async function(workspace) {
11036
+ await this.localRegistryScript.reset(workspace);
11037
+ }),
11038
+ smokeRegistry: target({ devOnly: true, desc: "Publish to local registry and build a generated workspace" }).with(Workspace).option("tag", String, {
11039
+ flag: "g",
11040
+ desc: "dist-tag for local registry publish",
11041
+ default: "rc"
11042
+ }).option("test", Boolean, {
11043
+ desc: "run package tests before publishing",
11044
+ default: true
11045
+ }).option("registry", String, {
11046
+ desc: "local npm registry URL",
11047
+ default: process.env.AKAN_NPM_REGISTRY
11048
+ }).exec(async function(workspace, tag, test, registry) {
11049
+ await this.localRegistryScript.smoke(workspace, { tag, test, registryUrl: registry });
11050
+ })
11051
+ })) {
11052
+ }
11053
+
10785
11054
  // pkgs/@akanjs/cli/module/module.command.ts
10786
11055
  import { lowerlize } from "akanjs/common";
10787
11056
 
@@ -11577,11 +11846,11 @@ class ScalarCommand extends command("scalar", [ScalarScript], ({ public: target
11577
11846
  }
11578
11847
 
11579
11848
  // pkgs/@akanjs/cli/workspace/workspace.script.ts
11580
- import path39 from "path";
11581
- import { Logger as Logger17 } from "akanjs/common";
11849
+ import path41 from "path";
11850
+ import { Logger as Logger18 } from "akanjs/common";
11582
11851
 
11583
11852
  // pkgs/@akanjs/cli/workspace/workspace.runner.ts
11584
- import path38 from "path";
11853
+ import path40 from "path";
11585
11854
  var defaultWorkspacePeerDependencies = new Set([
11586
11855
  "@radix-ui/react-dialog",
11587
11856
  "@react-spring/web",
@@ -11601,17 +11870,29 @@ var defaultWorkspacePeerDependencies = new Set([
11601
11870
  ]);
11602
11871
 
11603
11872
  class WorkspaceRunner extends runner("workspace") {
11604
- async createWorkspace(repoName, appName, { dirname: dirname3 = ".", init = true, akanVersion }) {
11873
+ async createWorkspace(repoName, appName, {
11874
+ dirname: dirname3 = ".",
11875
+ init = true,
11876
+ akanVersion,
11877
+ registryUrl
11878
+ }) {
11605
11879
  const cwdPath = process.cwd();
11606
- const workspaceRoot = path38.join(cwdPath, dirname3, repoName);
11880
+ const workspaceRoot = path40.join(cwdPath, dirname3, repoName);
11881
+ const normalizedRegistryUrl = registryUrl ? getNpmRegistryUrl(registryUrl) : undefined;
11607
11882
  const workspace = WorkspaceExecutor.fromRoot({ workspaceRoot, repoName });
11608
11883
  const templateSpinner = workspace.spinning(`Creating workspace template files in ${dirname3}/${repoName}...`);
11609
- const latestTypesBunVersion = await getLatestPackageVersion("@types/bun");
11884
+ const [latestBiomeVersion, latestTypesBunVersion] = await Promise.all([
11885
+ getLatestPackageVersion("@biomejs/biome", "latest", normalizedRegistryUrl),
11886
+ getLatestPackageVersion("@types/bun", "latest", normalizedRegistryUrl)
11887
+ ]);
11610
11888
  await workspace.applyTemplate({
11611
11889
  basePath: ".",
11612
11890
  template: "workspaceRoot",
11613
11891
  dict: { repoName, appName, serveDomain: "localhost" }
11614
11892
  });
11893
+ if (normalizedRegistryUrl)
11894
+ await workspace.writeFile(".npmrc", `registry=${normalizedRegistryUrl}/
11895
+ `);
11615
11896
  templateSpinner.succeed(`Workspace files created in ${dirname3}/${repoName}`);
11616
11897
  const [rootPackageJson, peerDependencies] = await Promise.all([
11617
11898
  workspace.getPackageJson(),
@@ -11627,7 +11908,9 @@ class WorkspaceRunner extends runner("workspace") {
11627
11908
  },
11628
11909
  devDependencies: {
11629
11910
  ...rootPackageJson.devDependencies,
11911
+ "@biomejs/biome": latestBiomeVersion,
11630
11912
  "@types/bun": latestTypesBunVersion,
11913
+ "@akanjs/devkit": akanVersion,
11631
11914
  ...typescript ? { typescript } : {}
11632
11915
  }
11633
11916
  };
@@ -11650,9 +11933,9 @@ class WorkspaceRunner extends runner("workspace") {
11650
11933
  }
11651
11934
  async#getCliPackageJson() {
11652
11935
  const packageJsonCandidates = [
11653
- path38.join(import.meta.dir, "../package.json"),
11654
- path38.join(import.meta.dir, "package.json"),
11655
- path38.join(path38.dirname(Bun.main), "package.json")
11936
+ path40.join(import.meta.dir, "../package.json"),
11937
+ path40.join(import.meta.dir, "package.json"),
11938
+ path40.join(path40.dirname(Bun.main), "package.json")
11656
11939
  ];
11657
11940
  try {
11658
11941
  packageJsonCandidates.unshift(Bun.resolveSync("@akanjs/cli/package.json", import.meta.dir));
@@ -11668,9 +11951,9 @@ class WorkspaceRunner extends runner("workspace") {
11668
11951
  }
11669
11952
  async#getAkanPackageJson() {
11670
11953
  const packageJsonCandidates = [
11671
- path38.join(import.meta.dir, "../../../akanjs/package.json"),
11672
- path38.join(process.cwd(), "pkgs/akanjs/package.json"),
11673
- path38.join(path38.dirname(Bun.main), "node_modules/akanjs/package.json")
11954
+ path40.join(import.meta.dir, "../../../akanjs/package.json"),
11955
+ path40.join(process.cwd(), "pkgs/akanjs/package.json"),
11956
+ path40.join(path40.dirname(Bun.main), "node_modules/akanjs/package.json")
11674
11957
  ];
11675
11958
  try {
11676
11959
  packageJsonCandidates.unshift(Bun.resolveSync("akanjs/package.json", import.meta.dir));
@@ -11684,13 +11967,13 @@ class WorkspaceRunner extends runner("workspace") {
11684
11967
  }
11685
11968
  let current = import.meta.dir;
11686
11969
  for (let depth = 0;depth < 6; depth++) {
11687
- const packageJsonPath = path38.join(current, "package.json");
11970
+ const packageJsonPath = path40.join(current, "package.json");
11688
11971
  if (await Bun.file(packageJsonPath).exists()) {
11689
11972
  const packageJson = await FileSys.readJson(packageJsonPath);
11690
11973
  if (packageJson.name === "akanjs")
11691
11974
  return packageJson;
11692
11975
  }
11693
- const parent = path38.dirname(current);
11976
+ const parent = path40.dirname(current);
11694
11977
  if (parent === current)
11695
11978
  break;
11696
11979
  current = parent;
@@ -11714,12 +11997,18 @@ class WorkspaceScript extends script("workspace", [
11714
11997
  LibraryScript,
11715
11998
  PackageScript
11716
11999
  ]) {
11717
- async createWorkspace(repoName, appName, { dirname: dirname3 = ".", installLibs = false, init = true }) {
12000
+ async createWorkspace(repoName, appName, {
12001
+ dirname: dirname3 = ".",
12002
+ installLibs = false,
12003
+ init = true,
12004
+ registryUrl
12005
+ }) {
11718
12006
  const akanVersion = await this.packageScript.version(null, { log: false });
11719
12007
  const workspace = await this.workspaceRunner.createWorkspace(repoName, appName, {
11720
12008
  dirname: dirname3,
11721
12009
  init,
11722
- akanVersion
12010
+ akanVersion,
12011
+ ...registryUrl ? { registryUrl } : {}
11723
12012
  });
11724
12013
  if (installLibs) {
11725
12014
  await this.libraryScript.installLibrary(workspace, "util");
@@ -11733,11 +12022,11 @@ class WorkspaceScript extends script("workspace", [
11733
12022
  } catch (_) {
11734
12023
  gitSpinner.fail("Git repository initialization failed. It's not fatal, you can commit manually");
11735
12024
  }
11736
- const workspacePath = path39.join(dirname3, repoName);
11737
- Logger17.rawLog(`
12025
+ const workspacePath = path41.join(dirname3, repoName);
12026
+ Logger18.rawLog(`
11738
12027
  \uD83C\uDF89 Welcome aboard! Workspace created in ${dirname3}/${repoName}`);
11739
- Logger17.rawLog(`\uD83D\uDE80 Run \`cd ${workspacePath} && akan start ${appName}\` to start the development server.`);
11740
- Logger17.rawLog(`
12028
+ Logger18.rawLog(`\uD83D\uDE80 Run \`cd ${workspacePath} && akan start ${appName}\` to start the development server.`);
12029
+ Logger18.rawLog(`
11741
12030
  \uD83D\uDC4B Happy coding!`);
11742
12031
  }
11743
12032
  async lint(exec2, workspace, { fix = true } = {}) {
@@ -11792,9 +12081,12 @@ class WorkspaceCommand extends command("workspace", [WorkspaceScript], ({ public
11792
12081
  }).option("init", Boolean, {
11793
12082
  desc: "Do you want to initialize the workspace? (Recommended)",
11794
12083
  default: true
11795
- }).exec(async function(workspaceName, app, dir, libs, init) {
12084
+ }).option("registry", String, {
12085
+ desc: "npm registry URL for installing Akan packages",
12086
+ default: process.env.AKAN_NPM_REGISTRY
12087
+ }).exec(async function(workspaceName, app, dir, libs, init, registry) {
11796
12088
  const appName = app || "app";
11797
- await this.workspaceScript.createWorkspace(workspaceName.toLowerCase().replace(/ /g, "-"), appName.toLowerCase().replace(/ /g, "-"), { dirname: dir, installLibs: libs, init });
12089
+ await this.workspaceScript.createWorkspace(workspaceName.toLowerCase().replace(/ /g, "-"), appName.toLowerCase().replace(/ /g, "-"), { dirname: dir, installLibs: libs, init, ...registry ? { registryUrl: registry } : {} });
11798
12090
  }),
11799
12091
  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) {
11800
12092
  await this.workspaceScript.lint(exec2, workspace, { fix });
@@ -11809,4 +12101,4 @@ class WorkspaceCommand extends command("workspace", [WorkspaceScript], ({ public
11809
12101
  }
11810
12102
 
11811
12103
  // pkgs/@akanjs/cli/index.ts
11812
- runCommands(WorkspaceCommand, ApplicationCommand, LibraryCommand, PackageCommand, ModuleCommand, PageCommand, CloudCommand, GuidelineCommand, ScalarCommand);
12104
+ runCommands(WorkspaceCommand, ApplicationCommand, LibraryCommand, LocalRegistryCommand, PackageCommand, ModuleCommand, PageCommand, CloudCommand, GuidelineCommand, ScalarCommand);