@geekmidas/manifest 10.0.0-alpha.11 → 10.0.0-alpha.110

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
@@ -1,13 +1,12 @@
1
- //#region rolldown:runtime
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ //#region \0rolldown/runtime.js
2
3
  var __create = Object.create;
3
4
  var __defProp = Object.defineProperty;
4
5
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
6
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
7
  var __getProtoOf = Object.getPrototypeOf;
7
8
  var __hasOwnProp = Object.prototype.hasOwnProperty;
8
- var __commonJS = (cb, mod) => function() {
9
- return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
10
- };
9
+ var __commonJSMin = (cb, mod) => () => (mod || (cb((mod = { exports: {} }).exports, mod), cb = null), mod.exports);
11
10
  var __copyProps = (to, from, except, desc) => {
12
11
  if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
13
12
  key = keys[i];
@@ -18,13 +17,11 @@ var __copyProps = (to, from, except, desc) => {
18
17
  }
19
18
  return to;
20
19
  };
21
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule || !__hasOwnProp.call(mod, "default") ? __defProp(target, "default", {
22
21
  value: mod,
23
22
  enumerable: true
24
23
  }) : target, mod));
25
-
26
24
  //#endregion
27
-
28
25
  //#region src/declaration.ts
29
26
  /**
30
27
  * The version used when a database names none.
@@ -37,6 +34,19 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
37
34
  */
38
35
  const DEFAULT_POSTGRES_VERSION = 18;
39
36
  /**
37
+ * What a `Telemetry` node provides to each process with an edge to it.
38
+ *
39
+ * `OTEL_SERVICE_NAME` is resolved per process — the app's name — so it is
40
+ * listed here but composed by whichever target hands it over.
41
+ */
42
+ const TELEMETRY_KEYS = [
43
+ "OTEL_EXPORTER_OTLP_ENDPOINT",
44
+ "OTEL_EXPORTER_OTLP_HEADERS",
45
+ "OTEL_SERVICE_NAME",
46
+ "OTEL_TRACES_SAMPLER",
47
+ "OTEL_TRACES_SAMPLER_ARG"
48
+ ];
49
+ /**
40
50
  * What each kind may derive from.
41
51
  *
42
52
  * Small enough to state exhaustively, and stating it makes cycles impossible
@@ -60,23 +70,26 @@ const DERIVES_FROM = {
60
70
  const PUBLIC = {
61
71
  objects: [],
62
72
  "file-server": ["url"],
63
- email: [],
73
+ email: ["inboxUrl"],
64
74
  database: [],
65
75
  "database-reader": [],
66
76
  "database-schema": [],
67
77
  cache: [],
68
78
  secret: [],
69
79
  credential: [],
80
+ encryption: [],
70
81
  "rest-api": ["url"],
71
82
  queue: [],
72
83
  topic: [],
73
84
  oidc: ["issuer", "audience"],
85
+ "external-api": [],
74
86
  function: [],
75
87
  cron: [],
88
+ "mobile-app": [],
76
89
  site: ["url"],
77
- worker: []
90
+ worker: [],
91
+ telemetry: []
78
92
  };
79
-
80
93
  //#endregion
81
94
  //#region src/errors.ts
82
95
  /**
@@ -135,20 +148,9 @@ var IllegalDerivation = class extends Error {
135
148
  this.allowed = allowed;
136
149
  }
137
150
  };
138
-
139
151
  //#endregion
140
- //#region ../../node_modules/.pnpm/lodash.snakecase@4.1.1/node_modules/lodash.snakecase/index.js
141
- var require_lodash = __commonJS({ "../../node_modules/.pnpm/lodash.snakecase@4.1.1/node_modules/lodash.snakecase/index.js"(exports, module) {
142
- /**
143
- * lodash (Custom Build) <https://lodash.com/>
144
- * Build: `lodash modularize exports="npm" -o ./`
145
- * Copyright jQuery Foundation and other contributors <https://jquery.org/>
146
- * Released under MIT license <https://lodash.com/license>
147
- * Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>
148
- * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
149
- */
150
- /** Used as references for various `Number` constants. */
151
- var INFINITY = Infinity;
152
+ //#region src/naming.ts
153
+ var import_lodash_snakecase = /* @__PURE__ */ __toESM((/* @__PURE__ */ __commonJSMin(((exports, module) => {
152
154
  /** `Object#toString` result references. */
153
155
  var symbolTag = "[object Symbol]";
154
156
  /** Used to match words composed of alphanumeric characters. */
@@ -156,15 +158,46 @@ var require_lodash = __commonJS({ "../../node_modules/.pnpm/lodash.snakecase@4.1
156
158
  /** Used to match Latin Unicode letters (excluding mathematical operators). */
157
159
  var reLatin = /[\xc0-\xd6\xd8-\xf6\xf8-\xff\u0100-\u017f]/g;
158
160
  /** Used to compose unicode character classes. */
159
- var rsAstralRange = "\\ud800-\\udfff", rsComboMarksRange = "\\u0300-\\u036f\\ufe20-\\ufe23", rsComboSymbolsRange = "\\u20d0-\\u20f0", rsDingbatRange = "\\u2700-\\u27bf", rsLowerRange = "a-z\\xdf-\\xf6\\xf8-\\xff", rsMathOpRange = "\\xac\\xb1\\xd7\\xf7", rsNonCharRange = "\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\xbf", rsPunctuationRange = "\\u2000-\\u206f", rsSpaceRange = " \\t\\x0b\\f\\xa0\\ufeff\\n\\r\\u2028\\u2029\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000", rsUpperRange = "A-Z\\xc0-\\xd6\\xd8-\\xde", rsVarRange = "\\ufe0e\\ufe0f", rsBreakRange = rsMathOpRange + rsNonCharRange + rsPunctuationRange + rsSpaceRange;
161
+ var rsAstralRange = "\\ud800-\\udfff";
162
+ var rsComboMarksRange = "\\u0300-\\u036f\\ufe20-\\ufe23";
163
+ var rsComboSymbolsRange = "\\u20d0-\\u20f0";
164
+ var rsDingbatRange = "\\u2700-\\u27bf";
165
+ var rsLowerRange = "a-z\\xdf-\\xf6\\xf8-\\xff";
166
+ var rsMathOpRange = "\\xac\\xb1\\xd7\\xf7";
167
+ var rsNonCharRange = "\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\xbf";
168
+ var rsPunctuationRange = "\\u2000-\\u206f";
169
+ var rsSpaceRange = " \\t\\x0b\\f\\xa0\\ufeff\\n\\r\\u2028\\u2029\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000";
170
+ var rsUpperRange = "A-Z\\xc0-\\xd6\\xd8-\\xde";
171
+ var rsVarRange = "\\ufe0e\\ufe0f";
172
+ var rsBreakRange = rsMathOpRange + rsNonCharRange + rsPunctuationRange + rsSpaceRange;
160
173
  /** Used to compose unicode capture groups. */
161
- var rsApos = "['’]", rsBreak = "[" + rsBreakRange + "]", rsCombo = "[" + rsComboMarksRange + rsComboSymbolsRange + "]", rsDigits = "\\d+", rsDingbat = "[" + rsDingbatRange + "]", rsLower = "[" + rsLowerRange + "]", rsMisc = "[^" + rsAstralRange + rsBreakRange + rsDigits + rsDingbatRange + rsLowerRange + rsUpperRange + "]", rsFitz = "\\ud83c[\\udffb-\\udfff]", rsModifier = "(?:" + rsCombo + "|" + rsFitz + ")", rsNonAstral = "[^" + rsAstralRange + "]", rsRegional = "(?:\\ud83c[\\udde6-\\uddff]){2}", rsSurrPair = "[\\ud800-\\udbff][\\udc00-\\udfff]", rsUpper = "[" + rsUpperRange + "]", rsZWJ = "\\u200d";
174
+ var rsApos = "['’]";
175
+ var rsBreak = "[" + rsBreakRange + "]";
176
+ var rsCombo = "[" + rsComboMarksRange + rsComboSymbolsRange + "]";
177
+ var rsDigits = "\\d+";
178
+ var rsDingbat = "[" + rsDingbatRange + "]";
179
+ var rsLower = "[" + rsLowerRange + "]";
180
+ var rsMisc = "[^" + rsAstralRange + rsBreakRange + rsDigits + rsDingbatRange + rsLowerRange + rsUpperRange + "]";
181
+ var rsModifier = "(?:" + rsCombo + "|\\ud83c[\\udffb-\\udfff])";
182
+ var rsNonAstral = "[^" + rsAstralRange + "]";
183
+ var rsRegional = "(?:\\ud83c[\\udde6-\\uddff]){2}";
184
+ var rsSurrPair = "[\\ud800-\\udbff][\\udc00-\\udfff]";
185
+ var rsUpper = "[" + rsUpperRange + "]";
186
+ var rsZWJ = "\\u200d";
162
187
  /** Used to compose unicode regexes. */
163
- var rsLowerMisc = "(?:" + rsLower + "|" + rsMisc + ")", rsUpperMisc = "(?:" + rsUpper + "|" + rsMisc + ")", rsOptLowerContr = "(?:" + rsApos + "(?:d|ll|m|re|s|t|ve))?", rsOptUpperContr = "(?:" + rsApos + "(?:D|LL|M|RE|S|T|VE))?", reOptMod = rsModifier + "?", rsOptVar = "[" + rsVarRange + "]?", rsOptJoin = "(?:" + rsZWJ + "(?:" + [
188
+ var rsLowerMisc = "(?:" + rsLower + "|" + rsMisc + ")";
189
+ var rsUpperMisc = "(?:" + rsUpper + "|" + rsMisc + ")";
190
+ var rsOptLowerContr = "(?:" + rsApos + "(?:d|ll|m|re|s|t|ve))?";
191
+ var rsOptUpperContr = "(?:" + rsApos + "(?:D|LL|M|RE|S|T|VE))?";
192
+ var reOptMod = rsModifier + "?";
193
+ var rsOptVar = "[" + rsVarRange + "]?";
194
+ var rsOptJoin = "(?:" + rsZWJ + "(?:" + [
164
195
  rsNonAstral,
165
196
  rsRegional,
166
197
  rsSurrPair
167
- ].join("|") + ")" + rsOptVar + reOptMod + ")*", rsSeq = rsOptVar + reOptMod + rsOptJoin, rsEmoji = "(?:" + [
198
+ ].join("|") + ")" + rsOptVar + reOptMod + ")*";
199
+ var rsSeq = rsOptVar + reOptMod + rsOptJoin;
200
+ var rsEmoji = "(?:" + [
168
201
  rsDingbat,
169
202
  rsRegional,
170
203
  rsSurrPair
@@ -463,18 +496,17 @@ var require_lodash = __commonJS({ "../../node_modules/.pnpm/lodash.snakecase@4.1
463
496
  function unicodeWords(string) {
464
497
  return string.match(reUnicodeWord) || [];
465
498
  }
466
- /** Used for built-in method references. */
467
- var objectProto = Object.prototype;
468
499
  /**
469
500
  * Used to resolve the
470
501
  * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)
471
502
  * of values.
472
503
  */
473
- var objectToString = objectProto.toString;
504
+ var objectToString = Object.prototype.toString;
474
505
  /** Built-in value references. */
475
506
  var Symbol = root.Symbol;
476
507
  /** Used to convert symbols to primitives and strings. */
477
- var symbolProto = Symbol ? Symbol.prototype : void 0, symbolToString = symbolProto ? symbolProto.toString : void 0;
508
+ var symbolProto = Symbol ? Symbol.prototype : void 0;
509
+ var symbolToString = symbolProto ? symbolProto.toString : void 0;
478
510
  /**
479
511
  * The base implementation of `_.toString` which doesn't convert nullish
480
512
  * values to empty strings.
@@ -487,7 +519,7 @@ var require_lodash = __commonJS({ "../../node_modules/.pnpm/lodash.snakecase@4.1
487
519
  if (typeof value == "string") return value;
488
520
  if (isSymbol(value)) return symbolToString ? symbolToString.call(value) : "";
489
521
  var result = value + "";
490
- return result == "0" && 1 / value == -INFINITY ? "-0" : result;
522
+ return result == "0" && 1 / value == -Infinity ? "-0" : result;
491
523
  }
492
524
  /**
493
525
  * Creates a function like `_.camelCase`.
@@ -644,11 +676,7 @@ var require_lodash = __commonJS({ "../../node_modules/.pnpm/lodash.snakecase@4.1
644
676
  return string.match(pattern) || [];
645
677
  }
646
678
  module.exports = snakeCase;
647
- } });
648
-
649
- //#endregion
650
- //#region src/naming.ts
651
- var import_lodash = __toESM(require_lodash(), 1);
679
+ })))(), 1);
652
680
  /**
653
681
  * `UPPER_SNAKE_CASE`, with numbers kept against the word they follow.
654
682
  *
@@ -660,7 +688,7 @@ var import_lodash = __toESM(require_lodash(), 1);
660
688
  * @example environmentCase('api2') // 'API2' (digit joins its word)
661
689
  */
662
690
  function environmentCase(name) {
663
- return (0, import_lodash.default)(name).toUpperCase().replace(/_\d+/g, (r) => r.replace("_", ""));
691
+ return (0, import_lodash_snakecase.default)(name).toUpperCase().replace(/_\d+/g, (r) => r.replace("_", ""));
664
692
  }
665
693
  /**
666
694
  * The env key a construct provides for one of its roles.
@@ -685,7 +713,7 @@ function provideKey(id, role) {
685
713
  * @example canonicalId('user-uploads') // 'UserUploads'
686
714
  */
687
715
  function canonicalId(input) {
688
- const id = (0, import_lodash.default)(input).split("_").filter(Boolean).map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join("");
716
+ const id = (0, import_lodash_snakecase.default)(input).split("_").filter(Boolean).map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join("");
689
717
  if (!VALID_ID.test(id)) throw new InvalidConstructId(input, id);
690
718
  return id;
691
719
  }
@@ -835,9 +863,10 @@ function cookieDomain(urls) {
835
863
  * cannot catch anything.
836
864
  */
837
865
  function providedKeyFor(id, kind, role) {
838
- return kind === "secret" ? environmentCase(id) : provideKey(id, role);
866
+ if (kind === "secret") return environmentCase(id);
867
+ if (kind === "telemetry") return "OTEL_EXPORTER_OTLP_ENDPOINT";
868
+ return provideKey(id, role);
839
869
  }
840
-
841
870
  //#endregion
842
871
  //#region src/derive.ts
843
872
  /** Whether a declaration names a parent. */
@@ -899,10 +928,15 @@ function dependenciesOf(declaration) {
899
928
  const own = "dependencies" in declaration ? declaration.dependencies ?? [] : [];
900
929
  const calls = "calls" in declaration ? declaration.calls ?? [] : [];
901
930
  const nested = declaration.kind === "rest-api" ? declaration.endpoints.flatMap((endpoint) => endpoint.dependencies) : [];
931
+ const telemetry = "telemetry" in declaration && typeof declaration.telemetry === "string" ? [{
932
+ target: declaration.telemetry,
933
+ kind: "telemetry"
934
+ }] : [];
902
935
  return [
903
936
  ...own,
904
937
  ...calls,
905
- ...nested
938
+ ...nested,
939
+ ...telemetry
906
940
  ];
907
941
  }
908
942
  /**
@@ -936,11 +970,13 @@ function dependentsOf(manifest, id) {
936
970
  const PUBLIC_PREFIX = {
937
971
  static: "VITE_",
938
972
  tanstack: "VITE_",
939
- next: "NEXT_PUBLIC_"
973
+ next: "NEXT_PUBLIC_",
974
+ expo: "EXPO_PUBLIC_"
940
975
  };
941
976
  /**
942
977
  * The keys a site's bundle needs, mapped to the key each value comes from —
943
- * `{ VITE_API_URL: 'API_URL' }`.
978
+ * `{ VITE_API_URL: 'API_URL' }` — its edges' public values, and a site's own
979
+ * address (`{ VITE_WEB_URL: 'WEB_URL' }`).
944
980
  *
945
981
  * A rename, not a second derivation: `API_URL` is resolved once, by whatever
946
982
  * resolved it for the server, and the site reads the same value under the name
@@ -959,6 +995,10 @@ const PUBLIC_PREFIX = {
959
995
  function publicEnvFor(declaration, manifest) {
960
996
  const prefix = PUBLIC_PREFIX[declaration.variant];
961
997
  const keys = {};
998
+ if (declaration.kind === "site") {
999
+ const own = provideKey(declaration.id, "url");
1000
+ keys[`${prefix}${own}`] = own;
1001
+ }
962
1002
  for (const edge of declaration.dependencies) {
963
1003
  const target = manifest[edge.target];
964
1004
  if (!target) continue;
@@ -969,38 +1009,269 @@ function publicEnvFor(declaration, manifest) {
969
1009
  }
970
1010
  return keys;
971
1011
  }
972
-
973
1012
  //#endregion
974
- //#region src/index.ts
975
- /** Flatten a manifest field (array or partitioned) into a plain array. */
976
- function flattenManifestField(field) {
977
- if (!field) return [];
978
- return Array.isArray(field) ? [...field] : Object.values(field).flat();
1013
+ //#region src/encryption.ts
1014
+ /**
1015
+ * The `kms://` URL an `Encryption` construct reads on AWS.
1016
+ *
1017
+ * Here because two packages meet on it: `@geekmidas/cloud` composes it from
1018
+ * the keys it provisioned, and `@geekmidas/constructs` parses it to reach
1019
+ * them. One function, so the two cannot disagree about a parameter's name.
1020
+ */
1021
+ const KMS_SCHEME = "kms:";
1022
+ /**
1023
+ * `kms://<region>?key=<key arn>&index=<hmac key arn>[&endpoint=<url>]`
1024
+ *
1025
+ * `endpoint` reaches an emulator instead of AWS — floci, locally and in tests —
1026
+ * the same parameter an `sns://` connection string carries for the same reason.
1027
+ */
1028
+ function kmsUrl(input) {
1029
+ const query = new URLSearchParams({
1030
+ key: input.key,
1031
+ index: input.index,
1032
+ ...input.endpoint ? { endpoint: input.endpoint } : {}
1033
+ });
1034
+ return `${KMS_SCHEME}//${input.region}?${query}`;
1035
+ }
1036
+ //#endregion
1037
+ //#region src/external.ts
1038
+ /** The key in a by-stage `url` that answers for every stage not listed. */
1039
+ const DEFAULT_STAGE_URL = "default";
1040
+ /**
1041
+ * Where an external API answers on a deployed stage.
1042
+ *
1043
+ * One URL answers every stage; a record answers by stage name, falling back
1044
+ * to `default`. Read at build and deploy, so a stage nobody gave a URL fails
1045
+ * there — with the stage named — rather than at the first request.
1046
+ *
1047
+ * @throws {NoUrlForStage} when a record names neither the stage nor a default.
1048
+ */
1049
+ function externalApiUrl(declaration, stage) {
1050
+ const { url } = declaration;
1051
+ if (typeof url === "string") return url;
1052
+ const resolved = url[stage] ?? url["default"];
1053
+ if (!resolved) throw new NoUrlForStage(declaration.id, stage, Object.keys(url));
1054
+ return resolved;
1055
+ }
1056
+ /** An external API's `url` record has nothing for the stage being deployed. */
1057
+ var NoUrlForStage = class extends Error {
1058
+ id;
1059
+ stage;
1060
+ stages;
1061
+ constructor(id, stage, stages) {
1062
+ super(`'${id}' has no URL for the stage '${stage}': its url names ${stages.length ? stages.map((s) => `'${s}'`).join(", ") : "no stages"}. Add '${stage}', or a '${DEFAULT_STAGE_URL}' for every stage not listed.`);
1063
+ this.id = id;
1064
+ this.stage = stage;
1065
+ this.stages = stages;
1066
+ this.name = "NoUrlForStage";
1067
+ }
1068
+ };
1069
+ //#endregion
1070
+ //#region src/headers.ts
1071
+ /**
1072
+ * Headers gkm reserves for its own services' calls to each other.
1073
+ *
1074
+ * Shared by `@geekmidas/constructs`, which sends and reads them, and
1075
+ * `@geekmidas/cli`, whose edges strip them from every request that arrives
1076
+ * from outside — so the two cannot name them differently.
1077
+ */
1078
+ /**
1079
+ * The address of the client a service-to-service call is made on behalf of.
1080
+ *
1081
+ * An API asking its auth server for a session sends the client's address in
1082
+ * this rather than `X-Forwarded-For`: a forwarding header marks a request as
1083
+ * outside traffic, which would start the auth server's span in a new trace,
1084
+ * and the address is still needed — Better Auth rate-limits per client.
1085
+ *
1086
+ * Reserved: the stack's edge (Caddy, Traefik, the `gkm dev` edge) removes it
1087
+ * from incoming requests, and the auth server ignores it on any request that
1088
+ * is not an internal caller's, so it cannot be spoofed from outside.
1089
+ */
1090
+ const CLIENT_IP_HEADER = "x-gkm-client-ip";
1091
+ //#endregion
1092
+ //#region src/migrations.ts
1093
+ /** Where every construct's folder lives, from the project root. */
1094
+ const MIGRATIONS_ROOT = "db";
1095
+ /** The two folders a construct's folder holds, and nothing else. */
1096
+ const DATABASE_FOLDERS = ["migrations", "seeds"];
1097
+ /**
1098
+ * The constructs that take migrations, parents before the tenants inside them.
1099
+ *
1100
+ * A database and each schema tenant: every one has an owner role and a schema
1101
+ * of its own, and so a history of its own. A reader has neither — it reads its
1102
+ * parent's schema — and a cache's table is created by provisioning, not by a
1103
+ * migration anyone writes.
1104
+ */
1105
+ function migrationTargets(manifest) {
1106
+ return provisionOrder(manifest).flatMap((id) => {
1107
+ const declaration = manifest[id];
1108
+ if (!declaration) return [];
1109
+ if (declaration.kind === "database") return [target(id)];
1110
+ if (declaration.kind === "database-schema") return [{
1111
+ ...target(id),
1112
+ of: declaration.of
1113
+ }];
1114
+ return [];
1115
+ });
1116
+ }
1117
+ /**
1118
+ * A construct's folder, relative to the project root.
1119
+ *
1120
+ * Named by the construct — `AuthDatabase` is `db/auth-database` — in the case
1121
+ * every other name outside TypeScript takes. Lowercase, because a folder that
1122
+ * differs from another only in case is two folders on Linux and one on a Mac;
1123
+ * and `canonicalId` reads it back to the construct exactly, which is how a
1124
+ * folder naming nothing is caught rather than skipped.
1125
+ */
1126
+ function databaseFolder(id) {
1127
+ return `db/${kebabCase(id)}`;
1128
+ }
1129
+ /** Where a construct's migrations live: `db/auth-database/migrations`. */
1130
+ function migrationFolder(id) {
1131
+ return `${databaseFolder(id)}/migrations`;
1132
+ }
1133
+ /**
1134
+ * Where a construct's seeds live: `db/auth-database/seeds`.
1135
+ *
1136
+ * Reference data the app needs to run — a permission catalogue, roles, lookup
1137
+ * tables. Seeds are upserts run on every pass, after the migrations, so a
1138
+ * changed seed is applied by running it again. Sample data is factories'.
1139
+ */
1140
+ function seedFolder(id) {
1141
+ return `${databaseFolder(id)}/seeds`;
1142
+ }
1143
+ function target(id) {
1144
+ return {
1145
+ id,
1146
+ folder: databaseFolder(id),
1147
+ migrations: migrationFolder(id),
1148
+ seeds: seedFolder(id)
1149
+ };
1150
+ }
1151
+ //#endregion
1152
+ //#region src/mobile.ts
1153
+ /**
1154
+ * How a mobile app is reached: its URL scheme, and the origins a surface trusts
1155
+ * for it.
1156
+ *
1157
+ * Stated once, here, because three targets ask — the local one (`gkm dev`,
1158
+ * `gkm test`), Dokploy and AWS — and a scheme one of them derived differently
1159
+ * would be an app whose sign-in callback the auth server refuses on exactly one
1160
+ * of them.
1161
+ */
1162
+ /**
1163
+ * An app's scheme: the one given, or the project's name made a valid scheme.
1164
+ *
1165
+ * One for every stage. A development build and the store build register the
1166
+ * same scheme, so the auth server of whichever stage a build talks to trusts
1167
+ * it, and nothing about the app differs between stages but its URLs.
1168
+ *
1169
+ * A scheme is a letter followed by letters, digits, `+`, `-` or `.` — so
1170
+ * `Corner Shop` becomes `corner-shop`, and a name that starts with a digit gets a
1171
+ * leading `app`.
1172
+ */
1173
+ function schemeBase(project, given) {
1174
+ const raw = (given ?? project).toLowerCase().replace(/[^a-z0-9+.-]+/g, "-").replace(/^-+|-+$/g, "");
1175
+ if (!raw) return "app";
1176
+ return /^[a-z]/.test(raw) ? raw : `app${raw}`;
1177
+ }
1178
+ /**
1179
+ * The origins a surface trusts for a mobile caller.
1180
+ *
1181
+ * Better Auth's Expo plugin sends the app's scheme as its origin
1182
+ * (`shop://`), and a link can carry a path after it (`shop://*`).
1183
+ * In development, Expo Go sends `exp://<host>:<port>` instead — so a local
1184
+ * stage adds the hosts a device actually reaches Metro on, and Metro's port
1185
+ * when the target placed it: a whole subnet is not trusted because one phone
1186
+ * is on it.
1187
+ */
1188
+ function mobileOrigins(scheme, metro) {
1189
+ return [
1190
+ `${scheme}://`,
1191
+ `${scheme}://*`,
1192
+ ...(metro?.hosts ?? []).flatMap((host) => [`exp://${host}:${metro?.port ?? "*"}`, `exp://${host}:${metro?.port ?? "*"}/**`])
1193
+ ];
1194
+ }
1195
+ /** Whether an origin is a web one — what a cookie domain is derived from. */
1196
+ function isWebOrigin(origin) {
1197
+ return origin.startsWith("http://") || origin.startsWith("https://");
979
1198
  }
980
-
981
1199
  //#endregion
1200
+ //#region src/secret.ts
1201
+ /**
1202
+ * What a generated secret looks like, and the one way every stage draws it.
1203
+ *
1204
+ * A server deploy draws from `crypto`, `gkm dev` and `gkm test` from a hash of
1205
+ * the project, stage and id, and an AWS deploy asks Pulumi for the same
1206
+ * alphabet. Sharing this is what keeps a password that passes a third party's
1207
+ * rules on one stage from failing them on the next.
1208
+ */
1209
+ /** 43 characters from 64 is 256 bits — as much as anything here needs. */
1210
+ const SECRET_LENGTH = 43;
1211
+ /**
1212
+ * Two symbols nothing has to escape — not a URL, a connection string, a shell
1213
+ * or a `.env` file — which with letters and digits is base64url's alphabet.
1214
+ */
1215
+ const SECRET_SYMBOLS = "-_";
1216
+ const LETTERS_AND_DIGITS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
1217
+ /**
1218
+ * A secret in `format`, each character chosen by `pick(n)` — an integer in
1219
+ * `[0, n)` from whatever source the caller trusts.
1220
+ *
1221
+ * When there are symbols, one is guaranteed: a rule that demands a symbol is
1222
+ * the reason anyone names them, and leaving it to chance fails it often —
1223
+ * about one draw in seven at 24 characters.
1224
+ */
1225
+ function drawSecret(pick, format = {}) {
1226
+ const length = format.length ?? 43;
1227
+ const symbols = [...new Set(format.symbols ?? "-_")].join("");
1228
+ const alphabet = LETTERS_AND_DIGITS + symbols;
1229
+ const chars = Array.from({ length }, () => alphabet[pick(alphabet.length)]);
1230
+ if (symbols && !chars.some((char) => symbols.includes(char))) chars[pick(length)] = symbols[pick(symbols.length)];
1231
+ return chars.join("");
1232
+ }
1233
+ //#endregion
1234
+ exports.CLIENT_IP_HEADER = CLIENT_IP_HEADER;
1235
+ exports.DATABASE_FOLDERS = DATABASE_FOLDERS;
982
1236
  exports.DEFAULT_POSTGRES_VERSION = DEFAULT_POSTGRES_VERSION;
1237
+ exports.DEFAULT_STAGE_URL = DEFAULT_STAGE_URL;
983
1238
  exports.DERIVES_FROM = DERIVES_FROM;
984
1239
  exports.IllegalDerivation = IllegalDerivation;
985
1240
  exports.InvalidConstructId = InvalidConstructId;
1241
+ exports.KMS_SCHEME = KMS_SCHEME;
1242
+ exports.MIGRATIONS_ROOT = MIGRATIONS_ROOT;
1243
+ exports.NoUrlForStage = NoUrlForStage;
986
1244
  exports.PUBLIC = PUBLIC;
987
1245
  exports.PUBLIC_PREFIX = PUBLIC_PREFIX;
1246
+ exports.SECRET_LENGTH = SECRET_LENGTH;
1247
+ exports.SECRET_SYMBOLS = SECRET_SYMBOLS;
1248
+ exports.TELEMETRY_KEYS = TELEMETRY_KEYS;
988
1249
  exports.UnknownParent = UnknownParent;
989
1250
  exports.assertDerivations = assertDerivations;
990
1251
  exports.cacheTable = cacheTable;
991
1252
  exports.canonicalId = canonicalId;
992
1253
  exports.cloudName = cloudName;
993
1254
  exports.cookieDomain = cookieDomain;
1255
+ exports.databaseFolder = databaseFolder;
994
1256
  exports.dependenciesOf = dependenciesOf;
995
1257
  exports.dependentsOf = dependentsOf;
1258
+ exports.drawSecret = drawSecret;
996
1259
  exports.environmentCase = environmentCase;
997
- exports.flattenManifestField = flattenManifestField;
1260
+ exports.externalApiUrl = externalApiUrl;
998
1261
  exports.isDerived = isDerived;
1262
+ exports.isWebOrigin = isWebOrigin;
999
1263
  exports.kebabCase = kebabCase;
1264
+ exports.kmsUrl = kmsUrl;
1265
+ exports.migrationFolder = migrationFolder;
1266
+ exports.migrationTargets = migrationTargets;
1267
+ exports.mobileOrigins = mobileOrigins;
1000
1268
  exports.provideKey = provideKey;
1001
1269
  exports.providedKeyFor = providedKeyFor;
1002
1270
  exports.provisionOrder = provisionOrder;
1003
1271
  exports.publicEnvFor = publicEnvFor;
1272
+ exports.schemeBase = schemeBase;
1004
1273
  exports.scopedName = scopedName;
1274
+ exports.seedFolder = seedFolder;
1005
1275
  exports.serviceKey = serviceKey;
1276
+
1006
1277
  //# sourceMappingURL=index.cjs.map