@akanjs/cli 2.1.0-rc.9 → 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("bun", ["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("bun", ["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");
@@ -10390,8 +10479,23 @@ ${chalk7.green("\u27A4")} Authentication Required`));
10390
10479
  rootPackageJson.dependencies["@akanjs/devkit"] = latestPublishedVersion;
10391
10480
  if (rootPackageJson.devDependencies?.["@akanjs/devkit"])
10392
10481
  rootPackageJson.devDependencies["@akanjs/devkit"] = latestPublishedVersion;
10393
- workspace.setPackageJson(rootPackageJson);
10394
- await workspace.spawn("bun", ["install"]);
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;
10395
10499
  }
10396
10500
  }
10397
10501
 
@@ -10413,7 +10517,7 @@ class CloudScript extends script("cloud", [CloudRunner, ApplicationScript, Packa
10413
10517
  const session = new AiSession("general", { workspace, isContinued: true });
10414
10518
  await session.ask(question);
10415
10519
  }
10416
- async deployAkan(workspace, { test = true } = {}) {
10520
+ async deployAkan(workspace, { test = true, registryUrl } = {}) {
10417
10521
  const akanPkgs = await this.cloudRunner.getAkanPkgs(workspace);
10418
10522
  await this.packageScript.updateWorskpaceRootPackageJson(workspace);
10419
10523
  const pkgs = akanPkgs.map((pkgName) => PkgExecutor.from(workspace, pkgName));
@@ -10422,11 +10526,11 @@ class CloudScript extends script("cloud", [CloudRunner, ApplicationScript, Packa
10422
10526
  await this.applicationScript.test(pkg);
10423
10527
  for (const pkg of pkgs)
10424
10528
  await this.packageScript.buildPackage(pkg);
10425
- await this.cloudRunner.deployAkan(workspace, akanPkgs);
10529
+ await this.cloudRunner.deployAkan(workspace, akanPkgs, { registryUrl });
10426
10530
  }
10427
- async update(workspace, tag = "latest") {
10531
+ async update(workspace, tag = "latest", { registryUrl } = {}) {
10428
10532
  const spinner2 = workspace.spinning("Updating Akan.js packages and CLI...");
10429
- await this.cloudRunner.update(workspace, tag);
10533
+ await this.cloudRunner.update(workspace, tag, { registryUrl });
10430
10534
  spinner2.succeed("Akan.js packages and CLI updated, global version is below");
10431
10535
  Logger16.raw("> Akan version: ");
10432
10536
  await workspace.spawn("akan", ["--version"], { stdio: "inherit" });
@@ -10434,6 +10538,9 @@ class CloudScript extends script("cloud", [CloudRunner, ApplicationScript, Packa
10434
10538
  }
10435
10539
 
10436
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
+
10437
10544
  class CloudCommand extends command("cloud", [CloudScript], ({ public: target }) => ({
10438
10545
  login: target({ desc: "Login to Akan Cloud services" }).with(Workspace).exec(async function(workspace) {
10439
10546
  await this.cloudScript.login(workspace);
@@ -10450,15 +10557,32 @@ class CloudCommand extends command("cloud", [CloudScript], ({ public: target })
10450
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) {
10451
10558
  await this.cloudScript.ask(question, workspace);
10452
10559
  }),
10453
- 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) {
10454
- 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
+ });
10455
10572
  }),
10456
10573
  update: target({ desc: "Update Akan.js framework to the latest version" }).with(Workspace).option("tag", String, {
10457
10574
  desc: "tag of the update",
10458
10575
  default: "latest",
10459
10576
  enum: ["latest", "dev", "canary", "beta", "rc", "alpha"]
10460
- }).exec(async function(workspace, tag) {
10461
- 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) });
10462
10586
  })
10463
10587
  })) {
10464
10588
  }
@@ -10484,14 +10608,14 @@ class GuidelinePrompt extends Prompter {
10484
10608
  async#getScanFilePaths(matchPattern, { avoidDirs = ["node_modules", ".next"], filterText } = {}) {
10485
10609
  const glob = new Bun.Glob(matchPattern);
10486
10610
  const paths = [];
10487
- for await (const path38 of glob.scan({ cwd: this.workspace.workspaceRoot, absolute: true })) {
10488
- 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)))
10489
10613
  continue;
10490
- const fileContent = await FileSys.readText(path38);
10614
+ const fileContent = await FileSys.readText(path39);
10491
10615
  const textFilter = filterText ? new RegExp(filterText) : null;
10492
10616
  if (filterText && !textFilter?.test(fileContent))
10493
10617
  continue;
10494
- paths.push(path38);
10618
+ paths.push(path39);
10495
10619
  }
10496
10620
  return paths;
10497
10621
  }
@@ -10786,6 +10910,147 @@ class LibraryCommand extends command("library", [LibraryScript], ({ public: targ
10786
10910
  })) {
10787
10911
  }
10788
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
+
10789
11054
  // pkgs/@akanjs/cli/module/module.command.ts
10790
11055
  import { lowerlize } from "akanjs/common";
10791
11056
 
@@ -11581,11 +11846,11 @@ class ScalarCommand extends command("scalar", [ScalarScript], ({ public: target
11581
11846
  }
11582
11847
 
11583
11848
  // pkgs/@akanjs/cli/workspace/workspace.script.ts
11584
- import path39 from "path";
11585
- import { Logger as Logger17 } from "akanjs/common";
11849
+ import path41 from "path";
11850
+ import { Logger as Logger18 } from "akanjs/common";
11586
11851
 
11587
11852
  // pkgs/@akanjs/cli/workspace/workspace.runner.ts
11588
- import path38 from "path";
11853
+ import path40 from "path";
11589
11854
  var defaultWorkspacePeerDependencies = new Set([
11590
11855
  "@radix-ui/react-dialog",
11591
11856
  "@react-spring/web",
@@ -11605,20 +11870,29 @@ var defaultWorkspacePeerDependencies = new Set([
11605
11870
  ]);
11606
11871
 
11607
11872
  class WorkspaceRunner extends runner("workspace") {
11608
- 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
+ }) {
11609
11879
  const cwdPath = process.cwd();
11610
- const workspaceRoot = path38.join(cwdPath, dirname3, repoName);
11880
+ const workspaceRoot = path40.join(cwdPath, dirname3, repoName);
11881
+ const normalizedRegistryUrl = registryUrl ? getNpmRegistryUrl(registryUrl) : undefined;
11611
11882
  const workspace = WorkspaceExecutor.fromRoot({ workspaceRoot, repoName });
11612
11883
  const templateSpinner = workspace.spinning(`Creating workspace template files in ${dirname3}/${repoName}...`);
11613
11884
  const [latestBiomeVersion, latestTypesBunVersion] = await Promise.all([
11614
- getLatestPackageVersion("@biomejs/biome"),
11615
- getLatestPackageVersion("@types/bun")
11885
+ getLatestPackageVersion("@biomejs/biome", "latest", normalizedRegistryUrl),
11886
+ getLatestPackageVersion("@types/bun", "latest", normalizedRegistryUrl)
11616
11887
  ]);
11617
11888
  await workspace.applyTemplate({
11618
11889
  basePath: ".",
11619
11890
  template: "workspaceRoot",
11620
11891
  dict: { repoName, appName, serveDomain: "localhost" }
11621
11892
  });
11893
+ if (normalizedRegistryUrl)
11894
+ await workspace.writeFile(".npmrc", `registry=${normalizedRegistryUrl}/
11895
+ `);
11622
11896
  templateSpinner.succeed(`Workspace files created in ${dirname3}/${repoName}`);
11623
11897
  const [rootPackageJson, peerDependencies] = await Promise.all([
11624
11898
  workspace.getPackageJson(),
@@ -11659,9 +11933,9 @@ class WorkspaceRunner extends runner("workspace") {
11659
11933
  }
11660
11934
  async#getCliPackageJson() {
11661
11935
  const packageJsonCandidates = [
11662
- path38.join(import.meta.dir, "../package.json"),
11663
- path38.join(import.meta.dir, "package.json"),
11664
- 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")
11665
11939
  ];
11666
11940
  try {
11667
11941
  packageJsonCandidates.unshift(Bun.resolveSync("@akanjs/cli/package.json", import.meta.dir));
@@ -11677,9 +11951,9 @@ class WorkspaceRunner extends runner("workspace") {
11677
11951
  }
11678
11952
  async#getAkanPackageJson() {
11679
11953
  const packageJsonCandidates = [
11680
- path38.join(import.meta.dir, "../../../akanjs/package.json"),
11681
- path38.join(process.cwd(), "pkgs/akanjs/package.json"),
11682
- 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")
11683
11957
  ];
11684
11958
  try {
11685
11959
  packageJsonCandidates.unshift(Bun.resolveSync("akanjs/package.json", import.meta.dir));
@@ -11693,13 +11967,13 @@ class WorkspaceRunner extends runner("workspace") {
11693
11967
  }
11694
11968
  let current = import.meta.dir;
11695
11969
  for (let depth = 0;depth < 6; depth++) {
11696
- const packageJsonPath = path38.join(current, "package.json");
11970
+ const packageJsonPath = path40.join(current, "package.json");
11697
11971
  if (await Bun.file(packageJsonPath).exists()) {
11698
11972
  const packageJson = await FileSys.readJson(packageJsonPath);
11699
11973
  if (packageJson.name === "akanjs")
11700
11974
  return packageJson;
11701
11975
  }
11702
- const parent = path38.dirname(current);
11976
+ const parent = path40.dirname(current);
11703
11977
  if (parent === current)
11704
11978
  break;
11705
11979
  current = parent;
@@ -11723,12 +11997,18 @@ class WorkspaceScript extends script("workspace", [
11723
11997
  LibraryScript,
11724
11998
  PackageScript
11725
11999
  ]) {
11726
- 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
+ }) {
11727
12006
  const akanVersion = await this.packageScript.version(null, { log: false });
11728
12007
  const workspace = await this.workspaceRunner.createWorkspace(repoName, appName, {
11729
12008
  dirname: dirname3,
11730
12009
  init,
11731
- akanVersion
12010
+ akanVersion,
12011
+ ...registryUrl ? { registryUrl } : {}
11732
12012
  });
11733
12013
  if (installLibs) {
11734
12014
  await this.libraryScript.installLibrary(workspace, "util");
@@ -11742,11 +12022,11 @@ class WorkspaceScript extends script("workspace", [
11742
12022
  } catch (_) {
11743
12023
  gitSpinner.fail("Git repository initialization failed. It's not fatal, you can commit manually");
11744
12024
  }
11745
- const workspacePath = path39.join(dirname3, repoName);
11746
- Logger17.rawLog(`
12025
+ const workspacePath = path41.join(dirname3, repoName);
12026
+ Logger18.rawLog(`
11747
12027
  \uD83C\uDF89 Welcome aboard! Workspace created in ${dirname3}/${repoName}`);
11748
- Logger17.rawLog(`\uD83D\uDE80 Run \`cd ${workspacePath} && akan start ${appName}\` to start the development server.`);
11749
- Logger17.rawLog(`
12028
+ Logger18.rawLog(`\uD83D\uDE80 Run \`cd ${workspacePath} && akan start ${appName}\` to start the development server.`);
12029
+ Logger18.rawLog(`
11750
12030
  \uD83D\uDC4B Happy coding!`);
11751
12031
  }
11752
12032
  async lint(exec2, workspace, { fix = true } = {}) {
@@ -11801,9 +12081,12 @@ class WorkspaceCommand extends command("workspace", [WorkspaceScript], ({ public
11801
12081
  }).option("init", Boolean, {
11802
12082
  desc: "Do you want to initialize the workspace? (Recommended)",
11803
12083
  default: true
11804
- }).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) {
11805
12088
  const appName = app || "app";
11806
- 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 } : {} });
11807
12090
  }),
11808
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) {
11809
12092
  await this.workspaceScript.lint(exec2, workspace, { fix });
@@ -11818,4 +12101,4 @@ class WorkspaceCommand extends command("workspace", [WorkspaceScript], ({ public
11818
12101
  }
11819
12102
 
11820
12103
  // pkgs/@akanjs/cli/index.ts
11821
- runCommands(WorkspaceCommand, ApplicationCommand, LibraryCommand, PackageCommand, ModuleCommand, PageCommand, CloudCommand, GuidelineCommand, ScalarCommand);
12104
+ runCommands(WorkspaceCommand, ApplicationCommand, LibraryCommand, LocalRegistryCommand, PackageCommand, ModuleCommand, PageCommand, CloudCommand, GuidelineCommand, ScalarCommand);