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

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 @@ import { c as loadWorkspaceAppInfo, f as appKey, l as loadWorkspaceConfig, r as
4
4
  import { E as TEST_STAGE, t as allConstructGlobs } from "./workspace-DOmIhiau.mjs";
5
5
  import { i as toEmbeddableSecrets } from "./storage-BzaUxmqe.mjs";
6
6
  import { i as FileSecretsStore, n as secretsStoreFor } from "./store-DeGATCS-.mjs";
7
- import { l as readFakes } from "./ready-BZ0fLpyL.mjs";
7
+ import { l as readFakes } from "./ready-Bdh5SSXn.mjs";
8
8
  import { existsSync } from "node:fs";
9
9
  import { mkdir, readFile, readdir, rm, writeFile } from "node:fs/promises";
10
10
  import { networkInterfaces } from "node:os";
@@ -2153,6 +2153,27 @@ async function allocate(project, containers, existing = {}, probe = isPortFree)
2153
2153
  }
2154
2154
  return assignments;
2155
2155
  }
2156
+ /**
2157
+ * The ports to keep: what running containers are observed on, then what was
2158
+ * saved — minus any saved entry whose port something else already holds.
2159
+ *
2160
+ * Spreading one over the other let an observed port override its own key and
2161
+ * leave a *different* key still saved on the same number: two services on one
2162
+ * port, and whichever answered first won. Saved keys for containers the plan no
2163
+ * longer has — a backend switched and back — were the usual source. Observed
2164
+ * wins because it is what is actually bound; a dropped entry is simply
2165
+ * allocated again.
2166
+ */
2167
+ function keptPorts(saved = {}, observed = {}) {
2168
+ const kept = { ...observed };
2169
+ const taken = new Set(Object.values(observed));
2170
+ for (const [key, port] of Object.entries(saved).sort(([a], [b]) => a < b ? -1 : 1)) {
2171
+ if (key in kept || taken.has(port)) continue;
2172
+ kept[key] = port;
2173
+ taken.add(port);
2174
+ }
2175
+ return kept;
2176
+ }
2156
2177
  /** The window was exhausted. */
2157
2178
  var NoPortAvailable = class extends Error {
2158
2179
  /** Where the search started. */
@@ -2469,6 +2490,25 @@ async function applyCarriers(client, carriers) {
2469
2490
  }
2470
2491
  return applied;
2471
2492
  }
2493
+ /** The Postgres databases the plan creates — each is a `CREATE DATABASE`. */
2494
+ function postgresDatabaseNames(plan) {
2495
+ return plan.resources.filter((resource) => resource.kind === "database" && resource.provisions && resource.container === "postgres").map((resource) => resource.name);
2496
+ }
2497
+ /**
2498
+ * Whether every one of these databases exists. A database dropped behind the
2499
+ * recorded state's back — by another checkout's test teardown, against the
2500
+ * same container — makes the state a lie, and only asking Postgres finds out.
2501
+ * Unreachable counts as missing: applying again is what finds out why.
2502
+ */
2503
+ async function databasesExist(client, names) {
2504
+ if (names.length === 0) return true;
2505
+ try {
2506
+ const rows = await client.query(void 0, "SELECT datname FROM pg_catalog.pg_database WHERE datname = ANY($1)", [names]);
2507
+ return new Set(rows.map((row) => row.datname)).size === names.length;
2508
+ } catch {
2509
+ return false;
2510
+ }
2511
+ }
2472
2512
  /**
2473
2513
  * Apply each served bucket's open-path policy, skipping those already correct.
2474
2514
  *
@@ -2665,10 +2705,7 @@ async function reconcile(options) {
2665
2705
  });
2666
2706
  const composePath = join(root, COMPOSE_PATH);
2667
2707
  const observed = await observedPorts(docker, composePath, plan.containers, plan.fakes);
2668
- const ports = await allocate(project, portKeys(plan.containers, plan.fakes), {
2669
- ...options.saved,
2670
- ...observed
2671
- }, probe);
2708
+ const ports = await allocate(project, portKeys(plan.containers, plan.fakes), keptPorts(options.saved, observed), probe);
2672
2709
  const compose = composeFor(plan, {
2673
2710
  project,
2674
2711
  ports,
@@ -2702,7 +2739,9 @@ async function reconcile(options) {
2702
2739
  hash,
2703
2740
  changed: false
2704
2741
  };
2705
- if ((await loadState(root, stage))?.hash === hash && existsSync(composePath) && (!start || await docker.healthy(composePath, plan.containers))) return result;
2742
+ const recorded = await loadState(root, stage);
2743
+ const postgresPort = ports[primaryPortKey("postgres")];
2744
+ if (recorded?.hash === hash && existsSync(composePath) && (!start || await docker.healthy(composePath, plan.containers)) && (!start || !provision || postgresPort === void 0 || await databasesExist(sql(postgresPort), postgresDatabaseNames(plan)))) return result;
2706
2745
  await write(composePath, toYaml(compose));
2707
2746
  if (plan.containers.includes("caddy")) {
2708
2747
  await write(join(root, CADDYFILE_PATH), caddyfileRoot());
@@ -2951,6 +2990,6 @@ function localAddress(port) {
2951
2990
  return `http://localhost:${port}`;
2952
2991
  }
2953
2992
  //#endregion
2954
- export { findAvailablePort as C, prepareEntryCredentials as D, loadSecretsForApp as E, createEntryWrapper as S, loadEnvFiles as T, cacheBackendFor as _, reconcileWorkspace as a, storageBackendFor as b, LOCAL_CA_PATH as c, quoteIdentifier as d, pgClient as f, primaryPortKey as g, fakeKey as h, derivedContainers as i, forgetState as l, rootSite as m, backendsOf as n, workspace_exports as o, resourceName as p, constructGlobs as r, COMPOSE_PATH as s, FAKE_ENV as t, applyPostgres as u, eventsBackendFor as v, isPortAvailable as w, createCredentialsPreload as x, providerOf as y };
2993
+ export { createEntryWrapper as C, loadSecretsForApp as D, loadEnvFiles as E, prepareEntryCredentials as O, createCredentialsPreload as S, isPortAvailable as T, primaryPortKey as _, reconcileWorkspace as a, providerOf as b, LOCAL_CA_PATH as c, postgresDatabaseNames as d, quoteIdentifier as f, fakeKey as g, rootSite as h, derivedContainers as i, forgetState as l, resourceName as m, backendsOf as n, workspace_exports as o, pgClient as p, constructGlobs as r, COMPOSE_PATH as s, FAKE_ENV as t, applyPostgres as u, cacheBackendFor as v, findAvailablePort as w, storageBackendFor as x, eventsBackendFor as y };
2955
2994
 
2956
- //# sourceMappingURL=workspace-BTM5-aaI.mjs.map
2995
+ //# sourceMappingURL=workspace-Bt-pXoIi.mjs.map