@adminiumjs/meta 0.1.0 → 0.2.1

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.
Files changed (55) hide show
  1. package/dist/connect.d.ts +26 -1
  2. package/dist/connect.d.ts.map +1 -1
  3. package/dist/connect.js +32 -1
  4. package/dist/connect.js.map +1 -1
  5. package/dist/ids.d.ts +2 -0
  6. package/dist/ids.d.ts.map +1 -1
  7. package/dist/ids.js +2 -0
  8. package/dist/ids.js.map +1 -1
  9. package/dist/migrations/0011_i18n_runtime.d.ts +42 -0
  10. package/dist/migrations/0011_i18n_runtime.d.ts.map +1 -0
  11. package/dist/migrations/0011_i18n_runtime.js +101 -0
  12. package/dist/migrations/0011_i18n_runtime.js.map +1 -0
  13. package/dist/migrations/0012_locale_width.d.ts +29 -0
  14. package/dist/migrations/0012_locale_width.d.ts.map +1 -0
  15. package/dist/migrations/0012_locale_width.js +42 -0
  16. package/dist/migrations/0012_locale_width.js.map +1 -0
  17. package/dist/migrations/index.d.ts.map +1 -1
  18. package/dist/migrations/index.js +4 -0
  19. package/dist/migrations/index.js.map +1 -1
  20. package/dist/repos/i18n-version.d.ts +32 -0
  21. package/dist/repos/i18n-version.d.ts.map +1 -0
  22. package/dist/repos/i18n-version.js +56 -0
  23. package/dist/repos/i18n-version.js.map +1 -0
  24. package/dist/repos/index.d.ts +3 -0
  25. package/dist/repos/index.d.ts.map +1 -1
  26. package/dist/repos/index.js +3 -0
  27. package/dist/repos/index.js.map +1 -1
  28. package/dist/repos/locales.d.ts +85 -0
  29. package/dist/repos/locales.d.ts.map +1 -0
  30. package/dist/repos/locales.js +189 -0
  31. package/dist/repos/locales.js.map +1 -0
  32. package/dist/repos/overrides.d.ts +2 -2
  33. package/dist/repos/overrides.d.ts.map +1 -1
  34. package/dist/repos/overrides.js.map +1 -1
  35. package/dist/repos/translations.d.ts +107 -0
  36. package/dist/repos/translations.d.ts.map +1 -0
  37. package/dist/repos/translations.js +231 -0
  38. package/dist/repos/translations.js.map +1 -0
  39. package/dist/repos/user-prefs.d.ts +8 -1
  40. package/dist/repos/user-prefs.d.ts.map +1 -1
  41. package/dist/repos/user-prefs.js +26 -3
  42. package/dist/repos/user-prefs.js.map +1 -1
  43. package/dist/schema/json-payloads.d.ts +31 -2
  44. package/dist/schema/json-payloads.d.ts.map +1 -1
  45. package/dist/schema/json-payloads.js +30 -3
  46. package/dist/schema/json-payloads.js.map +1 -1
  47. package/dist/schema/settings-registry.d.ts +16 -1
  48. package/dist/schema/settings-registry.d.ts.map +1 -1
  49. package/dist/schema/settings-registry.js +15 -0
  50. package/dist/schema/settings-registry.js.map +1 -1
  51. package/dist/schema/tables.d.ts +47 -1
  52. package/dist/schema/tables.d.ts.map +1 -1
  53. package/dist/schema/tables.js +2 -0
  54. package/dist/schema/tables.js.map +1 -1
  55. package/package.json +1 -1
package/dist/connect.d.ts CHANGED
@@ -26,9 +26,34 @@ export interface MetaDb {
26
26
  export declare function createSqliteMetaDb(config: SqliteDialectConfig): MetaDb;
27
27
  /**
28
28
  * PostgreSQL meta-store around an injected `pg` Pool. The pool must parse
29
- * int8 as JS number (all ts values < 2^53 — 07-meta-store.md §2.1).
29
+ * int8 as JS number (all ts values < 2^53 — 07-meta-store.md §2.1); build it
30
+ * with {@link postgresInt8AsNumber}.
30
31
  */
31
32
  export declare function createPostgresMetaDb(config: PostgresDialectConfig): MetaDb;
33
+ /**
34
+ * The `types` option that satisfies {@link createPostgresMetaDb}'s requirement:
35
+ * `new Pool({ …, types: postgresInt8AsNumber(pg) })`.
36
+ *
37
+ * The requirement was stated here and satisfiable nowhere, so every caller
38
+ * either forgot it (the product: each `ts` column arrived as a string and
39
+ * `GET /api/v1/bootstrap` 500'd on its own reply schema) or met it with a
40
+ * process-global `pg.types.setTypeParser`, which papered over the callers that
41
+ * had forgotten. Now there is one implementation, next to the contract.
42
+ *
43
+ * `node-postgres` decodes int8 as a string by default and is right to — int64
44
+ * outruns `Number.MAX_SAFE_INTEGER`. The META schema does not: `columns.ts`
45
+ * pins `ts` to epoch milliseconds and `bigint` to "values always < 2^53". So
46
+ * this is scoped to one pool ON PURPOSE. The global equivalent is a
47
+ * data-integrity bug waiting to happen: the server reads the USER's tables
48
+ * through the same `pg` module, and their `bigint` ids are under no such
49
+ * promise.
50
+ *
51
+ * Structurally typed over the module so this package still declares no driver
52
+ * dependency — the caller that imports `pg` passes it in.
53
+ */
54
+ export declare function postgresInt8AsNumber(pgModule: Record<string, unknown>): {
55
+ getTypeParser: (oid: number, format?: unknown) => unknown;
56
+ };
32
57
  /** MySQL/MariaDB meta-store around an injected `mysql2` pool. */
33
58
  export declare function createMysqlMetaDb(config: MysqlDialectConfig): MetaDb;
34
59
  /** One-time per-connection setup (currently: SQLite FK pragma). */
@@ -1 +1 @@
1
- {"version":3,"file":"connect.d.ts","sourceRoot":"","sources":["../src/connect.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAEL,MAAM,EAKN,KAAK,kBAAkB,EACvB,KAAK,qBAAqB,EAC1B,KAAK,mBAAmB,EACzB,MAAM,QAAQ,CAAC;AAEhB,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAEhD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAEjD,gEAAgE;AAChE,MAAM,WAAW,MAAM;IACrB,EAAE,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;IACnB,OAAO,EAAE,WAAW,CAAC;CACtB;AAiBD;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,mBAAmB,GAAG,MAAM,CAEtE;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,qBAAqB,GAAG,MAAM,CAE1E;AAED,iEAAiE;AACjE,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,kBAAkB,GAAG,MAAM,CAEpE;AAED,mEAAmE;AACnE,wBAAsB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAE5D;AAED,8CAA8C;AAC9C,wBAAsB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAE/D"}
1
+ {"version":3,"file":"connect.d.ts","sourceRoot":"","sources":["../src/connect.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAEL,MAAM,EAKN,KAAK,kBAAkB,EACvB,KAAK,qBAAqB,EAC1B,KAAK,mBAAmB,EACzB,MAAM,QAAQ,CAAC;AAEhB,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAEhD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAEjD,gEAAgE;AAChE,MAAM,WAAW,MAAM;IACrB,EAAE,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;IACnB,OAAO,EAAE,WAAW,CAAC;CACtB;AAiBD;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,mBAAmB,GAAG,MAAM,CAEtE;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,qBAAqB,GAAG,MAAM,CAE1E;AAKD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG;IACvE,aAAa,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,KAAK,OAAO,CAAC;CAC3D,CASA;AAED,iEAAiE;AACjE,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,kBAAkB,GAAG,MAAM,CAEpE;AAED,mEAAmE;AACnE,wBAAsB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAE5D;AAED,8CAA8C;AAC9C,wBAAsB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAE/D"}
package/dist/connect.js CHANGED
@@ -36,11 +36,42 @@ export function createSqliteMetaDb(config) {
36
36
  }
37
37
  /**
38
38
  * PostgreSQL meta-store around an injected `pg` Pool. The pool must parse
39
- * int8 as JS number (all ts values < 2^53 — 07-meta-store.md §2.1).
39
+ * int8 as JS number (all ts values < 2^53 — 07-meta-store.md §2.1); build it
40
+ * with {@link postgresInt8AsNumber}.
40
41
  */
41
42
  export function createPostgresMetaDb(config) {
42
43
  return build('postgres', new PostgresDialect(config));
43
44
  }
45
+ /** `pg`'s OID for `bigint`/`int8`. */
46
+ const PG_INT8_OID = 20;
47
+ /**
48
+ * The `types` option that satisfies {@link createPostgresMetaDb}'s requirement:
49
+ * `new Pool({ …, types: postgresInt8AsNumber(pg) })`.
50
+ *
51
+ * The requirement was stated here and satisfiable nowhere, so every caller
52
+ * either forgot it (the product: each `ts` column arrived as a string and
53
+ * `GET /api/v1/bootstrap` 500'd on its own reply schema) or met it with a
54
+ * process-global `pg.types.setTypeParser`, which papered over the callers that
55
+ * had forgotten. Now there is one implementation, next to the contract.
56
+ *
57
+ * `node-postgres` decodes int8 as a string by default and is right to — int64
58
+ * outruns `Number.MAX_SAFE_INTEGER`. The META schema does not: `columns.ts`
59
+ * pins `ts` to epoch milliseconds and `bigint` to "values always < 2^53". So
60
+ * this is scoped to one pool ON PURPOSE. The global equivalent is a
61
+ * data-integrity bug waiting to happen: the server reads the USER's tables
62
+ * through the same `pg` module, and their `bigint` ids are under no such
63
+ * promise.
64
+ *
65
+ * Structurally typed over the module so this package still declares no driver
66
+ * dependency — the caller that imports `pg` passes it in.
67
+ */
68
+ export function postgresInt8AsNumber(pgModule) {
69
+ const types = (pgModule.types ??
70
+ pgModule.default?.types);
71
+ return {
72
+ getTypeParser: (oid, format) => oid === PG_INT8_OID ? Number : (types?.getTypeParser(oid, format) ?? String),
73
+ };
74
+ }
44
75
  /** MySQL/MariaDB meta-store around an injected `mysql2` pool. */
45
76
  export function createMysqlMetaDb(config) {
46
77
  return build('mysql', new MysqlDialect(config));
@@ -1 +1 @@
1
- {"version":3,"file":"connect.js","sourceRoot":"","sources":["../src/connect.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EACL,eAAe,EACf,MAAM,EACN,YAAY,EACZ,eAAe,EACf,aAAa,GAKd,MAAM,QAAQ,CAAC;AAGhB,OAAO,EAAE,uBAAuB,EAAE,MAAM,eAAe,CAAC;AASxD,SAAS,KAAK,CAAC,OAAoB,EAAE,aAAsB;IACzD,OAAO;QACL,EAAE,EAAE,IAAI,MAAM,CAAS;YACrB,OAAO,EAAE,aAAa;YACtB,0EAA0E;YAC1E,qEAAqE;YACrE,wEAAwE;YACxE,uEAAuE;YACvE,6DAA6D;YAC7D,OAAO,EAAE,CAAC,IAAI,eAAe,CAAC,EAAE,wBAAwB,EAAE,IAAI,EAAE,CAAC,CAAC;SACnE,CAAC;QACF,OAAO;KACR,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,kBAAkB,CAAC,MAA2B;IAC5D,OAAO,KAAK,CAAC,QAAQ,EAAE,IAAI,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC;AACpD,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,oBAAoB,CAAC,MAA6B;IAChE,OAAO,KAAK,CAAC,UAAU,EAAE,IAAI,eAAe,CAAC,MAAM,CAAC,CAAC,CAAC;AACxD,CAAC;AAED,iEAAiE;AACjE,MAAM,UAAU,iBAAiB,CAAC,MAA0B;IAC1D,OAAO,KAAK,CAAC,OAAO,EAAE,IAAI,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC;AAClD,CAAC;AAED,mEAAmE;AACnE,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,IAAY;IAC3C,IAAI,IAAI,CAAC,OAAO,KAAK,QAAQ;QAAE,MAAM,uBAAuB,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;AACxE,CAAC;AAED,8CAA8C;AAC9C,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,IAAY;IAC9C,MAAM,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC;AAC1B,CAAC"}
1
+ {"version":3,"file":"connect.js","sourceRoot":"","sources":["../src/connect.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EACL,eAAe,EACf,MAAM,EACN,YAAY,EACZ,eAAe,EACf,aAAa,GAKd,MAAM,QAAQ,CAAC;AAGhB,OAAO,EAAE,uBAAuB,EAAE,MAAM,eAAe,CAAC;AASxD,SAAS,KAAK,CAAC,OAAoB,EAAE,aAAsB;IACzD,OAAO;QACL,EAAE,EAAE,IAAI,MAAM,CAAS;YACrB,OAAO,EAAE,aAAa;YACtB,0EAA0E;YAC1E,qEAAqE;YACrE,wEAAwE;YACxE,uEAAuE;YACvE,6DAA6D;YAC7D,OAAO,EAAE,CAAC,IAAI,eAAe,CAAC,EAAE,wBAAwB,EAAE,IAAI,EAAE,CAAC,CAAC;SACnE,CAAC;QACF,OAAO;KACR,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,kBAAkB,CAAC,MAA2B;IAC5D,OAAO,KAAK,CAAC,QAAQ,EAAE,IAAI,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC;AACpD,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,oBAAoB,CAAC,MAA6B;IAChE,OAAO,KAAK,CAAC,UAAU,EAAE,IAAI,eAAe,CAAC,MAAM,CAAC,CAAC,CAAC;AACxD,CAAC;AAED,sCAAsC;AACtC,MAAM,WAAW,GAAG,EAAE,CAAC;AAEvB;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,UAAU,oBAAoB,CAAC,QAAiC;IAGpE,MAAM,KAAK,GAAG,CAAC,QAAQ,CAAC,KAAK;QAC1B,QAAQ,CAAC,OAA+C,EAAE,KAAK,CAErD,CAAC;IACd,OAAO;QACL,aAAa,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,EAAE,CAC7B,GAAG,KAAK,WAAW,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,KAAK,EAAE,aAAa,CAAC,GAAG,EAAE,MAAM,CAAC,IAAI,MAAM,CAAC;KAC/E,CAAC;AACJ,CAAC;AAED,iEAAiE;AACjE,MAAM,UAAU,iBAAiB,CAAC,MAA0B;IAC1D,OAAO,KAAK,CAAC,OAAO,EAAE,IAAI,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC;AAClD,CAAC;AAED,mEAAmE;AACnE,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,IAAY;IAC3C,IAAI,IAAI,CAAC,OAAO,KAAK,QAAQ;QAAE,MAAM,uBAAuB,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;AACxE,CAAC;AAED,8CAA8C;AAC9C,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,IAAY;IAC9C,MAAM,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC;AAC1B,CAAC"}
package/dist/ids.d.ts CHANGED
@@ -44,6 +44,8 @@ export declare const ID_PREFIXES: {
44
44
  readonly whd: "adminium_webhook_deliveries";
45
45
  readonly flag: "adminium_feature_flags";
46
46
  readonly mft: "adminium_manifests";
47
+ readonly loc: "adminium_locales";
48
+ readonly trn: "adminium_translations";
47
49
  };
48
50
  export type IdPrefix = keyof typeof ID_PREFIXES;
49
51
  /** Maximum column width every id must fit (07-meta-store.md §2.1). */
package/dist/ids.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"ids.d.ts","sourceRoot":"","sources":["../src/ids.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAQH,QAAA,MAAM,QAAQ,QAAsB,CAAC;AAErC;;;;;GAKG;AACH,eAAO,MAAM,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;CA2Bd,CAAC;AAEX,MAAM,MAAM,QAAQ,GAAG,MAAM,OAAO,WAAW,CAAC;AAOhD,sEAAsE;AACtE,eAAO,MAAM,aAAa,KAAK,CAAC;AAEhC,qBAAa,cAAe,SAAQ,KAAK;IAC9B,IAAI,SAAoB;CAClC;AAiDD;;;;GAIG;AACH,wBAAgB,KAAK,CAAC,MAAM,EAAE,QAAQ,GAAG,MAAM,CAc9C;AAED,MAAM,WAAW,QAAQ;IACvB,qCAAqC;IACrC,MAAM,EAAE,QAAQ,CAAC;IACjB,2DAA2D;IAC3D,KAAK,EAAE,MAAM,CAAC;IACd,6BAA6B;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,iDAAiD;IACjD,IAAI,EAAE,MAAM,CAAC;CACd;AAED,8FAA8F;AAC9F,wBAAgB,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,QAAQ,CAY5C;AAED,uFAAuF;AACvF,wBAAgB,IAAI,CAAC,EAAE,EAAE,OAAO,EAAE,MAAM,CAAC,EAAE,QAAQ,GAAG,OAAO,CAQ5D;AAED,yDAAyD;AACzD,wBAAgB,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAEzC;AAED,2CAA2C;AAC3C,wBAAgB,aAAa,IAAI,IAAI,CAGpC;AAED,OAAO,EAAE,QAAQ,IAAI,YAAY,EAAE,CAAC"}
1
+ {"version":3,"file":"ids.d.ts","sourceRoot":"","sources":["../src/ids.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAQH,QAAA,MAAM,QAAQ,QAAsB,CAAC;AAErC;;;;;GAKG;AACH,eAAO,MAAM,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA6Bd,CAAC;AAEX,MAAM,MAAM,QAAQ,GAAG,MAAM,OAAO,WAAW,CAAC;AAOhD,sEAAsE;AACtE,eAAO,MAAM,aAAa,KAAK,CAAC;AAEhC,qBAAa,cAAe,SAAQ,KAAK;IAC9B,IAAI,SAAoB;CAClC;AAiDD;;;;GAIG;AACH,wBAAgB,KAAK,CAAC,MAAM,EAAE,QAAQ,GAAG,MAAM,CAc9C;AAED,MAAM,WAAW,QAAQ;IACvB,qCAAqC;IACrC,MAAM,EAAE,QAAQ,CAAC;IACjB,2DAA2D;IAC3D,KAAK,EAAE,MAAM,CAAC;IACd,6BAA6B;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,iDAAiD;IACjD,IAAI,EAAE,MAAM,CAAC;CACd;AAED,8FAA8F;AAC9F,wBAAgB,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,QAAQ,CAY5C;AAED,uFAAuF;AACvF,wBAAgB,IAAI,CAAC,EAAE,EAAE,OAAO,EAAE,MAAM,CAAC,EAAE,QAAQ,GAAG,OAAO,CAQ5D;AAED,yDAAyD;AACzD,wBAAgB,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAEzC;AAED,2CAA2C;AAC3C,wBAAgB,aAAa,IAAI,IAAI,CAGpC;AAED,OAAO,EAAE,QAAQ,IAAI,YAAY,EAAE,CAAC"}
package/dist/ids.js CHANGED
@@ -49,6 +49,8 @@ export const ID_PREFIXES = {
49
49
  whd: 'adminium_webhook_deliveries',
50
50
  flag: 'adminium_feature_flags',
51
51
  mft: 'adminium_manifests',
52
+ loc: 'adminium_locales',
53
+ trn: 'adminium_translations',
52
54
  };
53
55
  const PREFIX_SET = new Set(Object.keys(ID_PREFIXES));
54
56
  /** `<prefix>_<26 Crockford chars>` — Crockford charset excludes I, L, O, U. */
package/dist/ids.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"ids.js","sourceRoot":"","sources":["../src/ids.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ids.js","sourceRoot":"","sources":["../src/ids.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE1C,iDAAiD;AACjD,MAAM,QAAQ,GAAG,kCAAkC,CAAC;AACpD,MAAM,QAAQ,GAAG,EAAE,CAAC;AACpB,MAAM,QAAQ,GAAG,EAAE,CAAC;AACpB,MAAM,QAAQ,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAErC;;;;;GAKG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG;IACzB,GAAG,EAAE,gBAAgB;IACrB,IAAI,EAAE,mBAAmB;IACzB,GAAG,EAAE,0BAA0B;IAC/B,GAAG,EAAE,mBAAmB;IACxB,IAAI,EAAE,gBAAgB;IACtB,IAAI,EAAE,2BAA2B;IACjC,GAAG,EAAE,oBAAoB;IACzB,GAAG,EAAE,eAAe;IACpB,IAAI,EAAE,sBAAsB;IAC5B,IAAI,EAAE,2BAA2B;IACjC,GAAG,EAAE,2BAA2B;IAChC,IAAI,EAAE,gBAAgB;IACtB,IAAI,EAAE,gBAAgB;IACtB,GAAG,EAAE,mBAAmB;IACxB,GAAG,EAAE,wBAAwB;IAC7B,IAAI,EAAE,sBAAsB;IAC5B,IAAI,EAAE,0BAA0B;IAChC,GAAG,EAAE,4BAA4B;IACjC,GAAG,EAAE,kBAAkB;IACvB,GAAG,EAAE,kBAAkB;IACvB,IAAI,EAAE,gBAAgB;IACtB,GAAG,EAAE,0BAA0B;IAC/B,EAAE,EAAE,mBAAmB;IACvB,GAAG,EAAE,6BAA6B;IAClC,IAAI,EAAE,wBAAwB;IAC9B,GAAG,EAAE,oBAAoB;IACzB,GAAG,EAAE,kBAAkB;IACvB,GAAG,EAAE,uBAAuB;CACpB,CAAC;AAIX,MAAM,UAAU,GAAwB,IAAI,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC;AAE1E,+EAA+E;AAC/E,MAAM,KAAK,GAAG,kDAAkD,CAAC;AAEjE,sEAAsE;AACtE,MAAM,CAAC,MAAM,aAAa,GAAG,EAAE,CAAC;AAEhC,MAAM,OAAO,cAAe,SAAQ,KAAK;IAC9B,IAAI,GAAG,gBAAgB,CAAC;CAClC;AAED,SAAS,UAAU,CAAC,IAAY;IAC9B,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,IAAI,GAAG,CAAC,IAAI,IAAI,GAAG,CAAC,IAAI,EAAE,GAAG,CAAC,EAAE,CAAC;QAC9D,MAAM,IAAI,cAAc,CAAC,gCAAgC,IAAI,EAAE,CAAC,CAAC;IACnE,CAAC;IACD,IAAI,GAAG,GAAG,EAAE,CAAC;IACb,IAAI,CAAC,GAAG,IAAI,CAAC;IACb,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,QAAQ,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;QACrC,GAAG,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,GAAG,GAAG,CAAC;QACpC,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC;IACzB,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,SAAS,UAAU,CAAC,KAAa;IAC/B,IAAI,CAAC,GAAG,CAAC,CAAC;IACV,KAAK,MAAM,EAAE,IAAI,KAAK,EAAE,CAAC;QACvB,MAAM,CAAC,GAAG,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;QAC/B,IAAI,CAAC,GAAG,CAAC;YAAE,MAAM,IAAI,cAAc,CAAC,2BAA2B,EAAE,EAAE,CAAC,CAAC;QACrE,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;IACjB,CAAC;IACD,OAAO,CAAC,CAAC;AACX,CAAC;AAED,8EAA8E;AAC9E,SAAS,WAAW;IAClB,MAAM,KAAK,GAAG,WAAW,CAAC,QAAQ,CAAC,CAAC;IACpC,MAAM,GAAG,GAAG,IAAI,KAAK,CAAS,QAAQ,CAAC,CAAC;IACxC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,QAAQ,EAAE,CAAC,IAAI,CAAC;QAAE,GAAG,CAAC,CAAC,CAAC,GAAI,KAAK,CAAC,CAAC,CAAY,GAAG,EAAE,CAAC;IACzE,OAAO,GAAG,CAAC;AACb,CAAC;AAED,IAAI,QAAQ,GAAG,CAAC,CAAC,CAAC;AAClB,IAAI,QAAQ,GAAa,EAAE,CAAC;AAE5B,SAAS,aAAa,CAAC,IAAc;IACnC,KAAK,IAAI,CAAC,GAAG,QAAQ,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;QAC1C,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC,CAAW,CAAC;QAC5B,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC;YACX,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YAChB,OAAO;QACT,CAAC;QACD,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;IACd,CAAC;IACD,sEAAsE;IACtE,MAAM,IAAI,cAAc,CAAC,qDAAqD,CAAC,CAAC;AAClF,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,KAAK,CAAC,MAAgB;IACpC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;QAC5B,MAAM,IAAI,cAAc,CAAC,sBAAsB,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;IACnE,CAAC;IACD,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IACrB,IAAI,CAAC,IAAI,QAAQ,EAAE,CAAC;QAClB,0EAA0E;QAC1E,aAAa,CAAC,QAAQ,CAAC,CAAC;IAC1B,CAAC;SAAM,CAAC;QACN,QAAQ,GAAG,CAAC,CAAC;QACb,QAAQ,GAAG,WAAW,EAAE,CAAC;IAC3B,CAAC;IACD,MAAM,IAAI,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC9D,OAAO,GAAG,MAAM,IAAI,UAAU,CAAC,QAAQ,CAAC,GAAG,IAAI,EAAE,CAAC;AACpD,CAAC;AAaD,8FAA8F;AAC9F,MAAM,UAAU,OAAO,CAAC,EAAU;IAChC,MAAM,CAAC,GAAG,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACzB,IAAI,CAAC,CAAC;QAAE,MAAM,IAAI,cAAc,CAAC,iBAAiB,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;IACxE,MAAM,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,GAAG,CAAwC,CAAC;IAClE,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,MAAM,CAAC;QAAE,MAAM,IAAI,cAAc,CAAC,sBAAsB,MAAM,EAAE,CAAC,CAAC;IACtF,IAAI,EAAE,CAAC,MAAM,GAAG,aAAa;QAAE,MAAM,IAAI,cAAc,CAAC,wBAAwB,EAAE,EAAE,CAAC,CAAC;IACtF,OAAO;QACL,MAAM,EAAE,MAAkB;QAC1B,KAAK,EAAE,WAAW,CAAC,MAAkB,CAAC;QACtC,IAAI;QACJ,IAAI,EAAE,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC;KAC1C,CAAC;AACJ,CAAC;AAED,uFAAuF;AACvF,MAAM,UAAU,IAAI,CAAC,EAAW,EAAE,MAAiB;IACjD,IAAI,OAAO,EAAE,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC;IACzC,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,OAAO,CAAC,EAAE,CAAC,CAAC;QAC3B,OAAO,MAAM,KAAK,SAAS,IAAI,MAAM,CAAC,MAAM,KAAK,MAAM,CAAC;IAC1D,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,yDAAyD;AACzD,MAAM,UAAU,MAAM,CAAC,EAAU;IAC/B,OAAO,OAAO,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC;AAC1B,CAAC;AAED,2CAA2C;AAC3C,MAAM,UAAU,aAAa;IAC3B,QAAQ,GAAG,CAAC,CAAC,CAAC;IACd,QAAQ,GAAG,EAAE,CAAC;AAChB,CAAC;AAED,OAAO,EAAE,QAAQ,IAAI,YAAY,EAAE,CAAC"}
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Wave 0011 — runtime translations (23-runtime-translations.md §3.1, §3.2).
3
+ *
4
+ * Two tables, both deliberately SPARSE:
5
+ *
6
+ * - `adminium_locales` holds a row only when an admin deviates from a
7
+ * compiled locale's defaults (or invents a new one). A built-in locale
8
+ * with no row behaves exactly as it does today, and the immutable fields
9
+ * of a built-in row (`dir`, `font_hint`, `intl_tag`, names) are always
10
+ * read from the compiled registry — the row can only carry `enabled` and
11
+ * `sort_order`. That is what makes "zero rows ⇒ byte-identical to today"
12
+ * a structural guarantee rather than a convention, and it also means an
13
+ * admin cannot flip `ar_EG` to `ltr` and corrupt a shipped bundle.
14
+ * - `adminium_translations` holds one row per OVERRIDDEN message. Absence
15
+ * means "use the compiled built-in"; a row with an empty `value` means
16
+ * "deliberately blank" (§3.3). Reset-to-built-in is therefore a hard
17
+ * DELETE, which is why the version stamp is a counter in
18
+ * `adminium_settings` and not `MAX(updated_at)` over these rows.
19
+ *
20
+ * Column widths are index-budget driven, not guesses. The composite unique
21
+ * index spans scope(16) + locale(35) + namespace(16) + key(120) = 187 chars;
22
+ * MySQL's InnoDB utf8mb4 index-key limit of 3072 bytes allows 768, so this
23
+ * fits with 4x margin. The longest en-US key today is 64 chars. Widening
24
+ * `key` past ~200 would break MySQL, so it is bounded here rather than left
25
+ * to `text`.
26
+ *
27
+ * `scope` LEADS the unique index deliberately. It is reserved (always
28
+ * 'workspace' in v1) against a possible per-app string set; adding a leading
29
+ * column to a MySQL unique index later is the migration nobody wants.
30
+ *
31
+ * The column is `source_text`, NOT `src_hash`: `assertNoCredentialColumns`
32
+ * in the export path aborts an export on any column matching /hash$/i, and
33
+ * that assertion is a CI unit test.
34
+ *
35
+ * Index-guard note (index.ts): no `.ifNotExists()` on index creation — MySQL
36
+ * cannot parse it, and the ledger's exactly-once guarantee is the idempotency
37
+ * mechanism.
38
+ */
39
+ import type { Kysely } from 'kysely';
40
+ import type { ColumnHelpers } from '../columns.js';
41
+ export declare function up(db: Kysely<unknown>, c: ColumnHelpers): Promise<void>;
42
+ //# sourceMappingURL=0011_i18n_runtime.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"0011_i18n_runtime.d.ts","sourceRoot":"","sources":["../../src/migrations/0011_i18n_runtime.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAErC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAGnD,wBAAsB,EAAE,CAAC,EAAE,EAAE,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CA4E7E"}
@@ -0,0 +1,101 @@
1
+ /**
2
+ * Wave 0011 — runtime translations (23-runtime-translations.md §3.1, §3.2).
3
+ *
4
+ * Two tables, both deliberately SPARSE:
5
+ *
6
+ * - `adminium_locales` holds a row only when an admin deviates from a
7
+ * compiled locale's defaults (or invents a new one). A built-in locale
8
+ * with no row behaves exactly as it does today, and the immutable fields
9
+ * of a built-in row (`dir`, `font_hint`, `intl_tag`, names) are always
10
+ * read from the compiled registry — the row can only carry `enabled` and
11
+ * `sort_order`. That is what makes "zero rows ⇒ byte-identical to today"
12
+ * a structural guarantee rather than a convention, and it also means an
13
+ * admin cannot flip `ar_EG` to `ltr` and corrupt a shipped bundle.
14
+ * - `adminium_translations` holds one row per OVERRIDDEN message. Absence
15
+ * means "use the compiled built-in"; a row with an empty `value` means
16
+ * "deliberately blank" (§3.3). Reset-to-built-in is therefore a hard
17
+ * DELETE, which is why the version stamp is a counter in
18
+ * `adminium_settings` and not `MAX(updated_at)` over these rows.
19
+ *
20
+ * Column widths are index-budget driven, not guesses. The composite unique
21
+ * index spans scope(16) + locale(35) + namespace(16) + key(120) = 187 chars;
22
+ * MySQL's InnoDB utf8mb4 index-key limit of 3072 bytes allows 768, so this
23
+ * fits with 4x margin. The longest en-US key today is 64 chars. Widening
24
+ * `key` past ~200 would break MySQL, so it is bounded here rather than left
25
+ * to `text`.
26
+ *
27
+ * `scope` LEADS the unique index deliberately. It is reserved (always
28
+ * 'workspace' in v1) against a possible per-app string set; adding a leading
29
+ * column to a MySQL unique index later is the migration nobody wants.
30
+ *
31
+ * The column is `source_text`, NOT `src_hash`: `assertNoCredentialColumns`
32
+ * in the export path aborts an export on any column matching /hash$/i, and
33
+ * that assertion is a CI unit test.
34
+ *
35
+ * Index-guard note (index.ts): no `.ifNotExists()` on index creation — MySQL
36
+ * cannot parse it, and the ledger's exactly-once guarantee is the idempotency
37
+ * mechanism.
38
+ */
39
+ import { metaTable } from '../prefix.js';
40
+ export async function up(db, c) {
41
+ await db.schema
42
+ .createTable(metaTable('locales'))
43
+ .ifNotExists()
44
+ .addColumn('id', c.id, (col) => col.primaryKey())
45
+ .addColumn('locale', c.str(35), (col) => col.notNull())
46
+ .addColumn('is_builtin', c.bool, (col) => col.notNull().defaultTo(c.boolDefault(false)))
47
+ .addColumn('enabled', c.bool, (col) => col.notNull().defaultTo(c.boolDefault(true)))
48
+ .addColumn('sort_order', c.int, (col) => col.notNull().defaultTo(0))
49
+ // Custom locales only — a built-in row reads these from the compiled registry.
50
+ .addColumn('english', c.str(80))
51
+ .addColumn('native', c.str(80))
52
+ .addColumn('dir', c.str(3))
53
+ .addColumn('font_hint', c.str(16))
54
+ // A REAL BCP-47 tag whose Intl behaviour a custom locale borrows (§5.6).
55
+ .addColumn('intl_tag', c.str(35))
56
+ // Frozen at create time from `intl_tag` so write validation is
57
+ // deterministic across the browser's ICU and Node's (§5.6).
58
+ .addColumn('plural_categories', c.json)
59
+ .addColumn('updated_by', c.id)
60
+ .addColumn('created_at', c.ts, (col) => col.notNull())
61
+ .addColumn('updated_at', c.ts, (col) => col.notNull())
62
+ .addForeignKeyConstraint('fk_adminium_locales_updated_by', ['updated_by'], metaTable('users'), ['id'], (cb) => cb.onDelete('set null'))
63
+ .execute();
64
+ await db.schema
65
+ .createIndex('uq_adminium_locales_locale')
66
+ .on(metaTable('locales'))
67
+ .columns(['locale'])
68
+ .unique()
69
+ .execute();
70
+ await db.schema
71
+ .createTable(metaTable('translations'))
72
+ .ifNotExists()
73
+ .addColumn('id', c.id, (col) => col.primaryKey())
74
+ .addColumn('scope', c.str(16), (col) => col.notNull().defaultTo('workspace'))
75
+ .addColumn('locale', c.str(35), (col) => col.notNull())
76
+ .addColumn('namespace', c.str(16), (col) => col.notNull())
77
+ .addColumn('key', c.str(120), (col) => col.notNull())
78
+ .addColumn('value', c.text, (col) => col.notNull())
79
+ // The en-US text this override was authored against, so the editor can
80
+ // flag "the English changed since this was written" (§7 stale badge).
81
+ .addColumn('source_text', c.text)
82
+ .addColumn('updated_by', c.id)
83
+ .addColumn('created_at', c.ts, (col) => col.notNull())
84
+ .addColumn('updated_at', c.ts, (col) => col.notNull())
85
+ .addForeignKeyConstraint('fk_adminium_translations_updated_by', ['updated_by'], metaTable('users'), ['id'], (cb) => cb.onDelete('set null'))
86
+ .execute();
87
+ await db.schema
88
+ .createIndex('uq_adminium_translations_scope_locale_ns_key')
89
+ .on(metaTable('translations'))
90
+ .columns(['scope', 'locale', 'namespace', 'key'])
91
+ .unique()
92
+ .execute();
93
+ // The bundle read path is always (scope, locale, namespace) — one index
94
+ // serves it and the per-locale budget count without scanning.
95
+ await db.schema
96
+ .createIndex('ix_adminium_translations_scope_locale_ns')
97
+ .on(metaTable('translations'))
98
+ .columns(['scope', 'locale', 'namespace'])
99
+ .execute();
100
+ }
101
+ //# sourceMappingURL=0011_i18n_runtime.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"0011_i18n_runtime.js","sourceRoot":"","sources":["../../src/migrations/0011_i18n_runtime.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Wave 0012 — widen the locale columns (23-runtime-translations.md §3.5).
3
+ *
4
+ * `adminium_user_prefs.locale` (0001) and `adminium_email_templates.locale`
5
+ * (0006) were sized `str(5)` for `en_US`. An admin-created locale id may carry
6
+ * a script subtag (`zh_Hant_TW`, 11 chars) and the registry allows up to 35,
7
+ * so both columns must widen or a custom locale can never be stored as a user
8
+ * preference or carry an email variant.
9
+ *
10
+ * SQLite masked the mismatch as usual (`str(n)` maps to `text`, lengths
11
+ * unenforced); PostgreSQL and strict-mode MySQL would reject the write.
12
+ *
13
+ * Up-only rule (index.ts): 0001 and 0006 are applied and checksummed, so this
14
+ * ships as a compensating migration rather than an edit. Raw dialect-branched
15
+ * ALTERs following 0010 verbatim, because MySQL's MODIFY restates the WHOLE
16
+ * column definition and Kysely's `setDataType` would silently drop the rest.
17
+ *
18
+ * NULLABILITY IS NOT SYMMETRIC HERE — get this wrong and the migration
19
+ * changes data semantics:
20
+ * - `user_prefs.locale` is NULLABLE (0001 line 44: no `.notNull()`); NULL
21
+ * means "inherit the workspace default", which is the whole
22
+ * reset-to-default affordance. MySQL's MODIFY must NOT add NOT NULL.
23
+ * - `email_templates.locale` is NOT NULL DEFAULT 'en_US' (0006 line 232);
24
+ * MySQL's MODIFY must restate both.
25
+ */
26
+ import { type Kysely } from 'kysely';
27
+ import type { ColumnHelpers } from '../columns.js';
28
+ export declare function up(db: Kysely<unknown>, c: ColumnHelpers): Promise<void>;
29
+ //# sourceMappingURL=0012_locale_width.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"0012_locale_width.d.ts","sourceRoot":"","sources":["../../src/migrations/0012_locale_width.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,OAAO,EAAO,KAAK,MAAM,EAAE,MAAM,QAAQ,CAAC;AAE1C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAGnD,wBAAsB,EAAE,CAAC,EAAE,EAAE,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAiB7E"}
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Wave 0012 — widen the locale columns (23-runtime-translations.md §3.5).
3
+ *
4
+ * `adminium_user_prefs.locale` (0001) and `adminium_email_templates.locale`
5
+ * (0006) were sized `str(5)` for `en_US`. An admin-created locale id may carry
6
+ * a script subtag (`zh_Hant_TW`, 11 chars) and the registry allows up to 35,
7
+ * so both columns must widen or a custom locale can never be stored as a user
8
+ * preference or carry an email variant.
9
+ *
10
+ * SQLite masked the mismatch as usual (`str(n)` maps to `text`, lengths
11
+ * unenforced); PostgreSQL and strict-mode MySQL would reject the write.
12
+ *
13
+ * Up-only rule (index.ts): 0001 and 0006 are applied and checksummed, so this
14
+ * ships as a compensating migration rather than an edit. Raw dialect-branched
15
+ * ALTERs following 0010 verbatim, because MySQL's MODIFY restates the WHOLE
16
+ * column definition and Kysely's `setDataType` would silently drop the rest.
17
+ *
18
+ * NULLABILITY IS NOT SYMMETRIC HERE — get this wrong and the migration
19
+ * changes data semantics:
20
+ * - `user_prefs.locale` is NULLABLE (0001 line 44: no `.notNull()`); NULL
21
+ * means "inherit the workspace default", which is the whole
22
+ * reset-to-default affordance. MySQL's MODIFY must NOT add NOT NULL.
23
+ * - `email_templates.locale` is NOT NULL DEFAULT 'en_US' (0006 line 232);
24
+ * MySQL's MODIFY must restate both.
25
+ */
26
+ import { sql } from 'kysely';
27
+ import { metaTable } from '../prefix.js';
28
+ export async function up(db, c) {
29
+ const userPrefs = metaTable('user_prefs');
30
+ const emailTemplates = metaTable('email_templates');
31
+ if (c.dialect === 'postgres') {
32
+ await sql `ALTER TABLE ${sql.table(userPrefs)} ALTER COLUMN locale TYPE varchar(35)`.execute(db);
33
+ await sql `ALTER TABLE ${sql.table(emailTemplates)} ALTER COLUMN locale TYPE varchar(35)`.execute(db);
34
+ }
35
+ else if (c.dialect === 'mysql') {
36
+ // Nullable — restating NOT NULL here would destroy "inherit the default".
37
+ await sql `ALTER TABLE ${sql.table(userPrefs)} MODIFY COLUMN locale varchar(35) NULL`.execute(db);
38
+ await sql `ALTER TABLE ${sql.table(emailTemplates)} MODIFY COLUMN locale varchar(35) NOT NULL DEFAULT 'en_US'`.execute(db);
39
+ }
40
+ // sqlite: both columns are `text`; nothing to widen.
41
+ }
42
+ //# sourceMappingURL=0012_locale_width.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"0012_locale_width.js","sourceRoot":"","sources":["../../src/migrations/0012_locale_width.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,OAAO,EAAE,GAAG,EAAe,MAAM,QAAQ,CAAC;AAG1C,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAEzC,MAAM,CAAC,KAAK,UAAU,EAAE,CAAC,EAAmB,EAAE,CAAgB;IAC5D,MAAM,SAAS,GAAG,SAAS,CAAC,YAAY,CAAC,CAAC;IAC1C,MAAM,cAAc,GAAG,SAAS,CAAC,iBAAiB,CAAC,CAAC;IAEpD,IAAI,CAAC,CAAC,OAAO,KAAK,UAAU,EAAE,CAAC;QAC7B,MAAM,GAAG,CAAA,eAAe,GAAG,CAAC,KAAK,CAAC,SAAS,CAAC,uCAAuC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;QAChG,MAAM,GAAG,CAAA,eAAe,GAAG,CAAC,KAAK,CAAC,cAAc,CAAC,uCAAuC,CAAC,OAAO,CAC9F,EAAE,CACH,CAAC;IACJ,CAAC;SAAM,IAAI,CAAC,CAAC,OAAO,KAAK,OAAO,EAAE,CAAC;QACjC,0EAA0E;QAC1E,MAAM,GAAG,CAAA,eAAe,GAAG,CAAC,KAAK,CAAC,SAAS,CAAC,wCAAwC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;QACjG,MAAM,GAAG,CAAA,eAAe,GAAG,CAAC,KAAK,CAAC,cAAc,CAAC,4DAA4D,CAAC,OAAO,CACnH,EAAE,CACH,CAAC;IACJ,CAAC;IACD,qDAAqD;AACvD,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/migrations/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAErC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAYnD,MAAM,WAAW,aAAa;IAC5B,uDAAuD;IACvD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,EAAE,CAAC,EAAE,EAAE,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,aAAa,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACvE;AAED,eAAO,MAAM,cAAc,EAAE,SAAS,aAAa,EAWlD,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/migrations/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAErC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAcnD,MAAM,WAAW,aAAa;IAC5B,uDAAuD;IACvD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,EAAE,CAAC,EAAE,EAAE,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,aAAa,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACvE;AAED,eAAO,MAAM,cAAc,EAAE,SAAS,aAAa,EAalD,CAAC"}
@@ -28,6 +28,8 @@ import { up as up0007 } from './0007_llm_runs.js';
28
28
  import { up as up0008 } from './0008_llm_overrides.js';
29
29
  import { up as up0009 } from './0009_views_kind.js';
30
30
  import { up as up0010 } from './0010_llm_prompt_version_width.js';
31
+ import { up as up0011 } from './0011_i18n_runtime.js';
32
+ import { up as up0012 } from './0012_locale_width.js';
31
33
  export const ALL_MIGRATIONS = [
32
34
  { name: '0001_core_auth', up: up0001 },
33
35
  { name: '0002_rbac', up: up0002 },
@@ -39,5 +41,7 @@ export const ALL_MIGRATIONS = [
39
41
  { name: '0008_llm_overrides', up: up0008 },
40
42
  { name: '0009_views_kind', up: up0009 },
41
43
  { name: '0010_llm_prompt_version_width', up: up0010 },
44
+ { name: '0011_i18n_runtime', up: up0011 },
45
+ { name: '0012_locale_width', up: up0012 },
42
46
  ];
43
47
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/migrations/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAKH,OAAO,EAAE,EAAE,IAAI,MAAM,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,EAAE,IAAI,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,EAAE,IAAI,MAAM,EAAE,MAAM,8BAA8B,CAAC;AAC5D,OAAO,EAAE,EAAE,IAAI,MAAM,EAAE,MAAM,uBAAuB,CAAC;AACrD,OAAO,EAAE,EAAE,IAAI,MAAM,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,EAAE,EAAE,IAAI,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,EAAE,IAAI,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,EAAE,IAAI,MAAM,EAAE,MAAM,yBAAyB,CAAC;AACvD,OAAO,EAAE,EAAE,IAAI,MAAM,EAAE,MAAM,sBAAsB,CAAC;AACpD,OAAO,EAAE,EAAE,IAAI,MAAM,EAAE,MAAM,oCAAoC,CAAC;AAQlE,MAAM,CAAC,MAAM,cAAc,GAA6B;IACtD,EAAE,IAAI,EAAE,gBAAgB,EAAE,EAAE,EAAE,MAAM,EAAE;IACtC,EAAE,IAAI,EAAE,WAAW,EAAE,EAAE,EAAE,MAAM,EAAE;IACjC,EAAE,IAAI,EAAE,yBAAyB,EAAE,EAAE,EAAE,MAAM,EAAE;IAC/C,EAAE,IAAI,EAAE,kBAAkB,EAAE,EAAE,EAAE,MAAM,EAAE;IACxC,EAAE,IAAI,EAAE,UAAU,EAAE,EAAE,EAAE,MAAM,EAAE;IAChC,EAAE,IAAI,EAAE,eAAe,EAAE,EAAE,EAAE,MAAM,EAAE;IACrC,EAAE,IAAI,EAAE,eAAe,EAAE,EAAE,EAAE,MAAM,EAAE;IACrC,EAAE,IAAI,EAAE,oBAAoB,EAAE,EAAE,EAAE,MAAM,EAAE;IAC1C,EAAE,IAAI,EAAE,iBAAiB,EAAE,EAAE,EAAE,MAAM,EAAE;IACvC,EAAE,IAAI,EAAE,+BAA+B,EAAE,EAAE,EAAE,MAAM,EAAE;CACtD,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/migrations/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAKH,OAAO,EAAE,EAAE,IAAI,MAAM,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,EAAE,IAAI,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,EAAE,IAAI,MAAM,EAAE,MAAM,8BAA8B,CAAC;AAC5D,OAAO,EAAE,EAAE,IAAI,MAAM,EAAE,MAAM,uBAAuB,CAAC;AACrD,OAAO,EAAE,EAAE,IAAI,MAAM,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,EAAE,EAAE,IAAI,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,EAAE,IAAI,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,EAAE,IAAI,MAAM,EAAE,MAAM,yBAAyB,CAAC;AACvD,OAAO,EAAE,EAAE,IAAI,MAAM,EAAE,MAAM,sBAAsB,CAAC;AACpD,OAAO,EAAE,EAAE,IAAI,MAAM,EAAE,MAAM,oCAAoC,CAAC;AAClE,OAAO,EAAE,EAAE,IAAI,MAAM,EAAE,MAAM,wBAAwB,CAAC;AACtD,OAAO,EAAE,EAAE,IAAI,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAQtD,MAAM,CAAC,MAAM,cAAc,GAA6B;IACtD,EAAE,IAAI,EAAE,gBAAgB,EAAE,EAAE,EAAE,MAAM,EAAE;IACtC,EAAE,IAAI,EAAE,WAAW,EAAE,EAAE,EAAE,MAAM,EAAE;IACjC,EAAE,IAAI,EAAE,yBAAyB,EAAE,EAAE,EAAE,MAAM,EAAE;IAC/C,EAAE,IAAI,EAAE,kBAAkB,EAAE,EAAE,EAAE,MAAM,EAAE;IACxC,EAAE,IAAI,EAAE,UAAU,EAAE,EAAE,EAAE,MAAM,EAAE;IAChC,EAAE,IAAI,EAAE,eAAe,EAAE,EAAE,EAAE,MAAM,EAAE;IACrC,EAAE,IAAI,EAAE,eAAe,EAAE,EAAE,EAAE,MAAM,EAAE;IACrC,EAAE,IAAI,EAAE,oBAAoB,EAAE,EAAE,EAAE,MAAM,EAAE;IAC1C,EAAE,IAAI,EAAE,iBAAiB,EAAE,EAAE,EAAE,MAAM,EAAE;IACvC,EAAE,IAAI,EAAE,+BAA+B,EAAE,EAAE,EAAE,MAAM,EAAE;IACrD,EAAE,IAAI,EAAE,mBAAmB,EAAE,EAAE,EAAE,MAAM,EAAE;IACzC,EAAE,IAAI,EAAE,mBAAmB,EAAE,EAAE,EAAE,MAAM,EAAE;CAC1C,CAAC"}
@@ -0,0 +1,32 @@
1
+ /**
2
+ * The runtime-translation version stamp (23-runtime-translations.md §3.4).
3
+ *
4
+ * Clients key their bundle cache — and the server its ETag — on this counter,
5
+ * so it must move on EVERY mutation of `adminium_locales` /
6
+ * `adminium_translations`, from every writer.
7
+ *
8
+ * Two decisions are load-bearing:
9
+ *
10
+ * 1. **A counter, not `MAX(updated_at)`.** Reset-to-built-in is a hard
11
+ * DELETE, so a max-timestamp over the rows cannot observe the single most
12
+ * common admin operation — the cache would go stale exactly when someone
13
+ * undoes a bad edit.
14
+ * 2. **Bumped in the repo layer, not in route handlers.** Config-bundle
15
+ * import has no HTTP route: it writes through repos from the CLI. A
16
+ * route-level bump would leave every client serving stale strings after
17
+ * an import, forever, with the ETag answering 304.
18
+ *
19
+ * Always call this inside the same transaction as the write it stamps.
20
+ */
21
+ import type { Kysely, Transaction } from 'kysely';
22
+ import type { MetaDB } from '../schema/tables.js';
23
+ export type MetaExecutor = Kysely<MetaDB> | Transaction<MetaDB>;
24
+ /** Read the current stamp (0 when no override row exists yet). */
25
+ export declare function readI18nVersion(db: MetaExecutor): Promise<number>;
26
+ /**
27
+ * Increment the stamp and return the new value. Upserts by hand rather than
28
+ * through settingsRepo because that repo owns its own connection handle and
29
+ * this has to join the caller's transaction.
30
+ */
31
+ export declare function bumpI18nVersion(db: MetaExecutor, at: number, updatedBy: string | null): Promise<number>;
32
+ //# sourceMappingURL=i18n-version.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"i18n-version.d.ts","sourceRoot":"","sources":["../../src/repos/i18n-version.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,QAAQ,CAAC;AAElD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAKlD,MAAM,MAAM,YAAY,GAAG,MAAM,CAAC,MAAM,CAAC,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC;AAEhE,kEAAkE;AAClE,wBAAsB,eAAe,CAAC,EAAE,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC,CASvE;AAED;;;;GAIG;AACH,wBAAsB,eAAe,CACnC,EAAE,EAAE,YAAY,EAChB,EAAE,EAAE,MAAM,EACV,SAAS,EAAE,MAAM,GAAG,IAAI,GACvB,OAAO,CAAC,MAAM,CAAC,CAejB"}
@@ -0,0 +1,56 @@
1
+ /**
2
+ * The runtime-translation version stamp (23-runtime-translations.md §3.4).
3
+ *
4
+ * Clients key their bundle cache — and the server its ETag — on this counter,
5
+ * so it must move on EVERY mutation of `adminium_locales` /
6
+ * `adminium_translations`, from every writer.
7
+ *
8
+ * Two decisions are load-bearing:
9
+ *
10
+ * 1. **A counter, not `MAX(updated_at)`.** Reset-to-built-in is a hard
11
+ * DELETE, so a max-timestamp over the rows cannot observe the single most
12
+ * common admin operation — the cache would go stale exactly when someone
13
+ * undoes a bad edit.
14
+ * 2. **Bumped in the repo layer, not in route handlers.** Config-bundle
15
+ * import has no HTTP route: it writes through repos from the CLI. A
16
+ * route-level bump would leave every client serving stale strings after
17
+ * an import, forever, with the ETag answering 304.
18
+ *
19
+ * Always call this inside the same transaction as the write it stamps.
20
+ */
21
+ import { packJson, readJson } from './util.js';
22
+ const VERSION_KEY = 'i18n.version';
23
+ /** Read the current stamp (0 when no override row exists yet). */
24
+ export async function readI18nVersion(db) {
25
+ const row = await db
26
+ .selectFrom('adminium_settings')
27
+ .select(['value'])
28
+ .where('key', '=', VERSION_KEY)
29
+ .executeTakeFirst();
30
+ if (row === undefined)
31
+ return 0;
32
+ const parsed = readJson(row.value);
33
+ return typeof parsed === 'number' && Number.isFinite(parsed) ? parsed : 0;
34
+ }
35
+ /**
36
+ * Increment the stamp and return the new value. Upserts by hand rather than
37
+ * through settingsRepo because that repo owns its own connection handle and
38
+ * this has to join the caller's transaction.
39
+ */
40
+ export async function bumpI18nVersion(db, at, updatedBy) {
41
+ const next = (await readI18nVersion(db)) + 1;
42
+ const packed = packJson(next);
43
+ const res = await db
44
+ .updateTable('adminium_settings')
45
+ .set({ value: packed, updatedAt: at, updatedBy })
46
+ .where('key', '=', VERSION_KEY)
47
+ .executeTakeFirst();
48
+ if (Number(res.numUpdatedRows) === 0) {
49
+ await db
50
+ .insertInto('adminium_settings')
51
+ .values({ key: VERSION_KEY, value: packed, updatedAt: at, updatedBy })
52
+ .execute();
53
+ }
54
+ return next;
55
+ }
56
+ //# sourceMappingURL=i18n-version.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"i18n-version.js","sourceRoot":"","sources":["../../src/repos/i18n-version.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAKH,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAE/C,MAAM,WAAW,GAAG,cAAc,CAAC;AAInC,kEAAkE;AAClE,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,EAAgB;IACpD,MAAM,GAAG,GAAG,MAAM,EAAE;SACjB,UAAU,CAAC,mBAAmB,CAAC;SAC/B,MAAM,CAAC,CAAC,OAAO,CAAC,CAAC;SACjB,KAAK,CAAC,KAAK,EAAE,GAAG,EAAE,WAAW,CAAC;SAC9B,gBAAgB,EAAE,CAAC;IACtB,IAAI,GAAG,KAAK,SAAS;QAAE,OAAO,CAAC,CAAC;IAChC,MAAM,MAAM,GAAG,QAAQ,CAAU,GAAG,CAAC,KAAK,CAAC,CAAC;IAC5C,OAAO,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;AAC5E,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,EAAgB,EAChB,EAAU,EACV,SAAwB;IAExB,MAAM,IAAI,GAAG,CAAC,MAAM,eAAe,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC;IAC7C,MAAM,MAAM,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;IAC9B,MAAM,GAAG,GAAG,MAAM,EAAE;SACjB,WAAW,CAAC,mBAAmB,CAAC;SAChC,GAAG,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,EAAE,EAAE,SAAS,EAAE,CAAC;SAChD,KAAK,CAAC,KAAK,EAAE,GAAG,EAAE,WAAW,CAAC;SAC9B,gBAAgB,EAAE,CAAC;IACtB,IAAI,MAAM,CAAC,GAAG,CAAC,cAAc,CAAC,KAAK,CAAC,EAAE,CAAC;QACrC,MAAM,EAAE;aACL,UAAU,CAAC,mBAAmB,CAAC;aAC/B,MAAM,CAAC,EAAE,GAAG,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,EAAE,EAAE,SAAS,EAAE,CAAC;aACrE,OAAO,EAAE,CAAC;IACf,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC"}
@@ -23,4 +23,7 @@ export * from './notifications.js';
23
23
  export * from './notification-prefs.js';
24
24
  export * from './scheduled-reports.js';
25
25
  export * from './email-templates.js';
26
+ export * from './i18n-version.js';
27
+ export * from './locales.js';
28
+ export * from './translations.js';
26
29
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/repos/index.ts"],"names":[],"mappings":"AAAA,cAAc,WAAW,CAAC;AAC1B,cAAc,YAAY,CAAC;AAC3B,cAAc,eAAe,CAAC;AAC9B,cAAc,YAAY,CAAC;AAC3B,cAAc,kBAAkB,CAAC;AACjC,cAAc,eAAe,CAAC;AAC9B,cAAc,iBAAiB,CAAC;AAChC,cAAc,YAAY,CAAC;AAC3B,cAAc,eAAe,CAAC;AAC9B,cAAc,sBAAsB,CAAC;AACrC,cAAc,WAAW,CAAC;AAC1B,cAAc,kBAAkB,CAAC;AACjC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,oBAAoB,CAAC;AACnC,cAAc,YAAY,CAAC;AAC3B,cAAc,YAAY,CAAC;AAC3B,cAAc,eAAe,CAAC;AAC9B,cAAc,YAAY,CAAC;AAC3B,cAAc,cAAc,CAAC;AAC7B,cAAc,cAAc,CAAC;AAC7B,cAAc,oBAAoB,CAAC;AACnC,cAAc,yBAAyB,CAAC;AACxC,cAAc,wBAAwB,CAAC;AACvC,cAAc,sBAAsB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/repos/index.ts"],"names":[],"mappings":"AAAA,cAAc,WAAW,CAAC;AAC1B,cAAc,YAAY,CAAC;AAC3B,cAAc,eAAe,CAAC;AAC9B,cAAc,YAAY,CAAC;AAC3B,cAAc,kBAAkB,CAAC;AACjC,cAAc,eAAe,CAAC;AAC9B,cAAc,iBAAiB,CAAC;AAChC,cAAc,YAAY,CAAC;AAC3B,cAAc,eAAe,CAAC;AAC9B,cAAc,sBAAsB,CAAC;AACrC,cAAc,WAAW,CAAC;AAC1B,cAAc,kBAAkB,CAAC;AACjC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,oBAAoB,CAAC;AACnC,cAAc,YAAY,CAAC;AAC3B,cAAc,YAAY,CAAC;AAC3B,cAAc,eAAe,CAAC;AAC9B,cAAc,YAAY,CAAC;AAC3B,cAAc,cAAc,CAAC;AAC7B,cAAc,cAAc,CAAC;AAC7B,cAAc,oBAAoB,CAAC;AACnC,cAAc,yBAAyB,CAAC;AACxC,cAAc,wBAAwB,CAAC;AACvC,cAAc,sBAAsB,CAAC;AACrC,cAAc,mBAAmB,CAAC;AAClC,cAAc,cAAc,CAAC;AAC7B,cAAc,mBAAmB,CAAC"}
@@ -23,4 +23,7 @@ export * from './notifications.js';
23
23
  export * from './notification-prefs.js';
24
24
  export * from './scheduled-reports.js';
25
25
  export * from './email-templates.js';
26
+ export * from './i18n-version.js';
27
+ export * from './locales.js';
28
+ export * from './translations.js';
26
29
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/repos/index.ts"],"names":[],"mappings":"AAAA,cAAc,WAAW,CAAC;AAC1B,cAAc,YAAY,CAAC;AAC3B,cAAc,eAAe,CAAC;AAC9B,cAAc,YAAY,CAAC;AAC3B,cAAc,kBAAkB,CAAC;AACjC,cAAc,eAAe,CAAC;AAC9B,cAAc,iBAAiB,CAAC;AAChC,cAAc,YAAY,CAAC;AAC3B,cAAc,eAAe,CAAC;AAC9B,cAAc,sBAAsB,CAAC;AACrC,cAAc,WAAW,CAAC;AAC1B,cAAc,kBAAkB,CAAC;AACjC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,oBAAoB,CAAC;AACnC,cAAc,YAAY,CAAC;AAC3B,cAAc,YAAY,CAAC;AAC3B,cAAc,eAAe,CAAC;AAC9B,cAAc,YAAY,CAAC;AAC3B,cAAc,cAAc,CAAC;AAC7B,cAAc,cAAc,CAAC;AAC7B,cAAc,oBAAoB,CAAC;AACnC,cAAc,yBAAyB,CAAC;AACxC,cAAc,wBAAwB,CAAC;AACvC,cAAc,sBAAsB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/repos/index.ts"],"names":[],"mappings":"AAAA,cAAc,WAAW,CAAC;AAC1B,cAAc,YAAY,CAAC;AAC3B,cAAc,eAAe,CAAC;AAC9B,cAAc,YAAY,CAAC;AAC3B,cAAc,kBAAkB,CAAC;AACjC,cAAc,eAAe,CAAC;AAC9B,cAAc,iBAAiB,CAAC;AAChC,cAAc,YAAY,CAAC;AAC3B,cAAc,eAAe,CAAC;AAC9B,cAAc,sBAAsB,CAAC;AACrC,cAAc,WAAW,CAAC;AAC1B,cAAc,kBAAkB,CAAC;AACjC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,oBAAoB,CAAC;AACnC,cAAc,YAAY,CAAC;AAC3B,cAAc,YAAY,CAAC;AAC3B,cAAc,eAAe,CAAC;AAC9B,cAAc,YAAY,CAAC;AAC3B,cAAc,cAAc,CAAC;AAC7B,cAAc,cAAc,CAAC;AAC7B,cAAc,oBAAoB,CAAC;AACnC,cAAc,yBAAyB,CAAC;AACxC,cAAc,wBAAwB,CAAC;AACvC,cAAc,sBAAsB,CAAC;AACrC,cAAc,mBAAmB,CAAC;AAClC,cAAc,cAAc,CAAC;AAC7B,cAAc,mBAAmB,CAAC"}