@geekmidas/cli 10.0.0-alpha.42 → 10.0.0-alpha.44

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.
@@ -4,7 +4,7 @@ const require_config = require("./config-CJ-PAb7M.cjs");
4
4
  const require_workspace = require("./workspace-RYSYtHP7.cjs");
5
5
  const require_storage = require("./storage-CSGoC3bK.cjs");
6
6
  const require_store = require("./store-DQgxT_WR.cjs");
7
- const require_ready = require("./ready-DXqKVRYN.cjs");
7
+ const require_ready = require("./ready-3RfHxdA0.cjs");
8
8
  let node_fs = require("node:fs");
9
9
  let node_fs_promises = require("node:fs/promises");
10
10
  let node_os = require("node:os");
@@ -2155,6 +2155,27 @@ async function allocate(project, containers, existing = {}, probe = isPortFree)
2155
2155
  }
2156
2156
  return assignments;
2157
2157
  }
2158
+ /**
2159
+ * The ports to keep: what running containers are observed on, then what was
2160
+ * saved — minus any saved entry whose port something else already holds.
2161
+ *
2162
+ * Spreading one over the other let an observed port override its own key and
2163
+ * leave a *different* key still saved on the same number: two services on one
2164
+ * port, and whichever answered first won. Saved keys for containers the plan no
2165
+ * longer has — a backend switched and back — were the usual source. Observed
2166
+ * wins because it is what is actually bound; a dropped entry is simply
2167
+ * allocated again.
2168
+ */
2169
+ function keptPorts(saved = {}, observed = {}) {
2170
+ const kept = { ...observed };
2171
+ const taken = new Set(Object.values(observed));
2172
+ for (const [key, port] of Object.entries(saved).sort(([a], [b]) => a < b ? -1 : 1)) {
2173
+ if (key in kept || taken.has(port)) continue;
2174
+ kept[key] = port;
2175
+ taken.add(port);
2176
+ }
2177
+ return kept;
2178
+ }
2158
2179
  /** The window was exhausted. */
2159
2180
  var NoPortAvailable = class extends Error {
2160
2181
  /** Where the search started. */
@@ -2471,6 +2492,25 @@ async function applyCarriers(client, carriers) {
2471
2492
  }
2472
2493
  return applied;
2473
2494
  }
2495
+ /** The Postgres databases the plan creates — each is a `CREATE DATABASE`. */
2496
+ function postgresDatabaseNames(plan) {
2497
+ return plan.resources.filter((resource) => resource.kind === "database" && resource.provisions && resource.container === "postgres").map((resource) => resource.name);
2498
+ }
2499
+ /**
2500
+ * Whether every one of these databases exists. A database dropped behind the
2501
+ * recorded state's back — by another checkout's test teardown, against the
2502
+ * same container — makes the state a lie, and only asking Postgres finds out.
2503
+ * Unreachable counts as missing: applying again is what finds out why.
2504
+ */
2505
+ async function databasesExist(client, names) {
2506
+ if (names.length === 0) return true;
2507
+ try {
2508
+ const rows = await client.query(void 0, "SELECT datname FROM pg_catalog.pg_database WHERE datname = ANY($1)", [names]);
2509
+ return new Set(rows.map((row) => row.datname)).size === names.length;
2510
+ } catch {
2511
+ return false;
2512
+ }
2513
+ }
2474
2514
  /**
2475
2515
  * Apply each served bucket's open-path policy, skipping those already correct.
2476
2516
  *
@@ -2667,10 +2707,7 @@ async function reconcile(options) {
2667
2707
  });
2668
2708
  const composePath = (0, node_path.join)(root, COMPOSE_PATH);
2669
2709
  const observed = await observedPorts(docker, composePath, plan.containers, plan.fakes);
2670
- const ports = await allocate(project, portKeys(plan.containers, plan.fakes), {
2671
- ...options.saved,
2672
- ...observed
2673
- }, probe);
2710
+ const ports = await allocate(project, portKeys(plan.containers, plan.fakes), keptPorts(options.saved, observed), probe);
2674
2711
  const compose = composeFor(plan, {
2675
2712
  project,
2676
2713
  ports,
@@ -2704,7 +2741,9 @@ async function reconcile(options) {
2704
2741
  hash,
2705
2742
  changed: false
2706
2743
  };
2707
- if ((await loadState(root, stage))?.hash === hash && (0, node_fs.existsSync)(composePath) && (!start || await docker.healthy(composePath, plan.containers))) return result;
2744
+ const recorded = await loadState(root, stage);
2745
+ const postgresPort = ports[primaryPortKey("postgres")];
2746
+ if (recorded?.hash === hash && (0, node_fs.existsSync)(composePath) && (!start || await docker.healthy(composePath, plan.containers)) && (!start || !provision || postgresPort === void 0 || await databasesExist(sql(postgresPort), postgresDatabaseNames(plan)))) return result;
2708
2747
  await write(composePath, toYaml(compose));
2709
2748
  if (plan.containers.includes("caddy")) {
2710
2749
  await write((0, node_path.join)(root, CADDYFILE_PATH), caddyfileRoot());
@@ -3061,6 +3100,12 @@ Object.defineProperty(exports, "pgClient", {
3061
3100
  return pgClient;
3062
3101
  }
3063
3102
  });
3103
+ Object.defineProperty(exports, "postgresDatabaseNames", {
3104
+ enumerable: true,
3105
+ get: function() {
3106
+ return postgresDatabaseNames;
3107
+ }
3108
+ });
3064
3109
  Object.defineProperty(exports, "prepareEntryCredentials", {
3065
3110
  enumerable: true,
3066
3111
  get: function() {
@@ -3116,4 +3161,4 @@ Object.defineProperty(exports, "workspace_exports", {
3116
3161
  }
3117
3162
  });
3118
3163
 
3119
- //# sourceMappingURL=workspace-CPVcs6r_.cjs.map
3164
+ //# sourceMappingURL=workspace-dV6f-3vv.cjs.map