@akanjs/cli 2.3.5-rc.9 → 2.3.6-rc.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
@@ -3938,6 +3938,36 @@ var createTunnel = async (service, { app, environment, port = service === "postg
3938
3938
  return `localhost:${port}`;
3939
3939
  };
3940
3940
 
3941
+ // pkgs/@akanjs/devkit/incrementalBuilder/devWatchBatch.ts
3942
+ var prepareDevWatchBatch = ({
3943
+ generation,
3944
+ batch,
3945
+ indexSync,
3946
+ changePlanner
3947
+ }) => {
3948
+ const files = [...new Set([...batch.files, ...indexSync.changedFiles])].sort();
3949
+ const kindSet = new Set(batch.kinds);
3950
+ if (indexSync.changedFiles.length > 0)
3951
+ kindSet.add("code");
3952
+ const kinds = [...kindSet];
3953
+ const expandedBatch = { files, kinds: kindSet };
3954
+ const devPlan = changePlanner.plan({
3955
+ generation,
3956
+ files,
3957
+ kinds,
3958
+ generatedFiles: indexSync.changedFiles
3959
+ });
3960
+ if (indexSync.errors.length > 0 && !devPlan.actions.includes("report-error")) {
3961
+ devPlan.actions = [...devPlan.actions, "report-error"].sort();
3962
+ }
3963
+ return {
3964
+ files,
3965
+ kinds,
3966
+ expandedBatch,
3967
+ event: { type: "invalidate", kinds, files, generation, devPlan },
3968
+ hasSyncErrors: indexSync.errors.length > 0
3969
+ };
3970
+ };
3941
3971
  // pkgs/@akanjs/devkit/incrementalBuilder/incrementalBuilder.host.ts
3942
3972
  import path8 from "path";
3943
3973
  import { Logger as Logger4 } from "akanjs/common";
@@ -3946,7 +3976,8 @@ var builderMsgTypeSet = new Set([
3946
3976
  "builder-ready",
3947
3977
  "invalidate",
3948
3978
  "css-updated",
3949
- "pages-updated"
3979
+ "pages-updated",
3980
+ "build-status"
3950
3981
  ]);
3951
3982
 
3952
3983
  class IncrementalBuilderHost {
@@ -4089,12 +4120,76 @@ var BUILDER_READY_TIMEOUT_MS = 15000;
4089
4120
  var BUILDER_START_MAX_ATTEMPTS = 3;
4090
4121
  var SOURCE_EXTS = new Set([".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs"]);
4091
4122
  var NON_SOURCE_EXT_RE = /\.(css|scss|sass|less|json|svg|png|jpe?g|webp|gif|avif|ico|woff2?|ttf|otf|mp3|mp4|wav|html)$/i;
4123
+ var SERVER_SUFFIXES = [".service.ts", ".document.ts"];
4124
+ var SHARED_SUFFIXES = [".constant.ts", ".dictionary.ts", ".signal.ts"];
4125
+ var RUNTIME_METADATA_BASENAMES = new Set(["dict.ts", "sig.ts", "useClient.ts", "useServer.ts"]);
4092
4126
  var GRAPH_IMPORT_KINDS = new Set([
4093
4127
  "import-statement",
4094
4128
  "require-call",
4095
4129
  "require-resolve",
4096
4130
  "dynamic-import"
4097
4131
  ]);
4132
+ var shouldRestartBackendByDevPlan = (message) => {
4133
+ if (!message.devPlan)
4134
+ return null;
4135
+ if (message.devPlan.actions.includes("report-error"))
4136
+ return false;
4137
+ return message.devPlan.actions.includes("restart-backend");
4138
+ };
4139
+ var shouldRestartDevHostByDevPlan = (message) => message.devPlan?.actions.includes("restart-dev-host") ?? message.kinds.includes("config");
4140
+ var RESTART_ROLE_ORDER = ["server", "shared", "barrel", "config"];
4141
+ var generationValue = (generation) => generation ?? -1;
4142
+ var isLegacyBackendFallbackFile = (file, workspaceRoot) => {
4143
+ const abs = path9.resolve(file);
4144
+ const ext = path9.extname(abs).toLowerCase();
4145
+ if (!SOURCE_EXTS.has(ext))
4146
+ return false;
4147
+ const rel = path9.relative(path9.resolve(workspaceRoot), abs);
4148
+ if (!rel || rel.startsWith("..") || path9.isAbsolute(rel))
4149
+ return false;
4150
+ const parts = rel.split(path9.sep).filter(Boolean);
4151
+ const [scope] = parts;
4152
+ if (scope !== "apps" && scope !== "libs" && scope !== "pkgs")
4153
+ return false;
4154
+ const base = path9.basename(abs);
4155
+ return parts.includes("srvkit") || parts.includes("common") || SERVER_SUFFIXES.some((suffix) => base.endsWith(suffix)) || SHARED_SUFFIXES.some((suffix) => base.endsWith(suffix)) || RUNTIME_METADATA_BASENAMES.has(base) || base === "main.ts" || base === "server.ts";
4156
+ };
4157
+ var shouldMarkBuildPhaseRecovered = (previousByPhase, status) => {
4158
+ const previous = previousByPhase.get(status.phase);
4159
+ return Boolean(previous && status.ok && !previous.ok && generationValue(status.generation) >= previous.generation);
4160
+ };
4161
+ var createBackendBuildStatus = ({
4162
+ generation,
4163
+ ok,
4164
+ files = [],
4165
+ message
4166
+ }) => ({
4167
+ generation,
4168
+ phase: "backend",
4169
+ ok,
4170
+ files,
4171
+ message
4172
+ });
4173
+ var backendRestartReasonFromMessage = (message) => {
4174
+ const roleSet = new Set;
4175
+ for (const role of message.devPlan?.roles ?? []) {
4176
+ if (role === "server" || role === "shared" || role === "barrel" || role === "config")
4177
+ roleSet.add(role);
4178
+ }
4179
+ return {
4180
+ generation: message.devPlan?.generation ?? message.generation,
4181
+ files: [...new Set(message.files)].sort(),
4182
+ roles: RESTART_ROLE_ORDER.filter((role) => roleSet.has(role))
4183
+ };
4184
+ };
4185
+ var mergeBackendRestartReasons = (current, next) => ({
4186
+ generation: generationValue(next.generation) >= generationValue(current?.generation) ? next.generation : current?.generation,
4187
+ files: [...new Set([...current?.files ?? [], ...next.files])].sort(),
4188
+ roles: RESTART_ROLE_ORDER.filter((role) => current?.roles.includes(role) || next.roles.includes(role))
4189
+ });
4190
+ var shouldReplaceLastGoodMessage = (current, next) => !current || generationValue(next.data.generation) >= generationValue(current.data.generation);
4191
+ var shouldQueueBuildStatusReplay = (backendReady, pendingReplayCount) => !backendReady || pendingReplayCount > 0;
4192
+ var buildStatusReplaySequence = (pendingReplay, latestByPhase) => [...pendingReplay, ...latestByPhase.values()];
4098
4193
 
4099
4194
  class BackendImportGraph {
4100
4195
  #app;
@@ -4105,6 +4200,7 @@ class BackendImportGraph {
4105
4200
  #jsxTranspiler = new Bun.Transpiler({ loader: "jsx" });
4106
4201
  #files = new Set;
4107
4202
  #ready = false;
4203
+ #lastRefreshSucceeded = false;
4108
4204
  constructor(app, logger) {
4109
4205
  this.#app = app;
4110
4206
  this.#logger = logger;
@@ -4112,6 +4208,9 @@ class BackendImportGraph {
4112
4208
  get ready() {
4113
4209
  return this.#ready;
4114
4210
  }
4211
+ get lastRefreshSucceeded() {
4212
+ return this.#lastRefreshSucceeded;
4213
+ }
4115
4214
  has(file) {
4116
4215
  return this.#files.has(path9.resolve(file));
4117
4216
  }
@@ -4120,10 +4219,12 @@ class BackendImportGraph {
4120
4219
  const files = await this.#build();
4121
4220
  this.#files = files;
4122
4221
  this.#ready = true;
4222
+ this.#lastRefreshSucceeded = true;
4123
4223
  this.#logger.verbose(`[backend-graph] scanned ${files.size} files`);
4124
4224
  return true;
4125
4225
  } catch (err) {
4126
4226
  this.#ready = this.#files.size > 0;
4227
+ this.#lastRefreshSucceeded = false;
4127
4228
  this.#logger.warn(`[backend-graph] scan failed; ${this.#ready ? "using previous graph" : "using fallback rules"}: ${err instanceof Error ? err.message : String(err)}`);
4128
4229
  return this.#ready;
4129
4230
  }
@@ -4210,9 +4311,13 @@ class AkanAppHost {
4210
4311
  #restartTimer = null;
4211
4312
  #backendRecoveryTimer = null;
4212
4313
  #backendRecoveryAttempts = 0;
4213
- #restartFiles = new Set;
4214
- #latestPagesUpdated = null;
4215
- #latestCssUpdated = null;
4314
+ #backendLifecycleState = "stopped";
4315
+ #pendingRestartReason = null;
4316
+ #backendStartStatus = null;
4317
+ #backendBuildStatusGeneration = 0;
4318
+ #lastGoodFrontend = {};
4319
+ #buildStatusByPhase = new Map;
4320
+ #pendingBuildStatusReplay = [];
4216
4321
  #builderMessageQueue = Promise.resolve();
4217
4322
  #backendGraph;
4218
4323
  constructor(app, { env, withInk = false }) {
@@ -4257,7 +4362,9 @@ class AkanAppHost {
4257
4362
  return "localhost";
4258
4363
  return await createTunnel(type, { app: this.app, environment });
4259
4364
  }
4260
- #startBackend() {
4365
+ #startBackend(startStatus = null) {
4366
+ this.#backendStartStatus = startStatus;
4367
+ this.#setBackendLifecycleState("starting");
4261
4368
  this.#backendReady = false;
4262
4369
  const backend = Bun.spawn(["bun", `apps/${this.app.name}/main.ts`], {
4263
4370
  cwd: this.app.workspace.workspaceRoot,
@@ -4269,6 +4376,8 @@ class AkanAppHost {
4269
4376
  if (msg.type === "backend-ready") {
4270
4377
  this.#backendReady = true;
4271
4378
  this.#backendRecoveryAttempts = 0;
4379
+ this.#setBackendLifecycleState("ready", `pid=${msg.pid}`);
4380
+ this.#recordBackendReadyStatus();
4272
4381
  this.logger.verbose(`backend ready pid=${msg.pid}`);
4273
4382
  this.#replayBuilderState();
4274
4383
  return;
@@ -4291,9 +4400,53 @@ class AkanAppHost {
4291
4400
  this.#backend = backend;
4292
4401
  this.logger.verbose(`backend spawned pid=${backend.pid}`);
4293
4402
  }
4403
+ #nextBackendBuildStatusGeneration(generation) {
4404
+ if (typeof generation === "number") {
4405
+ this.#backendBuildStatusGeneration = Math.max(this.#backendBuildStatusGeneration, generation);
4406
+ return generation;
4407
+ }
4408
+ this.#backendBuildStatusGeneration += 1;
4409
+ return this.#backendBuildStatusGeneration;
4410
+ }
4411
+ #recordBackendBuildStatus({
4412
+ generation,
4413
+ ok,
4414
+ files,
4415
+ message
4416
+ }) {
4417
+ const status = createBackendBuildStatus({
4418
+ generation: this.#nextBackendBuildStatusGeneration(generation),
4419
+ ok,
4420
+ files,
4421
+ message
4422
+ });
4423
+ this.#recordBuildStatus(status);
4424
+ return status;
4425
+ }
4426
+ #recordBackendReadyStatus() {
4427
+ const previous = this.#buildStatusByPhase.get("backend");
4428
+ const startStatus = this.#backendStartStatus;
4429
+ if (startStatus || previous?.ok === false) {
4430
+ const status = this.#recordBackendBuildStatus({
4431
+ generation: startStatus?.generation ?? previous?.generation,
4432
+ ok: true,
4433
+ files: startStatus?.files ?? previous?.files ?? [],
4434
+ message: "Backend ready"
4435
+ });
4436
+ this.#sendOrQueueBuildStatus(status);
4437
+ }
4438
+ this.#backendStartStatus = null;
4439
+ }
4440
+ #setBackendLifecycleState(next, detail) {
4441
+ if (this.#backendLifecycleState === next && !detail)
4442
+ return;
4443
+ const prev = this.#backendLifecycleState;
4444
+ this.#backendLifecycleState = next;
4445
+ this.logger.verbose(`[backend-lifecycle] ${prev} -> ${next}${detail ? ` ${detail}` : ""}`);
4446
+ }
4294
4447
  #sendToBackend(message) {
4295
4448
  if (!this.#backend || !this.#backendReady) {
4296
- if (message.type === "css-updated" || message.type === "pages-updated") {
4449
+ if (message.type === "css-updated" || message.type === "pages-updated" || message.type === "build-status") {
4297
4450
  this.logger.verbose(`backend is not ready; will replay ${message.type}`);
4298
4451
  return;
4299
4452
  }
@@ -4313,6 +4466,7 @@ class AkanAppHost {
4313
4466
  const backend = this.#backend;
4314
4467
  this.#plannedBackendStops.add(backend);
4315
4468
  this.#backendReady = false;
4469
+ this.#setBackendLifecycleState("stopping", `pid=${backend.pid}`);
4316
4470
  this.logger.verbose(`stopping backend pid=${backend.pid}`);
4317
4471
  try {
4318
4472
  backend.kill("SIGTERM");
@@ -4328,11 +4482,13 @@ class AkanAppHost {
4328
4482
  } finally {
4329
4483
  if (this.#backend === backend)
4330
4484
  this.#backend = null;
4485
+ this.#setBackendLifecycleState("stopped", `pid=${backend.pid}`);
4331
4486
  }
4332
4487
  }
4333
- #scheduleBackendRestart(files) {
4334
- for (const file of files)
4335
- this.#restartFiles.add(file);
4488
+ #scheduleBackendRestart(reason) {
4489
+ this.#pendingRestartReason = mergeBackendRestartReasons(this.#pendingRestartReason, reason);
4490
+ const pending = this.#pendingRestartReason;
4491
+ this.#setBackendLifecycleState("restart-pending", `generation=${pending.generation ?? "(unknown)"} files=${pending.files.length} roles=${pending.roles.join(",") || "(none)"}`);
4336
4492
  if (this.#backendRecoveryTimer) {
4337
4493
  clearTimeout(this.#backendRecoveryTimer);
4338
4494
  this.#backendRecoveryTimer = null;
@@ -4341,23 +4497,31 @@ class AkanAppHost {
4341
4497
  clearTimeout(this.#restartTimer);
4342
4498
  this.#restartTimer = setTimeout(() => {
4343
4499
  this.#restartTimer = null;
4344
- const changed = [...this.#restartFiles];
4345
- this.#restartFiles.clear();
4346
- this.#restartBackend(changed);
4500
+ const next = this.#pendingRestartReason;
4501
+ this.#pendingRestartReason = null;
4502
+ if (next)
4503
+ this.#restartBackend(next);
4347
4504
  }, BACKEND_RESTART_DEBOUNCE_MS);
4348
4505
  }
4349
- async#restartBackend(files) {
4350
- this.logger.verbose(`[backend-reload] restarting backend for ${files.length} file(s)`);
4506
+ async#restartBackend(reason) {
4507
+ this.logger.verbose(`[backend-reload] restarting backend generation=${reason.generation ?? "(unknown)"} files=${reason.files.length} roles=${reason.roles.join(",") || "(none)"}`);
4351
4508
  this.#backendRecoveryAttempts = 0;
4352
4509
  await Promise.all([this.#stopBackend(), this.#backendGraph.refresh()]);
4353
- this.#startBackend();
4510
+ this.#startBackend({ generation: reason.generation, files: reason.files });
4354
4511
  }
4355
4512
  #scheduleBackendRecovery(reason) {
4356
4513
  if (this.#backendRecoveryTimer || this.#backend)
4357
4514
  return;
4515
+ this.#setBackendLifecycleState("recovering", reason);
4358
4516
  const attempt = this.#backendRecoveryAttempts;
4359
4517
  const delay = Math.min(BACKEND_RECOVERY_BASE_DELAY_MS * 2 ** attempt, BACKEND_RECOVERY_MAX_DELAY_MS);
4360
4518
  this.#backendRecoveryAttempts = attempt + 1;
4519
+ const failureStatus = this.#recordBackendBuildStatus({
4520
+ ok: false,
4521
+ files: [],
4522
+ message: `Backend exited unexpectedly (${reason}); restarting in ${delay}ms`
4523
+ });
4524
+ this.#sendOrQueueBuildStatus(failureStatus);
4361
4525
  this.logger.warn(`[backend-recovery] backend exited unexpectedly (${reason}); restarting in ${delay}ms (attempt ${this.#backendRecoveryAttempts})`);
4362
4526
  this.#backendRecoveryTimer = setTimeout(() => {
4363
4527
  this.#backendRecoveryTimer = null;
@@ -4365,7 +4529,7 @@ class AkanAppHost {
4365
4529
  return;
4366
4530
  this.#backendGraph.refresh().finally(() => {
4367
4531
  if (!this.#backend)
4368
- this.#startBackend();
4532
+ this.#startBackend({ generation: failureStatus.generation, files: failureStatus.files });
4369
4533
  });
4370
4534
  }, delay);
4371
4535
  }
@@ -4375,10 +4539,15 @@ class AkanAppHost {
4375
4539
  });
4376
4540
  }
4377
4541
  async#handleBuilderMessage(message) {
4542
+ if (message.type === "build-status") {
4543
+ this.#recordBuildStatus(message.data);
4544
+ this.#sendOrQueueBuildStatus(message.data);
4545
+ return;
4546
+ }
4378
4547
  if (message.type === "pages-updated")
4379
- this.#latestPagesUpdated = message;
4548
+ this.#recordLastGood(message);
4380
4549
  if (message.type === "css-updated")
4381
- this.#latestCssUpdated = message;
4550
+ this.#recordLastGood(message);
4382
4551
  if (message.type === "invalidate") {
4383
4552
  await this.#handleInvalidate(message);
4384
4553
  return;
@@ -4386,26 +4555,97 @@ class AkanAppHost {
4386
4555
  this.#sendToBackend(message);
4387
4556
  }
4388
4557
  async#handleInvalidate(message) {
4558
+ if (shouldRestartDevHostByDevPlan(message)) {
4559
+ this.#recordDevHostRestartRequired(message);
4560
+ return;
4561
+ }
4389
4562
  if (await this.#shouldRestartBackend(message)) {
4390
- this.#scheduleBackendRestart(message.files);
4563
+ this.#scheduleBackendRestart(backendRestartReasonFromMessage(message));
4391
4564
  return;
4392
4565
  }
4393
4566
  this.#sendToBackend(message);
4394
4567
  }
4568
+ #recordLastGood(message) {
4569
+ if (message.type === "pages-updated") {
4570
+ if (!shouldReplaceLastGoodMessage(this.#lastGoodFrontend.pages, message))
4571
+ return;
4572
+ this.#lastGoodFrontend.pages = message;
4573
+ this.logger.verbose(`[last-good] pages generation=${message.data.generation ?? "(unknown)"} buildId=${message.data.buildId}`);
4574
+ return;
4575
+ }
4576
+ if (!shouldReplaceLastGoodMessage(this.#lastGoodFrontend.css, message))
4577
+ return;
4578
+ this.#lastGoodFrontend.css = message;
4579
+ this.logger.verbose(`[last-good] css generation=${message.data.generation ?? "(unknown)"} assets=${Object.keys(message.data.cssAssets).length}`);
4580
+ }
4581
+ #recordDevHostRestartRequired(message) {
4582
+ const generation = message.devPlan?.generation ?? message.generation;
4583
+ const detail = `generation=${generation ?? "(unknown)"} files=${message.files.length}`;
4584
+ this.logger.warn(`[dev-host] config change requires a manual restart until controlled dev-host restart is implemented (${detail})`);
4585
+ if (typeof generation === "number") {
4586
+ const status = {
4587
+ generation,
4588
+ phase: "scan",
4589
+ ok: false,
4590
+ files: message.files,
4591
+ message: "Config change requires restarting `akan start` to apply."
4592
+ };
4593
+ this.#recordBuildStatus(status);
4594
+ this.#sendOrQueueBuildStatus(status);
4595
+ }
4596
+ }
4597
+ #recordBuildStatus(status) {
4598
+ const recovered = shouldMarkBuildPhaseRecovered(this.#buildStatusByPhase, status);
4599
+ this.#buildStatusByPhase.set(status.phase, status);
4600
+ const label = `[build-status] generation=${status.generation} phase=${status.phase} ok=${status.ok} files=${status.files.length}`;
4601
+ if (status.ok)
4602
+ this.logger.verbose(`${label}${recovered ? " recovered=1" : ""}`);
4603
+ else
4604
+ this.logger.warn(`${label}${status.message ? ` message=${status.message}` : ""}`);
4605
+ }
4606
+ #sendOrQueueBuildStatus(status) {
4607
+ if (!this.#backend || shouldQueueBuildStatusReplay(this.#backendReady, this.#pendingBuildStatusReplay.length)) {
4608
+ this.#pendingBuildStatusReplay.push(status);
4609
+ this.logger.verbose(`backend is not ready; will replay build-status generation=${status.generation} phase=${status.phase}`);
4610
+ return;
4611
+ }
4612
+ this.#sendToBackend({ type: "build-status", data: status });
4613
+ }
4395
4614
  #replayBuilderState() {
4396
4615
  if (!this.#backendReady)
4397
4616
  return;
4398
- if (this.#latestCssUpdated)
4399
- this.#sendToBackend(this.#latestCssUpdated);
4400
- if (this.#latestPagesUpdated)
4401
- this.#sendToBackend(this.#latestPagesUpdated);
4617
+ if (this.#lastGoodFrontend.css)
4618
+ this.#sendToBackend(this.#lastGoodFrontend.css);
4619
+ if (this.#lastGoodFrontend.pages)
4620
+ this.#sendToBackend(this.#lastGoodFrontend.pages);
4621
+ const queuedStatuses = this.#pendingBuildStatusReplay.splice(0);
4622
+ for (const status of buildStatusReplaySequence(queuedStatuses, this.#buildStatusByPhase)) {
4623
+ this.#sendToBackend({ type: "build-status", data: status });
4624
+ }
4402
4625
  }
4403
4626
  async#shouldRestartBackend(message) {
4404
4627
  if (message.kinds.length === 1 && message.kinds[0] === "css")
4405
4628
  return false;
4406
- if (!this.#backendGraph.ready && message.kinds.includes("code"))
4629
+ if (message.devPlan) {
4630
+ const { generation, roles, actions, reasonByFile } = message.devPlan;
4631
+ this.logger.verbose(`[dev-plan] generation=${generation} roles=${roles.join(",") || "(none)"} actions=${actions.join(",") || "(none)"} reasons=${Object.keys(reasonByFile).length}`);
4632
+ const shouldRestart = shouldRestartBackendByDevPlan(message) ?? false;
4633
+ if (shouldRestart && message.kinds.includes("code"))
4634
+ await this.#backendGraph.refresh();
4635
+ return shouldRestart;
4636
+ }
4637
+ if (message.kinds.includes("code"))
4407
4638
  await this.#backendGraph.refresh();
4408
- return message.files.some((file) => this.#isBackendFile(file));
4639
+ if (message.files.some((file) => this.#isBackendFile(file)))
4640
+ return true;
4641
+ if (!this.#backendGraph.lastRefreshSucceeded) {
4642
+ const fallbackFiles = message.files.filter((file) => isLegacyBackendFallbackFile(file, this.app.workspace.workspaceRoot));
4643
+ if (fallbackFiles.length > 0) {
4644
+ this.logger.warn(`[backend-graph] using path-role fallback for legacy invalidate; restart files=${fallbackFiles.length}`);
4645
+ return true;
4646
+ }
4647
+ }
4648
+ return false;
4409
4649
  }
4410
4650
  #isBackendFile(file) {
4411
4651
  return this.#backendGraph.has(file);
@@ -4761,8 +5001,8 @@ Caused by: ${ApplicationBuildReporter.formatError(error.cause)}` : "";
4761
5001
  }
4762
5002
  }
4763
5003
  // pkgs/@akanjs/devkit/applicationBuildRunner.ts
4764
- import { mkdir as mkdir7, rm as rm2 } from "fs/promises";
4765
- import path33 from "path";
5004
+ import { mkdir as mkdir8, rm as rm3 } from "fs/promises";
5005
+ import path35 from "path";
4766
5006
 
4767
5007
  // pkgs/@akanjs/devkit/frontendBuild/allRoutesBuilder.ts
4768
5008
  import path20 from "path";
@@ -7230,9 +7470,292 @@ function getPageKeyBasePath(pageKey, basePaths) {
7230
7470
  const firstPublicSegment = segments.find((segment) => segment !== "[lang]" && !/^\(.+\)$/.test(segment));
7231
7471
  return firstPublicSegment && basePaths.includes(firstPublicSegment) ? firstPublicSegment : null;
7232
7472
  }
7233
- // pkgs/@akanjs/devkit/frontendBuild/fontOptimizer.ts
7234
- import { mkdir as mkdir6 } from "fs/promises";
7473
+ // pkgs/@akanjs/devkit/frontendBuild/devChangePlanner.ts
7235
7474
  import path25 from "path";
7475
+ var SOURCE_EXTS4 = new Set([".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs"]);
7476
+ var CONFIG_BASENAMES = new Set(["akan.config.ts", "bunfig.toml", "tsconfig.json", "package.json"]);
7477
+ var BARREL_FACETS = new Set(["common", "srvkit", "ui", "webkit"]);
7478
+ var CLIENT_SUFFIXES = [".Template.tsx", ".Unit.tsx", ".Util.tsx", ".View.tsx", ".Zone.tsx", ".store.ts"];
7479
+ var SHARED_SUFFIXES2 = [".constant.ts", ".dictionary.ts", ".signal.ts"];
7480
+ var SERVER_SUFFIXES2 = [".service.ts", ".document.ts"];
7481
+ var RUNTIME_METADATA_BASENAMES2 = new Set(["dict.ts", "sig.ts", "useClient.ts", "useServer.ts"]);
7482
+
7483
+ class DevChangePlanner {
7484
+ #workspaceRoot;
7485
+ constructor({ workspaceRoot }) {
7486
+ this.#workspaceRoot = path25.resolve(workspaceRoot);
7487
+ }
7488
+ plan({ generation, files, kinds, generatedFiles: generatedFiles2 = [] }) {
7489
+ const fileList = uniqueResolved([...files, ...generatedFiles2]);
7490
+ const generatedSet = new Set(generatedFiles2.map((file) => path25.resolve(file)));
7491
+ const kindSet = new Set(kinds);
7492
+ const roles = new Set;
7493
+ const actions = new Set;
7494
+ const reasonByFile = {};
7495
+ for (const kind of kindSet) {
7496
+ if (kind === "css") {
7497
+ roles.add("css");
7498
+ actions.add("rebuild-css");
7499
+ }
7500
+ if (kind === "config") {
7501
+ roles.add("config");
7502
+ actions.add("restart-dev-host");
7503
+ }
7504
+ }
7505
+ for (const file of fileList) {
7506
+ const reasons = new Set;
7507
+ const fileRoles = this.#rolesForFile(file, { isGenerated: generatedSet.has(path25.resolve(file)), reasons });
7508
+ for (const role of fileRoles)
7509
+ roles.add(role);
7510
+ if (reasons.size > 0)
7511
+ reasonByFile[path25.resolve(file)] = [...reasons].sort();
7512
+ }
7513
+ if (roles.has("barrel"))
7514
+ actions.add("sync-generated");
7515
+ if (roles.has("server") || roles.has("shared"))
7516
+ actions.add("restart-backend");
7517
+ if (roles.has("client") || roles.has("shared"))
7518
+ actions.add("rebuild-client");
7519
+ if (roles.has("css"))
7520
+ actions.add("rebuild-css");
7521
+ return {
7522
+ generation,
7523
+ files: fileList,
7524
+ generatedFiles: uniqueResolved(generatedFiles2),
7525
+ roles: [...roles].sort(),
7526
+ actions: [...actions].sort(),
7527
+ reasonByFile
7528
+ };
7529
+ }
7530
+ #rolesForFile(file, { isGenerated, reasons }) {
7531
+ const roles = new Set;
7532
+ const abs = path25.resolve(file);
7533
+ const base = path25.basename(abs);
7534
+ const ext = path25.extname(abs).toLowerCase();
7535
+ const isSource = SOURCE_EXTS4.has(ext);
7536
+ const rel = path25.relative(this.#workspaceRoot, abs);
7537
+ const parts = rel.split(path25.sep).filter(Boolean);
7538
+ if (CONFIG_BASENAMES.has(base)) {
7539
+ roles.add("config");
7540
+ reasons.add("config-file");
7541
+ }
7542
+ if (ext === ".css") {
7543
+ roles.add("css");
7544
+ reasons.add("css-file");
7545
+ }
7546
+ if (isGenerated || isSource && this.#isBarrelFacetChild(parts)) {
7547
+ roles.add("barrel");
7548
+ reasons.add(isGenerated ? "generated-index" : "barrel-facet-child");
7549
+ }
7550
+ if (isSource && this.#isServerBiased(abs, parts)) {
7551
+ roles.add("server");
7552
+ reasons.add("server-path");
7553
+ }
7554
+ if (isSource && this.#isClientBiased(abs, parts)) {
7555
+ roles.add("client");
7556
+ reasons.add("client-path");
7557
+ }
7558
+ if (isSource && this.#isSharedBiased(abs, parts)) {
7559
+ roles.add("shared");
7560
+ reasons.add("shared-path");
7561
+ }
7562
+ if (roles.has("server") && roles.has("client")) {
7563
+ roles.delete("server");
7564
+ roles.delete("client");
7565
+ roles.add("shared");
7566
+ reasons.add("server-client-overlap");
7567
+ }
7568
+ if (roles.size === 0 && SOURCE_EXTS4.has(ext) && this.#isWorkspaceSource(rel)) {
7569
+ roles.add("shared");
7570
+ reasons.add("workspace-source-fallback");
7571
+ }
7572
+ return roles;
7573
+ }
7574
+ #isServerBiased(abs, parts) {
7575
+ const base = path25.basename(abs);
7576
+ return parts.includes("srvkit") || SERVER_SUFFIXES2.some((suffix) => base.endsWith(suffix)) || base === "main.ts" || base === "server.ts";
7577
+ }
7578
+ #isClientBiased(abs, parts) {
7579
+ const base = path25.basename(abs);
7580
+ return parts.includes("ui") || parts.includes("webkit") || parts.includes("page") || CLIENT_SUFFIXES.some((suffix) => base.endsWith(suffix));
7581
+ }
7582
+ #isSharedBiased(abs, parts) {
7583
+ const base = path25.basename(abs);
7584
+ return parts.includes("common") || SHARED_SUFFIXES2.some((suffix) => base.endsWith(suffix)) || RUNTIME_METADATA_BASENAMES2.has(base);
7585
+ }
7586
+ #isBarrelFacetChild(parts) {
7587
+ if (parts.length < 4)
7588
+ return false;
7589
+ const [scope, , facet, child] = parts;
7590
+ if (scope !== "apps" && scope !== "libs")
7591
+ return false;
7592
+ if (!facet || !BARREL_FACETS.has(facet))
7593
+ return false;
7594
+ if (!child || child.startsWith(".") || child === "index.ts" || child === "index.tsx")
7595
+ return false;
7596
+ return true;
7597
+ }
7598
+ #isWorkspaceSource(rel) {
7599
+ if (!rel || rel.startsWith("..") || path25.isAbsolute(rel))
7600
+ return false;
7601
+ const [scope] = rel.split(path25.sep);
7602
+ return scope === "apps" || scope === "libs" || scope === "pkgs";
7603
+ }
7604
+ }
7605
+ var uniqueResolved = (files) => [...new Set(files.map((file) => path25.resolve(file)))].sort();
7606
+ // pkgs/@akanjs/devkit/frontendBuild/devGeneratedIndexSync.ts
7607
+ import { mkdir as mkdir6, readdir as readdir2, readFile, rm as rm2, stat as stat3, writeFile } from "fs/promises";
7608
+ import path26 from "path";
7609
+ var BARREL_FACETS2 = new Set(["common", "srvkit", "ui", "webkit"]);
7610
+ var FACET_SOURCE_FILE_RE = /\.(ts|tsx)$/;
7611
+ var FACET_EXCLUDED_FILE_RE = /(^index\.tsx?$|\.d\.ts$|\.(test|spec)\.(ts|tsx)$|\.css$|\.scss$|\.sass$)/;
7612
+ var MODULE_UI_TYPES = ["Template", "Unit", "Util", "View", "Zone"];
7613
+ var SERVICE_UI_TYPES = ["Util", "Zone"];
7614
+ var SCALAR_UI_TYPES = ["Template", "Unit"];
7615
+
7616
+ class DevGeneratedIndexSync {
7617
+ #workspaceRoot;
7618
+ constructor({ workspaceRoot }) {
7619
+ this.#workspaceRoot = path26.resolve(workspaceRoot);
7620
+ }
7621
+ async syncForBatch(files) {
7622
+ const indexPaths = new Set;
7623
+ const errors = [];
7624
+ for (const file of files) {
7625
+ const facetIndex = this.#facetIndexFor(file);
7626
+ if (facetIndex)
7627
+ indexPaths.add(facetIndex);
7628
+ const moduleIndex = await this.#moduleIndexForDirectoryEvent(file).catch((err) => {
7629
+ errors.push(`[generated-index] module detection failed for ${file}: ${formatError(err)}`);
7630
+ return null;
7631
+ });
7632
+ if (moduleIndex)
7633
+ indexPaths.add(moduleIndex);
7634
+ }
7635
+ const changedFiles = [];
7636
+ for (const indexPath of [...indexPaths].sort()) {
7637
+ try {
7638
+ const changed = await this.#syncIndex(indexPath);
7639
+ if (changed)
7640
+ changedFiles.push(indexPath);
7641
+ } catch (err) {
7642
+ errors.push(`[generated-index] sync failed for ${indexPath}: ${formatError(err)}`);
7643
+ }
7644
+ }
7645
+ return { changedFiles, errors };
7646
+ }
7647
+ #facetIndexFor(file) {
7648
+ const abs = path26.resolve(file);
7649
+ const rel = path26.relative(this.#workspaceRoot, abs);
7650
+ if (rel.startsWith("..") || path26.isAbsolute(rel))
7651
+ return null;
7652
+ const parts = rel.split(path26.sep).filter(Boolean);
7653
+ if (parts.length < 4)
7654
+ return null;
7655
+ const [scope, project, facet, child] = parts;
7656
+ if (scope !== "apps" && scope !== "libs" || !project || !facet || !BARREL_FACETS2.has(facet))
7657
+ return null;
7658
+ if (!child || child.startsWith(".") || child === "index.ts" || child === "index.tsx")
7659
+ return null;
7660
+ return path26.join(this.#workspaceRoot, scope, project, facet, "index.ts");
7661
+ }
7662
+ async#moduleIndexForDirectoryEvent(file) {
7663
+ const abs = path26.resolve(file);
7664
+ const rel = path26.relative(this.#workspaceRoot, abs);
7665
+ if (rel.startsWith("..") || path26.isAbsolute(rel))
7666
+ return null;
7667
+ const parts = rel.split(path26.sep).filter(Boolean);
7668
+ if (parts.length !== 4 && parts.length !== 5)
7669
+ return null;
7670
+ const [scope, project, libSegment, moduleSegment, scalarSegment] = parts;
7671
+ if (scope !== "apps" && scope !== "libs" || !project || libSegment !== "lib")
7672
+ return null;
7673
+ const isExistingDirectory = await stat3(abs).then((s) => s.isDirectory()).catch(() => false);
7674
+ const looksLikeDeletedDirectory = !path26.extname(abs);
7675
+ if (!isExistingDirectory && !looksLikeDeletedDirectory)
7676
+ return null;
7677
+ if (moduleSegment === "__scalar" && scalarSegment) {
7678
+ return path26.join(this.#workspaceRoot, scope, project, "lib", "__scalar", scalarSegment, "index.ts");
7679
+ }
7680
+ if (!moduleSegment || moduleSegment === "__scalar")
7681
+ return null;
7682
+ return path26.join(this.#workspaceRoot, scope, project, "lib", moduleSegment, "index.ts");
7683
+ }
7684
+ async#syncIndex(indexPath) {
7685
+ const dir = path26.dirname(indexPath);
7686
+ const content = await this.#contentForIndex(indexPath);
7687
+ if (content === null) {
7688
+ if (!await exists(indexPath))
7689
+ return false;
7690
+ await rm2(indexPath, { force: true });
7691
+ return true;
7692
+ }
7693
+ const current = await readFile(indexPath, "utf8").catch(() => null);
7694
+ if (current === content)
7695
+ return false;
7696
+ await mkdir6(dir, { recursive: true });
7697
+ await writeFile(indexPath, content);
7698
+ return true;
7699
+ }
7700
+ async#contentForIndex(indexPath) {
7701
+ const parts = path26.relative(this.#workspaceRoot, indexPath).split(path26.sep).filter(Boolean);
7702
+ const facet = parts.at(-2);
7703
+ if (facet && BARREL_FACETS2.has(facet))
7704
+ return this.#facetContent(path26.dirname(indexPath));
7705
+ return this.#moduleContent(path26.dirname(indexPath));
7706
+ }
7707
+ async#facetContent(dir) {
7708
+ const entries = await readdir2(dir, { withFileTypes: true }).catch(() => []);
7709
+ const exportNames = entries.flatMap((entry) => {
7710
+ const name = entry.name;
7711
+ if (name.startsWith("."))
7712
+ return [];
7713
+ if (entry.isDirectory())
7714
+ return [name];
7715
+ if (!entry.isFile())
7716
+ return [];
7717
+ if (!FACET_SOURCE_FILE_RE.test(name) || FACET_EXCLUDED_FILE_RE.test(name))
7718
+ return [];
7719
+ return [name.replace(FACET_SOURCE_FILE_RE, "")];
7720
+ }).sort();
7721
+ if (exportNames.length === 0)
7722
+ return null;
7723
+ return `${exportNames.map((name) => `export * from "./${name}";`).join(`
7724
+ `)}
7725
+ `;
7726
+ }
7727
+ async#moduleContent(dir) {
7728
+ const rel = path26.relative(this.#workspaceRoot, dir);
7729
+ const parts = rel.split(path26.sep).filter(Boolean);
7730
+ const moduleSegment = parts.at(-1);
7731
+ if (!moduleSegment)
7732
+ return null;
7733
+ const isScalar = parts.at(-2) === "__scalar";
7734
+ const rawModel = moduleSegment.startsWith("_") ? moduleSegment.slice(1) : moduleSegment;
7735
+ if (!rawModel)
7736
+ return null;
7737
+ const modelName = capitalize3(rawModel);
7738
+ const allowedTypes = isScalar ? SCALAR_UI_TYPES : moduleSegment.startsWith("_") ? SERVICE_UI_TYPES : MODULE_UI_TYPES;
7739
+ const fileTypes = [];
7740
+ for (const type of allowedTypes) {
7741
+ if (await exists(path26.join(dir, `${modelName}.${type}.tsx`)))
7742
+ fileTypes.push(type);
7743
+ }
7744
+ if (fileTypes.length === 0)
7745
+ return null;
7746
+ return `
7747
+ ${fileTypes.map((type) => `import * as ${type} from "./${modelName}.${type}";`).join(`
7748
+ `)}
7749
+
7750
+ export const ${modelName} = { ${fileTypes.join(", ")} };`;
7751
+ }
7752
+ }
7753
+ var exists = async (file) => stat3(file).then(() => true).catch(() => false);
7754
+ var capitalize3 = (value) => `${value.charAt(0).toUpperCase()}${value.slice(1)}`;
7755
+ var formatError = (err) => err instanceof Error ? err.message : String(err);
7756
+ // pkgs/@akanjs/devkit/frontendBuild/fontOptimizer.ts
7757
+ import { mkdir as mkdir7 } from "fs/promises";
7758
+ import path27 from "path";
7236
7759
  import {
7237
7760
  generateFontFace,
7238
7761
  getMetricsForFamily,
@@ -7256,7 +7779,7 @@ class FontOptimizer {
7256
7779
  constructor(app, command = "start") {
7257
7780
  this.#app = app;
7258
7781
  this.#command = command;
7259
- this.#artifactRoot = path25.join(command === "build" ? app.dist.cwdPath : app.cwdPath, ".akan/artifact");
7782
+ this.#artifactRoot = path27.join(command === "build" ? app.dist.cwdPath : app.cwdPath, ".akan/artifact");
7260
7783
  }
7261
7784
  async optimize() {
7262
7785
  const fonts = await this.discoverFonts();
@@ -7275,7 +7798,7 @@ class FontOptimizer {
7275
7798
  const pageKeys = await this.#app.getPageKeys();
7276
7799
  const fonts = [];
7277
7800
  await Promise.all(pageKeys.map(async (key) => {
7278
- const filePath = path25.resolve(this.#app.cwdPath, "page", key);
7801
+ const filePath = path27.resolve(this.#app.cwdPath, "page", key);
7279
7802
  const file = Bun.file(filePath);
7280
7803
  if (!await file.exists())
7281
7804
  return;
@@ -7291,8 +7814,8 @@ class FontOptimizer {
7291
7814
  this.#app.logger.warn(`[font] source not found: ${face.src}`);
7292
7815
  continue;
7293
7816
  }
7294
- const outputPath = path25.join(this.#artifactRoot, face.optimizedSrc.replace(/^\/_akan\//, ""));
7295
- await mkdir6(path25.dirname(outputPath), { recursive: true });
7817
+ const outputPath = path27.join(this.#artifactRoot, face.optimizedSrc.replace(/^\/_akan\//, ""));
7818
+ await mkdir7(path27.dirname(outputPath), { recursive: true });
7296
7819
  const sourceBuffer = Buffer.from(await Bun.file(sourcePath).arrayBuffer());
7297
7820
  const outputBuffer = font.subset === false ? await this.#convertToWoff2(sourceBuffer, sourcePath) : await subsetFont(sourceBuffer, await this.#getSubsetText(font), { targetFormat: "woff2" });
7298
7821
  await Bun.write(outputPath, outputBuffer);
@@ -7439,8 +7962,8 @@ class FontOptimizer {
7439
7962
  return null;
7440
7963
  const rel = src.replace(/^\//, "");
7441
7964
  const candidates = [
7442
- this.#command === "build" ? path25.join(this.#app.dist.cwdPath, "public", rel) : null,
7443
- path25.join(this.#app.cwdPath, "public", rel),
7965
+ this.#command === "build" ? path27.join(this.#app.dist.cwdPath, "public", rel) : null,
7966
+ path27.join(this.#app.cwdPath, "public", rel),
7444
7967
  this.#resolveWorkspacePublicPath(rel)
7445
7968
  ].filter(Boolean);
7446
7969
  for (const candidate of candidates) {
@@ -7468,7 +7991,7 @@ class FontOptimizer {
7468
7991
  return "woff2";
7469
7992
  if (signature === "OTTO")
7470
7993
  return "otf";
7471
- const ext = path25.extname(sourcePath).slice(1).toLowerCase();
7994
+ const ext = path27.extname(sourcePath).slice(1).toLowerCase();
7472
7995
  if (ext === "otf" || ext === "woff" || ext === "woff2")
7473
7996
  return ext;
7474
7997
  return "ttf";
@@ -7477,7 +8000,7 @@ class FontOptimizer {
7477
8000
  const [root, dep, ...rest] = rel.split("/");
7478
8001
  if (root !== "libs" || !dep || rest.length === 0)
7479
8002
  return null;
7480
- return path25.join(this.#app.workspace.workspaceRoot, "libs", dep, "public", ...rest);
8003
+ return path27.join(this.#app.workspace.workspaceRoot, "libs", dep, "public", ...rest);
7481
8004
  }
7482
8005
  async#getSubsetText(font) {
7483
8006
  const parts = new Set;
@@ -7487,7 +8010,7 @@ class FontOptimizer {
7487
8010
  if (font.subsetText)
7488
8011
  parts.add(font.subsetText);
7489
8012
  for (const filePath of font.subsetFiles ?? []) {
7490
- const abs = path25.isAbsolute(filePath) ? filePath : path25.join(this.#app.cwdPath, filePath);
8013
+ const abs = path27.isAbsolute(filePath) ? filePath : path27.join(this.#app.cwdPath, filePath);
7491
8014
  const file = Bun.file(abs);
7492
8015
  if (await file.exists())
7493
8016
  parts.add(await file.text());
@@ -7506,7 +8029,7 @@ class FontOptimizer {
7506
8029
  return "";
7507
8030
  }
7508
8031
  async#collectAutoSubsetText() {
7509
- const roots = ["page", "ui"].map((dir) => path25.join(this.#app.cwdPath, dir));
8032
+ const roots = ["page", "ui"].map((dir) => path27.join(this.#app.cwdPath, dir));
7510
8033
  const glob = new Bun.Glob("**/*.{ts,tsx,js,jsx,html,md}");
7511
8034
  const parts = [];
7512
8035
  await Promise.all(roots.map(async (root) => {
@@ -7620,43 +8143,43 @@ ${declarations.map(([prop, value]) => ` ${prop}: ${value};`).join(`
7620
8143
  }
7621
8144
  }
7622
8145
  // pkgs/@akanjs/devkit/frontendBuild/hmrChangeClassifier.ts
7623
- import path26 from "path";
7624
- var SOURCE_EXTS4 = new Set([".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs"]);
8146
+ import path28 from "path";
8147
+ var SOURCE_EXTS5 = new Set([".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs"]);
7625
8148
  var CSS_EXTS = new Set([".css"]);
7626
- var CONFIG_BASENAMES = new Set(["akan.config.ts", "bunfig.toml", "tsconfig.json", "package.json"]);
8149
+ var CONFIG_BASENAMES2 = new Set(["akan.config.ts", "bunfig.toml", "tsconfig.json", "package.json"]);
7627
8150
 
7628
8151
  class HmrChangeClassifier {
7629
8152
  classify(abs) {
7630
8153
  if (this.#isUninteresting(abs))
7631
8154
  return "ignore";
7632
- const base = path26.basename(abs);
7633
- if (CONFIG_BASENAMES.has(base))
8155
+ const base = path28.basename(abs);
8156
+ if (CONFIG_BASENAMES2.has(base))
7634
8157
  return "config";
7635
- const ext = path26.extname(abs).toLowerCase();
8158
+ const ext = path28.extname(abs).toLowerCase();
7636
8159
  if (CSS_EXTS.has(ext))
7637
8160
  return "css";
7638
- if (SOURCE_EXTS4.has(ext))
8161
+ if (SOURCE_EXTS5.has(ext))
7639
8162
  return "code";
7640
8163
  return "ignore";
7641
8164
  }
7642
8165
  #isUninteresting(abs) {
7643
- const base = path26.basename(abs);
8166
+ const base = path28.basename(abs);
7644
8167
  if (!base)
7645
8168
  return true;
7646
8169
  if (base.startsWith("."))
7647
8170
  return true;
7648
8171
  if (base.endsWith("~") || base.endsWith(".swp") || base.endsWith(".swx") || base.endsWith(".tmp"))
7649
8172
  return true;
7650
- if (abs.includes(`${path26.sep}node_modules${path26.sep}`))
8173
+ if (abs.includes(`${path28.sep}node_modules${path28.sep}`))
7651
8174
  return true;
7652
- if (abs.includes(`${path26.sep}.akan${path26.sep}`))
8175
+ if (abs.includes(`${path28.sep}.akan${path28.sep}`))
7653
8176
  return true;
7654
8177
  return false;
7655
8178
  }
7656
8179
  }
7657
8180
  // pkgs/@akanjs/devkit/frontendBuild/hmrWatcher.ts
7658
8181
  import fs4 from "fs";
7659
- import path27 from "path";
8182
+ import path29 from "path";
7660
8183
  class HmrWatcher {
7661
8184
  #roots;
7662
8185
  #debounceMs;
@@ -7669,7 +8192,7 @@ class HmrWatcher {
7669
8192
  #stopped = false;
7670
8193
  #flushing = false;
7671
8194
  constructor(opts) {
7672
- this.#roots = [...new Set(opts.roots.map((r) => path27.resolve(r)))];
8195
+ this.#roots = [...new Set(opts.roots.map((r) => path29.resolve(r)))];
7673
8196
  this.#debounceMs = opts.debounceMs ?? 80;
7674
8197
  this.#onBatch = opts.onBatch;
7675
8198
  this.#logger = opts.logger;
@@ -7680,7 +8203,7 @@ class HmrWatcher {
7680
8203
  const w = fs4.watch(root, { recursive: true, persistent: false }, (_event, filename) => {
7681
8204
  if (!filename)
7682
8205
  return;
7683
- const abs = path27.resolve(root, filename.toString());
8206
+ const abs = path29.resolve(root, filename.toString());
7684
8207
  this.#queue(abs);
7685
8208
  });
7686
8209
  this.#watchers.push(w);
@@ -7738,10 +8261,10 @@ class HmrWatcher {
7738
8261
  }
7739
8262
  }
7740
8263
  // pkgs/@akanjs/devkit/frontendBuild/pagesBundleBuilder.ts
7741
- import path29 from "path";
8264
+ import path31 from "path";
7742
8265
 
7743
8266
  // pkgs/@akanjs/devkit/transforms/externalizeFrameworkPlugin.ts
7744
- import path28 from "path";
8267
+ import path30 from "path";
7745
8268
  var DEFAULT_INCLUDE = ["akanjs/", "@apps/", "@libs/"];
7746
8269
  var DEFAULT_EXCLUDE_EXACT = new Set(["akanjs/webkit", "@akanjs/cli", "@akanjs/devkit"]);
7747
8270
  var DEFAULT_EXCLUDE_PREFIX = ["@akanjs/cli/", "@akanjs/devkit/"];
@@ -7784,7 +8307,7 @@ async function createExternalizeFrameworkPlugin(options) {
7784
8307
  const replPath = repl?.endsWith("/*") ? repl.slice(0, -1) : repl ?? "";
7785
8308
  if (!replPath)
7786
8309
  continue;
7787
- const candidate = path28.resolve(workspaceRoot, replPath + suffix);
8310
+ const candidate = path30.resolve(workspaceRoot, replPath + suffix);
7788
8311
  const hit = await firstExisting(candidate);
7789
8312
  if (hit)
7790
8313
  return hit;
@@ -7796,8 +8319,8 @@ async function createExternalizeFrameworkPlugin(options) {
7796
8319
  if (spec === pkg)
7797
8320
  continue;
7798
8321
  const suffix = spec.slice(pkg.length + 1);
7799
- const pkgDir = path28.dirname(path28.resolve(workspaceRoot, entryFile));
7800
- const candidate = path28.join(pkgDir, suffix);
8322
+ const pkgDir = path30.dirname(path30.resolve(workspaceRoot, entryFile));
8323
+ const candidate = path30.join(pkgDir, suffix);
7801
8324
  const hit = await firstExisting(candidate);
7802
8325
  if (hit)
7803
8326
  return hit;
@@ -7847,7 +8370,7 @@ async function firstExisting(basePath2) {
7847
8370
  return candidate;
7848
8371
  }
7849
8372
  for (const ext of CANDIDATE_EXTS3) {
7850
- const candidate = path28.join(basePath2, `index${ext}`);
8373
+ const candidate = path30.join(basePath2, `index${ext}`);
7851
8374
  if (await Bun.file(candidate).exists())
7852
8375
  return candidate;
7853
8376
  }
@@ -7938,11 +8461,11 @@ class PagesBundleBuilder {
7938
8461
  const entryArtifact = result.outputs.find((a) => a.kind === "entry-point");
7939
8462
  if (!entryArtifact)
7940
8463
  throw new Error("[PagesBundleBuilder] Bun.build emitted no entry-point artifact");
7941
- const bundlePath = path29.resolve(entryArtifact.path);
8464
+ const bundlePath = path31.resolve(entryArtifact.path);
7942
8465
  const buildId = Date.now();
7943
8466
  const outputBytes = result.outputs.reduce((sum, output) => sum + output.size, 0);
7944
8467
  const chunkCount = result.outputs.filter((output) => output.kind === "chunk").length;
7945
- this.#app.verbose(`[PagesBundleBuilder] ${path29.basename(bundlePath)} emitted in ${Date.now() - this.#started}ms splitting=${this.#splitting} entry=${entryArtifact.size} bytes outputs=${result.outputs.length} chunks=${chunkCount} total=${outputBytes} bytes`);
8468
+ this.#app.verbose(`[PagesBundleBuilder] ${path31.basename(bundlePath)} emitted in ${Date.now() - this.#started}ms splitting=${this.#splitting} entry=${entryArtifact.size} bytes outputs=${result.outputs.length} chunks=${chunkCount} total=${outputBytes} bytes`);
7946
8469
  return {
7947
8470
  bundlePath,
7948
8471
  buildId,
@@ -8024,11 +8547,11 @@ function loaderFor4(absPath) {
8024
8547
  }
8025
8548
  // pkgs/@akanjs/devkit/frontendBuild/precompressArtifacts.ts
8026
8549
  import fs5 from "fs";
8027
- import path30 from "path";
8550
+ import path32 from "path";
8028
8551
  var COMPRESSIBLE_EXTS = new Set([".css", ".html", ".js", ".json", ".svg"]);
8029
8552
  var MIN_COMPRESS_BYTES = 1024;
8030
8553
  async function precompressArtifacts(app) {
8031
- const roots = [path30.join(app.dist.cwdPath, ".akan/artifact/client")];
8554
+ const roots = [path32.join(app.dist.cwdPath, ".akan/artifact/client")];
8032
8555
  const result = { files: 0, inputBytes: 0, outputBytes: 0 };
8033
8556
  await Promise.all(roots.map((root) => precompressRoot(root, result)));
8034
8557
  if (result.files > 0) {
@@ -8054,7 +8577,7 @@ async function precompressRoot(root, result) {
8054
8577
  async function shouldPrecompress(filePath) {
8055
8578
  if (filePath.endsWith(".gz"))
8056
8579
  return false;
8057
- if (!COMPRESSIBLE_EXTS.has(path30.extname(filePath).toLowerCase()))
8580
+ if (!COMPRESSIBLE_EXTS.has(path32.extname(filePath).toLowerCase()))
8058
8581
  return false;
8059
8582
  const file = Bun.file(filePath);
8060
8583
  if (!await file.exists())
@@ -8072,7 +8595,7 @@ function formatBytes(bytes) {
8072
8595
  return `${(bytes / 1024 / 1024).toFixed(1)}MB`;
8073
8596
  }
8074
8597
  // pkgs/@akanjs/devkit/frontendBuild/ssrBaseArtifactBuilder.ts
8075
- import path31 from "path";
8598
+ import path33 from "path";
8076
8599
  import { optimize } from "@tailwindcss/node";
8077
8600
  function prepareCssAsset(command, basePath2, cssText) {
8078
8601
  return optimize(cssText, { file: `${basePath2 || "root"}.css`, minify: command === "build" }).code;
@@ -8088,7 +8611,7 @@ class SsrBaseArtifactBuilder {
8088
8611
  this.#app = app;
8089
8612
  this.#command = command;
8090
8613
  this.#artifactDir = `${command === "build" ? app.dist.cwdPath : app.cwdPath}/.akan/artifact`;
8091
- this.#absArtifactDir = path31.resolve(this.#artifactDir);
8614
+ this.#absArtifactDir = path33.resolve(this.#artifactDir);
8092
8615
  }
8093
8616
  async build() {
8094
8617
  const akanConfig2 = await this.#app.getConfig();
@@ -8110,7 +8633,7 @@ class SsrBaseArtifactBuilder {
8110
8633
  rscRuntimeSsrManifest,
8111
8634
  vendorMap,
8112
8635
  cssAssets,
8113
- pagesBundlePath: this.#command === "build" ? path31.relative(this.#absArtifactDir, pagesBundle.bundlePath) : pagesBundle.bundlePath,
8636
+ pagesBundlePath: this.#command === "build" ? path33.relative(this.#absArtifactDir, pagesBundle.bundlePath) : pagesBundle.bundlePath,
8114
8637
  pagesBundleBuildId: pagesBundle.buildId,
8115
8638
  domains: [...akanConfig2.domains],
8116
8639
  subRoutes: Object.fromEntries(Array.from(akanConfig2.subRoutes.entries()).map(([basePath2, domains]) => [basePath2, [...domains]])),
@@ -8119,7 +8642,7 @@ class SsrBaseArtifactBuilder {
8119
8642
  i18n: akanConfig2.i18n,
8120
8643
  imageConfig: akanConfig2.images
8121
8644
  };
8122
- await Bun.write(path31.join(this.#absArtifactDir, "base-artifact.json"), `${JSON.stringify(artifact, null, 2)}
8645
+ await Bun.write(path33.join(this.#absArtifactDir, "base-artifact.json"), `${JSON.stringify(artifact, null, 2)}
8123
8646
  `);
8124
8647
  this.#app.verbose(`[base-artifact] complete in ${Date.now() - this.#started}ms`);
8125
8648
  return { artifact, seedIndex, cssCompiler, optimizedFonts };
@@ -8167,15 +8690,15 @@ class SsrBaseArtifactBuilder {
8167
8690
  async#resolveAkanServerPath() {
8168
8691
  const candidates = [];
8169
8692
  try {
8170
- candidates.push(path31.dirname(Bun.resolveSync("akanjs/server", this.#app.workspace.workspaceRoot)));
8693
+ candidates.push(path33.dirname(Bun.resolveSync("akanjs/server", this.#app.workspace.workspaceRoot)));
8171
8694
  } catch {}
8172
- candidates.push(path31.join(this.#app.workspace.workspaceRoot, "pkgs/akanjs/server"), path31.join(this.#app.workspace.workspaceRoot, "node_modules/akanjs/server"));
8695
+ candidates.push(path33.join(this.#app.workspace.workspaceRoot, "pkgs/akanjs/server"), path33.join(this.#app.workspace.workspaceRoot, "node_modules/akanjs/server"));
8173
8696
  try {
8174
- candidates.push(path31.dirname(Bun.resolveSync("akanjs/server", path31.dirname(Bun.main))));
8697
+ candidates.push(path33.dirname(Bun.resolveSync("akanjs/server", path33.dirname(Bun.main))));
8175
8698
  } catch {}
8176
- candidates.push(path31.join(path31.dirname(Bun.main), "node_modules/akanjs/server"), path31.join(path31.dirname(Bun.main), "../../akanjs/server"), path31.resolve(import.meta.dir, "../../server"), path31.resolve(import.meta.dir, "../server"));
8699
+ candidates.push(path33.join(path33.dirname(Bun.main), "node_modules/akanjs/server"), path33.join(path33.dirname(Bun.main), "../../akanjs/server"), path33.resolve(import.meta.dir, "../../server"), path33.resolve(import.meta.dir, "../server"));
8177
8700
  for (const candidate of candidates) {
8178
- if (await Bun.file(path31.join(candidate, "rscClient.tsx")).exists())
8701
+ if (await Bun.file(path33.join(candidate, "rscClient.tsx")).exists())
8179
8702
  return candidate;
8180
8703
  }
8181
8704
  throw new Error(`[base-artifact] failed to locate akanjs/server; looked in: ${candidates.join(", ")}`);
@@ -8204,14 +8727,14 @@ ${preparedCssText}`).toString(36);
8204
8727
  `styles/${cssAssetName}-${cssHash}.css`,
8205
8728
  `/_akan/styles/${cssAssetName}-${cssHash}.css`
8206
8729
  ];
8207
- await Bun.write(path31.join(this.#absArtifactDir, cssRelPath), preparedCssText);
8730
+ await Bun.write(path33.join(this.#absArtifactDir, cssRelPath), preparedCssText);
8208
8731
  this.#app.verbose(`[base-artifact] wrote ${preparedCssText.length} bytes of CSS for ${basePath2} -> ${cssRelPath}`);
8209
8732
  return [basePath2, { cssUrl, cssRelPath }];
8210
8733
  }
8211
8734
  }
8212
8735
  // pkgs/@akanjs/devkit/frontendBuild/watchRootResolver.ts
8213
8736
  import fs6 from "fs";
8214
- import path32 from "path";
8737
+ import path34 from "path";
8215
8738
 
8216
8739
  class WatchRootResolver {
8217
8740
  #app;
@@ -8221,15 +8744,15 @@ class WatchRootResolver {
8221
8744
  async resolve() {
8222
8745
  const tsconfig = await this.#app.getTsConfig();
8223
8746
  const set = new Set;
8224
- set.add(path32.resolve(`${this.#app.cwdPath}/page`));
8747
+ set.add(path34.resolve(`${this.#app.cwdPath}/page`));
8225
8748
  for (const targets of Object.values(tsconfig.compilerOptions.paths ?? {})) {
8226
8749
  for (const target of targets) {
8227
8750
  if (!target)
8228
8751
  continue;
8229
- if (path32.isAbsolute(target))
8752
+ if (path34.isAbsolute(target))
8230
8753
  continue;
8231
8754
  const cleaned = target.replace(/\/?\*+.*$/, "").replace(/\/[^/]+\.[^/]+$/, "");
8232
- const resolved = path32.resolve(this.#app.workspace.workspaceRoot, cleaned);
8755
+ const resolved = path34.resolve(this.#app.workspace.workspaceRoot, cleaned);
8233
8756
  if (fs6.existsSync(resolved))
8234
8757
  set.add(resolved);
8235
8758
  }
@@ -8296,7 +8819,7 @@ class ApplicationBuildRunner {
8296
8819
  phases: this.#phases,
8297
8820
  durationMs: Date.now() - this.#startedAt,
8298
8821
  outputDir: this.#app.dist.cwdPath,
8299
- artifactDir: path33.join(this.#app.dist.cwdPath, ".akan/artifact")
8822
+ artifactDir: path35.join(this.#app.dist.cwdPath, ".akan/artifact")
8300
8823
  };
8301
8824
  }
8302
8825
  async typecheck(options = {}) {
@@ -8304,7 +8827,7 @@ class ApplicationBuildRunner {
8304
8827
  await this.#app.getPageKeys({ refresh: true });
8305
8828
  const { typecheckDir, tsconfigPath } = await this.#writeTypecheckTsconfig({ incremental });
8306
8829
  if (clean)
8307
- await rm2(path33.join(typecheckDir, "tsconfig.tsbuildinfo"), { force: true });
8830
+ await rm3(path35.join(typecheckDir, "tsconfig.tsbuildinfo"), { force: true });
8308
8831
  await this.#checkProjectInChildProcess(tsconfigPath);
8309
8832
  }
8310
8833
  async#runPhase(id, label, task, summarize, options = {}) {
@@ -8376,7 +8899,7 @@ class ApplicationBuildRunner {
8376
8899
  };
8377
8900
  }
8378
8901
  async#writeConsoleShim() {
8379
- await Bun.write(path33.join(this.#app.dist.cwdPath, "console.js"), `import { cnst, db, dict, option, server, sig, srv } from "./server.js";
8902
+ await Bun.write(path35.join(this.#app.dist.cwdPath, "console.js"), `import { cnst, db, dict, option, server, sig, srv } from "./server.js";
8380
8903
  import { assertAkanConsoleAllowed, startAkanConsole } from "./console-runtime.js";
8381
8904
 
8382
8905
  const run = async () => {
@@ -8399,14 +8922,14 @@ void run().catch((error) => {
8399
8922
  try {
8400
8923
  return Bun.resolveSync("akanjs/server/rsc-worker", import.meta.dir);
8401
8924
  } catch {
8402
- return path33.join(this.#app.workspace.workspaceRoot, "pkgs/akanjs/server/rscWorker.tsx");
8925
+ return path35.join(this.#app.workspace.workspaceRoot, "pkgs/akanjs/server/rscWorker.tsx");
8403
8926
  }
8404
8927
  }
8405
8928
  #resolveConsoleRuntimeBuildEntry() {
8406
8929
  try {
8407
- return path33.join(path33.dirname(Bun.resolveSync("akanjs/server", import.meta.dir)), "console.ts");
8930
+ return path35.join(path35.dirname(Bun.resolveSync("akanjs/server", import.meta.dir)), "console.ts");
8408
8931
  } catch {
8409
- return path33.join(this.#app.workspace.workspaceRoot, "pkgs/akanjs/server/console.ts");
8932
+ return path35.join(this.#app.workspace.workspaceRoot, "pkgs/akanjs/server/console.ts");
8410
8933
  }
8411
8934
  }
8412
8935
  async#buildCsr() {
@@ -8423,8 +8946,8 @@ void run().catch((error) => {
8423
8946
  return { base, allRoutes };
8424
8947
  }
8425
8948
  async#writeTypecheckTsconfig({ incremental = true } = {}) {
8426
- const typecheckDir = path33.join(this.#app.cwdPath, ".akan", "typecheck");
8427
- await mkdir7(typecheckDir, { recursive: true });
8949
+ const typecheckDir = path35.join(this.#app.cwdPath, ".akan", "typecheck");
8950
+ await mkdir8(typecheckDir, { recursive: true });
8428
8951
  const tsconfig = {
8429
8952
  extends: "../../tsconfig.json",
8430
8953
  compilerOptions: {
@@ -8442,7 +8965,7 @@ void run().catch((error) => {
8442
8965
  ],
8443
8966
  references: []
8444
8967
  };
8445
- const tsconfigPath = path33.join(typecheckDir, "tsconfig.json");
8968
+ const tsconfigPath = path35.join(typecheckDir, "tsconfig.json");
8446
8969
  await Bun.write(tsconfigPath, `${JSON.stringify(tsconfig, null, 2)}
8447
8970
  `);
8448
8971
  return { typecheckDir, tsconfigPath };
@@ -8468,10 +8991,10 @@ void run().catch((error) => {
8468
8991
  }
8469
8992
  async#resolveTypecheckWorkerEntry() {
8470
8993
  const candidates = [
8471
- path33.join(this.#app.workspace.workspaceRoot, "pkgs/@akanjs/devkit/typecheck/typecheck.proc.ts"),
8472
- path33.join(this.#app.workspace.workspaceRoot, "node_modules/@akanjs/devkit/typecheck/typecheck.proc.ts"),
8473
- path33.join(import.meta.dir, "typecheck.proc.js"),
8474
- path33.join(import.meta.dir, "typecheck.proc.ts")
8994
+ path35.join(this.#app.workspace.workspaceRoot, "pkgs/@akanjs/devkit/typecheck/typecheck.proc.ts"),
8995
+ path35.join(this.#app.workspace.workspaceRoot, "node_modules/@akanjs/devkit/typecheck/typecheck.proc.ts"),
8996
+ path35.join(import.meta.dir, "typecheck.proc.js"),
8997
+ path35.join(import.meta.dir, "typecheck.proc.ts")
8475
8998
  ];
8476
8999
  for (const candidate of candidates)
8477
9000
  if (await Bun.file(candidate).exists())
@@ -8504,7 +9027,7 @@ void run().catch((error) => {
8504
9027
  }
8505
9028
  }
8506
9029
  // pkgs/@akanjs/devkit/applicationReleasePackager.ts
8507
- import { cp, mkdir as mkdir8, rm as rm3 } from "fs/promises";
9030
+ import { cp, mkdir as mkdir9, rm as rm4 } from "fs/promises";
8508
9031
 
8509
9032
  // pkgs/@akanjs/devkit/uploadRelease.ts
8510
9033
  import { HttpClient as HttpClient2, Logger as Logger9 } from "akanjs/common";
@@ -8610,16 +9133,16 @@ class ApplicationReleasePackager {
8610
9133
  const platformVersion = akanConfig2.mobile.version;
8611
9134
  const buildRoot = `${this.#app.workspace.workspaceRoot}/releases/builds/${this.#app.name}`;
8612
9135
  if (await FileSys.dirExists(buildRoot))
8613
- await rm3(buildRoot, { recursive: true, force: true });
8614
- await mkdir8(buildRoot, { recursive: true });
9136
+ await rm4(buildRoot, { recursive: true, force: true });
9137
+ await mkdir9(buildRoot, { recursive: true });
8615
9138
  if (rebuild || !await FileSys.dirExists(`${this.#app.dist.cwdPath}/backend`))
8616
9139
  await this.#build();
8617
9140
  const buildVersion = `${platformVersion}-${buildNum}`;
8618
9141
  const buildPath = `${buildRoot}/${buildVersion}`;
8619
- await mkdir8(buildPath, { recursive: true });
9142
+ await mkdir9(buildPath, { recursive: true });
8620
9143
  await cp(`${this.#app.dist.cwdPath}/backend`, `${buildPath}/backend`, { recursive: true });
8621
9144
  await cp(this.#app.dist.cwdPath, buildRoot, { recursive: true });
8622
- await rm3(`${buildRoot}/frontend/.next`, { recursive: true, force: true });
9145
+ await rm4(`${buildRoot}/frontend/.next`, { recursive: true, force: true });
8623
9146
  await this.#app.workspace.spawn("tar", [
8624
9147
  "-zcf",
8625
9148
  `${this.#app.workspace.workspaceRoot}/releases/builds/${this.#app.name}-release.tar.gz`,
@@ -8639,7 +9162,7 @@ class ApplicationReleasePackager {
8639
9162
  `${this.#app.workspace.workspaceRoot}/releases/builds/${this.#app.name}-appBuild.zip`,
8640
9163
  "./csr"
8641
9164
  ]);
8642
- await rm3("./csr", { recursive: true, force: true });
9165
+ await rm4("./csr", { recursive: true, force: true });
8643
9166
  }
8644
9167
  async#writeSourceArchive({ readme }) {
8645
9168
  const sourceRoot = `${this.#app.workspace.workspaceRoot}/releases/sources/${this.#app.name}`;
@@ -8647,13 +9170,13 @@ class ApplicationReleasePackager {
8647
9170
  await cp(this.#app.dist.cwdPath, `${sourceRoot}/apps/${this.#app.name}`, { recursive: true });
8648
9171
  const libDeps = ["social", "shared", "platform", "util"];
8649
9172
  await Promise.all(libDeps.map((lib) => cp(`${this.#app.workspace.cwdPath}/libs/${lib}`, `${sourceRoot}/libs/${lib}`, { recursive: true })));
8650
- await Promise.all([".next", "ios", "android", "public/libs"].map(async (path34) => {
8651
- const targetPath = `${sourceRoot}/apps/${this.#app.name}/${path34}`;
9173
+ await Promise.all([".next", "ios", "android", "public/libs"].map(async (path36) => {
9174
+ const targetPath = `${sourceRoot}/apps/${this.#app.name}/${path36}`;
8652
9175
  if (await FileSys.dirExists(targetPath))
8653
- await rm3(targetPath, { recursive: true, force: true });
9176
+ await rm4(targetPath, { recursive: true, force: true });
8654
9177
  }));
8655
9178
  const syncPaths = [".husky", ".gitignore", "package.json"];
8656
- await Promise.all(syncPaths.map((path34) => cp(`${this.#app.workspace.cwdPath}/${path34}`, `${sourceRoot}/${path34}`, { recursive: true })));
9179
+ await Promise.all(syncPaths.map((path36) => cp(`${this.#app.workspace.cwdPath}/${path36}`, `${sourceRoot}/${path36}`, { recursive: true })));
8657
9180
  await this.#writeSourceTsconfig(sourceRoot, libDeps);
8658
9181
  await Bun.write(`${sourceRoot}/README.md`, readme);
8659
9182
  await this.#app.workspace.spawn("tar", [
@@ -8669,11 +9192,11 @@ class ApplicationReleasePackager {
8669
9192
  const maxRetry = 3;
8670
9193
  for (let i = 0;i < maxRetry; i++) {
8671
9194
  try {
8672
- await rm3(sourceRoot, { recursive: true, force: true });
9195
+ await rm4(sourceRoot, { recursive: true, force: true });
8673
9196
  } catch {}
8674
9197
  }
8675
9198
  }
8676
- await mkdir8(sourceRoot, { recursive: true });
9199
+ await mkdir9(sourceRoot, { recursive: true });
8677
9200
  }
8678
9201
  async#writeSourceTsconfig(sourceRoot, libDeps) {
8679
9202
  const tsconfig = await this.#app.workspace.readJson("tsconfig.json");
@@ -8744,20 +9267,20 @@ class ApplicationReleasePackager {
8744
9267
  }
8745
9268
  }
8746
9269
  // pkgs/@akanjs/devkit/applicationTestPreload.ts
8747
- import path34 from "path";
9270
+ import path36 from "path";
8748
9271
  var SIGNAL_TEST_PRELOAD_PATH = "test/signalTest.preload.ts";
8749
9272
  async function resolveSignalTestPreloadPath(target) {
8750
9273
  const candidates = [];
8751
9274
  const addResolvedPackageCandidate = (basePath2) => {
8752
9275
  try {
8753
- candidates.push(path34.join(path34.dirname(Bun.resolveSync("akanjs/package.json", basePath2)), SIGNAL_TEST_PRELOAD_PATH));
9276
+ candidates.push(path36.join(path36.dirname(Bun.resolveSync("akanjs/package.json", basePath2)), SIGNAL_TEST_PRELOAD_PATH));
8754
9277
  } catch {}
8755
9278
  };
8756
9279
  addResolvedPackageCandidate(target.cwdPath);
8757
9280
  addResolvedPackageCandidate(process.cwd());
8758
- addResolvedPackageCandidate(path34.dirname(Bun.main));
9281
+ addResolvedPackageCandidate(path36.dirname(Bun.main));
8759
9282
  addResolvedPackageCandidate(import.meta.dir);
8760
- candidates.push(path34.join(target.cwdPath, "../../node_modules/akanjs", SIGNAL_TEST_PRELOAD_PATH), path34.join(target.cwdPath, "../../pkgs/akanjs", SIGNAL_TEST_PRELOAD_PATH), path34.join(process.cwd(), "node_modules/akanjs", SIGNAL_TEST_PRELOAD_PATH), path34.join(process.cwd(), "pkgs/akanjs", SIGNAL_TEST_PRELOAD_PATH), path34.join(path34.dirname(Bun.main), "../../akanjs", SIGNAL_TEST_PRELOAD_PATH), path34.resolve(import.meta.dir, "../../akanjs", SIGNAL_TEST_PRELOAD_PATH));
9283
+ candidates.push(path36.join(target.cwdPath, "../../node_modules/akanjs", SIGNAL_TEST_PRELOAD_PATH), path36.join(target.cwdPath, "../../pkgs/akanjs", SIGNAL_TEST_PRELOAD_PATH), path36.join(process.cwd(), "node_modules/akanjs", SIGNAL_TEST_PRELOAD_PATH), path36.join(process.cwd(), "pkgs/akanjs", SIGNAL_TEST_PRELOAD_PATH), path36.join(path36.dirname(Bun.main), "../../akanjs", SIGNAL_TEST_PRELOAD_PATH), path36.resolve(import.meta.dir, "../../akanjs", SIGNAL_TEST_PRELOAD_PATH));
8761
9284
  for (const candidate of [...new Set(candidates)]) {
8762
9285
  if (await Bun.file(candidate).exists())
8763
9286
  return candidate;
@@ -8766,8 +9289,8 @@ async function resolveSignalTestPreloadPath(target) {
8766
9289
  }
8767
9290
  // pkgs/@akanjs/devkit/builder.ts
8768
9291
  import { existsSync as existsSync2 } from "fs";
8769
- import { mkdir as mkdir9 } from "fs/promises";
8770
- import path35 from "path";
9292
+ import { mkdir as mkdir10 } from "fs/promises";
9293
+ import path37 from "path";
8771
9294
  var SKIP_ENTRY_DIR_SET = new Set(["node_modules", "dist", "build", ".git", ".next"]);
8772
9295
  var assetExtensions = [".css", ".md", ".js", ".png", ".ico", ".svg", ".json", ".template"];
8773
9296
  var assetLoader = Object.fromEntries(assetExtensions.map((ext) => [ext, "file"]));
@@ -8784,14 +9307,14 @@ class Builder {
8784
9307
  #globEntrypoints(cwd, pattern) {
8785
9308
  const glob = new Bun.Glob(pattern);
8786
9309
  return Array.from(glob.scanSync({ cwd, onlyFiles: true })).filter((relativePath) => {
8787
- const segments = relativePath.split(path35.sep);
9310
+ const segments = relativePath.split(path37.sep);
8788
9311
  return !segments.some((segment) => SKIP_ENTRY_DIR_SET.has(segment));
8789
- }).map((rel) => path35.join(cwd, rel));
9312
+ }).map((rel) => path37.join(cwd, rel));
8790
9313
  }
8791
9314
  #globFiles(cwd, pattern = "**/*.*") {
8792
9315
  const glob = new Bun.Glob(pattern);
8793
9316
  return Array.from(glob.scanSync({ cwd, onlyFiles: true })).filter((relativePath) => {
8794
- const segments = relativePath.split(path35.sep);
9317
+ const segments = relativePath.split(path37.sep);
8795
9318
  return !segments.some((segment) => SKIP_ENTRY_DIR_SET.has(segment));
8796
9319
  });
8797
9320
  }
@@ -8799,17 +9322,17 @@ class Builder {
8799
9322
  const out = [];
8800
9323
  for (const p of additionalEntryPoints) {
8801
9324
  if (p.includes("*")) {
8802
- const rel = p.startsWith(`${cwd}/`) || p.startsWith(`${cwd}${path35.sep}`) ? p.slice(cwd.length + 1) : p;
9325
+ const rel = p.startsWith(`${cwd}/`) || p.startsWith(`${cwd}${path37.sep}`) ? p.slice(cwd.length + 1) : p;
8803
9326
  out.push(...this.#globEntrypoints(cwd, rel));
8804
9327
  } else
8805
- out.push(path35.isAbsolute(p) ? p : path35.join(cwd, p));
9328
+ out.push(path37.isAbsolute(p) ? p : path37.join(cwd, p));
8806
9329
  }
8807
9330
  return out;
8808
9331
  }
8809
9332
  #getBuildOptions({ bundle = false, additionalEntryPoints = [] } = {}) {
8810
9333
  const cwd = this.#executor.cwdPath;
8811
9334
  const entrypoints = [
8812
- ...bundle ? [path35.join(cwd, "index.ts")] : this.#globEntrypoints(cwd, "**/*.{ts,tsx}"),
9335
+ ...bundle ? [path37.join(cwd, "index.ts")] : this.#globEntrypoints(cwd, "**/*.{ts,tsx}"),
8813
9336
  ...this.#resolveAdditionalEntrypoints(cwd, additionalEntryPoints)
8814
9337
  ];
8815
9338
  return {
@@ -8830,9 +9353,9 @@ class Builder {
8830
9353
  for (const relativePath of this.#globFiles(cwd)) {
8831
9354
  if (relativePath === "package.json")
8832
9355
  continue;
8833
- const sourcePath = path35.join(cwd, relativePath);
8834
- const targetPath = path35.join(this.#distExecutor.cwdPath, relativePath);
8835
- await mkdir9(path35.dirname(targetPath), { recursive: true });
9356
+ const sourcePath = path37.join(cwd, relativePath);
9357
+ const targetPath = path37.join(this.#distExecutor.cwdPath, relativePath);
9358
+ await mkdir10(path37.dirname(targetPath), { recursive: true });
8836
9359
  await Bun.write(targetPath, Bun.file(sourcePath));
8837
9360
  }
8838
9361
  }
@@ -8843,13 +9366,13 @@ class Builder {
8843
9366
  return withoutFormatDir;
8844
9367
  if (!hasDotSlash && withoutFormatDir === publishedPath)
8845
9368
  return publishedPath;
8846
- const parsed = path35.posix.parse(withoutFormatDir);
9369
+ const parsed = path37.posix.parse(withoutFormatDir);
8847
9370
  if (![".js", ".mjs", ".cjs"].includes(parsed.ext))
8848
9371
  return withoutFormatDir;
8849
- const withoutExt = path35.posix.join(parsed.dir, parsed.name);
9372
+ const withoutExt = path37.posix.join(parsed.dir, parsed.name);
8850
9373
  const sourcePath = withoutExt.startsWith("./") ? withoutExt.slice(2) : withoutExt;
8851
9374
  const sourceCandidates = [`${sourcePath}.ts`, `${sourcePath}.tsx`];
8852
- const matchedSource = sourceCandidates.find((candidate) => existsSync2(path35.join(this.#executor.cwdPath, candidate)));
9375
+ const matchedSource = sourceCandidates.find((candidate) => existsSync2(path37.join(this.#executor.cwdPath, candidate)));
8853
9376
  if (!matchedSource)
8854
9377
  return withoutFormatDir;
8855
9378
  return hasDotSlash ? `./${matchedSource}` : matchedSource;
@@ -8898,10 +9421,10 @@ class Builder {
8898
9421
  }
8899
9422
  }
8900
9423
  // pkgs/@akanjs/devkit/capacitorApp.ts
8901
- import { cp as cp2, mkdir as mkdir10, rm as rm4 } from "fs/promises";
8902
- import path36 from "path";
9424
+ import { cp as cp2, mkdir as mkdir11, rm as rm5 } from "fs/promises";
9425
+ import path38 from "path";
8903
9426
  import { MobileProject } from "@trapezedev/project";
8904
- import { capitalize as capitalize3 } from "akanjs/common";
9427
+ import { capitalize as capitalize4 } from "akanjs/common";
8905
9428
 
8906
9429
  // pkgs/@akanjs/devkit/fileEditor.ts
8907
9430
  class FileEditor {
@@ -9094,10 +9617,10 @@ class CapacitorApp {
9094
9617
  constructor(app, target) {
9095
9618
  this.app = app;
9096
9619
  this.target = target;
9097
- this.targetRootPath = path36.posix.join(".akan", "mobile", this.target.name);
9098
- this.targetRoot = path36.join(this.app.cwdPath, this.targetRootPath);
9099
- this.targetWebRoot = path36.join(this.targetRoot, "www");
9100
- this.targetAssetRoot = path36.join(this.targetRoot, "assets");
9620
+ this.targetRootPath = path38.posix.join(".akan", "mobile", this.target.name);
9621
+ this.targetRoot = path38.join(this.app.cwdPath, this.targetRootPath);
9622
+ this.targetWebRoot = path38.join(this.targetRoot, "www");
9623
+ this.targetAssetRoot = path38.join(this.targetRoot, "assets");
9101
9624
  this.project = new MobileProject(this.app.cwdPath, {
9102
9625
  android: { path: this.androidRootPath },
9103
9626
  ios: { path: this.iosProjectPath }
@@ -9109,13 +9632,13 @@ class CapacitorApp {
9109
9632
  env = "debug",
9110
9633
  regenerate = false
9111
9634
  } = {}) {
9112
- await mkdir10(this.targetRoot, { recursive: true });
9635
+ await mkdir11(this.targetRoot, { recursive: true });
9113
9636
  await this.#writeCapacitorConfig();
9114
9637
  if (regenerate) {
9115
9638
  if (!platform || platform === "ios")
9116
- await rm4(path36.join(this.app.cwdPath, this.iosRootPath), { recursive: true, force: true });
9639
+ await rm5(path38.join(this.app.cwdPath, this.iosRootPath), { recursive: true, force: true });
9117
9640
  if (!platform || platform === "android")
9118
- await rm4(path36.join(this.app.cwdPath, this.androidRootPath), { recursive: true, force: true });
9641
+ await rm5(path38.join(this.app.cwdPath, this.androidRootPath), { recursive: true, force: true });
9119
9642
  }
9120
9643
  const project = this.project;
9121
9644
  await this.project.load();
@@ -9179,7 +9702,7 @@ class CapacitorApp {
9179
9702
  await this.#spawnMobile("npx", ["cap", "sync", "android"], { operation, env });
9180
9703
  }
9181
9704
  async#updateAndroidBuildTypes() {
9182
- const appGradle = await FileEditor.create(path36.join(this.app.cwdPath, this.androidRootPath, "app/build.gradle"));
9705
+ const appGradle = await FileEditor.create(path38.join(this.app.cwdPath, this.androidRootPath, "app/build.gradle"));
9183
9706
  const buildTypesBlock = `
9184
9707
  debug {
9185
9708
  applicationIdSuffix ".debug"
@@ -9222,7 +9745,7 @@ class CapacitorApp {
9222
9745
  const gradleCommand = isWindows ? "gradlew.bat" : "./gradlew";
9223
9746
  await this.app.spawn(gradleCommand, [assembleType === "apk" ? "assembleRelease" : "bundleRelease"], {
9224
9747
  stdio: "inherit",
9225
- cwd: path36.join(this.app.cwdPath, this.androidRootPath),
9748
+ cwd: path38.join(this.app.cwdPath, this.androidRootPath),
9226
9749
  env: await this.#commandEnv("release", env)
9227
9750
  });
9228
9751
  }
@@ -9230,10 +9753,10 @@ class CapacitorApp {
9230
9753
  await this.#spawnMobile("npx", ["cap", "open", "android"], { operation: "local", env: "local" });
9231
9754
  }
9232
9755
  async#ensureAndroidAssetsDir() {
9233
- await mkdir10(path36.join(this.app.cwdPath, this.androidAssetsPath), { recursive: true });
9756
+ await mkdir11(path38.join(this.app.cwdPath, this.androidAssetsPath), { recursive: true });
9234
9757
  }
9235
9758
  async#ensureAndroidDebugKeystore() {
9236
- const keystorePath = path36.join(this.app.cwdPath, this.androidRootPath, "app/debug.keystore");
9759
+ const keystorePath = path38.join(this.app.cwdPath, this.androidRootPath, "app/debug.keystore");
9237
9760
  if (await Bun.file(keystorePath).exists())
9238
9761
  return;
9239
9762
  await this.#spawn("keytool", [
@@ -9279,12 +9802,12 @@ class CapacitorApp {
9279
9802
  await this.#prepareAndroid({ operation: "release", env: "main" });
9280
9803
  }
9281
9804
  async prepareWww() {
9282
- const htmlSource = path36.join(this.app.dist.cwdPath, "csr", targetHtmlFilename(this.target));
9805
+ const htmlSource = path38.join(this.app.dist.cwdPath, "csr", targetHtmlFilename(this.target));
9283
9806
  if (!await Bun.file(htmlSource).exists())
9284
9807
  throw new Error(`CSR html for mobile target '${this.target.name}' not found: ${htmlSource}`);
9285
- await rm4(this.targetWebRoot, { recursive: true, force: true });
9286
- await mkdir10(this.targetWebRoot, { recursive: true });
9287
- await Bun.write(path36.join(this.targetWebRoot, "index.html"), this.#injectMobileTargetMeta(await Bun.file(htmlSource).text()));
9808
+ await rm5(this.targetWebRoot, { recursive: true, force: true });
9809
+ await mkdir11(this.targetWebRoot, { recursive: true });
9810
+ await Bun.write(path38.join(this.targetWebRoot, "index.html"), this.#injectMobileTargetMeta(await Bun.file(htmlSource).text()));
9288
9811
  }
9289
9812
  #injectMobileTargetMeta(html) {
9290
9813
  const basePath2 = this.target.basePath?.replace(/^\/+|\/+$/g, "") ?? "";
@@ -9295,8 +9818,8 @@ class CapacitorApp {
9295
9818
  </head>`);
9296
9819
  }
9297
9820
  async#writeCapacitorConfig() {
9298
- await mkdir10(this.targetRoot, { recursive: true });
9299
- const appInfoPath = path36.relative(this.app.cwdPath, path36.join(this.app.cwdPath, "akan.app.json")).split(path36.sep).join("/");
9821
+ await mkdir11(this.targetRoot, { recursive: true });
9822
+ const appInfoPath = path38.relative(this.app.cwdPath, path38.join(this.app.cwdPath, "akan.app.json")).split(path38.sep).join("/");
9300
9823
  const content = `import type { AppScanResult } from "akanjs";
9301
9824
  import { withBase } from "${process.env.USE_AKANJS_PKGS === "true" ? "../../pkgs/" : ""}akanjs/capacitor.base.config";
9302
9825
  import appInfo from "${appInfoPath.startsWith(".") ? appInfoPath : `./${appInfoPath}`}";
@@ -9317,18 +9840,18 @@ export default withBase(
9317
9840
  appInfo as AppScanResult,
9318
9841
  );
9319
9842
  `;
9320
- await Bun.write(path36.join(this.app.cwdPath, "capacitor.config.ts"), content);
9843
+ await Bun.write(path38.join(this.app.cwdPath, "capacitor.config.ts"), content);
9321
9844
  }
9322
9845
  async#prepareTargetAssets() {
9323
9846
  if (!this.target.assets)
9324
9847
  return;
9325
- await mkdir10(this.targetAssetRoot, { recursive: true });
9848
+ await mkdir11(this.targetAssetRoot, { recursive: true });
9326
9849
  if (this.target.assets.icon)
9327
- await cp2(path36.join(this.app.cwdPath, this.target.assets.icon), path36.join(this.targetAssetRoot, "icon.png"), {
9850
+ await cp2(path38.join(this.app.cwdPath, this.target.assets.icon), path38.join(this.targetAssetRoot, "icon.png"), {
9328
9851
  force: true
9329
9852
  });
9330
9853
  if (this.target.assets.splash)
9331
- await cp2(path36.join(this.app.cwdPath, this.target.assets.splash), path36.join(this.targetAssetRoot, "splash.png"), {
9854
+ await cp2(path38.join(this.app.cwdPath, this.target.assets.splash), path38.join(this.targetAssetRoot, "splash.png"), {
9332
9855
  force: true
9333
9856
  });
9334
9857
  }
@@ -9336,11 +9859,11 @@ export default withBase(
9336
9859
  const files = this.target.files?.[platform];
9337
9860
  if (!files)
9338
9861
  return;
9339
- const platformRoot = path36.join(this.app.cwdPath, platform === "ios" ? this.iosRootPath : this.androidRootPath);
9862
+ const platformRoot = path38.join(this.app.cwdPath, platform === "ios" ? this.iosRootPath : this.androidRootPath);
9340
9863
  await Promise.all(Object.entries(files).map(async ([to, from]) => {
9341
- const targetPath = path36.join(platformRoot, to);
9342
- await mkdir10(path36.dirname(targetPath), { recursive: true });
9343
- await cp2(path36.join(this.app.cwdPath, from), targetPath, { force: true });
9864
+ const targetPath = path38.join(platformRoot, to);
9865
+ await mkdir11(path38.dirname(targetPath), { recursive: true });
9866
+ await cp2(path38.join(this.app.cwdPath, from), targetPath, { force: true });
9344
9867
  }));
9345
9868
  }
9346
9869
  async#generateAssets({ operation, env }) {
@@ -9350,7 +9873,7 @@ export default withBase(
9350
9873
  "@capacitor/assets",
9351
9874
  "generate",
9352
9875
  "--assetPath",
9353
- path36.posix.join(this.targetRootPath, "assets"),
9876
+ path38.posix.join(this.targetRootPath, "assets"),
9354
9877
  "--iosProject",
9355
9878
  this.iosProjectPath,
9356
9879
  "--androidProject",
@@ -9452,7 +9975,7 @@ export default withBase(
9452
9975
  this.#setPermissionsInAndroid(["POST_NOTIFICATIONS"]);
9453
9976
  }
9454
9977
  async#setPermissionInIos(permissions) {
9455
- const updateNs = Object.fromEntries(Object.entries(permissions).map(([key, value]) => [`NS${capitalize3(key)}`, value]));
9978
+ const updateNs = Object.fromEntries(Object.entries(permissions).map(([key, value]) => [`NS${capitalize4(key)}`, value]));
9456
9979
  await Promise.all([
9457
9980
  this.project.ios.updateInfoPlist(this.iosTargetName, "Debug", updateNs),
9458
9981
  this.project.ios.updateInfoPlist(this.iosTargetName, "Release", updateNs)
@@ -9537,15 +10060,15 @@ var Pkg = createInternalArgToken("Pkg");
9537
10060
  var Module = createInternalArgToken("Module");
9538
10061
  var Workspace = createInternalArgToken("Workspace");
9539
10062
  // pkgs/@akanjs/devkit/commandDecorators/command.ts
9540
- import path37 from "path";
10063
+ import path39 from "path";
9541
10064
  import { confirm, input as input2, select as select2 } from "@inquirer/prompts";
9542
10065
  import { Logger as Logger10 } from "akanjs/common";
9543
10066
  import chalk6 from "chalk";
9544
10067
  import { program } from "commander";
9545
10068
 
9546
10069
  // pkgs/@akanjs/devkit/commandDecorators/dependencyBuilder.ts
9547
- var capitalize4 = (value) => value.slice(0, 1).toUpperCase() + value.slice(1);
9548
- var createDependencyKey = (refName, kind) => `${refName}${capitalize4(kind)}`;
10070
+ var capitalize5 = (value) => value.slice(0, 1).toUpperCase() + value.slice(1);
10071
+ var createDependencyKey = (refName, kind) => `${refName}${capitalize5(kind)}`;
9549
10072
 
9550
10073
  class CommandContainer {
9551
10074
  static #instances = new Map;
@@ -10037,7 +10560,7 @@ var runCommands = async (...commands) => {
10037
10560
  process.exit(1);
10038
10561
  });
10039
10562
  const __dirname2 = getDirname(import.meta.url);
10040
- const packageJsonCandidates = [`${path37.dirname(Bun.main)}/package.json`, `${__dirname2}/../package.json`];
10563
+ const packageJsonCandidates = [`${path39.dirname(Bun.main)}/package.json`, `${__dirname2}/../package.json`];
10041
10564
  let cliPackageJson = null;
10042
10565
  for (const packageJsonPath of packageJsonCandidates) {
10043
10566
  if (!await FileSys.fileExists(packageJsonPath))
@@ -10315,8 +10838,8 @@ var scanModuleSpecifiers = (source, filePath, includeExports) => {
10315
10838
  return importSpecifiers;
10316
10839
  };
10317
10840
  var parseTsConfig = (tsConfigPath = "./tsconfig.json") => {
10318
- const configFile = ts7.readConfigFile(tsConfigPath, (path38) => {
10319
- return ts7.sys.readFile(path38);
10841
+ const configFile = ts7.readConfigFile(tsConfigPath, (path40) => {
10842
+ return ts7.sys.readFile(path40);
10320
10843
  });
10321
10844
  return ts7.parseJsonConfigFileContent(configFile.config, ts7.sys, realpathSync(tsConfigPath).replace(/[^/\\]+$/, ""));
10322
10845
  };
@@ -11513,7 +12036,7 @@ class ApplicationCommand extends command("application", [ApplicationScript], ({
11513
12036
  import { Logger as Logger16 } from "akanjs/common";
11514
12037
 
11515
12038
  // pkgs/@akanjs/cli/package/package.runner.ts
11516
- import path38 from "path";
12039
+ import path40 from "path";
11517
12040
  import { Logger as Logger14 } from "akanjs/common";
11518
12041
  var {$: $2 } = globalThis.Bun;
11519
12042
 
@@ -11533,11 +12056,11 @@ class PackageRunner extends runner("package") {
11533
12056
  }
11534
12057
  async#getInstalledPackageJson() {
11535
12058
  const packageJsonCandidates = [
11536
- `${path38.dirname(Bun.main)}/package.json`,
12059
+ `${path40.dirname(Bun.main)}/package.json`,
11537
12060
  `${process.cwd()}/node_modules/akanjs/package.json`
11538
12061
  ];
11539
12062
  try {
11540
- packageJsonCandidates.unshift(Bun.resolveSync("akanjs/package.json", path38.dirname(Bun.main)));
12063
+ packageJsonCandidates.unshift(Bun.resolveSync("akanjs/package.json", path40.dirname(Bun.main)));
11541
12064
  } catch {}
11542
12065
  for (const packageJsonPath of packageJsonCandidates) {
11543
12066
  if (!await Bun.file(packageJsonPath).exists())
@@ -11546,7 +12069,7 @@ class PackageRunner extends runner("package") {
11546
12069
  if (packageJson.name === "akanjs" || packageJson.name === "@akanjs/cli")
11547
12070
  return packageJson;
11548
12071
  }
11549
- throw new Error(`[package] failed to locate akanjs package.json from ${path38.dirname(Bun.main)}`);
12072
+ throw new Error(`[package] failed to locate akanjs package.json from ${path40.dirname(Bun.main)}`);
11550
12073
  }
11551
12074
  async createPackage(workspace, pkgName) {
11552
12075
  await workspace.applyTemplate({ basePath: `pkgs/${pkgName}`, template: "pkgRoot", dict: { pkgName } });
@@ -11721,7 +12244,7 @@ class PackageScript extends script("package", [PackageRunner]) {
11721
12244
  }
11722
12245
 
11723
12246
  // pkgs/@akanjs/cli/cloud/cloud.runner.ts
11724
- import path39 from "path";
12247
+ import path41 from "path";
11725
12248
  import { confirm as confirm4, input as input5, select as select7 } from "@inquirer/prompts";
11726
12249
  import { Logger as Logger15, sleep } from "akanjs/common";
11727
12250
  import chalk7 from "chalk";
@@ -11992,7 +12515,7 @@ ${chalk7.green("\u27A4")} Authentication Required`));
11992
12515
  await Promise.all(akanPkgs.map(async (library) => {
11993
12516
  Logger15.info(`Publishing ${library}@${nextVersion} to ${registry ?? "npm"}...`);
11994
12517
  await workspace.spawn("npm", ["publish", "--tag", tag, ...this.#getRegistryArgs(registry), ...this.#getLocalRegistryAuthArgs(registry)], {
11995
- cwd: path39.join(workspace.workspaceRoot, "dist/pkgs", library),
12518
+ cwd: path41.join(workspace.workspaceRoot, "dist/pkgs", library),
11996
12519
  env: this.#getRegistryEnv(registry),
11997
12520
  stdio: "inherit"
11998
12521
  });
@@ -12050,7 +12573,7 @@ ${chalk7.green("\u27A4")} Authentication Required`));
12050
12573
  await workspace.remove(localPath);
12051
12574
  }
12052
12575
  async uploadEnv(cloudApi2, workspaceId, filePath) {
12053
- const file = new File([Bun.file(filePath)], path39.basename(filePath));
12576
+ const file = new File([Bun.file(filePath)], path41.basename(filePath));
12054
12577
  await cloudApi2.uploadEnv(workspaceId, file);
12055
12578
  }
12056
12579
  async downloadEnvByScp(workspace) {
@@ -12142,14 +12665,14 @@ class CloudScript extends script("cloud", [CloudRunner, ApplicationScript, Packa
12142
12665
  }
12143
12666
  async uploadEnv(workspace) {
12144
12667
  const workspaceId = workspace.getWorkspaceId({ allowEmpty: true });
12145
- const { path: path40 } = await this.cloudRunner.gatherEnvFiles(workspace);
12668
+ const { path: path42 } = await this.cloudRunner.gatherEnvFiles(workspace);
12146
12669
  if (workspaceId) {
12147
12670
  await this.login(workspace);
12148
12671
  const cloudApi2 = await CloudApi.fromHost(workspace);
12149
- await this.cloudRunner.uploadEnv(cloudApi2, workspaceId, path40);
12672
+ await this.cloudRunner.uploadEnv(cloudApi2, workspaceId, path42);
12150
12673
  return;
12151
12674
  }
12152
- await this.cloudRunner.uploadEnvByScp(workspace, path40);
12675
+ await this.cloudRunner.uploadEnvByScp(workspace, path42);
12153
12676
  }
12154
12677
  async deployAkan(workspace, { test = true, registryUrl } = {}) {
12155
12678
  const akanPkgs = await this.cloudRunner.getAkanPkgs(workspace);
@@ -12563,14 +13086,14 @@ class GuidelinePrompt extends Prompter {
12563
13086
  async#getScanFilePaths(matchPattern, { avoidDirs = ["node_modules", ".next"], filterText } = {}) {
12564
13087
  const glob = new Bun.Glob(matchPattern);
12565
13088
  const paths = [];
12566
- for await (const path40 of glob.scan({ cwd: this.workspace.workspaceRoot, absolute: true })) {
12567
- if (avoidDirs.some((dir) => path40.includes(dir)))
13089
+ for await (const path42 of glob.scan({ cwd: this.workspace.workspaceRoot, absolute: true })) {
13090
+ if (avoidDirs.some((dir) => path42.includes(dir)))
12568
13091
  continue;
12569
- const fileContent = await FileSys.readText(path40);
13092
+ const fileContent = await FileSys.readText(path42);
12570
13093
  const textFilter = filterText ? new RegExp(filterText) : null;
12571
13094
  if (filterText && !textFilter?.test(fileContent))
12572
13095
  continue;
12573
- paths.push(path40);
13096
+ paths.push(path42);
12574
13097
  }
12575
13098
  return paths;
12576
13099
  }
@@ -12889,8 +13412,8 @@ class LibraryCommand extends command("library", [LibraryScript], ({ public: targ
12889
13412
  }
12890
13413
 
12891
13414
  // pkgs/@akanjs/cli/localRegistry/localRegistry.runner.ts
12892
- import { mkdir as mkdir11, rm as rm5 } from "fs/promises";
12893
- import path40 from "path";
13415
+ import { mkdir as mkdir12, rm as rm6 } from "fs/promises";
13416
+ import path42 from "path";
12894
13417
  import { Logger as Logger19 } from "akanjs/common";
12895
13418
  var defaultLocalRegistryUrl = "http://127.0.0.1:4873";
12896
13419
  var containerName = "akan-verdaccio";
@@ -12908,9 +13431,9 @@ class LocalRegistryRunner extends runner("localRegistry") {
12908
13431
  Logger19.info(`Local registry is already running at ${registry}`);
12909
13432
  return registry;
12910
13433
  } catch {}
12911
- const configPath2 = path40.join(workspace.workspaceRoot, "pkgs/@akanjs/cli/localRegistry/verdaccio.yaml");
12912
- const storagePath = path40.join(workspace.workspaceRoot, ".akan/verdaccio/storage");
12913
- await mkdir11(storagePath, { recursive: true });
13434
+ const configPath2 = path42.join(workspace.workspaceRoot, "pkgs/@akanjs/cli/localRegistry/verdaccio.yaml");
13435
+ const storagePath = path42.join(workspace.workspaceRoot, ".akan/verdaccio/storage");
13436
+ await mkdir12(storagePath, { recursive: true });
12914
13437
  await workspace.spawn("docker", [
12915
13438
  "run",
12916
13439
  "--rm",
@@ -12932,13 +13455,13 @@ class LocalRegistryRunner extends runner("localRegistry") {
12932
13455
  try {
12933
13456
  await workspace.spawn("docker", ["rm", "-f", containerName], { stdio: "inherit" });
12934
13457
  } catch {}
12935
- await rm5(path40.join(workspace.workspaceRoot, ".akan/verdaccio"), { recursive: true, force: true });
13458
+ await rm6(path42.join(workspace.workspaceRoot, ".akan/verdaccio"), { recursive: true, force: true });
12936
13459
  Logger19.info("Local registry storage has been reset");
12937
13460
  }
12938
13461
  async smoke(workspace, { registryUrl } = {}) {
12939
13462
  const registry = this.getRegistryUrl(registryUrl);
12940
- const smokeRoot = path40.join(workspace.workspaceRoot, ".akan/e2e");
12941
- await rm5(path40.join(smokeRoot, smokeRepoName), { recursive: true, force: true });
13463
+ const smokeRoot = path42.join(workspace.workspaceRoot, ".akan/e2e");
13464
+ await rm6(path42.join(smokeRoot, smokeRepoName), { recursive: true, force: true });
12942
13465
  await workspace.spawn(process.execPath, [
12943
13466
  "dist/pkgs/create-akan-workspace/index.js",
12944
13467
  smokeRepoName,
@@ -12955,12 +13478,12 @@ class LocalRegistryRunner extends runner("localRegistry") {
12955
13478
  stdio: "inherit"
12956
13479
  });
12957
13480
  await workspace.spawn("akan", ["typecheck", smokeAppName], {
12958
- cwd: path40.join(smokeRoot, smokeRepoName),
13481
+ cwd: path42.join(smokeRoot, smokeRepoName),
12959
13482
  env: { ...process.env, AKAN_NPM_REGISTRY: registry, NPM_CONFIG_REGISTRY: registry },
12960
13483
  stdio: "inherit"
12961
13484
  });
12962
13485
  await workspace.spawn("akan", ["build", smokeAppName], {
12963
- cwd: path40.join(smokeRoot, smokeRepoName),
13486
+ cwd: path42.join(smokeRoot, smokeRepoName),
12964
13487
  env: { ...process.env, AKAN_NPM_REGISTRY: registry, NPM_CONFIG_REGISTRY: registry },
12965
13488
  stdio: "inherit"
12966
13489
  });
@@ -13040,7 +13563,7 @@ import { lowerlize } from "akanjs/common";
13040
13563
 
13041
13564
  // pkgs/@akanjs/cli/module/module.script.ts
13042
13565
  import { input as input6 } from "@inquirer/prompts";
13043
- import { capitalize as capitalize7, randomPicks as randomPicks2 } from "akanjs/common";
13566
+ import { capitalize as capitalize8, randomPicks as randomPicks2 } from "akanjs/common";
13044
13567
 
13045
13568
  // pkgs/@akanjs/cli/page/page.runner.ts
13046
13569
  class PageRunner extends runner("page") {
@@ -13070,7 +13593,7 @@ function pluralizeName(name) {
13070
13593
  }
13071
13594
 
13072
13595
  // pkgs/@akanjs/cli/module/module.request.ts
13073
- import { capitalize as capitalize5 } from "akanjs/common";
13596
+ import { capitalize as capitalize6 } from "akanjs/common";
13074
13597
 
13075
13598
  // pkgs/@akanjs/cli/module/module.prompt.ts
13076
13599
  var componentDefaultDescription = ({
@@ -13195,7 +13718,7 @@ var requestTemplate = ({
13195
13718
  ${componentDefaultDescription({
13196
13719
  sysName,
13197
13720
  modelName,
13198
- ModelName: ModelName ?? capitalize5(modelName),
13721
+ ModelName: ModelName ?? capitalize6(modelName),
13199
13722
  exampleFiles,
13200
13723
  constant,
13201
13724
  properties
@@ -13252,7 +13775,7 @@ var requestView = ({
13252
13775
  ${componentDefaultDescription({
13253
13776
  sysName,
13254
13777
  modelName,
13255
- ModelName: ModelName ?? capitalize5(modelName),
13778
+ ModelName: ModelName ?? capitalize6(modelName),
13256
13779
  exampleFiles,
13257
13780
  constant,
13258
13781
  properties
@@ -13313,7 +13836,7 @@ var requestUnit = ({
13313
13836
  ${componentDefaultDescription({
13314
13837
  sysName,
13315
13838
  modelName,
13316
- ModelName: ModelName ?? capitalize5(modelName),
13839
+ ModelName: ModelName ?? capitalize6(modelName),
13317
13840
  exampleFiles,
13318
13841
  constant,
13319
13842
  properties
@@ -13362,7 +13885,7 @@ var requestUnit = ({
13362
13885
  `;
13363
13886
 
13364
13887
  // pkgs/@akanjs/cli/module/module.runner.ts
13365
- import { capitalize as capitalize6 } from "akanjs/common";
13888
+ import { capitalize as capitalize7 } from "akanjs/common";
13366
13889
  class ModuleRunner extends runner("module") {
13367
13890
  async createService(module) {
13368
13891
  const serviceName = module.name.replace(/^_+/, "");
@@ -13392,13 +13915,13 @@ class ModuleRunner extends runner("module") {
13392
13915
  async createComponentTemplate(module, type) {
13393
13916
  await module.sys.applyTemplate({
13394
13917
  basePath: `./lib/${module.name}`,
13395
- template: `module/__Model__.${capitalize6(type)}.tsx`,
13918
+ template: `module/__Model__.${capitalize7(type)}.tsx`,
13396
13919
  dict: { model: module.name, appName: module.sys.name }
13397
13920
  });
13398
13921
  return {
13399
13922
  component: {
13400
- filename: `${module.name}.${capitalize6(type)}.tsx`,
13401
- content: await module.sys.readFile(`lib/${module.name}/${capitalize6(module.name)}.${capitalize6(type)}.tsx`)
13923
+ filename: `${module.name}.${capitalize7(type)}.tsx`,
13924
+ content: await module.sys.readFile(`lib/${module.name}/${capitalize7(module.name)}.${capitalize7(type)}.tsx`)
13402
13925
  }
13403
13926
  };
13404
13927
  }
@@ -13524,7 +14047,7 @@ class ModuleScript extends script("module", [ModuleRunner, PageScript]) {
13524
14047
  async createTemplate(mod) {
13525
14048
  const { component: template } = await this.moduleRunner.createComponentTemplate(mod, "template");
13526
14049
  const templateExampleFiles = (await mod.sys.getTemplatesSourceCode()).filter((f) => !f.filePath.includes(`${mod.name}.Template.tsx`));
13527
- const Name = capitalize7(mod.name);
14050
+ const Name = capitalize8(mod.name);
13528
14051
  const relatedCnsts = getRelatedCnsts(`${mod.sys.cwdPath}/lib/${mod.name}/${mod.name}.constant.ts`);
13529
14052
  const constant = await FileSys.readText(`${mod.sys.cwdPath}/lib/${mod.name}/${mod.name}.constant.ts`);
13530
14053
  const session = new AiSession("createTemplate", { workspace: mod.sys.workspace, cacheKey: mod.name });
@@ -13543,7 +14066,7 @@ class ModuleScript extends script("module", [ModuleRunner, PageScript]) {
13543
14066
  }
13544
14067
  async createUnit(mod) {
13545
14068
  const { component: unit } = await this.moduleRunner.createComponentTemplate(mod, "unit");
13546
- const Name = capitalize7(mod.name);
14069
+ const Name = capitalize8(mod.name);
13547
14070
  const unitExampleFiles = (await mod.sys.getUnitsSourceCode()).filter((f) => !f.filePath.includes(`${mod.name}.Unit.tsx`));
13548
14071
  const relatedCnsts = getRelatedCnsts(`${mod.sys.cwdPath}/lib/${mod.name}/${mod.name}.constant.ts`);
13549
14072
  const constant = await FileSys.readText(`${mod.sys.cwdPath}/lib/${mod.name}/${mod.name}.constant.ts`);
@@ -13564,7 +14087,7 @@ class ModuleScript extends script("module", [ModuleRunner, PageScript]) {
13564
14087
  async createView(mod) {
13565
14088
  const { component: view } = await this.moduleRunner.createComponentTemplate(mod, "view");
13566
14089
  const viewExampleFiles = (await mod.sys.getViewsSourceCode()).filter((f) => !f.filePath.includes(`${mod.name}.View.tsx`));
13567
- const Name = capitalize7(mod.name);
14090
+ const Name = capitalize8(mod.name);
13568
14091
  const relatedCnsts = getRelatedCnsts(`${mod.sys.cwdPath}/lib/${mod.name}/${mod.name}.constant.ts`);
13569
14092
  const constant = await FileSys.readText(`${mod.sys.cwdPath}/lib/${mod.name}/${mod.name}.constant.ts`);
13570
14093
  const session = new AiSession("createView", { workspace: mod.sys.workspace, cacheKey: mod.name });
@@ -13841,11 +14364,11 @@ class ScalarCommand extends command("scalar", [ScalarScript], ({ public: target
13841
14364
  }
13842
14365
 
13843
14366
  // pkgs/@akanjs/cli/workspace/workspace.script.ts
13844
- import path42 from "path";
14367
+ import path44 from "path";
13845
14368
  import { Logger as Logger20 } from "akanjs/common";
13846
14369
 
13847
14370
  // pkgs/@akanjs/cli/workspace/workspace.runner.ts
13848
- import path41 from "path";
14371
+ import path43 from "path";
13849
14372
  var defaultWorkspacePeerDependencies = new Set([
13850
14373
  "@react-spring/web",
13851
14374
  "@use-gesture/react",
@@ -13893,10 +14416,10 @@ class WorkspaceRunner extends runner("workspace") {
13893
14416
  init = true,
13894
14417
  akanVersion,
13895
14418
  registryUrl,
13896
- owner
14419
+ owner = ""
13897
14420
  }) {
13898
14421
  const cwdPath = process.cwd();
13899
- const workspaceRoot = path41.join(cwdPath, dirname2, repoName);
14422
+ const workspaceRoot = path43.join(cwdPath, dirname2, repoName);
13900
14423
  const normalizedRegistryUrl = registryUrl ? getNpmRegistryUrl(registryUrl) : undefined;
13901
14424
  const workspace = WorkspaceExecutor.fromRoot({ workspaceRoot, repoName });
13902
14425
  const templateSpinner = workspace.spinning(`Creating workspace template files in ${dirname2}/${repoName}...`);
@@ -13907,7 +14430,7 @@ class WorkspaceRunner extends runner("workspace") {
13907
14430
  await workspace.applyTemplate({
13908
14431
  basePath: ".",
13909
14432
  template: "workspaceRoot",
13910
- dict: { repoName, appName, serveDomain: "localhost" }
14433
+ dict: { repoName, appName, serveDomain: "localhost", owner }
13911
14434
  });
13912
14435
  if (normalizedRegistryUrl)
13913
14436
  await workspace.writeFile(".npmrc", `registry=${normalizedRegistryUrl}/
@@ -13952,9 +14475,9 @@ class WorkspaceRunner extends runner("workspace") {
13952
14475
  }
13953
14476
  async#getCliPackageJson() {
13954
14477
  const packageJsonCandidates = [
13955
- path41.join(import.meta.dir, "../package.json"),
13956
- path41.join(import.meta.dir, "package.json"),
13957
- path41.join(path41.dirname(Bun.main), "package.json")
14478
+ path43.join(import.meta.dir, "../package.json"),
14479
+ path43.join(import.meta.dir, "package.json"),
14480
+ path43.join(path43.dirname(Bun.main), "package.json")
13958
14481
  ];
13959
14482
  try {
13960
14483
  packageJsonCandidates.unshift(Bun.resolveSync("@akanjs/cli/package.json", import.meta.dir));
@@ -13970,9 +14493,9 @@ class WorkspaceRunner extends runner("workspace") {
13970
14493
  }
13971
14494
  async#getAkanPackageJson() {
13972
14495
  const packageJsonCandidates = [
13973
- path41.join(import.meta.dir, "../../../akanjs/package.json"),
13974
- path41.join(process.cwd(), "pkgs/akanjs/package.json"),
13975
- path41.join(path41.dirname(Bun.main), "node_modules/akanjs/package.json")
14496
+ path43.join(import.meta.dir, "../../../akanjs/package.json"),
14497
+ path43.join(process.cwd(), "pkgs/akanjs/package.json"),
14498
+ path43.join(path43.dirname(Bun.main), "node_modules/akanjs/package.json")
13976
14499
  ];
13977
14500
  try {
13978
14501
  packageJsonCandidates.unshift(Bun.resolveSync("akanjs/package.json", import.meta.dir));
@@ -13986,13 +14509,13 @@ class WorkspaceRunner extends runner("workspace") {
13986
14509
  }
13987
14510
  let current = import.meta.dir;
13988
14511
  for (let depth = 0;depth < 6; depth++) {
13989
- const packageJsonPath = path41.join(current, "package.json");
14512
+ const packageJsonPath = path43.join(current, "package.json");
13990
14513
  if (await Bun.file(packageJsonPath).exists()) {
13991
14514
  const packageJson = await FileSys.readJson(packageJsonPath);
13992
14515
  if (packageJson.name === "akanjs")
13993
14516
  return packageJson;
13994
14517
  }
13995
- const parent = path41.dirname(current);
14518
+ const parent = path43.dirname(current);
13996
14519
  if (parent === current)
13997
14520
  break;
13998
14521
  current = parent;
@@ -14069,7 +14592,7 @@ class WorkspaceScript extends script("workspace", [
14069
14592
  } catch (_) {
14070
14593
  gitSpinner.fail("Git repository initialization failed. It's not fatal, you can commit manually");
14071
14594
  }
14072
- const workspacePath = path42.join(dirname2, repoName);
14595
+ const workspacePath = path44.join(dirname2, repoName);
14073
14596
  Logger20.rawLog(`
14074
14597
  \uD83C\uDF89 Welcome aboard! Workspace created in ${dirname2}/${repoName}`);
14075
14598
  Logger20.rawLog(`\uD83D\uDE80 Run \`cd ${workspacePath} && akan start ${appName}\` to start the development server.`);
@@ -14160,9 +14683,15 @@ class WorkspaceCommand extends command("workspace", [WorkspaceScript], ({ public
14160
14683
  desc: "owner of the workspace",
14161
14684
  default: process.env.GITHUB_OWNER,
14162
14685
  nullable: true
14163
- }).exec(async function(workspaceName, app, dir, libs, init, registry) {
14686
+ }).exec(async function(workspaceName, app, dir, libs, init, registry, owner) {
14164
14687
  const appName = app || "app";
14165
- await this.workspaceScript.createWorkspace(workspaceName.toLowerCase().replace(/ /g, "-"), appName.toLowerCase().replace(/ /g, "-"), { dirname: dir, installLibs: libs, init, ...registry ? { registryUrl: registry } : {} });
14688
+ await this.workspaceScript.createWorkspace(workspaceName.toLowerCase().replace(/ /g, "-"), appName.toLowerCase().replace(/ /g, "-"), {
14689
+ dirname: dir,
14690
+ installLibs: libs,
14691
+ init,
14692
+ owner,
14693
+ ...registry ? { registryUrl: registry } : {}
14694
+ });
14166
14695
  }),
14167
14696
  generateAgentRules: target({ desc: "Generate AGENTS.md and optional Cursor rules for Akan coding agents" }).option("overwrite", Boolean, { desc: "Overwrite existing agent rule files", default: false }).option("cursorRules", Boolean, { desc: "Generate .cursor/rules/akan.mdc", default: true }).with(Workspace).exec(async function(overwrite, cursorRules, workspace) {
14168
14697
  await this.workspaceScript.generateAgentRules(workspace, { overwrite, cursorRules });