@geekmidas/manifest 10.0.0-alpha.166 → 10.0.0-alpha.168

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 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.
@@ -76,7 +80,7 @@ const DERIVES_FROM = {
76
80
  * can legitimately use any of them. A bucket's `url` presigns and stays private.
77
81
  */
78
82
  const PUBLIC = {
79
- objects: [],
83
+ objects: ["signedOrigin"],
80
84
  "file-server": ["url"],
81
85
  email: ["inboxUrl"],
82
86
  inbox: [],
@@ -875,8 +879,32 @@ function cookieDomain(urls) {
875
879
  function providedKeyFor(id, kind, role) {
876
880
  if (kind === "secret") return environmentCase(id);
877
881
  if (kind === "telemetry") return "OTEL_EXPORTER_OTLP_ENDPOINT";
882
+ if (kind === "file-server") return provideKey(fileServerName(id), role);
878
883
  return provideKey(id, role);
879
884
  }
885
+ /**
886
+ * What a file server's surface node adds to the construct's id. The bucket
887
+ * keeps the plain id, so serving a bucket you already have adds a node rather
888
+ * than renaming the one holding the data.
889
+ */
890
+ const FILE_SERVER_SUFFIX = "Server";
891
+ /**
892
+ * A file server's surface node id, from the construct's id.
893
+ *
894
+ * @example fileServerSurfaceId('Assets') // 'AssetsServer'
895
+ */
896
+ function fileServerSurfaceId(id) {
897
+ return `${id}${FILE_SERVER_SUFFIX}`;
898
+ }
899
+ /**
900
+ * The construct's id, from its surface node's: what its key and its host are
901
+ * named after.
902
+ *
903
+ * @example fileServerName('AssetsServer') // 'Assets'
904
+ */
905
+ function fileServerName(surfaceId) {
906
+ return surfaceId.endsWith("Server") && surfaceId.length > 6 ? surfaceId.slice(0, -6) : surfaceId;
907
+ }
880
908
  //#endregion
881
909
  //#region src/derive.ts
882
910
  /** Whether a declaration names a parent. */
@@ -984,6 +1012,47 @@ const PUBLIC_PREFIX = {
984
1012
  expo: "EXPO_PUBLIC_"
985
1013
  };
986
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
+ /**
987
1056
  * The keys a site's bundle needs, mapped to the key each value comes from —
988
1057
  * `{ VITE_API_URL: 'API_URL' }` — its edges' public values, and a site's own
989
1058
  * address (`{ VITE_WEB_URL: 'WEB_URL' }`).
@@ -1006,23 +1075,50 @@ function publicEnvFor(declaration, manifest) {
1006
1075
  const prefix = PUBLIC_PREFIX[declaration.variant];
1007
1076
  const keys = {};
1008
1077
  if (declaration.kind === "site") {
1009
- const own = provideKey(declaration.id, "url");
1078
+ const own = providedKeyFor(declaration.id, "site", "url");
1010
1079
  keys[`${prefix}${own}`] = own;
1011
1080
  }
1012
1081
  if (isWildcardSite(declaration)) for (const role of ["domain", "protectedSubdomains"]) {
1013
- const key = provideKey(declaration.id, role);
1082
+ const key = providedKeyFor(declaration.id, "site", role);
1014
1083
  keys[`${prefix}${key}`] = key;
1015
1084
  }
1016
- for (const edge of declaration.dependencies) {
1017
- const target = manifest[edge.target];
1018
- if (!target) continue;
1019
- for (const role of PUBLIC[target.kind] ?? []) {
1020
- const key = provideKey(edge.target, role);
1021
- keys[`${prefix}${key}`] = key;
1022
- }
1023
- }
1085
+ for (const { key } of publicValues(declaration, manifest)) keys[`${prefix}${key}`] = key;
1024
1086
  return keys;
1025
1087
  }
1088
+ /**
1089
+ * The key, under a site's public prefix, that lists every origin its pages
1090
+ * load files from: `NEXT_PUBLIC_GKM_IMAGE_ORIGINS`. Comma-separated.
1091
+ *
1092
+ * One composed key rather than a rule over names, because a file server's
1093
+ * `<ID>_URL` and an API's look the same: which of a bundle's addresses serve
1094
+ * files is a fact about the graph, so the graph says it.
1095
+ */
1096
+ const IMAGE_ORIGINS_KEY = "GKM_IMAGE_ORIGINS";
1097
+ /**
1098
+ * The keys whose values are the origins a site's pages load files from: each
1099
+ * file server it reaches, and where each bucket it reaches signs its links —
1100
+ * by either edge, read off {@link publicValues}. Sorted, so the
1101
+ * value composed from them does not churn.
1102
+ */
1103
+ function imageOriginSources(declaration, manifest) {
1104
+ return publicValues(declaration, manifest).filter(({ kind, role }) => kind === "file-server" && role === "url" || kind === "objects" && role === "signedOrigin").map(({ key }) => key).sort();
1105
+ }
1106
+ /**
1107
+ * {@link IMAGE_ORIGINS_KEY}'s value: the origin of each source that resolved,
1108
+ * de-duplicated and comma-separated. `undefined` when none did, so a site
1109
+ * that shows no files is built without the key at all.
1110
+ */
1111
+ function imageOrigins(sources, resolve) {
1112
+ const origins = /* @__PURE__ */ new Set();
1113
+ for (const source of sources) {
1114
+ const value = resolve(source);
1115
+ if (!value) continue;
1116
+ try {
1117
+ origins.add(new URL(value).origin);
1118
+ } catch {}
1119
+ }
1120
+ return origins.size > 0 ? [...origins].sort().join(",") : void 0;
1121
+ }
1026
1122
  //#endregion
1027
1123
  //#region src/derived.ts
1028
1124
  /** Where a processor keeps what it made, in the bucket it reads. */
@@ -1451,6 +1547,8 @@ exports.DERIVED_PREFIX = DERIVED_PREFIX;
1451
1547
  exports.DERIVES_FROM = DERIVES_FROM;
1452
1548
  exports.EDGE_TOKEN_HEADER = EDGE_TOKEN_HEADER;
1453
1549
  exports.EDGE_TOKEN_KEY = EDGE_TOKEN_KEY;
1550
+ exports.FILE_SERVER_SUFFIX = FILE_SERVER_SUFFIX;
1551
+ exports.IMAGE_ORIGINS_KEY = IMAGE_ORIGINS_KEY;
1454
1552
  exports.INBOX_EVENT = INBOX_EVENT;
1455
1553
  exports.INBOX_MESSAGES_PREFIX = INBOX_MESSAGES_PREFIX;
1456
1554
  exports.IllegalDerivation = IllegalDerivation;
@@ -1479,8 +1577,13 @@ exports.dependentsOf = dependentsOf;
1479
1577
  exports.drawSecret = drawSecret;
1480
1578
  exports.environmentCase = environmentCase;
1481
1579
  exports.externalApiUrl = externalApiUrl;
1580
+ exports.fileServerName = fileServerName;
1581
+ exports.fileServerSurfaceId = fileServerSurfaceId;
1582
+ exports.imageOriginSources = imageOriginSources;
1583
+ exports.imageOrigins = imageOrigins;
1482
1584
  exports.inboxRecipient = inboxRecipient;
1483
1585
  exports.isDerived = isDerived;
1586
+ exports.isPublicDeclaration = isPublicDeclaration;
1484
1587
  exports.isWebOrigin = isWebOrigin;
1485
1588
  exports.isWildcardSite = isWildcardSite;
1486
1589
  exports.kebabCase = kebabCase;
@@ -1489,10 +1592,10 @@ exports.migrationFolder = migrationFolder;
1489
1592
  exports.migrationTargets = migrationTargets;
1490
1593
  exports.mobileOrigins = mobileOrigins;
1491
1594
  exports.parseApiGatewayWebSocketUrl = parseApiGatewayWebSocketUrl;
1492
- exports.provideKey = provideKey;
1493
1595
  exports.providedKeyFor = providedKeyFor;
1494
1596
  exports.provisionOrder = provisionOrder;
1495
1597
  exports.publicEnvFor = publicEnvFor;
1598
+ exports.publicValues = publicValues;
1496
1599
  exports.receiptRecipients = receiptRecipients;
1497
1600
  exports.schemeBase = schemeBase;
1498
1601
  exports.scopedName = scopedName;