@geekmidas/cli 10.0.0-alpha.34 → 10.0.0-alpha.36
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/{config-DMpzmsQL.cjs → config-DgAHy8nY.cjs} +9 -5
- package/dist/config-DgAHy8nY.cjs.map +1 -0
- package/dist/{config-Du8AQJRK.mjs → config-Dss1WwtH.mjs} +9 -5
- package/dist/config-Dss1WwtH.mjs.map +1 -0
- package/dist/config.cjs +1 -1
- package/dist/config.mjs +1 -1
- package/dist/{github-DN-92LWP.mjs → github-C99BMxf0.mjs} +2 -2
- package/dist/{github-DN-92LWP.mjs.map → github-C99BMxf0.mjs.map} +1 -1
- package/dist/{github-JhvrmjQp.cjs → github-tZmMZ7td.cjs} +2 -2
- package/dist/{github-JhvrmjQp.cjs.map → github-tZmMZ7td.cjs.map} +1 -1
- package/dist/index.cjs +209 -87
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +210 -88
- package/dist/index.mjs.map +1 -1
- package/dist/{migrate-u1oRHz6K.cjs → migrate-BsW4xBEO.cjs} +3 -3
- package/dist/{migrate-u1oRHz6K.cjs.map → migrate-BsW4xBEO.cjs.map} +1 -1
- package/dist/{migrate-BbhXxQer.mjs → migrate-CT8b3nt_.mjs} +3 -3
- package/dist/{migrate-BbhXxQer.mjs.map → migrate-CT8b3nt_.mjs.map} +1 -1
- package/dist/openapi.cjs +1 -1
- package/dist/openapi.mjs +1 -1
- package/dist/{workspace-LKFnEBX8.cjs → workspace-C0X8xSXV.cjs} +89 -15
- package/dist/workspace-C0X8xSXV.cjs.map +1 -0
- package/dist/{workspace-DB2YHgOl.mjs → workspace-EmXwO2qM.mjs} +90 -16
- package/dist/workspace-EmXwO2qM.mjs.map +1 -0
- package/package.json +14 -14
- package/dist/config-DMpzmsQL.cjs.map +0 -1
- package/dist/config-Du8AQJRK.mjs.map +0 -1
- package/dist/workspace-DB2YHgOl.mjs.map +0 -1
- package/dist/workspace-LKFnEBX8.cjs.map +0 -1
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
const require_rolldown_runtime = require("./rolldown-runtime-C0BPl7ul.cjs");
|
|
2
2
|
const require_discover = require("./discover-CroTIm0K.cjs");
|
|
3
|
-
const require_config = require("./config-
|
|
3
|
+
const require_config = require("./config-DgAHy8nY.cjs");
|
|
4
4
|
const require_workspace = require("./workspace-CAJk6UmC.cjs");
|
|
5
5
|
const require_storage = require("./storage-C2JC31V9.cjs");
|
|
6
6
|
let node_fs = require("node:fs");
|
|
7
7
|
let node_fs_promises = require("node:fs/promises");
|
|
8
|
+
let node_os = require("node:os");
|
|
8
9
|
let node_path = require("node:path");
|
|
9
10
|
let node_child_process = require("node:child_process");
|
|
10
11
|
let _geekmidas_manifest = require("@geekmidas/manifest");
|
|
@@ -210,6 +211,7 @@ async function prepareEntryCredentials(options) {
|
|
|
210
211
|
const stage = options.stage ?? workspace?.stages.local;
|
|
211
212
|
const credentials = stage ? await loadSecretsForApp(secretsRoot, stage, appName) : {};
|
|
212
213
|
credentials.PORT = String(resolvedPort);
|
|
214
|
+
if (appInfo?.app.type === "mobile") credentials.RCT_METRO_PORT = String(resolvedPort);
|
|
213
215
|
const declaredKeys = [];
|
|
214
216
|
if (workspace) {
|
|
215
217
|
const { reconcileWorkspace } = await Promise.resolve().then(() => workspace_exports);
|
|
@@ -689,7 +691,8 @@ const CONTAINERLESS = {
|
|
|
689
691
|
secret: true,
|
|
690
692
|
credential: true,
|
|
691
693
|
"rest-api": true,
|
|
692
|
-
site: true
|
|
694
|
+
site: true,
|
|
695
|
+
"mobile-app": true
|
|
693
696
|
};
|
|
694
697
|
/**
|
|
695
698
|
* Containers that cannot run alone.
|
|
@@ -709,7 +712,8 @@ const REQUIRES = { "redis-http": ["redis"] };
|
|
|
709
712
|
const ROLES = {
|
|
710
713
|
queue: "publisherConnectionString",
|
|
711
714
|
topic: "publisherConnectionString",
|
|
712
|
-
credential: "credential"
|
|
715
|
+
credential: "credential",
|
|
716
|
+
"mobile-app": "scheme"
|
|
713
717
|
};
|
|
714
718
|
/** The kinds whose container is the events backend's rather than their own. */
|
|
715
719
|
const EVENT_KINDS = {
|
|
@@ -820,6 +824,10 @@ function planFor(manifest, stage, order, options = {}) {
|
|
|
820
824
|
provisions: PROVISIONS[declaration.kind] === true,
|
|
821
825
|
...declaration.kind === "rest-api" ? { callers: (0, _geekmidas_manifest.dependentsOf)(manifest, id) } : {},
|
|
822
826
|
...declaration.kind === "site" ? { publicEnv: (0, _geekmidas_manifest.publicEnvFor)(declaration, manifest) } : {},
|
|
827
|
+
...declaration.kind === "mobile-app" ? {
|
|
828
|
+
publicEnv: (0, _geekmidas_manifest.publicEnvFor)(declaration, manifest),
|
|
829
|
+
...declaration.scheme ? { scheme: declaration.scheme } : {}
|
|
830
|
+
} : {},
|
|
823
831
|
...declaration.kind === "file-server" && declaration.open?.length ? { open: declaration.open } : {},
|
|
824
832
|
..."of" in declaration ? { of: declaration.of } : {},
|
|
825
833
|
..."schema" in declaration && declaration.schema ? { schema: declaration.schema } : {},
|
|
@@ -969,7 +977,12 @@ function envFor(plan, options) {
|
|
|
969
977
|
}
|
|
970
978
|
for (const resource of plan.resources) {
|
|
971
979
|
const url = resolved[resource.id];
|
|
972
|
-
if (resource.kind === "rest-api") Object.assign(env, surfaceEnv(resource, url, resolved
|
|
980
|
+
if (resource.kind === "rest-api") Object.assign(env, surfaceEnv(resource, url, resolved, {
|
|
981
|
+
plan,
|
|
982
|
+
...options.addresses ? { addresses: options.addresses } : {},
|
|
983
|
+
...options.lanAddress ? { lanAddress: options.lanAddress } : {},
|
|
984
|
+
...options.metroPorts ? { metroPorts: options.metroPorts } : {}
|
|
985
|
+
}));
|
|
973
986
|
if (url) env[resource.envKey] = url;
|
|
974
987
|
if (isDatabase(resource.kind) && resource.roles !== false) {
|
|
975
988
|
const owner = ownerUrl(resource, plan, options.ports, options.project ?? "");
|
|
@@ -981,7 +994,7 @@ function envFor(plan, options) {
|
|
|
981
994
|
if (inbox !== void 0) env[(0, _geekmidas_manifest.provideKey)(resource.id, "inboxUrl")] = `http://${LOCAL_HOST}:${inbox}`;
|
|
982
995
|
}
|
|
983
996
|
}
|
|
984
|
-
Object.assign(env, publicEnv(plan, env));
|
|
997
|
+
Object.assign(env, publicEnv(plan, env, options.addresses));
|
|
985
998
|
Object.assign(env, brokerEnv(plan, options.ports));
|
|
986
999
|
if (plan.resources.some((r) => r.kind === "objects" && env[r.envKey])) Object.assign(env, STORAGE_CREDENTIALS);
|
|
987
1000
|
return env;
|
|
@@ -999,10 +1012,11 @@ function envFor(plan, options) {
|
|
|
999
1012
|
* against `http:///`, where a missing variable fails at build with the name of
|
|
1000
1013
|
* the thing that is missing.
|
|
1001
1014
|
*/
|
|
1002
|
-
function publicEnv(plan, resolved) {
|
|
1015
|
+
function publicEnv(plan, resolved, addresses = {}) {
|
|
1003
1016
|
const env = {};
|
|
1017
|
+
const owners = new Map(plan.resources.map((r) => [r.envKey, r.id]));
|
|
1004
1018
|
for (const resource of plan.resources) for (const [key, source] of Object.entries(resource.publicEnv ?? {})) {
|
|
1005
|
-
const value = resolved[source];
|
|
1019
|
+
const value = (resource.kind === "mobile-app" ? addresses[owners.get(source) ?? ""] : void 0) ?? resolved[source];
|
|
1006
1020
|
if (value) env[key] = value;
|
|
1007
1021
|
}
|
|
1008
1022
|
return env;
|
|
@@ -1022,13 +1036,26 @@ function publicEnv(plan, resolved) {
|
|
|
1022
1036
|
* means it is not running in this stage, and keys belong with the address they
|
|
1023
1037
|
* describe.
|
|
1024
1038
|
*/
|
|
1025
|
-
function surfaceEnv(resource, url, resolved = {}) {
|
|
1039
|
+
function surfaceEnv(resource, url, resolved = {}, local = {}) {
|
|
1026
1040
|
if (!url) return {};
|
|
1027
1041
|
const origins = [...new Set((resource.callers ?? []).map((caller) => resolved[caller]).filter((address) => Boolean(address)).map(originOf).filter((origin) => Boolean(origin)))].sort();
|
|
1028
1042
|
const domain = (0, _geekmidas_manifest.cookieDomain)([url, ...origins]);
|
|
1043
|
+
const mobile = (resource.callers ?? []).map((caller) => local.plan?.resources.find((r) => r.id === caller && r.kind === "mobile-app")).filter((caller) => Boolean(caller));
|
|
1044
|
+
const hosts = [...local.lanAddress ? [local.lanAddress] : [], LOCAL_HOST];
|
|
1045
|
+
const schemes = mobile.flatMap((caller) => {
|
|
1046
|
+
const scheme = resolved[caller.id];
|
|
1047
|
+
const port = local.metroPorts?.[caller.id];
|
|
1048
|
+
return scheme ? (0, _geekmidas_manifest.mobileOrigins)(scheme, {
|
|
1049
|
+
hosts,
|
|
1050
|
+
...port ? { port } : {}
|
|
1051
|
+
}) : [];
|
|
1052
|
+
});
|
|
1053
|
+
const own = local.addresses?.[resource.id];
|
|
1054
|
+
const device = mobile.length > 0 && local.lanAddress && own ? own.replace(/\/\/(localhost|127\.0\.0\.1)(?=[:/]|$)/, `//${local.lanAddress}`) : void 0;
|
|
1029
1055
|
return {
|
|
1030
|
-
[(0, _geekmidas_manifest.provideKey)(resource.id, "trustedOrigins")]: origins.join(","),
|
|
1031
|
-
...domain ? { [(0, _geekmidas_manifest.provideKey)(resource.id, "cookieDomain")]: domain } : {}
|
|
1056
|
+
[(0, _geekmidas_manifest.provideKey)(resource.id, "trustedOrigins")]: [...origins, ...new Set(schemes)].join(","),
|
|
1057
|
+
...domain ? { [(0, _geekmidas_manifest.provideKey)(resource.id, "cookieDomain")]: domain } : {},
|
|
1058
|
+
...device ? { [(0, _geekmidas_manifest.provideKey)(resource.id, "deviceUrl")]: device } : {}
|
|
1032
1059
|
};
|
|
1033
1060
|
}
|
|
1034
1061
|
/** An address reduced to the origin a browser compares against. */
|
|
@@ -1108,6 +1135,7 @@ function workerBroker(plan, ports) {
|
|
|
1108
1135
|
*/
|
|
1109
1136
|
function urlFor(resource, plan, ports, project, addresses = {}) {
|
|
1110
1137
|
if (resource.kind === "secret") return localSecret(project, plan, resource);
|
|
1138
|
+
if (resource.kind === "mobile-app") return (0, _geekmidas_manifest.schemeBase)(project, resource.scheme);
|
|
1111
1139
|
if (resource.kind === "credential") return void 0;
|
|
1112
1140
|
if (resource.kind === "rest-api" || resource.kind === "site") {
|
|
1113
1141
|
const address = addresses[resource.id];
|
|
@@ -1352,7 +1380,7 @@ function inNetworkEnv(workspace, manifest) {
|
|
|
1352
1380
|
* port.
|
|
1353
1381
|
*/
|
|
1354
1382
|
function appEnvKeys(manifest, appName, runnables = {}) {
|
|
1355
|
-
const entry = Object.entries(manifest).find(([id, d]) => (d.kind === "rest-api" || d.kind === "site") && require_config.appKey(id) === appName);
|
|
1383
|
+
const entry = Object.entries(manifest).find(([id, d]) => (d.kind === "rest-api" || d.kind === "site" || d.kind === "mobile-app") && require_config.appKey(id) === appName);
|
|
1356
1384
|
if (!entry) return void 0;
|
|
1357
1385
|
const [id, declaration] = entry;
|
|
1358
1386
|
const keys = /* @__PURE__ */ new Set([
|
|
@@ -1381,7 +1409,7 @@ function appEnvKeys(manifest, appName, runnables = {}) {
|
|
|
1381
1409
|
keys.add("AWS_REGION");
|
|
1382
1410
|
}
|
|
1383
1411
|
}
|
|
1384
|
-
if (declaration.kind === "site") for (const key of Object.keys((0, _geekmidas_manifest.publicEnvFor)(declaration, manifest))) keys.add(key);
|
|
1412
|
+
if (declaration.kind === "site" || declaration.kind === "mobile-app") for (const key of Object.keys((0, _geekmidas_manifest.publicEnvFor)(declaration, manifest))) keys.add(key);
|
|
1385
1413
|
return keys;
|
|
1386
1414
|
}
|
|
1387
1415
|
/** One compose service per app the workspace runs, behind the apps profile. */
|
|
@@ -1881,6 +1909,30 @@ const dockerCli = {
|
|
|
1881
1909
|
}
|
|
1882
1910
|
};
|
|
1883
1911
|
//#endregion
|
|
1912
|
+
//#region src/reconcile/lan.ts
|
|
1913
|
+
/**
|
|
1914
|
+
* This machine's address on the local network — what a phone running the app
|
|
1915
|
+
* reaches it on.
|
|
1916
|
+
*/
|
|
1917
|
+
/**
|
|
1918
|
+
* The first private IPv4 address of an interface that is up and not loopback.
|
|
1919
|
+
*
|
|
1920
|
+
* Private ranges only (`10/8`, `172.16/12`, `192.168/16`): a public address
|
|
1921
|
+
* would mean listening for a phone on the open internet, and a link-local one
|
|
1922
|
+
* (`169.254/16`) is what an interface has when it found no network at all.
|
|
1923
|
+
* Undefined when there is none — a laptop on no network still runs, its mobile
|
|
1924
|
+
* app reaching only a simulator.
|
|
1925
|
+
*/
|
|
1926
|
+
function lanAddress(interfaces = (0, node_os.networkInterfaces)()) {
|
|
1927
|
+
for (const entries of Object.values(interfaces)) for (const entry of entries ?? []) {
|
|
1928
|
+
if (entry.family !== "IPv4" || entry.internal) continue;
|
|
1929
|
+
if (isPrivate(entry.address)) return entry.address;
|
|
1930
|
+
}
|
|
1931
|
+
}
|
|
1932
|
+
function isPrivate(address) {
|
|
1933
|
+
return /^10\./.test(address) || /^192\.168\./.test(address) || /^172\.(1[6-9]|2\d|3[01])\./.test(address);
|
|
1934
|
+
}
|
|
1935
|
+
//#endregion
|
|
1884
1936
|
//#region src/reconcile/ports.ts
|
|
1885
1937
|
/**
|
|
1886
1938
|
* Port allocation — why two projects can run at once.
|
|
@@ -2431,13 +2483,19 @@ async function reconcile(options) {
|
|
|
2431
2483
|
...options.apps ? { apps: options.apps(plan.containers) } : {}
|
|
2432
2484
|
});
|
|
2433
2485
|
const caddyfile = toCaddyfile(sitesFor(plan, project, options.addresses));
|
|
2434
|
-
const hash = planHash(plan, compose, {
|
|
2486
|
+
const hash = planHash(plan, compose, {
|
|
2487
|
+
caddyfile,
|
|
2488
|
+
postgres: postgresStatements(plan, project).map((statement) => statement.create).join(";\n")
|
|
2489
|
+
});
|
|
2435
2490
|
const addresses = addressesFor(plan.containers, ports);
|
|
2491
|
+
const lan = plan.resources.some((r) => r.kind === "mobile-app") ? options.lanAddress === void 0 ? lanAddress() : options.lanAddress ?? void 0 : void 0;
|
|
2436
2492
|
const env = envFor(plan, {
|
|
2437
2493
|
ports,
|
|
2438
2494
|
project,
|
|
2439
2495
|
...options.mailFrom ? { mailFrom: options.mailFrom } : {},
|
|
2440
|
-
...options.addresses ? { addresses: options.addresses } : {}
|
|
2496
|
+
...options.addresses ? { addresses: options.addresses } : {},
|
|
2497
|
+
...lan ? { lanAddress: lan } : {},
|
|
2498
|
+
...options.metroPorts ? { metroPorts: options.metroPorts } : {}
|
|
2441
2499
|
});
|
|
2442
2500
|
if (plan.containers.includes("caddy")) env.NODE_EXTRA_CA_CERTS = (0, node_path.join)(root, LOCAL_CA_PATH);
|
|
2443
2501
|
const result = {
|
|
@@ -2564,6 +2622,7 @@ var workspace_exports = /* @__PURE__ */ require_rolldown_runtime.__exportAll({
|
|
|
2564
2622
|
backendsOf: () => backendsOf,
|
|
2565
2623
|
constructGlobs: () => constructGlobs,
|
|
2566
2624
|
derivedContainers: () => derivedContainers,
|
|
2625
|
+
metroPorts: () => metroPorts,
|
|
2567
2626
|
reconcileWorkspace: () => reconcileWorkspace,
|
|
2568
2627
|
surfaceAddresses: () => surfaceAddresses
|
|
2569
2628
|
});
|
|
@@ -2627,6 +2686,7 @@ async function reconcileWorkspace(workspace, options) {
|
|
|
2627
2686
|
...backendsOf(workspace),
|
|
2628
2687
|
saved: await loadPortState(workspace.root),
|
|
2629
2688
|
addresses: surfaceAddresses(workspace, manifest),
|
|
2689
|
+
metroPorts: metroPorts(workspace, manifest),
|
|
2630
2690
|
apps: (containers) => appServices(workspace, manifest, containers, runnables),
|
|
2631
2691
|
...options.start === void 0 ? {} : { start: options.start }
|
|
2632
2692
|
});
|
|
@@ -2634,6 +2694,20 @@ async function reconcileWorkspace(workspace, options) {
|
|
|
2634
2694
|
return result;
|
|
2635
2695
|
}
|
|
2636
2696
|
/**
|
|
2697
|
+
* Where each mobile app's Metro runs: its app's port, which `gkm exec` hands
|
|
2698
|
+
* Expo as `RCT_METRO_PORT`. Kept apart from the surfaces' addresses — a phone
|
|
2699
|
+
* reaches Metro by `exp://`, not through the edge.
|
|
2700
|
+
*/
|
|
2701
|
+
function metroPorts(workspace, manifest) {
|
|
2702
|
+
const ports = {};
|
|
2703
|
+
for (const [id, declaration] of Object.entries(manifest)) {
|
|
2704
|
+
if (declaration.kind !== "mobile-app") continue;
|
|
2705
|
+
const port = workspace.apps[require_config.appKey(id)]?.port;
|
|
2706
|
+
if (port) ports[id] = port;
|
|
2707
|
+
}
|
|
2708
|
+
return ports;
|
|
2709
|
+
}
|
|
2710
|
+
/**
|
|
2637
2711
|
* Where each declared surface and site answers locally.
|
|
2638
2712
|
*
|
|
2639
2713
|
* The addresses come from the ports the workspace already assigns; which
|
|
@@ -2791,4 +2865,4 @@ Object.defineProperty(exports, "workspace_exports", {
|
|
|
2791
2865
|
}
|
|
2792
2866
|
});
|
|
2793
2867
|
|
|
2794
|
-
//# sourceMappingURL=workspace-
|
|
2868
|
+
//# sourceMappingURL=workspace-C0X8xSXV.cjs.map
|