@geekmidas/cli 10.0.0-alpha.27 → 10.0.0-alpha.28
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/dist/{HostingerProvider-BY26bWwB.mjs → HostingerProvider-Btxpto71.mjs} +2 -2
- package/dist/{HostingerProvider-BY26bWwB.mjs.map → HostingerProvider-Btxpto71.mjs.map} +1 -1
- package/dist/{bundler-mwH7WOb1.mjs → bundler-D5RcGmVM.mjs} +2 -2
- package/dist/{bundler-mwH7WOb1.mjs.map → bundler-D5RcGmVM.mjs.map} +1 -1
- package/dist/{config-7R_-WyHq.cjs → config-BTFLHfRb.cjs} +2 -2
- package/dist/{config-7R_-WyHq.cjs.map → config-BTFLHfRb.cjs.map} +1 -1
- package/dist/{config-DXrrYvob.mjs → config-Dqxa-_Ge.mjs} +2 -2
- package/dist/{config-DXrrYvob.mjs.map → config-Dqxa-_Ge.mjs.map} +1 -1
- package/dist/config.cjs +1 -1
- package/dist/config.mjs +1 -1
- package/dist/deploy/sniffer-loader.cjs +1 -1
- package/dist/{discover-B_HtYJCr.cjs → discover-BTh87DOO.cjs} +24 -2
- package/dist/{discover-B_HtYJCr.cjs.map → discover-BTh87DOO.cjs.map} +1 -1
- package/dist/{discover-0fhCbnk0.mjs → discover-CXGlQHm1.mjs} +24 -2
- package/dist/{discover-0fhCbnk0.mjs.map → discover-CXGlQHm1.mjs.map} +1 -1
- package/dist/{github-CQflOKKV.cjs → github-BUCXEl2v.cjs} +5 -5
- package/dist/{github-CQflOKKV.cjs.map → github-BUCXEl2v.cjs.map} +1 -1
- package/dist/{github-Ba5kXEJo.mjs → github-zkzu-ka2.mjs} +3 -3
- package/dist/{github-Ba5kXEJo.mjs.map → github-zkzu-ka2.mjs.map} +1 -1
- package/dist/index.cjs +740 -655
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +735 -652
- package/dist/index.mjs.map +1 -1
- package/dist/{openapi-3NLVvtz-.mjs → openapi-D-Lk5Hr5.mjs} +3 -3
- package/dist/{openapi-3NLVvtz-.mjs.map → openapi-D-Lk5Hr5.mjs.map} +1 -1
- package/dist/{openapi-rhJdy2GC.cjs → openapi-K4H5tHzA.cjs} +3 -3
- package/dist/{openapi-rhJdy2GC.cjs.map → openapi-K4H5tHzA.cjs.map} +1 -1
- package/dist/openapi.cjs +1 -1
- package/dist/openapi.mjs +1 -1
- package/dist/reconcile/public.cjs +1 -1
- package/dist/reconcile/public.d.cts +12 -0
- package/dist/reconcile/public.d.cts.map +1 -1
- package/dist/reconcile/public.d.mts +12 -0
- package/dist/reconcile/public.d.mts.map +1 -1
- package/dist/reconcile/public.mjs +1 -1
- package/dist/{workspace-DgeVgxmm.cjs → workspace-Cv48QwPK.cjs} +128 -9
- package/dist/workspace-Cv48QwPK.cjs.map +1 -0
- package/dist/{workspace-CUmR_k4J.mjs → workspace-cBobQVoA.mjs} +124 -11
- package/dist/workspace-cBobQVoA.mjs.map +1 -0
- package/package.json +14 -14
- package/dist/transfer-BV00TxZv.mjs +0 -122
- package/dist/transfer-BV00TxZv.mjs.map +0 -1
- package/dist/transfer-BYIn7z8m.cjs +0 -151
- package/dist/transfer-BYIn7z8m.cjs.map +0 -1
- package/dist/workspace-CUmR_k4J.mjs.map +0 -1
- package/dist/workspace-DgeVgxmm.cjs.map +0 -1
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { t as __exportAll } from "./rolldown-runtime-BhDjJH2R.mjs";
|
|
2
|
-
import { a as DEFAULT_EVENTS$1, i as DEFAULT_CACHE, o as DEFAULT_STORAGE, t as discover } from "./discover-
|
|
3
|
-
import { l as appKey, o as loadWorkspaceAppInfo, r as getAppNameFromCwd, s as loadWorkspaceConfig } from "./config-
|
|
2
|
+
import { a as DEFAULT_EVENTS$1, i as DEFAULT_CACHE, o as DEFAULT_STORAGE, t as discover } from "./discover-CXGlQHm1.mjs";
|
|
3
|
+
import { l as appKey, o as loadWorkspaceAppInfo, r as getAppNameFromCwd, s as loadWorkspaceConfig } from "./config-Dqxa-_Ge.mjs";
|
|
4
4
|
import { E as TEST_STAGE, t as allConstructGlobs } from "./workspace-T4IVGSoB.mjs";
|
|
5
5
|
import { n as readStageSecrets, o as toEmbeddableSecrets, r as secretsExist } from "./storage-TP0x118M.mjs";
|
|
6
6
|
import { existsSync } from "node:fs";
|
|
7
7
|
import { mkdir, readFile, readdir, rm, writeFile } from "node:fs/promises";
|
|
8
8
|
import { dirname, join, resolve } from "node:path";
|
|
9
9
|
import { execFile } from "node:child_process";
|
|
10
|
-
import { DEFAULT_POSTGRES_VERSION, cacheTable, cookieDomain, dependentsOf, provideKey, providedKeyFor, provisionOrder, publicEnvFor } from "@geekmidas/manifest";
|
|
10
|
+
import { DEFAULT_POSTGRES_VERSION, cacheTable, cookieDomain, dependenciesOf, dependentsOf, provideKey, providedKeyFor, provisionOrder, publicEnvFor } from "@geekmidas/manifest";
|
|
11
11
|
import { createServer } from "node:net";
|
|
12
12
|
import { config } from "dotenv";
|
|
13
13
|
import { createHash } from "node:crypto";
|
|
@@ -515,11 +515,16 @@ function portOf(address) {
|
|
|
515
515
|
*/
|
|
516
516
|
function hostFor(resource, project) {
|
|
517
517
|
return [
|
|
518
|
-
resource.name,
|
|
518
|
+
resource.root && project ? stageOf(resource) : resource.name,
|
|
519
519
|
project,
|
|
520
520
|
LOCAL_TLD
|
|
521
521
|
].filter(Boolean).join(".");
|
|
522
522
|
}
|
|
523
|
+
/** The stage a resource's name carries, or nothing for the local stage's. */
|
|
524
|
+
function stageOf(resource) {
|
|
525
|
+
const base = resource.id.toLowerCase();
|
|
526
|
+
return resource.name === base ? void 0 : resource.name.slice(base.length + 1);
|
|
527
|
+
}
|
|
523
528
|
/**
|
|
524
529
|
* The static root config, which only ever imports.
|
|
525
530
|
*
|
|
@@ -586,6 +591,49 @@ const GENERATED = `# Generated by gkm from the construct manifest — do not edi
|
|
|
586
591
|
# from code; a browser needs the root trusted once.
|
|
587
592
|
`;
|
|
588
593
|
//#endregion
|
|
594
|
+
//#region src/workspace/rootSite.ts
|
|
595
|
+
/**
|
|
596
|
+
* Which site the base domain points at — deployed and locally alike.
|
|
597
|
+
*
|
|
598
|
+
* Three rules, in order, and the last one is the point:
|
|
599
|
+
*
|
|
600
|
+
* 1. **One site** — it is the root. Unambiguous, so nothing has to be said.
|
|
601
|
+
* 2. **Named `web`** — the convention wins, because people already rely on it.
|
|
602
|
+
* 3. **Declared `root: true`** — the site says so itself.
|
|
603
|
+
*
|
|
604
|
+
* Anything else throws. It used to take the *first* site it iterated, and that
|
|
605
|
+
* order came from the manifest, which is built in glob traversal order — so two
|
|
606
|
+
* sites with neither named `web` meant renaming a file could move the root
|
|
607
|
+
* domain, silently.
|
|
608
|
+
*
|
|
609
|
+
* One rule for both targets: deployed the root site gets the base domain, and
|
|
610
|
+
* locally it gets the project's bare host behind the edge. Before this was
|
|
611
|
+
* shared, the local edge put every site on a subdomain, so what a developer
|
|
612
|
+
* browsed was not the shape production served.
|
|
613
|
+
*
|
|
614
|
+
* @returns the root site's name, or `undefined` when there are no sites
|
|
615
|
+
* @throws {AmbiguousRootSite} when several sites could be the root and none says it is
|
|
616
|
+
*/
|
|
617
|
+
function rootSite(sites) {
|
|
618
|
+
if (sites.length === 0) return void 0;
|
|
619
|
+
if (sites.length === 1) return sites[0].name;
|
|
620
|
+
if (sites.some(({ name }) => name === "web")) return "web";
|
|
621
|
+
const declared = sites.filter(({ root }) => root === true);
|
|
622
|
+
if (declared.length === 1) return declared[0].name;
|
|
623
|
+
throw new AmbiguousRootSite(sites.map(({ name }) => name), declared.length > 1);
|
|
624
|
+
}
|
|
625
|
+
/** Several sites could hold the base domain, and none of them says it does. */
|
|
626
|
+
var AmbiguousRootSite = class extends Error {
|
|
627
|
+
sites;
|
|
628
|
+
tooMany;
|
|
629
|
+
constructor(sites, tooMany = false) {
|
|
630
|
+
super(tooMany ? `More than one site declares \`root: true\` — ${sites.join(", ")}. The base domain points at one of them.` : `${sites.length} sites and nothing says which holds the base domain: ${sites.join(", ")}. Name one of them \`web\`, or declare \`root: true\` on the one the base domain points at. It used to be whichever the glob reached first, which is not a thing to decide a hostname.`);
|
|
631
|
+
this.sites = sites;
|
|
632
|
+
this.tooMany = tooMany;
|
|
633
|
+
this.name = "AmbiguousRootSite";
|
|
634
|
+
}
|
|
635
|
+
};
|
|
636
|
+
//#endregion
|
|
589
637
|
//#region src/reconcile/plan.ts
|
|
590
638
|
/**
|
|
591
639
|
* The reconcile plan — what a manifest wants to exist, for one stage.
|
|
@@ -793,6 +841,15 @@ function planFor(manifest, stage, order, options = {}) {
|
|
|
793
841
|
for (const resource of placeless) resource.of = only.id;
|
|
794
842
|
}
|
|
795
843
|
}
|
|
844
|
+
const sites = resources.filter((r) => r.kind === "site");
|
|
845
|
+
const root = rootSite(sites.map((r) => {
|
|
846
|
+
const declared = manifest[r.id];
|
|
847
|
+
return {
|
|
848
|
+
name: appKey(r.id),
|
|
849
|
+
...declared?.kind === "site" && declared.root ? { root: true } : {}
|
|
850
|
+
};
|
|
851
|
+
}));
|
|
852
|
+
for (const site of sites) if (appKey(site.id) === root) site.root = true;
|
|
796
853
|
const workerBroker = events === "pgboss" && Object.values(manifest).some((d) => d?.kind === "worker") && resources.some((r) => r.kind === "database");
|
|
797
854
|
return {
|
|
798
855
|
stage,
|
|
@@ -1276,14 +1333,67 @@ function inNetworkEnv(workspace, manifest) {
|
|
|
1276
1333
|
});
|
|
1277
1334
|
return Object.fromEntries(Object.entries(env).map(([key, value]) => [key, rewrite(value)]));
|
|
1278
1335
|
}
|
|
1336
|
+
/**
|
|
1337
|
+
* The keys one app's environment may hold: what its own declaration provides
|
|
1338
|
+
* and requires, and what each construct it has an edge to provides.
|
|
1339
|
+
*
|
|
1340
|
+
* The edges, not the manifest. Every app used to be handed every key the
|
|
1341
|
+
* workspace resolved — a web app got the database's owner URL and the auth
|
|
1342
|
+
* server's signing secret, and the API got the auth server's database — which
|
|
1343
|
+
* is exactly what a declared edge exists to rule out. A deploy composes an
|
|
1344
|
+
* app's environment from its edges; so does this.
|
|
1345
|
+
*
|
|
1346
|
+
* One hop: a surface an app calls is reached over HTTP, so its URL is the
|
|
1347
|
+
* app's business and its database is not. A site also gets the public
|
|
1348
|
+
* variant of each key its bundle inlines (`NEXT_PUBLIC_API_URL`), and a surface
|
|
1349
|
+
* the edges of the workers whose crons and subscribers its server runs.
|
|
1350
|
+
*
|
|
1351
|
+
* `undefined` for an app no declaration describes, which gets nothing but its
|
|
1352
|
+
* port.
|
|
1353
|
+
*/
|
|
1354
|
+
function appEnvKeys(manifest, appName, runnables = {}) {
|
|
1355
|
+
const entry = Object.entries(manifest).find(([id, d]) => (d.kind === "rest-api" || d.kind === "site") && appKey(id) === appName);
|
|
1356
|
+
if (!entry) return void 0;
|
|
1357
|
+
const [id, declaration] = entry;
|
|
1358
|
+
const keys = /* @__PURE__ */ new Set([
|
|
1359
|
+
...declaration.provides ?? [],
|
|
1360
|
+
...declaration.requires ?? [],
|
|
1361
|
+
...declaration.kind === "rest-api" ? declaration.endpoints.flatMap((endpoint) => endpoint.requires ?? []) : []
|
|
1362
|
+
]);
|
|
1363
|
+
const edges = [...dependenciesOf(declaration).map((edge) => edge.target), ...runnables[id] ?? []];
|
|
1364
|
+
if (declaration.kind === "rest-api" && declaration.endpoints.length === 0) for (const [otherId, other] of Object.entries(manifest)) {
|
|
1365
|
+
if (other.kind !== "worker") continue;
|
|
1366
|
+
edges.push(...dependenciesOf(other).map((edge) => edge.target), ...runnables[otherId] ?? []);
|
|
1367
|
+
keys.add("EVENT_PUBLISHER_CONNECTION_STRING");
|
|
1368
|
+
keys.add("EVENT_SUBSCRIBER_CONNECTION_STRING");
|
|
1369
|
+
}
|
|
1370
|
+
for (const id of edges) {
|
|
1371
|
+
const target = manifest[id];
|
|
1372
|
+
if (!target) continue;
|
|
1373
|
+
for (const key of target.provides ?? []) keys.add(key);
|
|
1374
|
+
if (target.kind === "queue" || target.kind === "topic") {
|
|
1375
|
+
keys.add("EVENT_PUBLISHER_CONNECTION_STRING");
|
|
1376
|
+
keys.add("EVENT_SUBSCRIBER_CONNECTION_STRING");
|
|
1377
|
+
}
|
|
1378
|
+
if (target.kind === "objects") {
|
|
1379
|
+
keys.add("AWS_ACCESS_KEY_ID");
|
|
1380
|
+
keys.add("AWS_SECRET_ACCESS_KEY");
|
|
1381
|
+
keys.add("AWS_REGION");
|
|
1382
|
+
}
|
|
1383
|
+
}
|
|
1384
|
+
if (declaration.kind === "site") for (const key of Object.keys(publicEnvFor(declaration, manifest))) keys.add(key);
|
|
1385
|
+
return keys;
|
|
1386
|
+
}
|
|
1279
1387
|
/** One compose service per app the workspace runs, behind the apps profile. */
|
|
1280
|
-
function appServices(workspace, manifest, containers) {
|
|
1388
|
+
function appServices(workspace, manifest, containers, runnables = {}) {
|
|
1281
1389
|
const env = inNetworkEnv(workspace, manifest);
|
|
1282
1390
|
const services = {};
|
|
1283
1391
|
for (const [name, app] of Object.entries(workspace.apps)) {
|
|
1284
1392
|
if (app.type === "mobile" || !app.port) continue;
|
|
1285
1393
|
const key = appKey(name);
|
|
1286
1394
|
const health = app.type === "web" ? "/" : "/health";
|
|
1395
|
+
const allowed = appEnvKeys(manifest, name, runnables);
|
|
1396
|
+
const own = Object.fromEntries(Object.entries(env).filter(([envKey]) => allowed?.has(envKey)));
|
|
1287
1397
|
services[key] = {
|
|
1288
1398
|
image: `${key}:\${TAG:-latest}`,
|
|
1289
1399
|
build: {
|
|
@@ -1295,7 +1405,7 @@ function appServices(workspace, manifest, containers) {
|
|
|
1295
1405
|
environment: {
|
|
1296
1406
|
NODE_ENV: "production",
|
|
1297
1407
|
PORT: String(app.port),
|
|
1298
|
-
...
|
|
1408
|
+
...own
|
|
1299
1409
|
},
|
|
1300
1410
|
...containers.some((c) => c !== "caddy") ? { depends_on: containers.filter((c) => c !== "caddy") } : {},
|
|
1301
1411
|
healthcheck: {
|
|
@@ -2500,10 +2610,13 @@ async function derivedContainers(workspace, stage, manifest) {
|
|
|
2500
2610
|
* stays a pure-ish function of its inputs and the store keeps its single owner.
|
|
2501
2611
|
*/
|
|
2502
2612
|
async function reconcileWorkspace(workspace, options) {
|
|
2503
|
-
const
|
|
2613
|
+
const runnables = {};
|
|
2614
|
+
const discovered = await discover({
|
|
2504
2615
|
patterns: constructGlobs(workspace),
|
|
2505
|
-
cwd: workspace.root
|
|
2616
|
+
cwd: workspace.root,
|
|
2617
|
+
runnables
|
|
2506
2618
|
});
|
|
2619
|
+
const manifest = options.manifest ?? discovered;
|
|
2507
2620
|
const result = await reconcile({
|
|
2508
2621
|
root: workspace.root,
|
|
2509
2622
|
project: workspace.name,
|
|
@@ -2513,7 +2626,7 @@ async function reconcileWorkspace(workspace, options) {
|
|
|
2513
2626
|
...backendsOf(workspace),
|
|
2514
2627
|
saved: await loadPortState(workspace.root),
|
|
2515
2628
|
addresses: surfaceAddresses(workspace, manifest),
|
|
2516
|
-
apps: (containers) => appServices(workspace, manifest, containers),
|
|
2629
|
+
apps: (containers) => appServices(workspace, manifest, containers, runnables),
|
|
2517
2630
|
...options.start === void 0 ? {} : { start: options.start }
|
|
2518
2631
|
});
|
|
2519
2632
|
await savePortState(workspace.root, { ...result.ports });
|
|
@@ -2550,6 +2663,6 @@ function localAddress(port) {
|
|
|
2550
2663
|
return `http://localhost:${port}`;
|
|
2551
2664
|
}
|
|
2552
2665
|
//#endregion
|
|
2553
|
-
export {
|
|
2666
|
+
export { findAvailablePort as _, workspace_exports as a, loadSecretsForApp as b, applyPostgres as c, cacheBackendFor as d, eventsBackendFor as f, createEntryWrapper as g, createCredentialsPreload as h, reconcileWorkspace as i, resourceName as l, storageBackendFor as m, constructGlobs as n, COMPOSE_PATH as o, providerOf as p, derivedContainers as r, LOCAL_CA_PATH as s, backendsOf as t, rootSite as u, isPortAvailable as v, prepareEntryCredentials as x, loadEnvFiles as y };
|
|
2554
2667
|
|
|
2555
|
-
//# sourceMappingURL=workspace-
|
|
2668
|
+
//# sourceMappingURL=workspace-cBobQVoA.mjs.map
|