@geekmidas/manifest 10.0.0-alpha.167 → 10.0.0-alpha.169
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/index.cjs +144 -38
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +141 -15
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +141 -15
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +135 -38
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -33,13 +33,17 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
33
33
|
* this.
|
|
34
34
|
*/
|
|
35
35
|
const DEFAULT_POSTGRES_VERSION = 18;
|
|
36
|
+
/** Whether a declaration is built into a public bundle — a site or an app. */
|
|
37
|
+
function isPublicDeclaration(declaration) {
|
|
38
|
+
return declaration.kind === "site" || declaration.kind === "mobile-app";
|
|
39
|
+
}
|
|
36
40
|
/** A site's subdomain that means every subdomain — see `SiteDeclaration`. */
|
|
37
41
|
const WILDCARD_SUBDOMAIN = "*";
|
|
38
42
|
/**
|
|
39
43
|
* Whether a declaration is a site answering on every subdomain.
|
|
40
44
|
*/
|
|
41
45
|
function isWildcardSite(declaration) {
|
|
42
|
-
return declaration?.kind === "site" && declaration.subdomain === "*";
|
|
46
|
+
return declaration?.kind === "site" && "subdomain" in declaration && declaration.subdomain === "*";
|
|
43
47
|
}
|
|
44
48
|
/**
|
|
45
49
|
* What a `Telemetry` node provides to each process with an edge to it.
|
|
@@ -1008,6 +1012,47 @@ const PUBLIC_PREFIX = {
|
|
|
1008
1012
|
expo: "EXPO_PUBLIC_"
|
|
1009
1013
|
};
|
|
1010
1014
|
/**
|
|
1015
|
+
* Every public value a site's or a mobile app's edges reach — the one walk of
|
|
1016
|
+
* its edges that every target makes, so what a bundle inlines cannot differ
|
|
1017
|
+
* between `gkm dev`, a compose build and the AWS target.
|
|
1018
|
+
*
|
|
1019
|
+
* Each edge's `PUBLIC` roles, and, because a bucket and the file server over
|
|
1020
|
+
* it are one construct to a page:
|
|
1021
|
+
*
|
|
1022
|
+
* - an edge to a bucket (a full-stack site's `.dependsOn([assets.server])`)
|
|
1023
|
+
* also reaches each file server over it — its objects are shown from there;
|
|
1024
|
+
* - an edge to a file server also reaches its bucket's public values — where
|
|
1025
|
+
* the bucket signs the links to its private objects.
|
|
1026
|
+
*
|
|
1027
|
+
* A bucket's connection is never one: `PUBLIC.objects` does not list it.
|
|
1028
|
+
*/
|
|
1029
|
+
function publicValues(declaration, manifest) {
|
|
1030
|
+
const values = /* @__PURE__ */ new Map();
|
|
1031
|
+
const reach = (id) => {
|
|
1032
|
+
const target = manifest[id];
|
|
1033
|
+
if (!target) return;
|
|
1034
|
+
for (const role of PUBLIC[target.kind] ?? []) {
|
|
1035
|
+
const key = providedKeyFor(id, target.kind, role);
|
|
1036
|
+
values.set(key, {
|
|
1037
|
+
id,
|
|
1038
|
+
kind: target.kind,
|
|
1039
|
+
role,
|
|
1040
|
+
key
|
|
1041
|
+
});
|
|
1042
|
+
}
|
|
1043
|
+
};
|
|
1044
|
+
for (const edge of declaration.dependencies) {
|
|
1045
|
+
const target = manifest[edge.target];
|
|
1046
|
+
if (!target) continue;
|
|
1047
|
+
reach(edge.target);
|
|
1048
|
+
if (target.kind === "objects") {
|
|
1049
|
+
for (const [id, other] of Object.entries(manifest)) if (other.kind === "file-server" && other.of === edge.target) reach(id);
|
|
1050
|
+
}
|
|
1051
|
+
if (target.kind === "file-server") reach(target.of);
|
|
1052
|
+
}
|
|
1053
|
+
return [...values.values()];
|
|
1054
|
+
}
|
|
1055
|
+
/**
|
|
1011
1056
|
* The keys a site's bundle needs, mapped to the key each value comes from —
|
|
1012
1057
|
* `{ VITE_API_URL: 'API_URL' }` — its edges' public values, and a site's own
|
|
1013
1058
|
* address (`{ VITE_WEB_URL: 'WEB_URL' }`).
|
|
@@ -1030,31 +1075,14 @@ function publicEnvFor(declaration, manifest) {
|
|
|
1030
1075
|
const prefix = PUBLIC_PREFIX[declaration.variant];
|
|
1031
1076
|
const keys = {};
|
|
1032
1077
|
if (declaration.kind === "site") {
|
|
1033
|
-
const own =
|
|
1078
|
+
const own = providedKeyFor(declaration.id, "site", "url");
|
|
1034
1079
|
keys[`${prefix}${own}`] = own;
|
|
1035
1080
|
}
|
|
1036
1081
|
if (isWildcardSite(declaration)) for (const role of ["domain", "protectedSubdomains"]) {
|
|
1037
|
-
const key =
|
|
1082
|
+
const key = providedKeyFor(declaration.id, "site", role);
|
|
1038
1083
|
keys[`${prefix}${key}`] = key;
|
|
1039
1084
|
}
|
|
1040
|
-
const
|
|
1041
|
-
for (const role of PUBLIC[target.kind] ?? []) {
|
|
1042
|
-
const key = providedKeyFor(id, target.kind, role);
|
|
1043
|
-
keys[`${prefix}${key}`] = key;
|
|
1044
|
-
}
|
|
1045
|
-
};
|
|
1046
|
-
for (const edge of declaration.dependencies) {
|
|
1047
|
-
const target = manifest[edge.target];
|
|
1048
|
-
if (!target) continue;
|
|
1049
|
-
inline(edge.target, target);
|
|
1050
|
-
if (target.kind === "objects") {
|
|
1051
|
-
for (const [id, other] of Object.entries(manifest)) if (other.kind === "file-server" && other.of === edge.target) inline(id, other);
|
|
1052
|
-
}
|
|
1053
|
-
if (target.kind === "file-server") {
|
|
1054
|
-
const bucket = manifest[target.of];
|
|
1055
|
-
if (bucket) inline(target.of, bucket);
|
|
1056
|
-
}
|
|
1057
|
-
}
|
|
1085
|
+
for (const { key } of publicValues(declaration, manifest)) keys[`${prefix}${key}`] = key;
|
|
1058
1086
|
return keys;
|
|
1059
1087
|
}
|
|
1060
1088
|
/**
|
|
@@ -1069,25 +1097,11 @@ const IMAGE_ORIGINS_KEY = "GKM_IMAGE_ORIGINS";
|
|
|
1069
1097
|
/**
|
|
1070
1098
|
* The keys whose values are the origins a site's pages load files from: each
|
|
1071
1099
|
* file server it reaches, and where each bucket it reaches signs its links —
|
|
1072
|
-
* by either edge,
|
|
1100
|
+
* by either edge, read off {@link publicValues}. Sorted, so the
|
|
1073
1101
|
* value composed from them does not churn.
|
|
1074
1102
|
*/
|
|
1075
1103
|
function imageOriginSources(declaration, manifest) {
|
|
1076
|
-
|
|
1077
|
-
const bucket = (id) => sources.add(providedKeyFor(id, "objects", "signedOrigin"));
|
|
1078
|
-
const server = (id) => sources.add(providedKeyFor(id, "file-server", "url"));
|
|
1079
|
-
for (const edge of declaration.dependencies) {
|
|
1080
|
-
const target = manifest[edge.target];
|
|
1081
|
-
if (target?.kind === "objects") {
|
|
1082
|
-
bucket(edge.target);
|
|
1083
|
-
for (const [id, other] of Object.entries(manifest)) if (other.kind === "file-server" && other.of === edge.target) server(id);
|
|
1084
|
-
}
|
|
1085
|
-
if (target?.kind === "file-server") {
|
|
1086
|
-
server(edge.target);
|
|
1087
|
-
if (manifest[target.of]?.kind === "objects") bucket(target.of);
|
|
1088
|
-
}
|
|
1089
|
-
}
|
|
1090
|
-
return [...sources].sort();
|
|
1104
|
+
return publicValues(declaration, manifest).filter(({ kind, role }) => kind === "file-server" && role === "url" || kind === "objects" && role === "signedOrigin").map(({ key }) => key).sort();
|
|
1091
1105
|
}
|
|
1092
1106
|
/**
|
|
1093
1107
|
* {@link IMAGE_ORIGINS_KEY}'s value: the origin of each source that resolved,
|
|
@@ -1123,6 +1137,14 @@ function bucketExpiry(manifest, bucketId) {
|
|
|
1123
1137
|
return Object.keys(expire).length > 0 ? expire : void 0;
|
|
1124
1138
|
}
|
|
1125
1139
|
//#endregion
|
|
1140
|
+
//#region src/email.ts
|
|
1141
|
+
/** The local part mail is sent from when the construct names none. */
|
|
1142
|
+
const DEFAULT_SENDER = "noreply";
|
|
1143
|
+
/** `<local part>@<domain>` — `info@shop.example.com`, else `noreply@…`. */
|
|
1144
|
+
function senderAddress(email, domain) {
|
|
1145
|
+
return `${email.from ?? "noreply"}@${domain}`;
|
|
1146
|
+
}
|
|
1147
|
+
//#endregion
|
|
1126
1148
|
//#region src/encryption.ts
|
|
1127
1149
|
/**
|
|
1128
1150
|
* The `kms://` URL an `Encryption` construct reads on AWS.
|
|
@@ -1219,6 +1241,81 @@ const EDGE_TOKEN_HEADER = "x-gkm-edge-token";
|
|
|
1219
1241
|
/** Where a stack's processes read the token {@link EDGE_TOKEN_HEADER} carries. */
|
|
1220
1242
|
const EDGE_TOKEN_KEY = "GKM_EDGE_TOKEN";
|
|
1221
1243
|
//#endregion
|
|
1244
|
+
//#region src/hosts.ts
|
|
1245
|
+
/** Whether a declaration answers on a host of its own: a surface or a site. */
|
|
1246
|
+
function isHostedDeclaration(declaration) {
|
|
1247
|
+
return declaration?.kind === "rest-api" || declaration?.kind === "websocket-api" || declaration?.kind === "site";
|
|
1248
|
+
}
|
|
1249
|
+
/**
|
|
1250
|
+
* The one derivation of a construct's labels: its primary label, its
|
|
1251
|
+
* aliases and its redirects, in declared order.
|
|
1252
|
+
*/
|
|
1253
|
+
function hostLabels(source) {
|
|
1254
|
+
return {
|
|
1255
|
+
primary: source.subdomain ?? kebabCase(source.id),
|
|
1256
|
+
aliases: [...source.aliases ?? []],
|
|
1257
|
+
redirects: [...source.redirects ?? []]
|
|
1258
|
+
};
|
|
1259
|
+
}
|
|
1260
|
+
/** One label of a DNS name: lowercase letters, digits and inner hyphens. */
|
|
1261
|
+
const LABEL$1 = /^[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?$/;
|
|
1262
|
+
/** An alias or redirect that cannot be a label of its own under the domain. */
|
|
1263
|
+
var InvalidHostLabel = class extends Error {
|
|
1264
|
+
id;
|
|
1265
|
+
label;
|
|
1266
|
+
field;
|
|
1267
|
+
constructor(id, label, field) {
|
|
1268
|
+
super(`'${id}' lists '${label}' in ${field}, which is not a host label it can add: each entry is one lowercase label under the stage's domain ('rest', 'www') — no '*', no dots — listed once, and not the construct's own label. Fix or remove the entry.`);
|
|
1269
|
+
this.id = id;
|
|
1270
|
+
this.label = label;
|
|
1271
|
+
this.field = field;
|
|
1272
|
+
this.name = "InvalidHostLabel";
|
|
1273
|
+
}
|
|
1274
|
+
};
|
|
1275
|
+
/** A wildcard site with aliases or redirects. */
|
|
1276
|
+
var WildcardSiteCannotHaveAliases = class extends Error {
|
|
1277
|
+
id;
|
|
1278
|
+
constructor(id) {
|
|
1279
|
+
super(`'${id}' answers on every subdomain, so it has no single host for an alias to repeat or a redirect to point at. Drop \`aliases\` and \`redirects\`, or give the site a subdomain of its own.`);
|
|
1280
|
+
this.id = id;
|
|
1281
|
+
this.name = "WildcardSiteCannotHaveAliases";
|
|
1282
|
+
}
|
|
1283
|
+
};
|
|
1284
|
+
/** One label listed as both an alias and a redirect. */
|
|
1285
|
+
var HostLabelBothAliasAndRedirect = class extends Error {
|
|
1286
|
+
id;
|
|
1287
|
+
label;
|
|
1288
|
+
constructor(id, label) {
|
|
1289
|
+
super(`'${id}' lists '${label}' in both aliases and redirects, but a host either serves the site or sends the browser elsewhere. Keep it in one of the two.`);
|
|
1290
|
+
this.id = id;
|
|
1291
|
+
this.label = label;
|
|
1292
|
+
this.name = "HostLabelBothAliasAndRedirect";
|
|
1293
|
+
}
|
|
1294
|
+
};
|
|
1295
|
+
/**
|
|
1296
|
+
* What a construct's aliases and redirects have to be, checked where it is
|
|
1297
|
+
* constructed.
|
|
1298
|
+
*
|
|
1299
|
+
* @throws {WildcardSiteCannotHaveAliases} on a wildcard site with either
|
|
1300
|
+
* @throws {HostLabelBothAliasAndRedirect} when a label is in both lists
|
|
1301
|
+
* @throws {InvalidHostLabel} for `'*'`, a dot, a repeat, or its own label
|
|
1302
|
+
*/
|
|
1303
|
+
function assertHostLabels(source) {
|
|
1304
|
+
const { primary, aliases, redirects } = hostLabels(source);
|
|
1305
|
+
if (aliases.length === 0 && redirects.length === 0) return;
|
|
1306
|
+
if (primary === "*") throw new WildcardSiteCannotHaveAliases(source.id);
|
|
1307
|
+
for (const label of aliases) if (redirects.includes(label)) throw new HostLabelBothAliasAndRedirect(source.id, label);
|
|
1308
|
+
const seen = /* @__PURE__ */ new Set([primary]);
|
|
1309
|
+
const check = (labels, field) => {
|
|
1310
|
+
for (const label of labels) {
|
|
1311
|
+
if (!LABEL$1.test(label) || seen.has(label)) throw new InvalidHostLabel(source.id, label, field);
|
|
1312
|
+
seen.add(label);
|
|
1313
|
+
}
|
|
1314
|
+
};
|
|
1315
|
+
check(aliases, "aliases");
|
|
1316
|
+
check(redirects, "redirects");
|
|
1317
|
+
}
|
|
1318
|
+
//#endregion
|
|
1222
1319
|
//#region src/inbox.ts
|
|
1223
1320
|
/** The event type a received message is announced as on its inbox's topic. */
|
|
1224
1321
|
const INBOX_EVENT = "email.received";
|
|
@@ -1528,18 +1625,21 @@ exports.CLIENT_IP_HEADER = CLIENT_IP_HEADER;
|
|
|
1528
1625
|
exports.DATABASE_FOLDERS = DATABASE_FOLDERS;
|
|
1529
1626
|
exports.DEFAULT_DERIVED_DAYS = DEFAULT_DERIVED_DAYS;
|
|
1530
1627
|
exports.DEFAULT_POSTGRES_VERSION = DEFAULT_POSTGRES_VERSION;
|
|
1628
|
+
exports.DEFAULT_SENDER = DEFAULT_SENDER;
|
|
1531
1629
|
exports.DEFAULT_STAGE_URL = DEFAULT_STAGE_URL;
|
|
1532
1630
|
exports.DERIVED_PREFIX = DERIVED_PREFIX;
|
|
1533
1631
|
exports.DERIVES_FROM = DERIVES_FROM;
|
|
1534
1632
|
exports.EDGE_TOKEN_HEADER = EDGE_TOKEN_HEADER;
|
|
1535
1633
|
exports.EDGE_TOKEN_KEY = EDGE_TOKEN_KEY;
|
|
1536
1634
|
exports.FILE_SERVER_SUFFIX = FILE_SERVER_SUFFIX;
|
|
1635
|
+
exports.HostLabelBothAliasAndRedirect = HostLabelBothAliasAndRedirect;
|
|
1537
1636
|
exports.IMAGE_ORIGINS_KEY = IMAGE_ORIGINS_KEY;
|
|
1538
1637
|
exports.INBOX_EVENT = INBOX_EVENT;
|
|
1539
1638
|
exports.INBOX_MESSAGES_PREFIX = INBOX_MESSAGES_PREFIX;
|
|
1540
1639
|
exports.IllegalDerivation = IllegalDerivation;
|
|
1541
1640
|
exports.InvalidApiGatewayWebSocketUrl = InvalidApiGatewayWebSocketUrl;
|
|
1542
1641
|
exports.InvalidConstructId = InvalidConstructId;
|
|
1642
|
+
exports.InvalidHostLabel = InvalidHostLabel;
|
|
1543
1643
|
exports.KMS_SCHEME = KMS_SCHEME;
|
|
1544
1644
|
exports.MIGRATIONS_ROOT = MIGRATIONS_ROOT;
|
|
1545
1645
|
exports.NoUrlForStage = NoUrlForStage;
|
|
@@ -1550,8 +1650,10 @@ exports.SECRET_SYMBOLS = SECRET_SYMBOLS;
|
|
|
1550
1650
|
exports.TELEMETRY_KEYS = TELEMETRY_KEYS;
|
|
1551
1651
|
exports.UnknownParent = UnknownParent;
|
|
1552
1652
|
exports.WILDCARD_SUBDOMAIN = WILDCARD_SUBDOMAIN;
|
|
1653
|
+
exports.WildcardSiteCannotHaveAliases = WildcardSiteCannotHaveAliases;
|
|
1553
1654
|
exports.apiGatewayWebSocketUrl = apiGatewayWebSocketUrl;
|
|
1554
1655
|
exports.assertDerivations = assertDerivations;
|
|
1656
|
+
exports.assertHostLabels = assertHostLabels;
|
|
1555
1657
|
exports.bucketExpiry = bucketExpiry;
|
|
1556
1658
|
exports.cacheTable = cacheTable;
|
|
1557
1659
|
exports.canonicalId = canonicalId;
|
|
@@ -1565,10 +1667,13 @@ exports.environmentCase = environmentCase;
|
|
|
1565
1667
|
exports.externalApiUrl = externalApiUrl;
|
|
1566
1668
|
exports.fileServerName = fileServerName;
|
|
1567
1669
|
exports.fileServerSurfaceId = fileServerSurfaceId;
|
|
1670
|
+
exports.hostLabels = hostLabels;
|
|
1568
1671
|
exports.imageOriginSources = imageOriginSources;
|
|
1569
1672
|
exports.imageOrigins = imageOrigins;
|
|
1570
1673
|
exports.inboxRecipient = inboxRecipient;
|
|
1571
1674
|
exports.isDerived = isDerived;
|
|
1675
|
+
exports.isHostedDeclaration = isHostedDeclaration;
|
|
1676
|
+
exports.isPublicDeclaration = isPublicDeclaration;
|
|
1572
1677
|
exports.isWebOrigin = isWebOrigin;
|
|
1573
1678
|
exports.isWildcardSite = isWildcardSite;
|
|
1574
1679
|
exports.kebabCase = kebabCase;
|
|
@@ -1577,14 +1682,15 @@ exports.migrationFolder = migrationFolder;
|
|
|
1577
1682
|
exports.migrationTargets = migrationTargets;
|
|
1578
1683
|
exports.mobileOrigins = mobileOrigins;
|
|
1579
1684
|
exports.parseApiGatewayWebSocketUrl = parseApiGatewayWebSocketUrl;
|
|
1580
|
-
exports.provideKey = provideKey;
|
|
1581
1685
|
exports.providedKeyFor = providedKeyFor;
|
|
1582
1686
|
exports.provisionOrder = provisionOrder;
|
|
1583
1687
|
exports.publicEnvFor = publicEnvFor;
|
|
1688
|
+
exports.publicValues = publicValues;
|
|
1584
1689
|
exports.receiptRecipients = receiptRecipients;
|
|
1585
1690
|
exports.schemeBase = schemeBase;
|
|
1586
1691
|
exports.scopedName = scopedName;
|
|
1587
1692
|
exports.seedFolder = seedFolder;
|
|
1693
|
+
exports.senderAddress = senderAddress;
|
|
1588
1694
|
exports.serviceKey = serviceKey;
|
|
1589
1695
|
exports.trustsOrigin = trustsOrigin;
|
|
1590
1696
|
exports.wildcardDomainOf = wildcardDomainOf;
|