@akanjs/cli 2.3.5 → 2.3.6-rc.1

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,79 @@ 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
+ if (message.devPlan.actions.includes("restart-builder"))
4138
+ return false;
4139
+ return message.devPlan.actions.includes("restart-backend");
4140
+ };
4141
+ var shouldRestartBuilderByDevPlan = (message) => message.devPlan?.actions.includes("restart-builder") ?? false;
4142
+ var shouldRestartDevHostByDevPlan = (message) => message.devPlan?.actions.includes("restart-dev-host") ?? message.kinds.includes("config");
4143
+ var RESTART_ROLE_ORDER = ["server", "shared", "barrel", "config"];
4144
+ var generationValue = (generation) => generation ?? -1;
4145
+ var isLegacyBackendFallbackFile = (file, workspaceRoot) => {
4146
+ const abs = path9.resolve(file);
4147
+ const ext = path9.extname(abs).toLowerCase();
4148
+ if (!SOURCE_EXTS.has(ext))
4149
+ return false;
4150
+ const rel = path9.relative(path9.resolve(workspaceRoot), abs);
4151
+ if (!rel || rel.startsWith("..") || path9.isAbsolute(rel))
4152
+ return false;
4153
+ const parts = rel.split(path9.sep).filter(Boolean);
4154
+ const [scope] = parts;
4155
+ if (scope !== "apps" && scope !== "libs" && scope !== "pkgs")
4156
+ return false;
4157
+ const base = path9.basename(abs);
4158
+ 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";
4159
+ };
4160
+ var shouldMarkBuildPhaseRecovered = (previousByPhase, status) => {
4161
+ const previous = previousByPhase.get(status.phase);
4162
+ return Boolean(previous && status.ok && !previous.ok && generationValue(status.generation) >= previous.generation);
4163
+ };
4164
+ var createBackendBuildStatus = ({
4165
+ generation,
4166
+ ok,
4167
+ files = [],
4168
+ message
4169
+ }) => ({
4170
+ generation,
4171
+ phase: "backend",
4172
+ ok,
4173
+ files,
4174
+ message
4175
+ });
4176
+ var backendRestartReasonFromMessage = (message) => {
4177
+ const roleSet = new Set;
4178
+ for (const role of message.devPlan?.roles ?? []) {
4179
+ if (role === "server" || role === "shared" || role === "barrel" || role === "config")
4180
+ roleSet.add(role);
4181
+ }
4182
+ return {
4183
+ generation: message.devPlan?.generation ?? message.generation,
4184
+ files: [...new Set(message.files)].sort(),
4185
+ roles: RESTART_ROLE_ORDER.filter((role) => roleSet.has(role))
4186
+ };
4187
+ };
4188
+ var mergeBackendRestartReasons = (current, next) => ({
4189
+ generation: generationValue(next.generation) >= generationValue(current?.generation) ? next.generation : current?.generation,
4190
+ files: [...new Set([...current?.files ?? [], ...next.files])].sort(),
4191
+ roles: RESTART_ROLE_ORDER.filter((role) => current?.roles.includes(role) || next.roles.includes(role))
4192
+ });
4193
+ var shouldReplaceLastGoodMessage = (current, next) => !current || generationValue(next.data.generation) >= generationValue(current.data.generation);
4194
+ var shouldQueueBuildStatusReplay = (backendReady, pendingReplayCount) => !backendReady || pendingReplayCount > 0;
4195
+ var buildStatusReplaySequence = (pendingReplay, latestByPhase) => [...pendingReplay, ...latestByPhase.values()];
4098
4196
 
4099
4197
  class BackendImportGraph {
4100
4198
  #app;
@@ -4105,6 +4203,7 @@ class BackendImportGraph {
4105
4203
  #jsxTranspiler = new Bun.Transpiler({ loader: "jsx" });
4106
4204
  #files = new Set;
4107
4205
  #ready = false;
4206
+ #lastRefreshSucceeded = false;
4108
4207
  constructor(app, logger) {
4109
4208
  this.#app = app;
4110
4209
  this.#logger = logger;
@@ -4112,6 +4211,9 @@ class BackendImportGraph {
4112
4211
  get ready() {
4113
4212
  return this.#ready;
4114
4213
  }
4214
+ get lastRefreshSucceeded() {
4215
+ return this.#lastRefreshSucceeded;
4216
+ }
4115
4217
  has(file) {
4116
4218
  return this.#files.has(path9.resolve(file));
4117
4219
  }
@@ -4120,10 +4222,12 @@ class BackendImportGraph {
4120
4222
  const files = await this.#build();
4121
4223
  this.#files = files;
4122
4224
  this.#ready = true;
4225
+ this.#lastRefreshSucceeded = true;
4123
4226
  this.#logger.verbose(`[backend-graph] scanned ${files.size} files`);
4124
4227
  return true;
4125
4228
  } catch (err) {
4126
4229
  this.#ready = this.#files.size > 0;
4230
+ this.#lastRefreshSucceeded = false;
4127
4231
  this.#logger.warn(`[backend-graph] scan failed; ${this.#ready ? "using previous graph" : "using fallback rules"}: ${err instanceof Error ? err.message : String(err)}`);
4128
4232
  return this.#ready;
4129
4233
  }
@@ -4210,9 +4314,13 @@ class AkanAppHost {
4210
4314
  #restartTimer = null;
4211
4315
  #backendRecoveryTimer = null;
4212
4316
  #backendRecoveryAttempts = 0;
4213
- #restartFiles = new Set;
4214
- #latestPagesUpdated = null;
4215
- #latestCssUpdated = null;
4317
+ #backendLifecycleState = "stopped";
4318
+ #pendingRestartReason = null;
4319
+ #backendStartStatus = null;
4320
+ #backendBuildStatusGeneration = 0;
4321
+ #lastGoodFrontend = {};
4322
+ #buildStatusByPhase = new Map;
4323
+ #pendingBuildStatusReplay = [];
4216
4324
  #builderMessageQueue = Promise.resolve();
4217
4325
  #backendGraph;
4218
4326
  constructor(app, { env, withInk = false }) {
@@ -4257,7 +4365,9 @@ class AkanAppHost {
4257
4365
  return "localhost";
4258
4366
  return await createTunnel(type, { app: this.app, environment });
4259
4367
  }
4260
- #startBackend() {
4368
+ #startBackend(startStatus = null) {
4369
+ this.#backendStartStatus = startStatus;
4370
+ this.#setBackendLifecycleState("starting");
4261
4371
  this.#backendReady = false;
4262
4372
  const backend = Bun.spawn(["bun", `apps/${this.app.name}/main.ts`], {
4263
4373
  cwd: this.app.workspace.workspaceRoot,
@@ -4269,6 +4379,8 @@ class AkanAppHost {
4269
4379
  if (msg.type === "backend-ready") {
4270
4380
  this.#backendReady = true;
4271
4381
  this.#backendRecoveryAttempts = 0;
4382
+ this.#setBackendLifecycleState("ready", `pid=${msg.pid}`);
4383
+ this.#recordBackendReadyStatus();
4272
4384
  this.logger.verbose(`backend ready pid=${msg.pid}`);
4273
4385
  this.#replayBuilderState();
4274
4386
  return;
@@ -4291,9 +4403,53 @@ class AkanAppHost {
4291
4403
  this.#backend = backend;
4292
4404
  this.logger.verbose(`backend spawned pid=${backend.pid}`);
4293
4405
  }
4406
+ #nextBackendBuildStatusGeneration(generation) {
4407
+ if (typeof generation === "number") {
4408
+ this.#backendBuildStatusGeneration = Math.max(this.#backendBuildStatusGeneration, generation);
4409
+ return generation;
4410
+ }
4411
+ this.#backendBuildStatusGeneration += 1;
4412
+ return this.#backendBuildStatusGeneration;
4413
+ }
4414
+ #recordBackendBuildStatus({
4415
+ generation,
4416
+ ok,
4417
+ files,
4418
+ message
4419
+ }) {
4420
+ const status = createBackendBuildStatus({
4421
+ generation: this.#nextBackendBuildStatusGeneration(generation),
4422
+ ok,
4423
+ files,
4424
+ message
4425
+ });
4426
+ this.#recordBuildStatus(status);
4427
+ return status;
4428
+ }
4429
+ #recordBackendReadyStatus() {
4430
+ const previous = this.#buildStatusByPhase.get("backend");
4431
+ const startStatus = this.#backendStartStatus;
4432
+ if (startStatus || previous?.ok === false) {
4433
+ const status = this.#recordBackendBuildStatus({
4434
+ generation: startStatus?.generation ?? previous?.generation,
4435
+ ok: true,
4436
+ files: startStatus?.files ?? previous?.files ?? [],
4437
+ message: "Backend ready"
4438
+ });
4439
+ this.#sendOrQueueBuildStatus(status);
4440
+ }
4441
+ this.#backendStartStatus = null;
4442
+ }
4443
+ #setBackendLifecycleState(next, detail) {
4444
+ if (this.#backendLifecycleState === next && !detail)
4445
+ return;
4446
+ const prev = this.#backendLifecycleState;
4447
+ this.#backendLifecycleState = next;
4448
+ this.logger.verbose(`[backend-lifecycle] ${prev} -> ${next}${detail ? ` ${detail}` : ""}`);
4449
+ }
4294
4450
  #sendToBackend(message) {
4295
4451
  if (!this.#backend || !this.#backendReady) {
4296
- if (message.type === "css-updated" || message.type === "pages-updated") {
4452
+ if (message.type === "css-updated" || message.type === "pages-updated" || message.type === "build-status") {
4297
4453
  this.logger.verbose(`backend is not ready; will replay ${message.type}`);
4298
4454
  return;
4299
4455
  }
@@ -4313,6 +4469,7 @@ class AkanAppHost {
4313
4469
  const backend = this.#backend;
4314
4470
  this.#plannedBackendStops.add(backend);
4315
4471
  this.#backendReady = false;
4472
+ this.#setBackendLifecycleState("stopping", `pid=${backend.pid}`);
4316
4473
  this.logger.verbose(`stopping backend pid=${backend.pid}`);
4317
4474
  try {
4318
4475
  backend.kill("SIGTERM");
@@ -4328,11 +4485,13 @@ class AkanAppHost {
4328
4485
  } finally {
4329
4486
  if (this.#backend === backend)
4330
4487
  this.#backend = null;
4488
+ this.#setBackendLifecycleState("stopped", `pid=${backend.pid}`);
4331
4489
  }
4332
4490
  }
4333
- #scheduleBackendRestart(files) {
4334
- for (const file of files)
4335
- this.#restartFiles.add(file);
4491
+ #scheduleBackendRestart(reason) {
4492
+ this.#pendingRestartReason = mergeBackendRestartReasons(this.#pendingRestartReason, reason);
4493
+ const pending = this.#pendingRestartReason;
4494
+ this.#setBackendLifecycleState("restart-pending", `generation=${pending.generation ?? "(unknown)"} files=${pending.files.length} roles=${pending.roles.join(",") || "(none)"}`);
4336
4495
  if (this.#backendRecoveryTimer) {
4337
4496
  clearTimeout(this.#backendRecoveryTimer);
4338
4497
  this.#backendRecoveryTimer = null;
@@ -4341,23 +4500,31 @@ class AkanAppHost {
4341
4500
  clearTimeout(this.#restartTimer);
4342
4501
  this.#restartTimer = setTimeout(() => {
4343
4502
  this.#restartTimer = null;
4344
- const changed = [...this.#restartFiles];
4345
- this.#restartFiles.clear();
4346
- this.#restartBackend(changed);
4503
+ const next = this.#pendingRestartReason;
4504
+ this.#pendingRestartReason = null;
4505
+ if (next)
4506
+ this.#restartBackend(next);
4347
4507
  }, BACKEND_RESTART_DEBOUNCE_MS);
4348
4508
  }
4349
- async#restartBackend(files) {
4350
- this.logger.verbose(`[backend-reload] restarting backend for ${files.length} file(s)`);
4509
+ async#restartBackend(reason) {
4510
+ this.logger.verbose(`[backend-reload] restarting backend generation=${reason.generation ?? "(unknown)"} files=${reason.files.length} roles=${reason.roles.join(",") || "(none)"}`);
4351
4511
  this.#backendRecoveryAttempts = 0;
4352
4512
  await Promise.all([this.#stopBackend(), this.#backendGraph.refresh()]);
4353
- this.#startBackend();
4513
+ this.#startBackend({ generation: reason.generation, files: reason.files });
4354
4514
  }
4355
4515
  #scheduleBackendRecovery(reason) {
4356
4516
  if (this.#backendRecoveryTimer || this.#backend)
4357
4517
  return;
4518
+ this.#setBackendLifecycleState("recovering", reason);
4358
4519
  const attempt = this.#backendRecoveryAttempts;
4359
4520
  const delay = Math.min(BACKEND_RECOVERY_BASE_DELAY_MS * 2 ** attempt, BACKEND_RECOVERY_MAX_DELAY_MS);
4360
4521
  this.#backendRecoveryAttempts = attempt + 1;
4522
+ const failureStatus = this.#recordBackendBuildStatus({
4523
+ ok: false,
4524
+ files: [],
4525
+ message: `Backend exited unexpectedly (${reason}); restarting in ${delay}ms`
4526
+ });
4527
+ this.#sendOrQueueBuildStatus(failureStatus);
4361
4528
  this.logger.warn(`[backend-recovery] backend exited unexpectedly (${reason}); restarting in ${delay}ms (attempt ${this.#backendRecoveryAttempts})`);
4362
4529
  this.#backendRecoveryTimer = setTimeout(() => {
4363
4530
  this.#backendRecoveryTimer = null;
@@ -4365,7 +4532,7 @@ class AkanAppHost {
4365
4532
  return;
4366
4533
  this.#backendGraph.refresh().finally(() => {
4367
4534
  if (!this.#backend)
4368
- this.#startBackend();
4535
+ this.#startBackend({ generation: failureStatus.generation, files: failureStatus.files });
4369
4536
  });
4370
4537
  }, delay);
4371
4538
  }
@@ -4375,10 +4542,15 @@ class AkanAppHost {
4375
4542
  });
4376
4543
  }
4377
4544
  async#handleBuilderMessage(message) {
4545
+ if (message.type === "build-status") {
4546
+ this.#recordBuildStatus(message.data);
4547
+ this.#sendOrQueueBuildStatus(message.data);
4548
+ return;
4549
+ }
4378
4550
  if (message.type === "pages-updated")
4379
- this.#latestPagesUpdated = message;
4551
+ this.#recordLastGood(message);
4380
4552
  if (message.type === "css-updated")
4381
- this.#latestCssUpdated = message;
4553
+ this.#recordLastGood(message);
4382
4554
  if (message.type === "invalidate") {
4383
4555
  await this.#handleInvalidate(message);
4384
4556
  return;
@@ -4386,26 +4558,140 @@ class AkanAppHost {
4386
4558
  this.#sendToBackend(message);
4387
4559
  }
4388
4560
  async#handleInvalidate(message) {
4561
+ if (shouldRestartBuilderByDevPlan(message)) {
4562
+ try {
4563
+ await this.#restartDevChildren(message);
4564
+ } catch (err) {
4565
+ this.#recordDevHostRestartFailure(message, err);
4566
+ }
4567
+ return;
4568
+ }
4569
+ if (shouldRestartDevHostByDevPlan(message)) {
4570
+ this.#recordDevHostRestartRequired(message);
4571
+ return;
4572
+ }
4389
4573
  if (await this.#shouldRestartBackend(message)) {
4390
- this.#scheduleBackendRestart(message.files);
4574
+ this.#scheduleBackendRestart(backendRestartReasonFromMessage(message));
4391
4575
  return;
4392
4576
  }
4393
4577
  this.#sendToBackend(message);
4394
4578
  }
4579
+ async#restartDevChildren(message) {
4580
+ const generation = message.devPlan?.generation ?? message.generation;
4581
+ this.logger.warn(`[dev-host] recycling builder/backend for runtime metadata generation=${generation ?? "(unknown)"} files=${message.files.length}`);
4582
+ if (this.#restartTimer) {
4583
+ clearTimeout(this.#restartTimer);
4584
+ this.#restartTimer = null;
4585
+ }
4586
+ if (this.#backendRecoveryTimer) {
4587
+ clearTimeout(this.#backendRecoveryTimer);
4588
+ this.#backendRecoveryTimer = null;
4589
+ }
4590
+ this.#pendingRestartReason = null;
4591
+ this.#lastGoodFrontend = {};
4592
+ this.#buildStatusByPhase.clear();
4593
+ this.#pendingBuildStatusReplay = [];
4594
+ await this.#stopBackend();
4595
+ this.#stopBuilder();
4596
+ await this.#backendGraph.refresh();
4597
+ await this.#startBuilder();
4598
+ this.#startBackend({ generation, files: message.files });
4599
+ }
4600
+ #recordLastGood(message) {
4601
+ if (message.type === "pages-updated") {
4602
+ if (!shouldReplaceLastGoodMessage(this.#lastGoodFrontend.pages, message))
4603
+ return;
4604
+ this.#lastGoodFrontend.pages = message;
4605
+ this.logger.verbose(`[last-good] pages generation=${message.data.generation ?? "(unknown)"} buildId=${message.data.buildId}`);
4606
+ return;
4607
+ }
4608
+ if (!shouldReplaceLastGoodMessage(this.#lastGoodFrontend.css, message))
4609
+ return;
4610
+ this.#lastGoodFrontend.css = message;
4611
+ this.logger.verbose(`[last-good] css generation=${message.data.generation ?? "(unknown)"} assets=${Object.keys(message.data.cssAssets).length}`);
4612
+ }
4613
+ #recordDevHostRestartRequired(message) {
4614
+ const generation = message.devPlan?.generation ?? message.generation;
4615
+ const detail = `generation=${generation ?? "(unknown)"} files=${message.files.length}`;
4616
+ this.logger.warn(`[dev-host] config change requires a manual restart until controlled dev-host restart is implemented (${detail})`);
4617
+ if (typeof generation === "number") {
4618
+ const status = {
4619
+ generation,
4620
+ phase: "scan",
4621
+ ok: false,
4622
+ files: message.files,
4623
+ message: "Config change requires restarting `akan start` to apply."
4624
+ };
4625
+ this.#recordBuildStatus(status);
4626
+ this.#sendOrQueueBuildStatus(status);
4627
+ }
4628
+ }
4629
+ #recordDevHostRestartFailure(message, err) {
4630
+ const generation = message.devPlan?.generation ?? message.generation ?? this.#nextBackendBuildStatusGeneration();
4631
+ const detail = err instanceof Error ? err.message : String(err);
4632
+ this.logger.warn(`[dev-host] runtime metadata restart failed generation=${generation}: ${detail}`);
4633
+ const status = {
4634
+ generation,
4635
+ phase: "scan",
4636
+ ok: false,
4637
+ files: message.files,
4638
+ message: `Runtime metadata change requires restarting \`akan start\` to apply: ${detail}`
4639
+ };
4640
+ this.#recordBuildStatus(status);
4641
+ this.#sendOrQueueBuildStatus(status);
4642
+ }
4643
+ #recordBuildStatus(status) {
4644
+ const recovered = shouldMarkBuildPhaseRecovered(this.#buildStatusByPhase, status);
4645
+ this.#buildStatusByPhase.set(status.phase, status);
4646
+ const label = `[build-status] generation=${status.generation} phase=${status.phase} ok=${status.ok} files=${status.files.length}`;
4647
+ if (status.ok)
4648
+ this.logger.verbose(`${label}${recovered ? " recovered=1" : ""}`);
4649
+ else
4650
+ this.logger.warn(`${label}${status.message ? ` message=${status.message}` : ""}`);
4651
+ }
4652
+ #sendOrQueueBuildStatus(status) {
4653
+ if (!this.#backend || shouldQueueBuildStatusReplay(this.#backendReady, this.#pendingBuildStatusReplay.length)) {
4654
+ this.#pendingBuildStatusReplay.push(status);
4655
+ this.logger.verbose(`backend is not ready; will replay build-status generation=${status.generation} phase=${status.phase}`);
4656
+ return;
4657
+ }
4658
+ this.#sendToBackend({ type: "build-status", data: status });
4659
+ }
4395
4660
  #replayBuilderState() {
4396
4661
  if (!this.#backendReady)
4397
4662
  return;
4398
- if (this.#latestCssUpdated)
4399
- this.#sendToBackend(this.#latestCssUpdated);
4400
- if (this.#latestPagesUpdated)
4401
- this.#sendToBackend(this.#latestPagesUpdated);
4663
+ if (this.#lastGoodFrontend.css)
4664
+ this.#sendToBackend(this.#lastGoodFrontend.css);
4665
+ if (this.#lastGoodFrontend.pages)
4666
+ this.#sendToBackend(this.#lastGoodFrontend.pages);
4667
+ const queuedStatuses = this.#pendingBuildStatusReplay.splice(0);
4668
+ for (const status of buildStatusReplaySequence(queuedStatuses, this.#buildStatusByPhase)) {
4669
+ this.#sendToBackend({ type: "build-status", data: status });
4670
+ }
4402
4671
  }
4403
4672
  async#shouldRestartBackend(message) {
4404
4673
  if (message.kinds.length === 1 && message.kinds[0] === "css")
4405
4674
  return false;
4406
- if (!this.#backendGraph.ready && message.kinds.includes("code"))
4675
+ if (message.devPlan) {
4676
+ const { generation, roles, actions, reasonByFile } = message.devPlan;
4677
+ this.logger.verbose(`[dev-plan] generation=${generation} roles=${roles.join(",") || "(none)"} actions=${actions.join(",") || "(none)"} reasons=${Object.keys(reasonByFile).length}`);
4678
+ const shouldRestart = shouldRestartBackendByDevPlan(message) ?? false;
4679
+ if (shouldRestart && message.kinds.includes("code"))
4680
+ await this.#backendGraph.refresh();
4681
+ return shouldRestart;
4682
+ }
4683
+ if (message.kinds.includes("code"))
4407
4684
  await this.#backendGraph.refresh();
4408
- return message.files.some((file) => this.#isBackendFile(file));
4685
+ if (message.files.some((file) => this.#isBackendFile(file)))
4686
+ return true;
4687
+ if (!this.#backendGraph.lastRefreshSucceeded) {
4688
+ const fallbackFiles = message.files.filter((file) => isLegacyBackendFallbackFile(file, this.app.workspace.workspaceRoot));
4689
+ if (fallbackFiles.length > 0) {
4690
+ this.logger.warn(`[backend-graph] using path-role fallback for legacy invalidate; restart files=${fallbackFiles.length}`);
4691
+ return true;
4692
+ }
4693
+ }
4694
+ return false;
4409
4695
  }
4410
4696
  #isBackendFile(file) {
4411
4697
  return this.#backendGraph.has(file);
@@ -4761,8 +5047,8 @@ Caused by: ${ApplicationBuildReporter.formatError(error.cause)}` : "";
4761
5047
  }
4762
5048
  }
4763
5049
  // pkgs/@akanjs/devkit/applicationBuildRunner.ts
4764
- import { mkdir as mkdir7, rm as rm2 } from "fs/promises";
4765
- import path33 from "path";
5050
+ import { mkdir as mkdir8, rm as rm3 } from "fs/promises";
5051
+ import path35 from "path";
4766
5052
 
4767
5053
  // pkgs/@akanjs/devkit/frontendBuild/allRoutesBuilder.ts
4768
5054
  import path20 from "path";
@@ -7230,9 +7516,306 @@ function getPageKeyBasePath(pageKey, basePaths) {
7230
7516
  const firstPublicSegment = segments.find((segment) => segment !== "[lang]" && !/^\(.+\)$/.test(segment));
7231
7517
  return firstPublicSegment && basePaths.includes(firstPublicSegment) ? firstPublicSegment : null;
7232
7518
  }
7233
- // pkgs/@akanjs/devkit/frontendBuild/fontOptimizer.ts
7234
- import { mkdir as mkdir6 } from "fs/promises";
7519
+ // pkgs/@akanjs/devkit/frontendBuild/devChangePlanner.ts
7235
7520
  import path25 from "path";
7521
+ var SOURCE_EXTS4 = new Set([".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs"]);
7522
+ var CONFIG_BASENAMES = new Set(["akan.config.ts", "bunfig.toml", "tsconfig.json", "package.json"]);
7523
+ var BARREL_FACETS = new Set(["common", "srvkit", "ui", "webkit"]);
7524
+ var CLIENT_SUFFIXES = [".Template.tsx", ".Unit.tsx", ".Util.tsx", ".View.tsx", ".Zone.tsx", ".store.ts"];
7525
+ var SHARED_SUFFIXES2 = [".constant.ts", ".dictionary.ts", ".signal.ts"];
7526
+ var SERVER_SUFFIXES2 = [".service.ts", ".document.ts"];
7527
+ var RUNTIME_METADATA_BASENAMES2 = new Set(["dict.ts", "sig.ts", "useClient.ts", "useServer.ts"]);
7528
+
7529
+ class DevChangePlanner {
7530
+ #workspaceRoot;
7531
+ constructor({ workspaceRoot }) {
7532
+ this.#workspaceRoot = path25.resolve(workspaceRoot);
7533
+ }
7534
+ plan({ generation, files, kinds, generatedFiles: generatedFiles2 = [] }) {
7535
+ const fileList = uniqueResolved([...files, ...generatedFiles2]);
7536
+ const generatedSet = new Set(generatedFiles2.map((file) => path25.resolve(file)));
7537
+ const kindSet = new Set(kinds);
7538
+ const roles = new Set;
7539
+ const actions = new Set;
7540
+ const reasonByFile = {};
7541
+ for (const kind of kindSet) {
7542
+ if (kind === "css") {
7543
+ roles.add("css");
7544
+ actions.add("rebuild-css");
7545
+ }
7546
+ if (kind === "config") {
7547
+ roles.add("config");
7548
+ actions.add("restart-dev-host");
7549
+ }
7550
+ }
7551
+ for (const file of fileList) {
7552
+ const reasons = new Set;
7553
+ const fileRoles = this.#rolesForFile(file, { isGenerated: generatedSet.has(path25.resolve(file)), reasons });
7554
+ for (const role of fileRoles)
7555
+ roles.add(role);
7556
+ if (reasons.has("runtime-metadata"))
7557
+ actions.add("restart-builder");
7558
+ if (reasons.size > 0)
7559
+ reasonByFile[path25.resolve(file)] = [...reasons].sort();
7560
+ }
7561
+ if (roles.has("barrel"))
7562
+ actions.add("sync-generated");
7563
+ if (roles.has("server") || roles.has("shared"))
7564
+ actions.add("restart-backend");
7565
+ if (roles.has("client") || roles.has("shared"))
7566
+ actions.add("rebuild-client");
7567
+ if (roles.has("css"))
7568
+ actions.add("rebuild-css");
7569
+ return {
7570
+ generation,
7571
+ files: fileList,
7572
+ generatedFiles: uniqueResolved(generatedFiles2),
7573
+ roles: [...roles].sort(),
7574
+ actions: [...actions].sort(),
7575
+ reasonByFile
7576
+ };
7577
+ }
7578
+ #rolesForFile(file, { isGenerated, reasons }) {
7579
+ const roles = new Set;
7580
+ const abs = path25.resolve(file);
7581
+ const base = path25.basename(abs);
7582
+ const ext = path25.extname(abs).toLowerCase();
7583
+ const isSource = SOURCE_EXTS4.has(ext);
7584
+ const rel = path25.relative(this.#workspaceRoot, abs);
7585
+ const parts = rel.split(path25.sep).filter(Boolean);
7586
+ if (CONFIG_BASENAMES.has(base)) {
7587
+ roles.add("config");
7588
+ reasons.add("config-file");
7589
+ }
7590
+ if (ext === ".css") {
7591
+ roles.add("css");
7592
+ reasons.add("css-file");
7593
+ }
7594
+ if (isGenerated || isSource && this.#isBarrelFacetChild(parts)) {
7595
+ roles.add("barrel");
7596
+ reasons.add(isGenerated ? "generated-index" : "barrel-facet-child");
7597
+ }
7598
+ if (isSource && this.#isServerBiased(abs, parts)) {
7599
+ roles.add("server");
7600
+ reasons.add("server-path");
7601
+ }
7602
+ if (isSource && this.#isClientBiased(abs, parts)) {
7603
+ roles.add("client");
7604
+ reasons.add("client-path");
7605
+ }
7606
+ if (isSource && this.#isSharedBiased(abs, parts)) {
7607
+ roles.add("shared");
7608
+ reasons.add("shared-path");
7609
+ }
7610
+ if (isSource && this.#isRuntimeMetadataFile(parts, base)) {
7611
+ reasons.add("runtime-metadata");
7612
+ }
7613
+ if (roles.has("server") && roles.has("client")) {
7614
+ roles.delete("server");
7615
+ roles.delete("client");
7616
+ roles.add("shared");
7617
+ reasons.add("server-client-overlap");
7618
+ }
7619
+ if (roles.size === 0 && SOURCE_EXTS4.has(ext) && this.#isWorkspaceSource(rel)) {
7620
+ roles.add("shared");
7621
+ reasons.add("workspace-source-fallback");
7622
+ }
7623
+ return roles;
7624
+ }
7625
+ #isServerBiased(abs, parts) {
7626
+ const base = path25.basename(abs);
7627
+ return parts.includes("srvkit") || SERVER_SUFFIXES2.some((suffix) => base.endsWith(suffix)) || base === "main.ts" || base === "server.ts";
7628
+ }
7629
+ #isClientBiased(abs, parts) {
7630
+ const base = path25.basename(abs);
7631
+ return parts.includes("ui") || parts.includes("webkit") || parts.includes("page") || CLIENT_SUFFIXES.some((suffix) => base.endsWith(suffix));
7632
+ }
7633
+ #isSharedBiased(abs, parts) {
7634
+ const base = path25.basename(abs);
7635
+ return parts.includes("common") || SHARED_SUFFIXES2.some((suffix) => base.endsWith(suffix)) || RUNTIME_METADATA_BASENAMES2.has(base);
7636
+ }
7637
+ #isRuntimeMetadataFile(parts, base) {
7638
+ const parent = parts.at(-2);
7639
+ if (parent === "lib" && RUNTIME_METADATA_BASENAMES2.has(base))
7640
+ return true;
7641
+ const libIndex = parts.lastIndexOf("lib");
7642
+ if (libIndex < 0 || parts.length <= libIndex + 1)
7643
+ return false;
7644
+ return base.endsWith(".dictionary.ts") || base.endsWith(".signal.ts");
7645
+ }
7646
+ #isBarrelFacetChild(parts) {
7647
+ if (parts.length < 4)
7648
+ return false;
7649
+ const [scope, , facet, child] = parts;
7650
+ if (scope !== "apps" && scope !== "libs")
7651
+ return false;
7652
+ if (!facet || !BARREL_FACETS.has(facet))
7653
+ return false;
7654
+ if (!child || child.startsWith(".") || child === "index.ts" || child === "index.tsx")
7655
+ return false;
7656
+ return true;
7657
+ }
7658
+ #isWorkspaceSource(rel) {
7659
+ if (!rel || rel.startsWith("..") || path25.isAbsolute(rel))
7660
+ return false;
7661
+ const [scope] = rel.split(path25.sep);
7662
+ return scope === "apps" || scope === "libs" || scope === "pkgs";
7663
+ }
7664
+ }
7665
+ var uniqueResolved = (files) => [...new Set(files.map((file) => path25.resolve(file)))].sort();
7666
+ // pkgs/@akanjs/devkit/frontendBuild/devGeneratedIndexSync.ts
7667
+ import { mkdir as mkdir6, readdir as readdir2, readFile, rm as rm2, stat as stat3, writeFile } from "fs/promises";
7668
+ import path26 from "path";
7669
+ var BARREL_FACETS2 = new Set(["common", "srvkit", "ui", "webkit"]);
7670
+ var FACET_SOURCE_FILE_RE = /\.(ts|tsx)$/;
7671
+ var FACET_EXCLUDED_FILE_RE = /(^index\.tsx?$|\.d\.ts$|\.(test|spec)\.(ts|tsx)$|\.css$|\.scss$|\.sass$)/;
7672
+ var MODULE_UI_TYPES = ["Template", "Unit", "Util", "View", "Zone"];
7673
+ var SERVICE_UI_TYPES = ["Util", "Zone"];
7674
+ var SCALAR_UI_TYPES = ["Template", "Unit"];
7675
+
7676
+ class DevGeneratedIndexSync {
7677
+ #workspaceRoot;
7678
+ constructor({ workspaceRoot }) {
7679
+ this.#workspaceRoot = path26.resolve(workspaceRoot);
7680
+ }
7681
+ async syncForBatch(files) {
7682
+ const indexPaths = new Set;
7683
+ const errors = [];
7684
+ for (const file of files) {
7685
+ const facetIndex = this.#facetIndexFor(file);
7686
+ if (facetIndex)
7687
+ indexPaths.add(facetIndex);
7688
+ const moduleIndex = await this.#moduleIndexForDirectoryEvent(file).catch((err) => {
7689
+ errors.push(`[generated-index] module detection failed for ${file}: ${formatError(err)}`);
7690
+ return null;
7691
+ });
7692
+ if (moduleIndex)
7693
+ indexPaths.add(moduleIndex);
7694
+ }
7695
+ const changedFiles = [];
7696
+ for (const indexPath of [...indexPaths].sort()) {
7697
+ try {
7698
+ const changed = await this.#syncIndex(indexPath);
7699
+ if (changed)
7700
+ changedFiles.push(indexPath);
7701
+ } catch (err) {
7702
+ errors.push(`[generated-index] sync failed for ${indexPath}: ${formatError(err)}`);
7703
+ }
7704
+ }
7705
+ return { changedFiles, errors };
7706
+ }
7707
+ #facetIndexFor(file) {
7708
+ const abs = path26.resolve(file);
7709
+ const rel = path26.relative(this.#workspaceRoot, abs);
7710
+ if (rel.startsWith("..") || path26.isAbsolute(rel))
7711
+ return null;
7712
+ const parts = rel.split(path26.sep).filter(Boolean);
7713
+ if (parts.length < 4)
7714
+ return null;
7715
+ const [scope, project, facet, child] = parts;
7716
+ if (scope !== "apps" && scope !== "libs" || !project || !facet || !BARREL_FACETS2.has(facet))
7717
+ return null;
7718
+ if (!child || child.startsWith(".") || child === "index.ts" || child === "index.tsx")
7719
+ return null;
7720
+ return path26.join(this.#workspaceRoot, scope, project, facet, "index.ts");
7721
+ }
7722
+ async#moduleIndexForDirectoryEvent(file) {
7723
+ const abs = path26.resolve(file);
7724
+ const rel = path26.relative(this.#workspaceRoot, abs);
7725
+ if (rel.startsWith("..") || path26.isAbsolute(rel))
7726
+ return null;
7727
+ const parts = rel.split(path26.sep).filter(Boolean);
7728
+ if (parts.length !== 4 && parts.length !== 5)
7729
+ return null;
7730
+ const [scope, project, libSegment, moduleSegment, scalarSegment] = parts;
7731
+ if (scope !== "apps" && scope !== "libs" || !project || libSegment !== "lib")
7732
+ return null;
7733
+ const isExistingDirectory = await stat3(abs).then((s) => s.isDirectory()).catch(() => false);
7734
+ const looksLikeDeletedDirectory = !path26.extname(abs);
7735
+ if (!isExistingDirectory && !looksLikeDeletedDirectory)
7736
+ return null;
7737
+ if (moduleSegment === "__scalar" && scalarSegment) {
7738
+ return path26.join(this.#workspaceRoot, scope, project, "lib", "__scalar", scalarSegment, "index.ts");
7739
+ }
7740
+ if (!moduleSegment || moduleSegment === "__scalar")
7741
+ return null;
7742
+ return path26.join(this.#workspaceRoot, scope, project, "lib", moduleSegment, "index.ts");
7743
+ }
7744
+ async#syncIndex(indexPath) {
7745
+ const dir = path26.dirname(indexPath);
7746
+ const content = await this.#contentForIndex(indexPath);
7747
+ if (content === null) {
7748
+ if (!await exists(indexPath))
7749
+ return false;
7750
+ await rm2(indexPath, { force: true });
7751
+ return true;
7752
+ }
7753
+ const current = await readFile(indexPath, "utf8").catch(() => null);
7754
+ if (current === content)
7755
+ return false;
7756
+ await mkdir6(dir, { recursive: true });
7757
+ await writeFile(indexPath, content);
7758
+ return true;
7759
+ }
7760
+ async#contentForIndex(indexPath) {
7761
+ const parts = path26.relative(this.#workspaceRoot, indexPath).split(path26.sep).filter(Boolean);
7762
+ const facet = parts.at(-2);
7763
+ if (facet && BARREL_FACETS2.has(facet))
7764
+ return this.#facetContent(path26.dirname(indexPath));
7765
+ return this.#moduleContent(path26.dirname(indexPath));
7766
+ }
7767
+ async#facetContent(dir) {
7768
+ const entries = await readdir2(dir, { withFileTypes: true }).catch(() => []);
7769
+ const exportNames = entries.flatMap((entry) => {
7770
+ const name = entry.name;
7771
+ if (name.startsWith("."))
7772
+ return [];
7773
+ if (entry.isDirectory())
7774
+ return [name];
7775
+ if (!entry.isFile())
7776
+ return [];
7777
+ if (!FACET_SOURCE_FILE_RE.test(name) || FACET_EXCLUDED_FILE_RE.test(name))
7778
+ return [];
7779
+ return [name.replace(FACET_SOURCE_FILE_RE, "")];
7780
+ }).sort();
7781
+ if (exportNames.length === 0)
7782
+ return null;
7783
+ return `${exportNames.map((name) => `export * from "./${name}";`).join(`
7784
+ `)}
7785
+ `;
7786
+ }
7787
+ async#moduleContent(dir) {
7788
+ const rel = path26.relative(this.#workspaceRoot, dir);
7789
+ const parts = rel.split(path26.sep).filter(Boolean);
7790
+ const moduleSegment = parts.at(-1);
7791
+ if (!moduleSegment)
7792
+ return null;
7793
+ const isScalar = parts.at(-2) === "__scalar";
7794
+ const rawModel = moduleSegment.startsWith("_") ? moduleSegment.slice(1) : moduleSegment;
7795
+ if (!rawModel)
7796
+ return null;
7797
+ const modelName = capitalize3(rawModel);
7798
+ const allowedTypes = isScalar ? SCALAR_UI_TYPES : moduleSegment.startsWith("_") ? SERVICE_UI_TYPES : MODULE_UI_TYPES;
7799
+ const fileTypes = [];
7800
+ for (const type of allowedTypes) {
7801
+ if (await exists(path26.join(dir, `${modelName}.${type}.tsx`)))
7802
+ fileTypes.push(type);
7803
+ }
7804
+ if (fileTypes.length === 0)
7805
+ return null;
7806
+ return `
7807
+ ${fileTypes.map((type) => `import * as ${type} from "./${modelName}.${type}";`).join(`
7808
+ `)}
7809
+
7810
+ export const ${modelName} = { ${fileTypes.join(", ")} };`;
7811
+ }
7812
+ }
7813
+ var exists = async (file) => stat3(file).then(() => true).catch(() => false);
7814
+ var capitalize3 = (value) => `${value.charAt(0).toUpperCase()}${value.slice(1)}`;
7815
+ var formatError = (err) => err instanceof Error ? err.message : String(err);
7816
+ // pkgs/@akanjs/devkit/frontendBuild/fontOptimizer.ts
7817
+ import { mkdir as mkdir7 } from "fs/promises";
7818
+ import path27 from "path";
7236
7819
  import {
7237
7820
  generateFontFace,
7238
7821
  getMetricsForFamily,
@@ -7256,7 +7839,7 @@ class FontOptimizer {
7256
7839
  constructor(app, command = "start") {
7257
7840
  this.#app = app;
7258
7841
  this.#command = command;
7259
- this.#artifactRoot = path25.join(command === "build" ? app.dist.cwdPath : app.cwdPath, ".akan/artifact");
7842
+ this.#artifactRoot = path27.join(command === "build" ? app.dist.cwdPath : app.cwdPath, ".akan/artifact");
7260
7843
  }
7261
7844
  async optimize() {
7262
7845
  const fonts = await this.discoverFonts();
@@ -7275,7 +7858,7 @@ class FontOptimizer {
7275
7858
  const pageKeys = await this.#app.getPageKeys();
7276
7859
  const fonts = [];
7277
7860
  await Promise.all(pageKeys.map(async (key) => {
7278
- const filePath = path25.resolve(this.#app.cwdPath, "page", key);
7861
+ const filePath = path27.resolve(this.#app.cwdPath, "page", key);
7279
7862
  const file = Bun.file(filePath);
7280
7863
  if (!await file.exists())
7281
7864
  return;
@@ -7291,8 +7874,8 @@ class FontOptimizer {
7291
7874
  this.#app.logger.warn(`[font] source not found: ${face.src}`);
7292
7875
  continue;
7293
7876
  }
7294
- const outputPath = path25.join(this.#artifactRoot, face.optimizedSrc.replace(/^\/_akan\//, ""));
7295
- await mkdir6(path25.dirname(outputPath), { recursive: true });
7877
+ const outputPath = path27.join(this.#artifactRoot, face.optimizedSrc.replace(/^\/_akan\//, ""));
7878
+ await mkdir7(path27.dirname(outputPath), { recursive: true });
7296
7879
  const sourceBuffer = Buffer.from(await Bun.file(sourcePath).arrayBuffer());
7297
7880
  const outputBuffer = font.subset === false ? await this.#convertToWoff2(sourceBuffer, sourcePath) : await subsetFont(sourceBuffer, await this.#getSubsetText(font), { targetFormat: "woff2" });
7298
7881
  await Bun.write(outputPath, outputBuffer);
@@ -7439,8 +8022,8 @@ class FontOptimizer {
7439
8022
  return null;
7440
8023
  const rel = src.replace(/^\//, "");
7441
8024
  const candidates = [
7442
- this.#command === "build" ? path25.join(this.#app.dist.cwdPath, "public", rel) : null,
7443
- path25.join(this.#app.cwdPath, "public", rel),
8025
+ this.#command === "build" ? path27.join(this.#app.dist.cwdPath, "public", rel) : null,
8026
+ path27.join(this.#app.cwdPath, "public", rel),
7444
8027
  this.#resolveWorkspacePublicPath(rel)
7445
8028
  ].filter(Boolean);
7446
8029
  for (const candidate of candidates) {
@@ -7468,7 +8051,7 @@ class FontOptimizer {
7468
8051
  return "woff2";
7469
8052
  if (signature === "OTTO")
7470
8053
  return "otf";
7471
- const ext = path25.extname(sourcePath).slice(1).toLowerCase();
8054
+ const ext = path27.extname(sourcePath).slice(1).toLowerCase();
7472
8055
  if (ext === "otf" || ext === "woff" || ext === "woff2")
7473
8056
  return ext;
7474
8057
  return "ttf";
@@ -7477,7 +8060,7 @@ class FontOptimizer {
7477
8060
  const [root, dep, ...rest] = rel.split("/");
7478
8061
  if (root !== "libs" || !dep || rest.length === 0)
7479
8062
  return null;
7480
- return path25.join(this.#app.workspace.workspaceRoot, "libs", dep, "public", ...rest);
8063
+ return path27.join(this.#app.workspace.workspaceRoot, "libs", dep, "public", ...rest);
7481
8064
  }
7482
8065
  async#getSubsetText(font) {
7483
8066
  const parts = new Set;
@@ -7487,7 +8070,7 @@ class FontOptimizer {
7487
8070
  if (font.subsetText)
7488
8071
  parts.add(font.subsetText);
7489
8072
  for (const filePath of font.subsetFiles ?? []) {
7490
- const abs = path25.isAbsolute(filePath) ? filePath : path25.join(this.#app.cwdPath, filePath);
8073
+ const abs = path27.isAbsolute(filePath) ? filePath : path27.join(this.#app.cwdPath, filePath);
7491
8074
  const file = Bun.file(abs);
7492
8075
  if (await file.exists())
7493
8076
  parts.add(await file.text());
@@ -7506,7 +8089,7 @@ class FontOptimizer {
7506
8089
  return "";
7507
8090
  }
7508
8091
  async#collectAutoSubsetText() {
7509
- const roots = ["page", "ui"].map((dir) => path25.join(this.#app.cwdPath, dir));
8092
+ const roots = ["page", "ui"].map((dir) => path27.join(this.#app.cwdPath, dir));
7510
8093
  const glob = new Bun.Glob("**/*.{ts,tsx,js,jsx,html,md}");
7511
8094
  const parts = [];
7512
8095
  await Promise.all(roots.map(async (root) => {
@@ -7620,43 +8203,43 @@ ${declarations.map(([prop, value]) => ` ${prop}: ${value};`).join(`
7620
8203
  }
7621
8204
  }
7622
8205
  // pkgs/@akanjs/devkit/frontendBuild/hmrChangeClassifier.ts
7623
- import path26 from "path";
7624
- var SOURCE_EXTS4 = new Set([".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs"]);
8206
+ import path28 from "path";
8207
+ var SOURCE_EXTS5 = new Set([".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs"]);
7625
8208
  var CSS_EXTS = new Set([".css"]);
7626
- var CONFIG_BASENAMES = new Set(["akan.config.ts", "bunfig.toml", "tsconfig.json", "package.json"]);
8209
+ var CONFIG_BASENAMES2 = new Set(["akan.config.ts", "bunfig.toml", "tsconfig.json", "package.json"]);
7627
8210
 
7628
8211
  class HmrChangeClassifier {
7629
8212
  classify(abs) {
7630
8213
  if (this.#isUninteresting(abs))
7631
8214
  return "ignore";
7632
- const base = path26.basename(abs);
7633
- if (CONFIG_BASENAMES.has(base))
8215
+ const base = path28.basename(abs);
8216
+ if (CONFIG_BASENAMES2.has(base))
7634
8217
  return "config";
7635
- const ext = path26.extname(abs).toLowerCase();
8218
+ const ext = path28.extname(abs).toLowerCase();
7636
8219
  if (CSS_EXTS.has(ext))
7637
8220
  return "css";
7638
- if (SOURCE_EXTS4.has(ext))
8221
+ if (SOURCE_EXTS5.has(ext))
7639
8222
  return "code";
7640
8223
  return "ignore";
7641
8224
  }
7642
8225
  #isUninteresting(abs) {
7643
- const base = path26.basename(abs);
8226
+ const base = path28.basename(abs);
7644
8227
  if (!base)
7645
8228
  return true;
7646
8229
  if (base.startsWith("."))
7647
8230
  return true;
7648
8231
  if (base.endsWith("~") || base.endsWith(".swp") || base.endsWith(".swx") || base.endsWith(".tmp"))
7649
8232
  return true;
7650
- if (abs.includes(`${path26.sep}node_modules${path26.sep}`))
8233
+ if (abs.includes(`${path28.sep}node_modules${path28.sep}`))
7651
8234
  return true;
7652
- if (abs.includes(`${path26.sep}.akan${path26.sep}`))
8235
+ if (abs.includes(`${path28.sep}.akan${path28.sep}`))
7653
8236
  return true;
7654
8237
  return false;
7655
8238
  }
7656
8239
  }
7657
8240
  // pkgs/@akanjs/devkit/frontendBuild/hmrWatcher.ts
7658
8241
  import fs4 from "fs";
7659
- import path27 from "path";
8242
+ import path29 from "path";
7660
8243
  class HmrWatcher {
7661
8244
  #roots;
7662
8245
  #debounceMs;
@@ -7669,7 +8252,7 @@ class HmrWatcher {
7669
8252
  #stopped = false;
7670
8253
  #flushing = false;
7671
8254
  constructor(opts) {
7672
- this.#roots = [...new Set(opts.roots.map((r) => path27.resolve(r)))];
8255
+ this.#roots = [...new Set(opts.roots.map((r) => path29.resolve(r)))];
7673
8256
  this.#debounceMs = opts.debounceMs ?? 80;
7674
8257
  this.#onBatch = opts.onBatch;
7675
8258
  this.#logger = opts.logger;
@@ -7680,7 +8263,7 @@ class HmrWatcher {
7680
8263
  const w = fs4.watch(root, { recursive: true, persistent: false }, (_event, filename) => {
7681
8264
  if (!filename)
7682
8265
  return;
7683
- const abs = path27.resolve(root, filename.toString());
8266
+ const abs = path29.resolve(root, filename.toString());
7684
8267
  this.#queue(abs);
7685
8268
  });
7686
8269
  this.#watchers.push(w);
@@ -7738,10 +8321,10 @@ class HmrWatcher {
7738
8321
  }
7739
8322
  }
7740
8323
  // pkgs/@akanjs/devkit/frontendBuild/pagesBundleBuilder.ts
7741
- import path29 from "path";
8324
+ import path31 from "path";
7742
8325
 
7743
8326
  // pkgs/@akanjs/devkit/transforms/externalizeFrameworkPlugin.ts
7744
- import path28 from "path";
8327
+ import path30 from "path";
7745
8328
  var DEFAULT_INCLUDE = ["akanjs/", "@apps/", "@libs/"];
7746
8329
  var DEFAULT_EXCLUDE_EXACT = new Set(["akanjs/webkit", "@akanjs/cli", "@akanjs/devkit"]);
7747
8330
  var DEFAULT_EXCLUDE_PREFIX = ["@akanjs/cli/", "@akanjs/devkit/"];
@@ -7784,7 +8367,7 @@ async function createExternalizeFrameworkPlugin(options) {
7784
8367
  const replPath = repl?.endsWith("/*") ? repl.slice(0, -1) : repl ?? "";
7785
8368
  if (!replPath)
7786
8369
  continue;
7787
- const candidate = path28.resolve(workspaceRoot, replPath + suffix);
8370
+ const candidate = path30.resolve(workspaceRoot, replPath + suffix);
7788
8371
  const hit = await firstExisting(candidate);
7789
8372
  if (hit)
7790
8373
  return hit;
@@ -7796,8 +8379,8 @@ async function createExternalizeFrameworkPlugin(options) {
7796
8379
  if (spec === pkg)
7797
8380
  continue;
7798
8381
  const suffix = spec.slice(pkg.length + 1);
7799
- const pkgDir = path28.dirname(path28.resolve(workspaceRoot, entryFile));
7800
- const candidate = path28.join(pkgDir, suffix);
8382
+ const pkgDir = path30.dirname(path30.resolve(workspaceRoot, entryFile));
8383
+ const candidate = path30.join(pkgDir, suffix);
7801
8384
  const hit = await firstExisting(candidate);
7802
8385
  if (hit)
7803
8386
  return hit;
@@ -7847,7 +8430,7 @@ async function firstExisting(basePath2) {
7847
8430
  return candidate;
7848
8431
  }
7849
8432
  for (const ext of CANDIDATE_EXTS3) {
7850
- const candidate = path28.join(basePath2, `index${ext}`);
8433
+ const candidate = path30.join(basePath2, `index${ext}`);
7851
8434
  if (await Bun.file(candidate).exists())
7852
8435
  return candidate;
7853
8436
  }
@@ -7938,11 +8521,11 @@ class PagesBundleBuilder {
7938
8521
  const entryArtifact = result.outputs.find((a) => a.kind === "entry-point");
7939
8522
  if (!entryArtifact)
7940
8523
  throw new Error("[PagesBundleBuilder] Bun.build emitted no entry-point artifact");
7941
- const bundlePath = path29.resolve(entryArtifact.path);
8524
+ const bundlePath = path31.resolve(entryArtifact.path);
7942
8525
  const buildId = Date.now();
7943
8526
  const outputBytes = result.outputs.reduce((sum, output) => sum + output.size, 0);
7944
8527
  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`);
8528
+ 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
8529
  return {
7947
8530
  bundlePath,
7948
8531
  buildId,
@@ -8024,11 +8607,11 @@ function loaderFor4(absPath) {
8024
8607
  }
8025
8608
  // pkgs/@akanjs/devkit/frontendBuild/precompressArtifacts.ts
8026
8609
  import fs5 from "fs";
8027
- import path30 from "path";
8610
+ import path32 from "path";
8028
8611
  var COMPRESSIBLE_EXTS = new Set([".css", ".html", ".js", ".json", ".svg"]);
8029
8612
  var MIN_COMPRESS_BYTES = 1024;
8030
8613
  async function precompressArtifacts(app) {
8031
- const roots = [path30.join(app.dist.cwdPath, ".akan/artifact/client")];
8614
+ const roots = [path32.join(app.dist.cwdPath, ".akan/artifact/client")];
8032
8615
  const result = { files: 0, inputBytes: 0, outputBytes: 0 };
8033
8616
  await Promise.all(roots.map((root) => precompressRoot(root, result)));
8034
8617
  if (result.files > 0) {
@@ -8054,7 +8637,7 @@ async function precompressRoot(root, result) {
8054
8637
  async function shouldPrecompress(filePath) {
8055
8638
  if (filePath.endsWith(".gz"))
8056
8639
  return false;
8057
- if (!COMPRESSIBLE_EXTS.has(path30.extname(filePath).toLowerCase()))
8640
+ if (!COMPRESSIBLE_EXTS.has(path32.extname(filePath).toLowerCase()))
8058
8641
  return false;
8059
8642
  const file = Bun.file(filePath);
8060
8643
  if (!await file.exists())
@@ -8072,7 +8655,7 @@ function formatBytes(bytes) {
8072
8655
  return `${(bytes / 1024 / 1024).toFixed(1)}MB`;
8073
8656
  }
8074
8657
  // pkgs/@akanjs/devkit/frontendBuild/ssrBaseArtifactBuilder.ts
8075
- import path31 from "path";
8658
+ import path33 from "path";
8076
8659
  import { optimize } from "@tailwindcss/node";
8077
8660
  function prepareCssAsset(command, basePath2, cssText) {
8078
8661
  return optimize(cssText, { file: `${basePath2 || "root"}.css`, minify: command === "build" }).code;
@@ -8088,7 +8671,7 @@ class SsrBaseArtifactBuilder {
8088
8671
  this.#app = app;
8089
8672
  this.#command = command;
8090
8673
  this.#artifactDir = `${command === "build" ? app.dist.cwdPath : app.cwdPath}/.akan/artifact`;
8091
- this.#absArtifactDir = path31.resolve(this.#artifactDir);
8674
+ this.#absArtifactDir = path33.resolve(this.#artifactDir);
8092
8675
  }
8093
8676
  async build() {
8094
8677
  const akanConfig2 = await this.#app.getConfig();
@@ -8110,7 +8693,7 @@ class SsrBaseArtifactBuilder {
8110
8693
  rscRuntimeSsrManifest,
8111
8694
  vendorMap,
8112
8695
  cssAssets,
8113
- pagesBundlePath: this.#command === "build" ? path31.relative(this.#absArtifactDir, pagesBundle.bundlePath) : pagesBundle.bundlePath,
8696
+ pagesBundlePath: this.#command === "build" ? path33.relative(this.#absArtifactDir, pagesBundle.bundlePath) : pagesBundle.bundlePath,
8114
8697
  pagesBundleBuildId: pagesBundle.buildId,
8115
8698
  domains: [...akanConfig2.domains],
8116
8699
  subRoutes: Object.fromEntries(Array.from(akanConfig2.subRoutes.entries()).map(([basePath2, domains]) => [basePath2, [...domains]])),
@@ -8119,7 +8702,7 @@ class SsrBaseArtifactBuilder {
8119
8702
  i18n: akanConfig2.i18n,
8120
8703
  imageConfig: akanConfig2.images
8121
8704
  };
8122
- await Bun.write(path31.join(this.#absArtifactDir, "base-artifact.json"), `${JSON.stringify(artifact, null, 2)}
8705
+ await Bun.write(path33.join(this.#absArtifactDir, "base-artifact.json"), `${JSON.stringify(artifact, null, 2)}
8123
8706
  `);
8124
8707
  this.#app.verbose(`[base-artifact] complete in ${Date.now() - this.#started}ms`);
8125
8708
  return { artifact, seedIndex, cssCompiler, optimizedFonts };
@@ -8167,15 +8750,15 @@ class SsrBaseArtifactBuilder {
8167
8750
  async#resolveAkanServerPath() {
8168
8751
  const candidates = [];
8169
8752
  try {
8170
- candidates.push(path31.dirname(Bun.resolveSync("akanjs/server", this.#app.workspace.workspaceRoot)));
8753
+ candidates.push(path33.dirname(Bun.resolveSync("akanjs/server", this.#app.workspace.workspaceRoot)));
8171
8754
  } catch {}
8172
- candidates.push(path31.join(this.#app.workspace.workspaceRoot, "pkgs/akanjs/server"), path31.join(this.#app.workspace.workspaceRoot, "node_modules/akanjs/server"));
8755
+ candidates.push(path33.join(this.#app.workspace.workspaceRoot, "pkgs/akanjs/server"), path33.join(this.#app.workspace.workspaceRoot, "node_modules/akanjs/server"));
8173
8756
  try {
8174
- candidates.push(path31.dirname(Bun.resolveSync("akanjs/server", path31.dirname(Bun.main))));
8757
+ candidates.push(path33.dirname(Bun.resolveSync("akanjs/server", path33.dirname(Bun.main))));
8175
8758
  } 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"));
8759
+ 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
8760
  for (const candidate of candidates) {
8178
- if (await Bun.file(path31.join(candidate, "rscClient.tsx")).exists())
8761
+ if (await Bun.file(path33.join(candidate, "rscClient.tsx")).exists())
8179
8762
  return candidate;
8180
8763
  }
8181
8764
  throw new Error(`[base-artifact] failed to locate akanjs/server; looked in: ${candidates.join(", ")}`);
@@ -8204,14 +8787,14 @@ ${preparedCssText}`).toString(36);
8204
8787
  `styles/${cssAssetName}-${cssHash}.css`,
8205
8788
  `/_akan/styles/${cssAssetName}-${cssHash}.css`
8206
8789
  ];
8207
- await Bun.write(path31.join(this.#absArtifactDir, cssRelPath), preparedCssText);
8790
+ await Bun.write(path33.join(this.#absArtifactDir, cssRelPath), preparedCssText);
8208
8791
  this.#app.verbose(`[base-artifact] wrote ${preparedCssText.length} bytes of CSS for ${basePath2} -> ${cssRelPath}`);
8209
8792
  return [basePath2, { cssUrl, cssRelPath }];
8210
8793
  }
8211
8794
  }
8212
8795
  // pkgs/@akanjs/devkit/frontendBuild/watchRootResolver.ts
8213
8796
  import fs6 from "fs";
8214
- import path32 from "path";
8797
+ import path34 from "path";
8215
8798
 
8216
8799
  class WatchRootResolver {
8217
8800
  #app;
@@ -8221,15 +8804,15 @@ class WatchRootResolver {
8221
8804
  async resolve() {
8222
8805
  const tsconfig = await this.#app.getTsConfig();
8223
8806
  const set = new Set;
8224
- set.add(path32.resolve(`${this.#app.cwdPath}/page`));
8807
+ set.add(path34.resolve(`${this.#app.cwdPath}/page`));
8225
8808
  for (const targets of Object.values(tsconfig.compilerOptions.paths ?? {})) {
8226
8809
  for (const target of targets) {
8227
8810
  if (!target)
8228
8811
  continue;
8229
- if (path32.isAbsolute(target))
8812
+ if (path34.isAbsolute(target))
8230
8813
  continue;
8231
8814
  const cleaned = target.replace(/\/?\*+.*$/, "").replace(/\/[^/]+\.[^/]+$/, "");
8232
- const resolved = path32.resolve(this.#app.workspace.workspaceRoot, cleaned);
8815
+ const resolved = path34.resolve(this.#app.workspace.workspaceRoot, cleaned);
8233
8816
  if (fs6.existsSync(resolved))
8234
8817
  set.add(resolved);
8235
8818
  }
@@ -8296,7 +8879,7 @@ class ApplicationBuildRunner {
8296
8879
  phases: this.#phases,
8297
8880
  durationMs: Date.now() - this.#startedAt,
8298
8881
  outputDir: this.#app.dist.cwdPath,
8299
- artifactDir: path33.join(this.#app.dist.cwdPath, ".akan/artifact")
8882
+ artifactDir: path35.join(this.#app.dist.cwdPath, ".akan/artifact")
8300
8883
  };
8301
8884
  }
8302
8885
  async typecheck(options = {}) {
@@ -8304,7 +8887,7 @@ class ApplicationBuildRunner {
8304
8887
  await this.#app.getPageKeys({ refresh: true });
8305
8888
  const { typecheckDir, tsconfigPath } = await this.#writeTypecheckTsconfig({ incremental });
8306
8889
  if (clean)
8307
- await rm2(path33.join(typecheckDir, "tsconfig.tsbuildinfo"), { force: true });
8890
+ await rm3(path35.join(typecheckDir, "tsconfig.tsbuildinfo"), { force: true });
8308
8891
  await this.#checkProjectInChildProcess(tsconfigPath);
8309
8892
  }
8310
8893
  async#runPhase(id, label, task, summarize, options = {}) {
@@ -8376,7 +8959,7 @@ class ApplicationBuildRunner {
8376
8959
  };
8377
8960
  }
8378
8961
  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";
8962
+ await Bun.write(path35.join(this.#app.dist.cwdPath, "console.js"), `import { cnst, db, dict, option, server, sig, srv } from "./server.js";
8380
8963
  import { assertAkanConsoleAllowed, startAkanConsole } from "./console-runtime.js";
8381
8964
 
8382
8965
  const run = async () => {
@@ -8399,14 +8982,14 @@ void run().catch((error) => {
8399
8982
  try {
8400
8983
  return Bun.resolveSync("akanjs/server/rsc-worker", import.meta.dir);
8401
8984
  } catch {
8402
- return path33.join(this.#app.workspace.workspaceRoot, "pkgs/akanjs/server/rscWorker.tsx");
8985
+ return path35.join(this.#app.workspace.workspaceRoot, "pkgs/akanjs/server/rscWorker.tsx");
8403
8986
  }
8404
8987
  }
8405
8988
  #resolveConsoleRuntimeBuildEntry() {
8406
8989
  try {
8407
- return path33.join(path33.dirname(Bun.resolveSync("akanjs/server", import.meta.dir)), "console.ts");
8990
+ return path35.join(path35.dirname(Bun.resolveSync("akanjs/server", import.meta.dir)), "console.ts");
8408
8991
  } catch {
8409
- return path33.join(this.#app.workspace.workspaceRoot, "pkgs/akanjs/server/console.ts");
8992
+ return path35.join(this.#app.workspace.workspaceRoot, "pkgs/akanjs/server/console.ts");
8410
8993
  }
8411
8994
  }
8412
8995
  async#buildCsr() {
@@ -8423,8 +9006,8 @@ void run().catch((error) => {
8423
9006
  return { base, allRoutes };
8424
9007
  }
8425
9008
  async#writeTypecheckTsconfig({ incremental = true } = {}) {
8426
- const typecheckDir = path33.join(this.#app.cwdPath, ".akan", "typecheck");
8427
- await mkdir7(typecheckDir, { recursive: true });
9009
+ const typecheckDir = path35.join(this.#app.cwdPath, ".akan", "typecheck");
9010
+ await mkdir8(typecheckDir, { recursive: true });
8428
9011
  const tsconfig = {
8429
9012
  extends: "../../tsconfig.json",
8430
9013
  compilerOptions: {
@@ -8442,7 +9025,7 @@ void run().catch((error) => {
8442
9025
  ],
8443
9026
  references: []
8444
9027
  };
8445
- const tsconfigPath = path33.join(typecheckDir, "tsconfig.json");
9028
+ const tsconfigPath = path35.join(typecheckDir, "tsconfig.json");
8446
9029
  await Bun.write(tsconfigPath, `${JSON.stringify(tsconfig, null, 2)}
8447
9030
  `);
8448
9031
  return { typecheckDir, tsconfigPath };
@@ -8468,10 +9051,10 @@ void run().catch((error) => {
8468
9051
  }
8469
9052
  async#resolveTypecheckWorkerEntry() {
8470
9053
  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")
9054
+ path35.join(this.#app.workspace.workspaceRoot, "pkgs/@akanjs/devkit/typecheck/typecheck.proc.ts"),
9055
+ path35.join(this.#app.workspace.workspaceRoot, "node_modules/@akanjs/devkit/typecheck/typecheck.proc.ts"),
9056
+ path35.join(import.meta.dir, "typecheck.proc.js"),
9057
+ path35.join(import.meta.dir, "typecheck.proc.ts")
8475
9058
  ];
8476
9059
  for (const candidate of candidates)
8477
9060
  if (await Bun.file(candidate).exists())
@@ -8504,7 +9087,7 @@ void run().catch((error) => {
8504
9087
  }
8505
9088
  }
8506
9089
  // pkgs/@akanjs/devkit/applicationReleasePackager.ts
8507
- import { cp, mkdir as mkdir8, rm as rm3 } from "fs/promises";
9090
+ import { cp, mkdir as mkdir9, rm as rm4 } from "fs/promises";
8508
9091
 
8509
9092
  // pkgs/@akanjs/devkit/uploadRelease.ts
8510
9093
  import { HttpClient as HttpClient2, Logger as Logger9 } from "akanjs/common";
@@ -8610,16 +9193,16 @@ class ApplicationReleasePackager {
8610
9193
  const platformVersion = akanConfig2.mobile.version;
8611
9194
  const buildRoot = `${this.#app.workspace.workspaceRoot}/releases/builds/${this.#app.name}`;
8612
9195
  if (await FileSys.dirExists(buildRoot))
8613
- await rm3(buildRoot, { recursive: true, force: true });
8614
- await mkdir8(buildRoot, { recursive: true });
9196
+ await rm4(buildRoot, { recursive: true, force: true });
9197
+ await mkdir9(buildRoot, { recursive: true });
8615
9198
  if (rebuild || !await FileSys.dirExists(`${this.#app.dist.cwdPath}/backend`))
8616
9199
  await this.#build();
8617
9200
  const buildVersion = `${platformVersion}-${buildNum}`;
8618
9201
  const buildPath = `${buildRoot}/${buildVersion}`;
8619
- await mkdir8(buildPath, { recursive: true });
9202
+ await mkdir9(buildPath, { recursive: true });
8620
9203
  await cp(`${this.#app.dist.cwdPath}/backend`, `${buildPath}/backend`, { recursive: true });
8621
9204
  await cp(this.#app.dist.cwdPath, buildRoot, { recursive: true });
8622
- await rm3(`${buildRoot}/frontend/.next`, { recursive: true, force: true });
9205
+ await rm4(`${buildRoot}/frontend/.next`, { recursive: true, force: true });
8623
9206
  await this.#app.workspace.spawn("tar", [
8624
9207
  "-zcf",
8625
9208
  `${this.#app.workspace.workspaceRoot}/releases/builds/${this.#app.name}-release.tar.gz`,
@@ -8639,7 +9222,7 @@ class ApplicationReleasePackager {
8639
9222
  `${this.#app.workspace.workspaceRoot}/releases/builds/${this.#app.name}-appBuild.zip`,
8640
9223
  "./csr"
8641
9224
  ]);
8642
- await rm3("./csr", { recursive: true, force: true });
9225
+ await rm4("./csr", { recursive: true, force: true });
8643
9226
  }
8644
9227
  async#writeSourceArchive({ readme }) {
8645
9228
  const sourceRoot = `${this.#app.workspace.workspaceRoot}/releases/sources/${this.#app.name}`;
@@ -8647,13 +9230,13 @@ class ApplicationReleasePackager {
8647
9230
  await cp(this.#app.dist.cwdPath, `${sourceRoot}/apps/${this.#app.name}`, { recursive: true });
8648
9231
  const libDeps = ["social", "shared", "platform", "util"];
8649
9232
  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}`;
9233
+ await Promise.all([".next", "ios", "android", "public/libs"].map(async (path36) => {
9234
+ const targetPath = `${sourceRoot}/apps/${this.#app.name}/${path36}`;
8652
9235
  if (await FileSys.dirExists(targetPath))
8653
- await rm3(targetPath, { recursive: true, force: true });
9236
+ await rm4(targetPath, { recursive: true, force: true });
8654
9237
  }));
8655
9238
  const syncPaths = [".husky", ".gitignore", "package.json"];
8656
- await Promise.all(syncPaths.map((path34) => cp(`${this.#app.workspace.cwdPath}/${path34}`, `${sourceRoot}/${path34}`, { recursive: true })));
9239
+ await Promise.all(syncPaths.map((path36) => cp(`${this.#app.workspace.cwdPath}/${path36}`, `${sourceRoot}/${path36}`, { recursive: true })));
8657
9240
  await this.#writeSourceTsconfig(sourceRoot, libDeps);
8658
9241
  await Bun.write(`${sourceRoot}/README.md`, readme);
8659
9242
  await this.#app.workspace.spawn("tar", [
@@ -8669,11 +9252,11 @@ class ApplicationReleasePackager {
8669
9252
  const maxRetry = 3;
8670
9253
  for (let i = 0;i < maxRetry; i++) {
8671
9254
  try {
8672
- await rm3(sourceRoot, { recursive: true, force: true });
9255
+ await rm4(sourceRoot, { recursive: true, force: true });
8673
9256
  } catch {}
8674
9257
  }
8675
9258
  }
8676
- await mkdir8(sourceRoot, { recursive: true });
9259
+ await mkdir9(sourceRoot, { recursive: true });
8677
9260
  }
8678
9261
  async#writeSourceTsconfig(sourceRoot, libDeps) {
8679
9262
  const tsconfig = await this.#app.workspace.readJson("tsconfig.json");
@@ -8744,20 +9327,20 @@ class ApplicationReleasePackager {
8744
9327
  }
8745
9328
  }
8746
9329
  // pkgs/@akanjs/devkit/applicationTestPreload.ts
8747
- import path34 from "path";
9330
+ import path36 from "path";
8748
9331
  var SIGNAL_TEST_PRELOAD_PATH = "test/signalTest.preload.ts";
8749
9332
  async function resolveSignalTestPreloadPath(target) {
8750
9333
  const candidates = [];
8751
9334
  const addResolvedPackageCandidate = (basePath2) => {
8752
9335
  try {
8753
- candidates.push(path34.join(path34.dirname(Bun.resolveSync("akanjs/package.json", basePath2)), SIGNAL_TEST_PRELOAD_PATH));
9336
+ candidates.push(path36.join(path36.dirname(Bun.resolveSync("akanjs/package.json", basePath2)), SIGNAL_TEST_PRELOAD_PATH));
8754
9337
  } catch {}
8755
9338
  };
8756
9339
  addResolvedPackageCandidate(target.cwdPath);
8757
9340
  addResolvedPackageCandidate(process.cwd());
8758
- addResolvedPackageCandidate(path34.dirname(Bun.main));
9341
+ addResolvedPackageCandidate(path36.dirname(Bun.main));
8759
9342
  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));
9343
+ 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
9344
  for (const candidate of [...new Set(candidates)]) {
8762
9345
  if (await Bun.file(candidate).exists())
8763
9346
  return candidate;
@@ -8766,8 +9349,8 @@ async function resolveSignalTestPreloadPath(target) {
8766
9349
  }
8767
9350
  // pkgs/@akanjs/devkit/builder.ts
8768
9351
  import { existsSync as existsSync2 } from "fs";
8769
- import { mkdir as mkdir9 } from "fs/promises";
8770
- import path35 from "path";
9352
+ import { mkdir as mkdir10 } from "fs/promises";
9353
+ import path37 from "path";
8771
9354
  var SKIP_ENTRY_DIR_SET = new Set(["node_modules", "dist", "build", ".git", ".next"]);
8772
9355
  var assetExtensions = [".css", ".md", ".js", ".png", ".ico", ".svg", ".json", ".template"];
8773
9356
  var assetLoader = Object.fromEntries(assetExtensions.map((ext) => [ext, "file"]));
@@ -8784,14 +9367,14 @@ class Builder {
8784
9367
  #globEntrypoints(cwd, pattern) {
8785
9368
  const glob = new Bun.Glob(pattern);
8786
9369
  return Array.from(glob.scanSync({ cwd, onlyFiles: true })).filter((relativePath) => {
8787
- const segments = relativePath.split(path35.sep);
9370
+ const segments = relativePath.split(path37.sep);
8788
9371
  return !segments.some((segment) => SKIP_ENTRY_DIR_SET.has(segment));
8789
- }).map((rel) => path35.join(cwd, rel));
9372
+ }).map((rel) => path37.join(cwd, rel));
8790
9373
  }
8791
9374
  #globFiles(cwd, pattern = "**/*.*") {
8792
9375
  const glob = new Bun.Glob(pattern);
8793
9376
  return Array.from(glob.scanSync({ cwd, onlyFiles: true })).filter((relativePath) => {
8794
- const segments = relativePath.split(path35.sep);
9377
+ const segments = relativePath.split(path37.sep);
8795
9378
  return !segments.some((segment) => SKIP_ENTRY_DIR_SET.has(segment));
8796
9379
  });
8797
9380
  }
@@ -8799,17 +9382,17 @@ class Builder {
8799
9382
  const out = [];
8800
9383
  for (const p of additionalEntryPoints) {
8801
9384
  if (p.includes("*")) {
8802
- const rel = p.startsWith(`${cwd}/`) || p.startsWith(`${cwd}${path35.sep}`) ? p.slice(cwd.length + 1) : p;
9385
+ const rel = p.startsWith(`${cwd}/`) || p.startsWith(`${cwd}${path37.sep}`) ? p.slice(cwd.length + 1) : p;
8803
9386
  out.push(...this.#globEntrypoints(cwd, rel));
8804
9387
  } else
8805
- out.push(path35.isAbsolute(p) ? p : path35.join(cwd, p));
9388
+ out.push(path37.isAbsolute(p) ? p : path37.join(cwd, p));
8806
9389
  }
8807
9390
  return out;
8808
9391
  }
8809
9392
  #getBuildOptions({ bundle = false, additionalEntryPoints = [] } = {}) {
8810
9393
  const cwd = this.#executor.cwdPath;
8811
9394
  const entrypoints = [
8812
- ...bundle ? [path35.join(cwd, "index.ts")] : this.#globEntrypoints(cwd, "**/*.{ts,tsx}"),
9395
+ ...bundle ? [path37.join(cwd, "index.ts")] : this.#globEntrypoints(cwd, "**/*.{ts,tsx}"),
8813
9396
  ...this.#resolveAdditionalEntrypoints(cwd, additionalEntryPoints)
8814
9397
  ];
8815
9398
  return {
@@ -8830,9 +9413,9 @@ class Builder {
8830
9413
  for (const relativePath of this.#globFiles(cwd)) {
8831
9414
  if (relativePath === "package.json")
8832
9415
  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 });
9416
+ const sourcePath = path37.join(cwd, relativePath);
9417
+ const targetPath = path37.join(this.#distExecutor.cwdPath, relativePath);
9418
+ await mkdir10(path37.dirname(targetPath), { recursive: true });
8836
9419
  await Bun.write(targetPath, Bun.file(sourcePath));
8837
9420
  }
8838
9421
  }
@@ -8843,13 +9426,13 @@ class Builder {
8843
9426
  return withoutFormatDir;
8844
9427
  if (!hasDotSlash && withoutFormatDir === publishedPath)
8845
9428
  return publishedPath;
8846
- const parsed = path35.posix.parse(withoutFormatDir);
9429
+ const parsed = path37.posix.parse(withoutFormatDir);
8847
9430
  if (![".js", ".mjs", ".cjs"].includes(parsed.ext))
8848
9431
  return withoutFormatDir;
8849
- const withoutExt = path35.posix.join(parsed.dir, parsed.name);
9432
+ const withoutExt = path37.posix.join(parsed.dir, parsed.name);
8850
9433
  const sourcePath = withoutExt.startsWith("./") ? withoutExt.slice(2) : withoutExt;
8851
9434
  const sourceCandidates = [`${sourcePath}.ts`, `${sourcePath}.tsx`];
8852
- const matchedSource = sourceCandidates.find((candidate) => existsSync2(path35.join(this.#executor.cwdPath, candidate)));
9435
+ const matchedSource = sourceCandidates.find((candidate) => existsSync2(path37.join(this.#executor.cwdPath, candidate)));
8853
9436
  if (!matchedSource)
8854
9437
  return withoutFormatDir;
8855
9438
  return hasDotSlash ? `./${matchedSource}` : matchedSource;
@@ -8898,10 +9481,10 @@ class Builder {
8898
9481
  }
8899
9482
  }
8900
9483
  // pkgs/@akanjs/devkit/capacitorApp.ts
8901
- import { cp as cp2, mkdir as mkdir10, rm as rm4 } from "fs/promises";
8902
- import path36 from "path";
9484
+ import { cp as cp2, mkdir as mkdir11, rm as rm5 } from "fs/promises";
9485
+ import path38 from "path";
8903
9486
  import { MobileProject } from "@trapezedev/project";
8904
- import { capitalize as capitalize3 } from "akanjs/common";
9487
+ import { capitalize as capitalize4 } from "akanjs/common";
8905
9488
 
8906
9489
  // pkgs/@akanjs/devkit/fileEditor.ts
8907
9490
  class FileEditor {
@@ -9094,10 +9677,10 @@ class CapacitorApp {
9094
9677
  constructor(app, target) {
9095
9678
  this.app = app;
9096
9679
  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");
9680
+ this.targetRootPath = path38.posix.join(".akan", "mobile", this.target.name);
9681
+ this.targetRoot = path38.join(this.app.cwdPath, this.targetRootPath);
9682
+ this.targetWebRoot = path38.join(this.targetRoot, "www");
9683
+ this.targetAssetRoot = path38.join(this.targetRoot, "assets");
9101
9684
  this.project = new MobileProject(this.app.cwdPath, {
9102
9685
  android: { path: this.androidRootPath },
9103
9686
  ios: { path: this.iosProjectPath }
@@ -9109,13 +9692,13 @@ class CapacitorApp {
9109
9692
  env = "debug",
9110
9693
  regenerate = false
9111
9694
  } = {}) {
9112
- await mkdir10(this.targetRoot, { recursive: true });
9695
+ await mkdir11(this.targetRoot, { recursive: true });
9113
9696
  await this.#writeCapacitorConfig();
9114
9697
  if (regenerate) {
9115
9698
  if (!platform || platform === "ios")
9116
- await rm4(path36.join(this.app.cwdPath, this.iosRootPath), { recursive: true, force: true });
9699
+ await rm5(path38.join(this.app.cwdPath, this.iosRootPath), { recursive: true, force: true });
9117
9700
  if (!platform || platform === "android")
9118
- await rm4(path36.join(this.app.cwdPath, this.androidRootPath), { recursive: true, force: true });
9701
+ await rm5(path38.join(this.app.cwdPath, this.androidRootPath), { recursive: true, force: true });
9119
9702
  }
9120
9703
  const project = this.project;
9121
9704
  await this.project.load();
@@ -9179,7 +9762,7 @@ class CapacitorApp {
9179
9762
  await this.#spawnMobile("npx", ["cap", "sync", "android"], { operation, env });
9180
9763
  }
9181
9764
  async#updateAndroidBuildTypes() {
9182
- const appGradle = await FileEditor.create(path36.join(this.app.cwdPath, this.androidRootPath, "app/build.gradle"));
9765
+ const appGradle = await FileEditor.create(path38.join(this.app.cwdPath, this.androidRootPath, "app/build.gradle"));
9183
9766
  const buildTypesBlock = `
9184
9767
  debug {
9185
9768
  applicationIdSuffix ".debug"
@@ -9222,7 +9805,7 @@ class CapacitorApp {
9222
9805
  const gradleCommand = isWindows ? "gradlew.bat" : "./gradlew";
9223
9806
  await this.app.spawn(gradleCommand, [assembleType === "apk" ? "assembleRelease" : "bundleRelease"], {
9224
9807
  stdio: "inherit",
9225
- cwd: path36.join(this.app.cwdPath, this.androidRootPath),
9808
+ cwd: path38.join(this.app.cwdPath, this.androidRootPath),
9226
9809
  env: await this.#commandEnv("release", env)
9227
9810
  });
9228
9811
  }
@@ -9230,10 +9813,10 @@ class CapacitorApp {
9230
9813
  await this.#spawnMobile("npx", ["cap", "open", "android"], { operation: "local", env: "local" });
9231
9814
  }
9232
9815
  async#ensureAndroidAssetsDir() {
9233
- await mkdir10(path36.join(this.app.cwdPath, this.androidAssetsPath), { recursive: true });
9816
+ await mkdir11(path38.join(this.app.cwdPath, this.androidAssetsPath), { recursive: true });
9234
9817
  }
9235
9818
  async#ensureAndroidDebugKeystore() {
9236
- const keystorePath = path36.join(this.app.cwdPath, this.androidRootPath, "app/debug.keystore");
9819
+ const keystorePath = path38.join(this.app.cwdPath, this.androidRootPath, "app/debug.keystore");
9237
9820
  if (await Bun.file(keystorePath).exists())
9238
9821
  return;
9239
9822
  await this.#spawn("keytool", [
@@ -9279,12 +9862,12 @@ class CapacitorApp {
9279
9862
  await this.#prepareAndroid({ operation: "release", env: "main" });
9280
9863
  }
9281
9864
  async prepareWww() {
9282
- const htmlSource = path36.join(this.app.dist.cwdPath, "csr", targetHtmlFilename(this.target));
9865
+ const htmlSource = path38.join(this.app.dist.cwdPath, "csr", targetHtmlFilename(this.target));
9283
9866
  if (!await Bun.file(htmlSource).exists())
9284
9867
  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()));
9868
+ await rm5(this.targetWebRoot, { recursive: true, force: true });
9869
+ await mkdir11(this.targetWebRoot, { recursive: true });
9870
+ await Bun.write(path38.join(this.targetWebRoot, "index.html"), this.#injectMobileTargetMeta(await Bun.file(htmlSource).text()));
9288
9871
  }
9289
9872
  #injectMobileTargetMeta(html) {
9290
9873
  const basePath2 = this.target.basePath?.replace(/^\/+|\/+$/g, "") ?? "";
@@ -9295,8 +9878,8 @@ class CapacitorApp {
9295
9878
  </head>`);
9296
9879
  }
9297
9880
  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("/");
9881
+ await mkdir11(this.targetRoot, { recursive: true });
9882
+ const appInfoPath = path38.relative(this.app.cwdPath, path38.join(this.app.cwdPath, "akan.app.json")).split(path38.sep).join("/");
9300
9883
  const content = `import type { AppScanResult } from "akanjs";
9301
9884
  import { withBase } from "${process.env.USE_AKANJS_PKGS === "true" ? "../../pkgs/" : ""}akanjs/capacitor.base.config";
9302
9885
  import appInfo from "${appInfoPath.startsWith(".") ? appInfoPath : `./${appInfoPath}`}";
@@ -9317,18 +9900,18 @@ export default withBase(
9317
9900
  appInfo as AppScanResult,
9318
9901
  );
9319
9902
  `;
9320
- await Bun.write(path36.join(this.app.cwdPath, "capacitor.config.ts"), content);
9903
+ await Bun.write(path38.join(this.app.cwdPath, "capacitor.config.ts"), content);
9321
9904
  }
9322
9905
  async#prepareTargetAssets() {
9323
9906
  if (!this.target.assets)
9324
9907
  return;
9325
- await mkdir10(this.targetAssetRoot, { recursive: true });
9908
+ await mkdir11(this.targetAssetRoot, { recursive: true });
9326
9909
  if (this.target.assets.icon)
9327
- await cp2(path36.join(this.app.cwdPath, this.target.assets.icon), path36.join(this.targetAssetRoot, "icon.png"), {
9910
+ await cp2(path38.join(this.app.cwdPath, this.target.assets.icon), path38.join(this.targetAssetRoot, "icon.png"), {
9328
9911
  force: true
9329
9912
  });
9330
9913
  if (this.target.assets.splash)
9331
- await cp2(path36.join(this.app.cwdPath, this.target.assets.splash), path36.join(this.targetAssetRoot, "splash.png"), {
9914
+ await cp2(path38.join(this.app.cwdPath, this.target.assets.splash), path38.join(this.targetAssetRoot, "splash.png"), {
9332
9915
  force: true
9333
9916
  });
9334
9917
  }
@@ -9336,11 +9919,11 @@ export default withBase(
9336
9919
  const files = this.target.files?.[platform];
9337
9920
  if (!files)
9338
9921
  return;
9339
- const platformRoot = path36.join(this.app.cwdPath, platform === "ios" ? this.iosRootPath : this.androidRootPath);
9922
+ const platformRoot = path38.join(this.app.cwdPath, platform === "ios" ? this.iosRootPath : this.androidRootPath);
9340
9923
  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 });
9924
+ const targetPath = path38.join(platformRoot, to);
9925
+ await mkdir11(path38.dirname(targetPath), { recursive: true });
9926
+ await cp2(path38.join(this.app.cwdPath, from), targetPath, { force: true });
9344
9927
  }));
9345
9928
  }
9346
9929
  async#generateAssets({ operation, env }) {
@@ -9350,7 +9933,7 @@ export default withBase(
9350
9933
  "@capacitor/assets",
9351
9934
  "generate",
9352
9935
  "--assetPath",
9353
- path36.posix.join(this.targetRootPath, "assets"),
9936
+ path38.posix.join(this.targetRootPath, "assets"),
9354
9937
  "--iosProject",
9355
9938
  this.iosProjectPath,
9356
9939
  "--androidProject",
@@ -9452,7 +10035,7 @@ export default withBase(
9452
10035
  this.#setPermissionsInAndroid(["POST_NOTIFICATIONS"]);
9453
10036
  }
9454
10037
  async#setPermissionInIos(permissions) {
9455
- const updateNs = Object.fromEntries(Object.entries(permissions).map(([key, value]) => [`NS${capitalize3(key)}`, value]));
10038
+ const updateNs = Object.fromEntries(Object.entries(permissions).map(([key, value]) => [`NS${capitalize4(key)}`, value]));
9456
10039
  await Promise.all([
9457
10040
  this.project.ios.updateInfoPlist(this.iosTargetName, "Debug", updateNs),
9458
10041
  this.project.ios.updateInfoPlist(this.iosTargetName, "Release", updateNs)
@@ -9537,15 +10120,15 @@ var Pkg = createInternalArgToken("Pkg");
9537
10120
  var Module = createInternalArgToken("Module");
9538
10121
  var Workspace = createInternalArgToken("Workspace");
9539
10122
  // pkgs/@akanjs/devkit/commandDecorators/command.ts
9540
- import path37 from "path";
10123
+ import path39 from "path";
9541
10124
  import { confirm, input as input2, select as select2 } from "@inquirer/prompts";
9542
10125
  import { Logger as Logger10 } from "akanjs/common";
9543
10126
  import chalk6 from "chalk";
9544
10127
  import { program } from "commander";
9545
10128
 
9546
10129
  // 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)}`;
10130
+ var capitalize5 = (value) => value.slice(0, 1).toUpperCase() + value.slice(1);
10131
+ var createDependencyKey = (refName, kind) => `${refName}${capitalize5(kind)}`;
9549
10132
 
9550
10133
  class CommandContainer {
9551
10134
  static #instances = new Map;
@@ -10037,7 +10620,7 @@ var runCommands = async (...commands) => {
10037
10620
  process.exit(1);
10038
10621
  });
10039
10622
  const __dirname2 = getDirname(import.meta.url);
10040
- const packageJsonCandidates = [`${path37.dirname(Bun.main)}/package.json`, `${__dirname2}/../package.json`];
10623
+ const packageJsonCandidates = [`${path39.dirname(Bun.main)}/package.json`, `${__dirname2}/../package.json`];
10041
10624
  let cliPackageJson = null;
10042
10625
  for (const packageJsonPath of packageJsonCandidates) {
10043
10626
  if (!await FileSys.fileExists(packageJsonPath))
@@ -10315,8 +10898,8 @@ var scanModuleSpecifiers = (source, filePath, includeExports) => {
10315
10898
  return importSpecifiers;
10316
10899
  };
10317
10900
  var parseTsConfig = (tsConfigPath = "./tsconfig.json") => {
10318
- const configFile = ts7.readConfigFile(tsConfigPath, (path38) => {
10319
- return ts7.sys.readFile(path38);
10901
+ const configFile = ts7.readConfigFile(tsConfigPath, (path40) => {
10902
+ return ts7.sys.readFile(path40);
10320
10903
  });
10321
10904
  return ts7.parseJsonConfigFileContent(configFile.config, ts7.sys, realpathSync(tsConfigPath).replace(/[^/\\]+$/, ""));
10322
10905
  };
@@ -11513,7 +12096,7 @@ class ApplicationCommand extends command("application", [ApplicationScript], ({
11513
12096
  import { Logger as Logger16 } from "akanjs/common";
11514
12097
 
11515
12098
  // pkgs/@akanjs/cli/package/package.runner.ts
11516
- import path38 from "path";
12099
+ import path40 from "path";
11517
12100
  import { Logger as Logger14 } from "akanjs/common";
11518
12101
  var {$: $2 } = globalThis.Bun;
11519
12102
 
@@ -11533,11 +12116,11 @@ class PackageRunner extends runner("package") {
11533
12116
  }
11534
12117
  async#getInstalledPackageJson() {
11535
12118
  const packageJsonCandidates = [
11536
- `${path38.dirname(Bun.main)}/package.json`,
12119
+ `${path40.dirname(Bun.main)}/package.json`,
11537
12120
  `${process.cwd()}/node_modules/akanjs/package.json`
11538
12121
  ];
11539
12122
  try {
11540
- packageJsonCandidates.unshift(Bun.resolveSync("akanjs/package.json", path38.dirname(Bun.main)));
12123
+ packageJsonCandidates.unshift(Bun.resolveSync("akanjs/package.json", path40.dirname(Bun.main)));
11541
12124
  } catch {}
11542
12125
  for (const packageJsonPath of packageJsonCandidates) {
11543
12126
  if (!await Bun.file(packageJsonPath).exists())
@@ -11546,7 +12129,7 @@ class PackageRunner extends runner("package") {
11546
12129
  if (packageJson.name === "akanjs" || packageJson.name === "@akanjs/cli")
11547
12130
  return packageJson;
11548
12131
  }
11549
- throw new Error(`[package] failed to locate akanjs package.json from ${path38.dirname(Bun.main)}`);
12132
+ throw new Error(`[package] failed to locate akanjs package.json from ${path40.dirname(Bun.main)}`);
11550
12133
  }
11551
12134
  async createPackage(workspace, pkgName) {
11552
12135
  await workspace.applyTemplate({ basePath: `pkgs/${pkgName}`, template: "pkgRoot", dict: { pkgName } });
@@ -11721,7 +12304,7 @@ class PackageScript extends script("package", [PackageRunner]) {
11721
12304
  }
11722
12305
 
11723
12306
  // pkgs/@akanjs/cli/cloud/cloud.runner.ts
11724
- import path39 from "path";
12307
+ import path41 from "path";
11725
12308
  import { confirm as confirm4, input as input5, select as select7 } from "@inquirer/prompts";
11726
12309
  import { Logger as Logger15, sleep } from "akanjs/common";
11727
12310
  import chalk7 from "chalk";
@@ -11992,7 +12575,7 @@ ${chalk7.green("\u27A4")} Authentication Required`));
11992
12575
  await Promise.all(akanPkgs.map(async (library) => {
11993
12576
  Logger15.info(`Publishing ${library}@${nextVersion} to ${registry ?? "npm"}...`);
11994
12577
  await workspace.spawn("npm", ["publish", "--tag", tag, ...this.#getRegistryArgs(registry), ...this.#getLocalRegistryAuthArgs(registry)], {
11995
- cwd: path39.join(workspace.workspaceRoot, "dist/pkgs", library),
12578
+ cwd: path41.join(workspace.workspaceRoot, "dist/pkgs", library),
11996
12579
  env: this.#getRegistryEnv(registry),
11997
12580
  stdio: "inherit"
11998
12581
  });
@@ -12050,7 +12633,7 @@ ${chalk7.green("\u27A4")} Authentication Required`));
12050
12633
  await workspace.remove(localPath);
12051
12634
  }
12052
12635
  async uploadEnv(cloudApi2, workspaceId, filePath) {
12053
- const file = new File([Bun.file(filePath)], path39.basename(filePath));
12636
+ const file = new File([Bun.file(filePath)], path41.basename(filePath));
12054
12637
  await cloudApi2.uploadEnv(workspaceId, file);
12055
12638
  }
12056
12639
  async downloadEnvByScp(workspace) {
@@ -12142,14 +12725,14 @@ class CloudScript extends script("cloud", [CloudRunner, ApplicationScript, Packa
12142
12725
  }
12143
12726
  async uploadEnv(workspace) {
12144
12727
  const workspaceId = workspace.getWorkspaceId({ allowEmpty: true });
12145
- const { path: path40 } = await this.cloudRunner.gatherEnvFiles(workspace);
12728
+ const { path: path42 } = await this.cloudRunner.gatherEnvFiles(workspace);
12146
12729
  if (workspaceId) {
12147
12730
  await this.login(workspace);
12148
12731
  const cloudApi2 = await CloudApi.fromHost(workspace);
12149
- await this.cloudRunner.uploadEnv(cloudApi2, workspaceId, path40);
12732
+ await this.cloudRunner.uploadEnv(cloudApi2, workspaceId, path42);
12150
12733
  return;
12151
12734
  }
12152
- await this.cloudRunner.uploadEnvByScp(workspace, path40);
12735
+ await this.cloudRunner.uploadEnvByScp(workspace, path42);
12153
12736
  }
12154
12737
  async deployAkan(workspace, { test = true, registryUrl } = {}) {
12155
12738
  const akanPkgs = await this.cloudRunner.getAkanPkgs(workspace);
@@ -12563,14 +13146,14 @@ class GuidelinePrompt extends Prompter {
12563
13146
  async#getScanFilePaths(matchPattern, { avoidDirs = ["node_modules", ".next"], filterText } = {}) {
12564
13147
  const glob = new Bun.Glob(matchPattern);
12565
13148
  const paths = [];
12566
- for await (const path40 of glob.scan({ cwd: this.workspace.workspaceRoot, absolute: true })) {
12567
- if (avoidDirs.some((dir) => path40.includes(dir)))
13149
+ for await (const path42 of glob.scan({ cwd: this.workspace.workspaceRoot, absolute: true })) {
13150
+ if (avoidDirs.some((dir) => path42.includes(dir)))
12568
13151
  continue;
12569
- const fileContent = await FileSys.readText(path40);
13152
+ const fileContent = await FileSys.readText(path42);
12570
13153
  const textFilter = filterText ? new RegExp(filterText) : null;
12571
13154
  if (filterText && !textFilter?.test(fileContent))
12572
13155
  continue;
12573
- paths.push(path40);
13156
+ paths.push(path42);
12574
13157
  }
12575
13158
  return paths;
12576
13159
  }
@@ -12889,8 +13472,8 @@ class LibraryCommand extends command("library", [LibraryScript], ({ public: targ
12889
13472
  }
12890
13473
 
12891
13474
  // pkgs/@akanjs/cli/localRegistry/localRegistry.runner.ts
12892
- import { mkdir as mkdir11, rm as rm5 } from "fs/promises";
12893
- import path40 from "path";
13475
+ import { mkdir as mkdir12, rm as rm6 } from "fs/promises";
13476
+ import path42 from "path";
12894
13477
  import { Logger as Logger19 } from "akanjs/common";
12895
13478
  var defaultLocalRegistryUrl = "http://127.0.0.1:4873";
12896
13479
  var containerName = "akan-verdaccio";
@@ -12908,9 +13491,9 @@ class LocalRegistryRunner extends runner("localRegistry") {
12908
13491
  Logger19.info(`Local registry is already running at ${registry}`);
12909
13492
  return registry;
12910
13493
  } 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 });
13494
+ const configPath2 = path42.join(workspace.workspaceRoot, "pkgs/@akanjs/cli/localRegistry/verdaccio.yaml");
13495
+ const storagePath = path42.join(workspace.workspaceRoot, ".akan/verdaccio/storage");
13496
+ await mkdir12(storagePath, { recursive: true });
12914
13497
  await workspace.spawn("docker", [
12915
13498
  "run",
12916
13499
  "--rm",
@@ -12932,13 +13515,13 @@ class LocalRegistryRunner extends runner("localRegistry") {
12932
13515
  try {
12933
13516
  await workspace.spawn("docker", ["rm", "-f", containerName], { stdio: "inherit" });
12934
13517
  } catch {}
12935
- await rm5(path40.join(workspace.workspaceRoot, ".akan/verdaccio"), { recursive: true, force: true });
13518
+ await rm6(path42.join(workspace.workspaceRoot, ".akan/verdaccio"), { recursive: true, force: true });
12936
13519
  Logger19.info("Local registry storage has been reset");
12937
13520
  }
12938
13521
  async smoke(workspace, { registryUrl } = {}) {
12939
13522
  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 });
13523
+ const smokeRoot = path42.join(workspace.workspaceRoot, ".akan/e2e");
13524
+ await rm6(path42.join(smokeRoot, smokeRepoName), { recursive: true, force: true });
12942
13525
  await workspace.spawn(process.execPath, [
12943
13526
  "dist/pkgs/create-akan-workspace/index.js",
12944
13527
  smokeRepoName,
@@ -12955,12 +13538,12 @@ class LocalRegistryRunner extends runner("localRegistry") {
12955
13538
  stdio: "inherit"
12956
13539
  });
12957
13540
  await workspace.spawn("akan", ["typecheck", smokeAppName], {
12958
- cwd: path40.join(smokeRoot, smokeRepoName),
13541
+ cwd: path42.join(smokeRoot, smokeRepoName),
12959
13542
  env: { ...process.env, AKAN_NPM_REGISTRY: registry, NPM_CONFIG_REGISTRY: registry },
12960
13543
  stdio: "inherit"
12961
13544
  });
12962
13545
  await workspace.spawn("akan", ["build", smokeAppName], {
12963
- cwd: path40.join(smokeRoot, smokeRepoName),
13546
+ cwd: path42.join(smokeRoot, smokeRepoName),
12964
13547
  env: { ...process.env, AKAN_NPM_REGISTRY: registry, NPM_CONFIG_REGISTRY: registry },
12965
13548
  stdio: "inherit"
12966
13549
  });
@@ -13040,7 +13623,7 @@ import { lowerlize } from "akanjs/common";
13040
13623
 
13041
13624
  // pkgs/@akanjs/cli/module/module.script.ts
13042
13625
  import { input as input6 } from "@inquirer/prompts";
13043
- import { capitalize as capitalize7, randomPicks as randomPicks2 } from "akanjs/common";
13626
+ import { capitalize as capitalize8, randomPicks as randomPicks2 } from "akanjs/common";
13044
13627
 
13045
13628
  // pkgs/@akanjs/cli/page/page.runner.ts
13046
13629
  class PageRunner extends runner("page") {
@@ -13070,7 +13653,7 @@ function pluralizeName(name) {
13070
13653
  }
13071
13654
 
13072
13655
  // pkgs/@akanjs/cli/module/module.request.ts
13073
- import { capitalize as capitalize5 } from "akanjs/common";
13656
+ import { capitalize as capitalize6 } from "akanjs/common";
13074
13657
 
13075
13658
  // pkgs/@akanjs/cli/module/module.prompt.ts
13076
13659
  var componentDefaultDescription = ({
@@ -13195,7 +13778,7 @@ var requestTemplate = ({
13195
13778
  ${componentDefaultDescription({
13196
13779
  sysName,
13197
13780
  modelName,
13198
- ModelName: ModelName ?? capitalize5(modelName),
13781
+ ModelName: ModelName ?? capitalize6(modelName),
13199
13782
  exampleFiles,
13200
13783
  constant,
13201
13784
  properties
@@ -13252,7 +13835,7 @@ var requestView = ({
13252
13835
  ${componentDefaultDescription({
13253
13836
  sysName,
13254
13837
  modelName,
13255
- ModelName: ModelName ?? capitalize5(modelName),
13838
+ ModelName: ModelName ?? capitalize6(modelName),
13256
13839
  exampleFiles,
13257
13840
  constant,
13258
13841
  properties
@@ -13313,7 +13896,7 @@ var requestUnit = ({
13313
13896
  ${componentDefaultDescription({
13314
13897
  sysName,
13315
13898
  modelName,
13316
- ModelName: ModelName ?? capitalize5(modelName),
13899
+ ModelName: ModelName ?? capitalize6(modelName),
13317
13900
  exampleFiles,
13318
13901
  constant,
13319
13902
  properties
@@ -13362,7 +13945,7 @@ var requestUnit = ({
13362
13945
  `;
13363
13946
 
13364
13947
  // pkgs/@akanjs/cli/module/module.runner.ts
13365
- import { capitalize as capitalize6 } from "akanjs/common";
13948
+ import { capitalize as capitalize7 } from "akanjs/common";
13366
13949
  class ModuleRunner extends runner("module") {
13367
13950
  async createService(module) {
13368
13951
  const serviceName = module.name.replace(/^_+/, "");
@@ -13392,13 +13975,13 @@ class ModuleRunner extends runner("module") {
13392
13975
  async createComponentTemplate(module, type) {
13393
13976
  await module.sys.applyTemplate({
13394
13977
  basePath: `./lib/${module.name}`,
13395
- template: `module/__Model__.${capitalize6(type)}.tsx`,
13978
+ template: `module/__Model__.${capitalize7(type)}.tsx`,
13396
13979
  dict: { model: module.name, appName: module.sys.name }
13397
13980
  });
13398
13981
  return {
13399
13982
  component: {
13400
- filename: `${module.name}.${capitalize6(type)}.tsx`,
13401
- content: await module.sys.readFile(`lib/${module.name}/${capitalize6(module.name)}.${capitalize6(type)}.tsx`)
13983
+ filename: `${module.name}.${capitalize7(type)}.tsx`,
13984
+ content: await module.sys.readFile(`lib/${module.name}/${capitalize7(module.name)}.${capitalize7(type)}.tsx`)
13402
13985
  }
13403
13986
  };
13404
13987
  }
@@ -13524,7 +14107,7 @@ class ModuleScript extends script("module", [ModuleRunner, PageScript]) {
13524
14107
  async createTemplate(mod) {
13525
14108
  const { component: template } = await this.moduleRunner.createComponentTemplate(mod, "template");
13526
14109
  const templateExampleFiles = (await mod.sys.getTemplatesSourceCode()).filter((f) => !f.filePath.includes(`${mod.name}.Template.tsx`));
13527
- const Name = capitalize7(mod.name);
14110
+ const Name = capitalize8(mod.name);
13528
14111
  const relatedCnsts = getRelatedCnsts(`${mod.sys.cwdPath}/lib/${mod.name}/${mod.name}.constant.ts`);
13529
14112
  const constant = await FileSys.readText(`${mod.sys.cwdPath}/lib/${mod.name}/${mod.name}.constant.ts`);
13530
14113
  const session = new AiSession("createTemplate", { workspace: mod.sys.workspace, cacheKey: mod.name });
@@ -13543,7 +14126,7 @@ class ModuleScript extends script("module", [ModuleRunner, PageScript]) {
13543
14126
  }
13544
14127
  async createUnit(mod) {
13545
14128
  const { component: unit } = await this.moduleRunner.createComponentTemplate(mod, "unit");
13546
- const Name = capitalize7(mod.name);
14129
+ const Name = capitalize8(mod.name);
13547
14130
  const unitExampleFiles = (await mod.sys.getUnitsSourceCode()).filter((f) => !f.filePath.includes(`${mod.name}.Unit.tsx`));
13548
14131
  const relatedCnsts = getRelatedCnsts(`${mod.sys.cwdPath}/lib/${mod.name}/${mod.name}.constant.ts`);
13549
14132
  const constant = await FileSys.readText(`${mod.sys.cwdPath}/lib/${mod.name}/${mod.name}.constant.ts`);
@@ -13564,7 +14147,7 @@ class ModuleScript extends script("module", [ModuleRunner, PageScript]) {
13564
14147
  async createView(mod) {
13565
14148
  const { component: view } = await this.moduleRunner.createComponentTemplate(mod, "view");
13566
14149
  const viewExampleFiles = (await mod.sys.getViewsSourceCode()).filter((f) => !f.filePath.includes(`${mod.name}.View.tsx`));
13567
- const Name = capitalize7(mod.name);
14150
+ const Name = capitalize8(mod.name);
13568
14151
  const relatedCnsts = getRelatedCnsts(`${mod.sys.cwdPath}/lib/${mod.name}/${mod.name}.constant.ts`);
13569
14152
  const constant = await FileSys.readText(`${mod.sys.cwdPath}/lib/${mod.name}/${mod.name}.constant.ts`);
13570
14153
  const session = new AiSession("createView", { workspace: mod.sys.workspace, cacheKey: mod.name });
@@ -13841,11 +14424,11 @@ class ScalarCommand extends command("scalar", [ScalarScript], ({ public: target
13841
14424
  }
13842
14425
 
13843
14426
  // pkgs/@akanjs/cli/workspace/workspace.script.ts
13844
- import path42 from "path";
14427
+ import path44 from "path";
13845
14428
  import { Logger as Logger20 } from "akanjs/common";
13846
14429
 
13847
14430
  // pkgs/@akanjs/cli/workspace/workspace.runner.ts
13848
- import path41 from "path";
14431
+ import path43 from "path";
13849
14432
  var defaultWorkspacePeerDependencies = new Set([
13850
14433
  "@react-spring/web",
13851
14434
  "@use-gesture/react",
@@ -13896,7 +14479,7 @@ class WorkspaceRunner extends runner("workspace") {
13896
14479
  owner = ""
13897
14480
  }) {
13898
14481
  const cwdPath = process.cwd();
13899
- const workspaceRoot = path41.join(cwdPath, dirname2, repoName);
14482
+ const workspaceRoot = path43.join(cwdPath, dirname2, repoName);
13900
14483
  const normalizedRegistryUrl = registryUrl ? getNpmRegistryUrl(registryUrl) : undefined;
13901
14484
  const workspace = WorkspaceExecutor.fromRoot({ workspaceRoot, repoName });
13902
14485
  const templateSpinner = workspace.spinning(`Creating workspace template files in ${dirname2}/${repoName}...`);
@@ -13952,9 +14535,9 @@ class WorkspaceRunner extends runner("workspace") {
13952
14535
  }
13953
14536
  async#getCliPackageJson() {
13954
14537
  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")
14538
+ path43.join(import.meta.dir, "../package.json"),
14539
+ path43.join(import.meta.dir, "package.json"),
14540
+ path43.join(path43.dirname(Bun.main), "package.json")
13958
14541
  ];
13959
14542
  try {
13960
14543
  packageJsonCandidates.unshift(Bun.resolveSync("@akanjs/cli/package.json", import.meta.dir));
@@ -13970,9 +14553,9 @@ class WorkspaceRunner extends runner("workspace") {
13970
14553
  }
13971
14554
  async#getAkanPackageJson() {
13972
14555
  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")
14556
+ path43.join(import.meta.dir, "../../../akanjs/package.json"),
14557
+ path43.join(process.cwd(), "pkgs/akanjs/package.json"),
14558
+ path43.join(path43.dirname(Bun.main), "node_modules/akanjs/package.json")
13976
14559
  ];
13977
14560
  try {
13978
14561
  packageJsonCandidates.unshift(Bun.resolveSync("akanjs/package.json", import.meta.dir));
@@ -13986,13 +14569,13 @@ class WorkspaceRunner extends runner("workspace") {
13986
14569
  }
13987
14570
  let current = import.meta.dir;
13988
14571
  for (let depth = 0;depth < 6; depth++) {
13989
- const packageJsonPath = path41.join(current, "package.json");
14572
+ const packageJsonPath = path43.join(current, "package.json");
13990
14573
  if (await Bun.file(packageJsonPath).exists()) {
13991
14574
  const packageJson = await FileSys.readJson(packageJsonPath);
13992
14575
  if (packageJson.name === "akanjs")
13993
14576
  return packageJson;
13994
14577
  }
13995
- const parent = path41.dirname(current);
14578
+ const parent = path43.dirname(current);
13996
14579
  if (parent === current)
13997
14580
  break;
13998
14581
  current = parent;
@@ -14069,7 +14652,7 @@ class WorkspaceScript extends script("workspace", [
14069
14652
  } catch (_) {
14070
14653
  gitSpinner.fail("Git repository initialization failed. It's not fatal, you can commit manually");
14071
14654
  }
14072
- const workspacePath = path42.join(dirname2, repoName);
14655
+ const workspacePath = path44.join(dirname2, repoName);
14073
14656
  Logger20.rawLog(`
14074
14657
  \uD83C\uDF89 Welcome aboard! Workspace created in ${dirname2}/${repoName}`);
14075
14658
  Logger20.rawLog(`\uD83D\uDE80 Run \`cd ${workspacePath} && akan start ${appName}\` to start the development server.`);