@akanjs/cli 2.1.0-rc.10 → 2.1.0-rc.12

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.
@@ -486,7 +486,18 @@ var DEFAULT_OPTIMIZE_IMPORTS = [
486
486
  var WORKSPACE_BARREL_FACETS = ["ui", "webkit", "common", "client", "server"];
487
487
  var SSR_RUNTIME_PACKAGES = ["react", "react-dom", "react-server-dom-webpack"];
488
488
  var NATIVE_RUNTIME_PACKAGES = ["sharp"];
489
- var AKAN_RUNTIME_PACKAGES = new Set([...SSR_RUNTIME_PACKAGES, ...NATIVE_RUNTIME_PACKAGES]);
489
+ var DEFAULT_BACKEND_RUNTIME_PACKAGES = ["croner"];
490
+ var DATABASE_MODE_RUNTIME_PACKAGES = {
491
+ single: [],
492
+ multiple: ["@libsql/client", "bullmq", "ioredis", "protobufjs"],
493
+ cluster: ["bullmq", "ioredis", "postgres", "protobufjs"]
494
+ };
495
+ var AKAN_RUNTIME_PACKAGES = new Set([
496
+ ...SSR_RUNTIME_PACKAGES,
497
+ ...NATIVE_RUNTIME_PACKAGES,
498
+ ...DEFAULT_BACKEND_RUNTIME_PACKAGES,
499
+ ...Object.values(DATABASE_MODE_RUNTIME_PACKAGES).flat()
500
+ ]);
490
501
  var DEFAULT_AKAN_IMAGE_CONFIG = {
491
502
  deviceSizes: [640, 750, 828, 1080, 1200, 1920, 2048, 3840],
492
503
  imageSizes: [32, 48, 64, 96, 128, 256, 384],
@@ -695,13 +706,22 @@ CMD [${command.map((c) => `"${c}"`).join(",")}]`;
695
706
  if (AKAN_RUNTIME_PACKAGES.has(lib))
696
707
  return akanPackageJson.dependencies?.[lib] ?? akanPackageJson.peerDependencies?.[lib];
697
708
  }
709
+ #getProductionRuntimePackages() {
710
+ return [
711
+ ...this.externalLibs,
712
+ ...SSR_RUNTIME_PACKAGES,
713
+ ...NATIVE_RUNTIME_PACKAGES,
714
+ ...DEFAULT_BACKEND_RUNTIME_PACKAGES,
715
+ ...DATABASE_MODE_RUNTIME_PACKAGES[this.defaultDatabaseMode]
716
+ ];
717
+ }
698
718
  getProductionPackageJson(data = {}) {
699
719
  return {
700
720
  name: this.app.name,
701
721
  description: this.app.name,
702
722
  version: "1.0.0",
703
723
  main: "./main.js",
704
- dependencies: Object.fromEntries([...new Set([...this.externalLibs, ...SSR_RUNTIME_PACKAGES, ...NATIVE_RUNTIME_PACKAGES])].map((lib) => {
724
+ dependencies: Object.fromEntries([...new Set(this.#getProductionRuntimePackages())].map((lib) => {
705
725
  const version = this.#resolveProductionDependencyVersion(lib);
706
726
  if (!version)
707
727
  throw new Error(`Dependency ${lib} not found in package.json`);
@@ -7173,6 +7193,14 @@ var SSR_RENDER_EXTERNALS = [
7173
7193
  "react-server-dom-webpack/client.node",
7174
7194
  "react-server-dom-webpack/client.browser"
7175
7195
  ];
7196
+ var AKAN_OPTIONAL_BACKEND_EXTERNALS = [
7197
+ "@libsql/client",
7198
+ "bullmq",
7199
+ "croner",
7200
+ "ioredis",
7201
+ "postgres",
7202
+ "protobufjs"
7203
+ ];
7176
7204
 
7177
7205
  class ApplicationBuildRunner {
7178
7206
  #app;
@@ -7241,7 +7269,9 @@ class ApplicationBuildRunner {
7241
7269
  }
7242
7270
  async#buildBackend() {
7243
7271
  const akanConfig2 = await this.#app.getConfig();
7244
- const backendExternals = [...new Set([...akanConfig2.externalLibs, ...SSR_RENDER_EXTERNALS])];
7272
+ const backendExternals = [
7273
+ ...new Set([...akanConfig2.externalLibs, ...SSR_RENDER_EXTERNALS, ...AKAN_OPTIONAL_BACKEND_EXTERNALS])
7274
+ ];
7245
7275
  const backendEntryPoints = [`${this.#app.cwdPath}/main.ts`, `${this.#app.cwdPath}/server.ts`];
7246
7276
  for (const entrypoint of backendEntryPoints) {
7247
7277
  if (!await Bun.file(entrypoint).exists())
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`);
@@ -7171,6 +7191,14 @@ var SSR_RENDER_EXTERNALS = [
7171
7191
  "react-server-dom-webpack/client.node",
7172
7192
  "react-server-dom-webpack/client.browser"
7173
7193
  ];
7194
+ var AKAN_OPTIONAL_BACKEND_EXTERNALS = [
7195
+ "@libsql/client",
7196
+ "bullmq",
7197
+ "croner",
7198
+ "ioredis",
7199
+ "postgres",
7200
+ "protobufjs"
7201
+ ];
7174
7202
 
7175
7203
  class ApplicationBuildRunner {
7176
7204
  #app;
@@ -7239,7 +7267,9 @@ class ApplicationBuildRunner {
7239
7267
  }
7240
7268
  async#buildBackend() {
7241
7269
  const akanConfig2 = await this.#app.getConfig();
7242
- 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
+ ];
7243
7273
  const backendEntryPoints = [`${this.#app.cwdPath}/main.ts`, `${this.#app.cwdPath}/server.ts`];
7244
7274
  for (const entrypoint of backendEntryPoints) {
7245
7275
  if (!await Bun.file(entrypoint).exists())
@@ -10256,17 +10286,21 @@ class PackageScript extends script("package", [PackageRunner]) {
10256
10286
  }
10257
10287
 
10258
10288
  // pkgs/@akanjs/cli/cloud/cloud.runner.ts
10289
+ import path38 from "path";
10259
10290
  import { confirm as confirm3 } from "@inquirer/prompts";
10260
10291
  import { Logger as Logger15, sleep } from "akanjs/common";
10261
10292
  import chalk7 from "chalk";
10262
10293
  import * as QRcode from "qrcode";
10263
10294
 
10264
10295
  // pkgs/@akanjs/cli/npmRegistry.ts
10265
- async function getLatestPackageVersion(packageName, tag = "latest") {
10266
- 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/, "@")}`;
10267
10301
  const res = await fetch(url);
10268
10302
  if (!res.ok)
10269
- throw new Error(`Failed to fetch ${packageName} metadata from npm registry`);
10303
+ throw new Error(`Failed to fetch ${packageName} metadata from ${registry}`);
10270
10304
  const metadata = await res.json();
10271
10305
  const version = metadata["dist-tags"]?.[tag];
10272
10306
  if (!version)
@@ -10276,6 +10310,24 @@ async function getLatestPackageVersion(packageName, tag = "latest") {
10276
10310
 
10277
10311
  // pkgs/@akanjs/cli/cloud/cloud.runner.ts
10278
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
+ }
10279
10331
  async login() {
10280
10332
  const config = await getHostConfig();
10281
10333
  const self = config.auth ? await getSelf(config.auth.token) : null;
@@ -10354,15 +10406,16 @@ ${chalk7.green("\u27A4")} Authentication Required`));
10354
10406
  const pkgs = await workspace.getPkgs();
10355
10407
  return pkgs.filter((pkg) => pkg === "akanjs" || pkg === "create-akan-workspace" || pkg.startsWith("@akanjs/"));
10356
10408
  }
10357
- async deployAkan(workspace, akanPkgs) {
10409
+ async deployAkan(workspace, akanPkgs, { registryUrl, confirmPublish = true, tag: distTag } = {}) {
10410
+ const registry = registryUrl ? getNpmRegistryUrl(registryUrl) : undefined;
10358
10411
  const akanPackageJson2 = await workspace.readJson("pkgs/akanjs/package.json");
10359
10412
  const [majorVersion, minorVersion, patchVersion, devPatchVersion] = akanPackageJson2.version.split(".");
10360
10413
  const isOfficialRelease = !devPatchVersion;
10361
10414
  const targetVersionPrefix = isOfficialRelease ? `${majorVersion}.${minorVersion}` : `${majorVersion}.${minorVersion}.${patchVersion}`;
10362
- const tag = isOfficialRelease ? "latest" : patchVersion.split("-").at(1) ?? "dev";
10415
+ const tag = distTag ?? (isOfficialRelease ? "latest" : patchVersion.split("-").at(1) ?? "dev");
10363
10416
  const getNextVersion = async (prefix, tag2) => {
10364
10417
  try {
10365
- const latestPublishedVersion2 = await getLatestPackageVersion("akanjs", tag2);
10418
+ const latestPublishedVersion2 = await getLatestPackageVersion("akanjs", tag2, registry);
10366
10419
  const latestPatch = latestPublishedVersion2.startsWith(prefix) ? parseInt(latestPublishedVersion2.split(".").at(-1) ?? "-1") : -1;
10367
10420
  const nextVersion2 = `${prefix}.${latestPatch + 1}`;
10368
10421
  return { nextVersion: nextVersion2, latestPublishedVersion: latestPublishedVersion2 };
@@ -10375,37 +10428,46 @@ ${chalk7.green("\u27A4")} Authentication Required`));
10375
10428
  Logger15.info(`Next version of akanjs: ${nextVersion}`);
10376
10429
  for (const library of akanPkgs) {
10377
10430
  const packageJson = await workspace.readJson(`pkgs/${library}/package.json`);
10378
- const newPackageJsonStr = JSON.stringify({ ...packageJson, version: nextVersion }, null, 2);
10431
+ const newPackageJsonStr = JSON.stringify(this.#normalizeAkanPackageJson(packageJson, library, nextVersion), null, 2);
10379
10432
  await workspace.writeFile(`pkgs/${library}/package.json`, newPackageJsonStr);
10380
10433
  const distPackageJson = await workspace.readJson(`dist/pkgs/${library}/package.json`);
10381
- const newDistPackageJson = { ...distPackageJson, version: nextVersion };
10434
+ const newDistPackageJson = this.#normalizeAkanPackageJson(distPackageJson, library, nextVersion);
10382
10435
  await workspace.writeJson(`dist/pkgs/${library}/package.json`, newDistPackageJson);
10383
10436
  }
10384
- const isDeployConfirmed = await confirm3({
10385
- message: "Are you sure you want to deploy the libraries?"
10386
- });
10387
- if (!isDeployConfirmed) {
10388
- Logger15.error("Deployment cancelled");
10389
- 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
+ }
10390
10445
  }
10391
10446
  await Promise.all(akanPkgs.map(async (library) => {
10392
- Logger15.info(`Publishing ${library}@${nextVersion} to npm...`);
10393
- await workspace.exec(`npm publish --tag ${tag}`, { cwd: `dist/pkgs/${library}` });
10394
- 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"}`);
10395
10454
  }));
10396
- Logger15.info("All libraries are published to npm");
10455
+ Logger15.info(`All libraries are published to ${registry ?? "npm"}`);
10397
10456
  }
10398
- 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);
10399
10461
  if (!await workspace.exists("package.json"))
10400
- await workspace.spawn("bun", ["update", "-g", "akanjs", "--latest", `--tag=${tag}`]);
10462
+ await workspace.spawn("bun", ["update", "-g", "akanjs", "--latest", `--tag=${tag}`, ...registryArgs], { env });
10401
10463
  else
10402
10464
  await Promise.all([
10403
- workspace.spawn("bun", ["update", "-g", "akanjs", "--latest", `--tag=${tag}`]),
10404
- this.#updateAkanPkgs(workspace, tag)
10465
+ workspace.spawn("bun", ["update", "-g", "akanjs", "--latest", `--tag=${tag}`, ...registryArgs], { env }),
10466
+ this.#updateAkanPkgs(workspace, tag, registry)
10405
10467
  ]);
10406
10468
  }
10407
- async#updateAkanPkgs(workspace, tag = "latest") {
10408
- const latestPublishedVersion = await getLatestPackageVersion("akanjs", tag);
10469
+ async#updateAkanPkgs(workspace, tag = "latest", registryUrl) {
10470
+ const latestPublishedVersion = await getLatestPackageVersion("akanjs", tag, registryUrl);
10409
10471
  const rootPackageJson = await workspace.getPackageJson();
10410
10472
  if (!rootPackageJson.dependencies)
10411
10473
  throw new Error("No dependencies found in package.json");
@@ -10417,8 +10479,23 @@ ${chalk7.green("\u27A4")} Authentication Required`));
10417
10479
  rootPackageJson.dependencies["@akanjs/devkit"] = latestPublishedVersion;
10418
10480
  if (rootPackageJson.devDependencies?.["@akanjs/devkit"])
10419
10481
  rootPackageJson.devDependencies["@akanjs/devkit"] = latestPublishedVersion;
10420
- workspace.setPackageJson(rootPackageJson);
10421
- 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;
10422
10499
  }
10423
10500
  }
10424
10501
 
@@ -10440,7 +10517,7 @@ class CloudScript extends script("cloud", [CloudRunner, ApplicationScript, Packa
10440
10517
  const session = new AiSession("general", { workspace, isContinued: true });
10441
10518
  await session.ask(question);
10442
10519
  }
10443
- async deployAkan(workspace, { test = true } = {}) {
10520
+ async deployAkan(workspace, { test = true, registryUrl } = {}) {
10444
10521
  const akanPkgs = await this.cloudRunner.getAkanPkgs(workspace);
10445
10522
  await this.packageScript.updateWorskpaceRootPackageJson(workspace);
10446
10523
  const pkgs = akanPkgs.map((pkgName) => PkgExecutor.from(workspace, pkgName));
@@ -10449,11 +10526,11 @@ class CloudScript extends script("cloud", [CloudRunner, ApplicationScript, Packa
10449
10526
  await this.applicationScript.test(pkg);
10450
10527
  for (const pkg of pkgs)
10451
10528
  await this.packageScript.buildPackage(pkg);
10452
- await this.cloudRunner.deployAkan(workspace, akanPkgs);
10529
+ await this.cloudRunner.deployAkan(workspace, akanPkgs, { registryUrl });
10453
10530
  }
10454
- async update(workspace, tag = "latest") {
10531
+ async update(workspace, tag = "latest", { registryUrl } = {}) {
10455
10532
  const spinner2 = workspace.spinning("Updating Akan.js packages and CLI...");
10456
- await this.cloudRunner.update(workspace, tag);
10533
+ await this.cloudRunner.update(workspace, tag, { registryUrl });
10457
10534
  spinner2.succeed("Akan.js packages and CLI updated, global version is below");
10458
10535
  Logger16.raw("> Akan version: ");
10459
10536
  await workspace.spawn("akan", ["--version"], { stdio: "inherit" });
@@ -10461,6 +10538,9 @@ class CloudScript extends script("cloud", [CloudRunner, ApplicationScript, Packa
10461
10538
  }
10462
10539
 
10463
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
+
10464
10544
  class CloudCommand extends command("cloud", [CloudScript], ({ public: target }) => ({
10465
10545
  login: target({ desc: "Login to Akan Cloud services" }).with(Workspace).exec(async function(workspace) {
10466
10546
  await this.cloudScript.login(workspace);
@@ -10477,15 +10557,32 @@ class CloudCommand extends command("cloud", [CloudScript], ({ public: target })
10477
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) {
10478
10558
  await this.cloudScript.ask(question, workspace);
10479
10559
  }),
10480
- 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) {
10481
- 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
+ });
10482
10572
  }),
10483
10573
  update: target({ desc: "Update Akan.js framework to the latest version" }).with(Workspace).option("tag", String, {
10484
10574
  desc: "tag of the update",
10485
10575
  default: "latest",
10486
10576
  enum: ["latest", "dev", "canary", "beta", "rc", "alpha"]
10487
- }).exec(async function(workspace, tag) {
10488
- 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) });
10489
10586
  })
10490
10587
  })) {
10491
10588
  }
@@ -10511,14 +10608,14 @@ class GuidelinePrompt extends Prompter {
10511
10608
  async#getScanFilePaths(matchPattern, { avoidDirs = ["node_modules", ".next"], filterText } = {}) {
10512
10609
  const glob = new Bun.Glob(matchPattern);
10513
10610
  const paths = [];
10514
- for await (const path38 of glob.scan({ cwd: this.workspace.workspaceRoot, absolute: true })) {
10515
- 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)))
10516
10613
  continue;
10517
- const fileContent = await FileSys.readText(path38);
10614
+ const fileContent = await FileSys.readText(path39);
10518
10615
  const textFilter = filterText ? new RegExp(filterText) : null;
10519
10616
  if (filterText && !textFilter?.test(fileContent))
10520
10617
  continue;
10521
- paths.push(path38);
10618
+ paths.push(path39);
10522
10619
  }
10523
10620
  return paths;
10524
10621
  }
@@ -10813,6 +10910,147 @@ class LibraryCommand extends command("library", [LibraryScript], ({ public: targ
10813
10910
  })) {
10814
10911
  }
10815
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
+
10816
11054
  // pkgs/@akanjs/cli/module/module.command.ts
10817
11055
  import { lowerlize } from "akanjs/common";
10818
11056
 
@@ -11608,11 +11846,11 @@ class ScalarCommand extends command("scalar", [ScalarScript], ({ public: target
11608
11846
  }
11609
11847
 
11610
11848
  // pkgs/@akanjs/cli/workspace/workspace.script.ts
11611
- import path39 from "path";
11612
- import { Logger as Logger17 } from "akanjs/common";
11849
+ import path41 from "path";
11850
+ import { Logger as Logger18 } from "akanjs/common";
11613
11851
 
11614
11852
  // pkgs/@akanjs/cli/workspace/workspace.runner.ts
11615
- import path38 from "path";
11853
+ import path40 from "path";
11616
11854
  var defaultWorkspacePeerDependencies = new Set([
11617
11855
  "@radix-ui/react-dialog",
11618
11856
  "@react-spring/web",
@@ -11632,20 +11870,29 @@ var defaultWorkspacePeerDependencies = new Set([
11632
11870
  ]);
11633
11871
 
11634
11872
  class WorkspaceRunner extends runner("workspace") {
11635
- 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
+ }) {
11636
11879
  const cwdPath = process.cwd();
11637
- const workspaceRoot = path38.join(cwdPath, dirname3, repoName);
11880
+ const workspaceRoot = path40.join(cwdPath, dirname3, repoName);
11881
+ const normalizedRegistryUrl = registryUrl ? getNpmRegistryUrl(registryUrl) : undefined;
11638
11882
  const workspace = WorkspaceExecutor.fromRoot({ workspaceRoot, repoName });
11639
11883
  const templateSpinner = workspace.spinning(`Creating workspace template files in ${dirname3}/${repoName}...`);
11640
11884
  const [latestBiomeVersion, latestTypesBunVersion] = await Promise.all([
11641
- getLatestPackageVersion("@biomejs/biome"),
11642
- getLatestPackageVersion("@types/bun")
11885
+ getLatestPackageVersion("@biomejs/biome", "latest", normalizedRegistryUrl),
11886
+ getLatestPackageVersion("@types/bun", "latest", normalizedRegistryUrl)
11643
11887
  ]);
11644
11888
  await workspace.applyTemplate({
11645
11889
  basePath: ".",
11646
11890
  template: "workspaceRoot",
11647
11891
  dict: { repoName, appName, serveDomain: "localhost" }
11648
11892
  });
11893
+ if (normalizedRegistryUrl)
11894
+ await workspace.writeFile(".npmrc", `registry=${normalizedRegistryUrl}/
11895
+ `);
11649
11896
  templateSpinner.succeed(`Workspace files created in ${dirname3}/${repoName}`);
11650
11897
  const [rootPackageJson, peerDependencies] = await Promise.all([
11651
11898
  workspace.getPackageJson(),
@@ -11686,9 +11933,9 @@ class WorkspaceRunner extends runner("workspace") {
11686
11933
  }
11687
11934
  async#getCliPackageJson() {
11688
11935
  const packageJsonCandidates = [
11689
- path38.join(import.meta.dir, "../package.json"),
11690
- path38.join(import.meta.dir, "package.json"),
11691
- 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")
11692
11939
  ];
11693
11940
  try {
11694
11941
  packageJsonCandidates.unshift(Bun.resolveSync("@akanjs/cli/package.json", import.meta.dir));
@@ -11704,9 +11951,9 @@ class WorkspaceRunner extends runner("workspace") {
11704
11951
  }
11705
11952
  async#getAkanPackageJson() {
11706
11953
  const packageJsonCandidates = [
11707
- path38.join(import.meta.dir, "../../../akanjs/package.json"),
11708
- path38.join(process.cwd(), "pkgs/akanjs/package.json"),
11709
- 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")
11710
11957
  ];
11711
11958
  try {
11712
11959
  packageJsonCandidates.unshift(Bun.resolveSync("akanjs/package.json", import.meta.dir));
@@ -11720,13 +11967,13 @@ class WorkspaceRunner extends runner("workspace") {
11720
11967
  }
11721
11968
  let current = import.meta.dir;
11722
11969
  for (let depth = 0;depth < 6; depth++) {
11723
- const packageJsonPath = path38.join(current, "package.json");
11970
+ const packageJsonPath = path40.join(current, "package.json");
11724
11971
  if (await Bun.file(packageJsonPath).exists()) {
11725
11972
  const packageJson = await FileSys.readJson(packageJsonPath);
11726
11973
  if (packageJson.name === "akanjs")
11727
11974
  return packageJson;
11728
11975
  }
11729
- const parent = path38.dirname(current);
11976
+ const parent = path40.dirname(current);
11730
11977
  if (parent === current)
11731
11978
  break;
11732
11979
  current = parent;
@@ -11750,12 +11997,18 @@ class WorkspaceScript extends script("workspace", [
11750
11997
  LibraryScript,
11751
11998
  PackageScript
11752
11999
  ]) {
11753
- 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
+ }) {
11754
12006
  const akanVersion = await this.packageScript.version(null, { log: false });
11755
12007
  const workspace = await this.workspaceRunner.createWorkspace(repoName, appName, {
11756
12008
  dirname: dirname3,
11757
12009
  init,
11758
- akanVersion
12010
+ akanVersion,
12011
+ ...registryUrl ? { registryUrl } : {}
11759
12012
  });
11760
12013
  if (installLibs) {
11761
12014
  await this.libraryScript.installLibrary(workspace, "util");
@@ -11769,11 +12022,11 @@ class WorkspaceScript extends script("workspace", [
11769
12022
  } catch (_) {
11770
12023
  gitSpinner.fail("Git repository initialization failed. It's not fatal, you can commit manually");
11771
12024
  }
11772
- const workspacePath = path39.join(dirname3, repoName);
11773
- Logger17.rawLog(`
12025
+ const workspacePath = path41.join(dirname3, repoName);
12026
+ Logger18.rawLog(`
11774
12027
  \uD83C\uDF89 Welcome aboard! Workspace created in ${dirname3}/${repoName}`);
11775
- Logger17.rawLog(`\uD83D\uDE80 Run \`cd ${workspacePath} && akan start ${appName}\` to start the development server.`);
11776
- Logger17.rawLog(`
12028
+ Logger18.rawLog(`\uD83D\uDE80 Run \`cd ${workspacePath} && akan start ${appName}\` to start the development server.`);
12029
+ Logger18.rawLog(`
11777
12030
  \uD83D\uDC4B Happy coding!`);
11778
12031
  }
11779
12032
  async lint(exec2, workspace, { fix = true } = {}) {
@@ -11828,9 +12081,12 @@ class WorkspaceCommand extends command("workspace", [WorkspaceScript], ({ public
11828
12081
  }).option("init", Boolean, {
11829
12082
  desc: "Do you want to initialize the workspace? (Recommended)",
11830
12083
  default: true
11831
- }).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) {
11832
12088
  const appName = app || "app";
11833
- 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 } : {} });
11834
12090
  }),
11835
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) {
11836
12092
  await this.workspaceScript.lint(exec2, workspace, { fix });
@@ -11845,4 +12101,4 @@ class WorkspaceCommand extends command("workspace", [WorkspaceScript], ({ public
11845
12101
  }
11846
12102
 
11847
12103
  // pkgs/@akanjs/cli/index.ts
11848
- runCommands(WorkspaceCommand, ApplicationCommand, LibraryCommand, PackageCommand, ModuleCommand, PageCommand, CloudCommand, GuidelineCommand, ScalarCommand);
12104
+ runCommands(WorkspaceCommand, ApplicationCommand, LibraryCommand, LocalRegistryCommand, PackageCommand, ModuleCommand, PageCommand, CloudCommand, GuidelineCommand, ScalarCommand);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@akanjs/cli",
3
- "version": "2.1.0-rc.10",
3
+ "version": "2.1.0-rc.12",
4
4
  "sourceType": "module",
5
5
  "type": "module",
6
6
  "publishConfig": {
@@ -34,7 +34,7 @@
34
34
  "@langchain/deepseek": "^1.0.26",
35
35
  "@langchain/openai": "^1.4.6",
36
36
  "@trapezedev/project": "^7.1.4",
37
- "akanjs": "2.1.0-rc.9",
37
+ "akanjs": "2.1.0-rc.12",
38
38
  "chalk": "^5.6.2",
39
39
  "commander": "^14.0.3",
40
40
  "daisyui": "^5.5.20",