@ultimat3/entity 1.0.0 → 1.1.0

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 (61) hide show
  1. package/package.json +4 -4
  2. package/src/column.d.ts +0 -28
  3. package/src/column.d.ts.map +0 -1
  4. package/src/column.js +0 -75
  5. package/src/column.js.map +0 -1
  6. package/src/columns.d.ts +0 -39
  7. package/src/columns.d.ts.map +0 -1
  8. package/src/columns.js +0 -136
  9. package/src/columns.js.map +0 -1
  10. package/src/database.d.ts +0 -21
  11. package/src/database.d.ts.map +0 -1
  12. package/src/database.js +0 -38
  13. package/src/database.js.map +0 -1
  14. package/src/describe.d.ts +0 -16
  15. package/src/describe.d.ts.map +0 -1
  16. package/src/describe.js +0 -79
  17. package/src/describe.js.map +0 -1
  18. package/src/entity.d.ts +0 -58
  19. package/src/entity.d.ts.map +0 -1
  20. package/src/entity.js +0 -160
  21. package/src/entity.js.map +0 -1
  22. package/src/errors.d.ts +0 -18
  23. package/src/errors.d.ts.map +0 -1
  24. package/src/errors.js +0 -59
  25. package/src/errors.js.map +0 -1
  26. package/src/expr.d.ts +0 -41
  27. package/src/expr.d.ts.map +0 -1
  28. package/src/expr.js +0 -94
  29. package/src/expr.js.map +0 -1
  30. package/src/index.d.ts +0 -23
  31. package/src/index.d.ts.map +0 -1
  32. package/src/index.js +0 -12
  33. package/src/index.js.map +0 -1
  34. package/src/invariants.d.ts +0 -36
  35. package/src/invariants.d.ts.map +0 -1
  36. package/src/invariants.js +0 -53
  37. package/src/invariants.js.map +0 -1
  38. package/src/query.d.ts +0 -30
  39. package/src/query.d.ts.map +0 -1
  40. package/src/query.js +0 -74
  41. package/src/query.js.map +0 -1
  42. package/src/registry.d.ts +0 -45
  43. package/src/registry.d.ts.map +0 -1
  44. package/src/registry.js +0 -26
  45. package/src/registry.js.map +0 -1
  46. package/src/repo.d.ts +0 -54
  47. package/src/repo.d.ts.map +0 -1
  48. package/src/repo.js +0 -203
  49. package/src/repo.js.map +0 -1
  50. package/src/seed.d.ts +0 -20
  51. package/src/seed.d.ts.map +0 -1
  52. package/src/seed.js +0 -43
  53. package/src/seed.js.map +0 -1
  54. package/src/tenancy.d.ts +0 -41
  55. package/src/tenancy.d.ts.map +0 -1
  56. package/src/tenancy.js +0 -57
  57. package/src/tenancy.js.map +0 -1
  58. package/src/types.d.ts +0 -99
  59. package/src/types.d.ts.map +0 -1
  60. package/src/types.js +0 -8
  61. package/src/types.js.map +0 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ultimat3/entity",
3
- "version": "1.0.0",
3
+ "version": "1.1.0",
4
4
  "description": "A table + its domain type + invariants the database also enforces",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -30,8 +30,8 @@
30
30
  "test": "bun test"
31
31
  },
32
32
  "dependencies": {
33
- "@ultimat3/core": "1.0.0",
34
- "@ultimat3/db": "1.0.0",
35
- "@ultimat3/schema": "1.0.0"
33
+ "@ultimat3/core": "1.1.0",
34
+ "@ultimat3/db": "1.1.0",
35
+ "@ultimat3/schema": "1.1.0"
36
36
  }
37
37
  }
package/src/column.d.ts DELETED
@@ -1,28 +0,0 @@
1
- import type { AnyColumn, Column, ColumnDefault, ColumnMeta, TimestampColumn } from './types';
2
- export declare const snake: (value: string) => string;
3
- export declare const GENERATED_UUID: ColumnDefault;
4
- export declare const GENERATED_NOW: ColumnDefault;
5
- /** Every column starts here: not null, no key, no index. */
6
- export declare const BARE: Omit<ColumnMeta, 'kind'>;
7
- export interface Binding {
8
- readonly table: string;
9
- /** camelCase key on the row. */
10
- readonly property: string;
11
- /** snake_case physical column name. */
12
- readonly name: string;
13
- }
14
- /**
15
- * Called once per column by `entity()`. A column object belongs to exactly one table: sharing
16
- * one between two entities would give it two physical names and silently mis-name a foreign
17
- * key, so a second binding is a declaration-time error.
18
- */
19
- export declare const bindColumn: (column: AnyColumn, table: string, property: string) => Binding;
20
- export declare const bindingOf: (column: AnyColumn) => Binding | undefined;
21
- export declare const makeColumn: <T, Optional extends boolean>(meta: ColumnMeta, parse: (value: unknown) => T, optional: Optional) => Column<T, Optional>;
22
- export declare const column: <T>(kind: ColumnMeta['kind'], parse: (value: unknown) => T, extra?: Partial<ColumnMeta>) => Column<T>;
23
- /**
24
- * `timestamptz`, always. There is no naive-timestamp builder and there will not be one: a
25
- * `timestamp without time zone` is a bug that only surfaces twice a year.
26
- */
27
- export declare const makeTimestamp: <Optional extends boolean>(meta: ColumnMeta, parse: (value: unknown) => Date, optional: Optional) => TimestampColumn<Optional>;
28
- //# sourceMappingURL=column.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"column.d.ts","sourceRoot":"","sources":["column.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,aAAa,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAE7F,eAAO,MAAM,KAAK,UAAW,MAAM,KAAG,MACsB,CAAC;AAE7D,eAAO,MAAM,cAAc,EAAE,aAAoD,CAAC;AAClF,eAAO,MAAM,aAAa,EAAE,aAAgD,CAAC;AAE7E,4DAA4D;AAC5D,eAAO,MAAM,IAAI,EAAE,IAAI,CAAC,UAAU,EAAE,MAAM,CAMzC,CAAC;AAEF,MAAM,WAAW,OAAO;IACtB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,gCAAgC;IAChC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,uCAAuC;IACvC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAID;;;;GAIG;AACH,eAAO,MAAM,UAAU,WAAY,SAAS,SAAS,MAAM,YAAY,MAAM,KAAG,OAa/E,CAAC;AAEF,eAAO,MAAM,SAAS,WAAY,SAAS,KAAG,OAAO,GAAG,SAAiC,CAAC;AAc1F,eAAO,MAAM,UAAU,GAAI,CAAC,EAAE,QAAQ,SAAS,OAAO,QAC9C,UAAU,SACT,CAAC,KAAK,EAAE,OAAO,KAAK,CAAC,YAClB,QAAQ,KACjB,MAAM,CAAC,CAAC,EAAE,QAAQ,CAuCnB,CAAC;AAEH,eAAO,MAAM,MAAM,GAAI,CAAC,QAChB,UAAU,CAAC,MAAM,CAAC,SACjB,CAAC,KAAK,EAAE,OAAO,KAAK,CAAC,UACrB,OAAO,CAAC,UAAU,CAAC,KACzB,MAAM,CAAC,CAAC,CAAoE,CAAC;AAEhF;;;GAGG;AACH,eAAO,MAAM,aAAa,GAAI,QAAQ,SAAS,OAAO,QAC9C,UAAU,SACT,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,YACrB,QAAQ,KACjB,eAAe,CAAC,QAAQ,CAIzB,CAAC"}
package/src/column.js DELETED
@@ -1,75 +0,0 @@
1
- // The chain every column builder is made of. Each link returns a new column, so a chain reads
2
- // in declaration order and a builder is never mutated behind someone's back.
3
- //
4
- // Where a column landed (table, property key, physical name) is recorded in a binding rather
5
- // than on the column: the author writes the property key once, `entity()` derives `orgId` ->
6
- // `org_id` from it, and a lazy `.references(() => orgs.id)` can still resolve the target's
7
- // physical name even though two schema modules import each other in a cycle.
8
- import { invariantViolated } from './errors';
9
- export const snake = (value) => value.replace(/([a-z0-9])([A-Z])/g, '$1_$2').toLowerCase();
10
- export const GENERATED_UUID = { kind: 'generated', by: 'uuid-v7' };
11
- export const GENERATED_NOW = { kind: 'generated', by: 'now' };
12
- /** Every column starts here: not null, no key, no index. */
13
- export const BARE = {
14
- notNull: true,
15
- primaryKey: false,
16
- unique: false,
17
- index: false,
18
- tenant: false,
19
- };
20
- const bindings = new WeakMap();
21
- /**
22
- * Called once per column by `entity()`. A column object belongs to exactly one table: sharing
23
- * one between two entities would give it two physical names and silently mis-name a foreign
24
- * key, so a second binding is a declaration-time error.
25
- */
26
- export const bindColumn = (column, table, property) => {
27
- const existing = bindings.get(column);
28
- if (existing !== undefined && existing.table !== table) {
29
- throw invariantViolated(table, property, `this column is already bound to ${existing.table}.${existing.name}; ` +
30
- 'build a new column instead of sharing one between entities');
31
- }
32
- const binding = { table, property, name: snake(property) };
33
- bindings.set(column, binding);
34
- return binding;
35
- };
36
- export const bindingOf = (column) => bindings.get(column);
37
- const literal = (value) => {
38
- if (value === null)
39
- return { kind: 'value', value: null };
40
- if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') {
41
- return { kind: 'value', value };
42
- }
43
- throw invariantViolated('column', 'default', `a default must be a literal; got ${typeof value}. For an instant use timestamp().defaultNow()`);
44
- };
45
- export const makeColumn = (meta, parse, optional) => ({
46
- $meta: meta,
47
- $parse: parse,
48
- $optional: optional,
49
- primaryKey: () => {
50
- // Only a uuid key can be generated for the caller; any other key must be supplied.
51
- const generated = meta.kind === 'uuid' && meta.default === undefined;
52
- return makeColumn({ ...meta, primaryKey: true, ...(generated ? { default: GENERATED_UUID } : {}) }, parse, generated || meta.default !== undefined);
53
- },
54
- nullable: () => makeColumn({ ...meta, notNull: false }, (value) => (value === null || value === undefined ? null : parse(value)), optional),
55
- unique: () => makeColumn({ ...meta, unique: true }, parse, optional),
56
- tenant: () => makeColumn({ ...meta, tenant: true, index: true }, parse, optional),
57
- references: (target, options = {}) => makeColumn({
58
- ...meta,
59
- references: target,
60
- index: true,
61
- ...(options.onDelete === undefined ? {} : { onDelete: options.onDelete }),
62
- }, parse, optional),
63
- default: (value) => makeColumn({ ...meta, default: literal(value) }, parse, true),
64
- });
65
- export const column = (kind, parse, extra = {}) => makeColumn({ ...BARE, ...extra, kind }, parse, false);
66
- /**
67
- * `timestamptz`, always. There is no naive-timestamp builder and there will not be one: a
68
- * `timestamp without time zone` is a bug that only surfaces twice a year.
69
- */
70
- export const makeTimestamp = (meta, parse, optional) => ({
71
- ...makeColumn(meta, parse, optional),
72
- defaultNow: () => makeTimestamp({ ...meta, default: GENERATED_NOW }, parse, true),
73
- onUpdateNow: () => makeTimestamp({ ...meta, onUpdate: GENERATED_NOW }, parse, optional),
74
- });
75
- //# sourceMappingURL=column.js.map
package/src/column.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"column.js","sourceRoot":"","sources":["column.ts"],"names":[],"mappings":"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"}
package/src/columns.d.ts DELETED
@@ -1,39 +0,0 @@
1
- import type { Column, MoneyValue, TimestampColumn, UuidColumn } from './types';
2
- /** uuid v7: time-ordered, so a primary key index stays append-friendly. */
3
- export declare const newId: () => string;
4
- export declare const uuid: () => UuidColumn;
5
- export interface TextOptions {
6
- /** Emits `char_length(<column>) <= max`, so Postgres refuses an over-long string too. */
7
- readonly max?: number;
8
- }
9
- export declare const text: (options?: TextOptions) => Column<string>;
10
- export declare const integer: () => Column<number>;
11
- export declare const boolean: () => Column<boolean>;
12
- /** Always `timestamptz`. UTC storage is not a per-table decision. */
13
- export declare const timestamp: () => TimestampColumn;
14
- /**
15
- * A closed set of strings, emitted as a CHECK rather than a Postgres `ENUM` type: adding a
16
- * variant is then a one-line migration instead of `ALTER TYPE`, which cannot run inside a
17
- * transaction on older servers.
18
- */
19
- export declare const enumerated: <const V extends readonly string[]>(values: V) => Column<V[number]>;
20
- /**
21
- * An absolute http(s) URL, validated on write rather than on render: a bad URL stored once is
22
- * served to every reader, and `<img src>` fails silently in the browser.
23
- */
24
- export declare const url: () => Column<string>;
25
- /**
26
- * IANA identifiers, checked against `Intl` when the column is declared — a typo or a UTC offset
27
- * is a startup error rather than a row nobody can format. An offset is wrong twice a year.
28
- */
29
- export declare const tz: <const Z extends readonly string[]>(zones: Z) => Column<Z[number]>;
30
- export declare const locale: <const L extends readonly string[]>(locales: L) => Column<L[number]>;
31
- /**
32
- * One property, two physical columns: `<name>_minor bigint` and `<name>_currency char(3)`.
33
- * A single implied currency is a migration nobody wants to write later, and a float is a
34
- * rounding bug nobody wants to debug.
35
- */
36
- export declare const money: () => Column<MoneyValue>;
37
- /** The CHECK that stops a psql session writing a currency the app would refuse. */
38
- export declare const currencyCheck: (currencyColumn: string) => string;
39
- //# sourceMappingURL=columns.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"columns.d.ts","sourceRoot":"","sources":["columns.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,MAAM,EAAc,UAAU,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAM3F,2EAA2E;AAC3E,eAAO,MAAM,KAAK,QAAO,MAAkB,CAAC;AAS5C,eAAO,MAAM,IAAI,QAAO,UAUtB,CAAC;AAEH,MAAM,WAAW,WAAW;IAC1B,yFAAyF;IACzF,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,eAAO,MAAM,IAAI,aAAa,WAAW,KAAQ,MAAM,CAAC,MAAM,CAQ3D,CAAC;AAEJ,eAAO,MAAM,OAAO,QAAO,MAAM,CAAC,MAAM,CAKrC,CAAC;AAEJ,eAAO,MAAM,OAAO,QAAO,MAAM,CAAC,OAAO,CAGtC,CAAC;AAWJ,qEAAqE;AACrE,eAAO,MAAM,SAAS,QAAO,eACgD,CAAC;AAS9E;;;;GAIG;AACH,eAAO,MAAM,UAAU,GAAI,KAAK,CAAC,CAAC,SAAS,SAAS,MAAM,EAAE,UAAU,CAAC,KAAG,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAUzF,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,GAAG,QAAO,MAAM,CAAC,MAAM,CAejC,CAAC;AAWJ;;;GAGG;AACH,eAAO,MAAM,EAAE,GAAI,KAAK,CAAC,CAAC,SAAS,SAAS,MAAM,EAAE,SAAS,CAAC,KAAG,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAahF,CAAC;AAIF,eAAO,MAAM,MAAM,GAAI,KAAK,CAAC,CAAC,SAAS,SAAS,MAAM,EAAE,WAAW,CAAC,KAAG,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAatF,CAAC;AA8BF;;;;GAIG;AACH,eAAO,MAAM,KAAK,QAAO,MAAM,CAAC,UAAU,CAA4C,CAAC;AAEvF,mFAAmF;AACnF,eAAO,MAAM,aAAa,mBAAoB,MAAM,KAAG,MAA4C,CAAC"}
package/src/columns.js DELETED
@@ -1,136 +0,0 @@
1
- // The blessed column builders. There is exactly one way to store an id, an instant, money, a
2
- // locale and a time zone — the alternatives (float money, naive timestamps, a single implied
3
- // currency) are the bugs this file exists to make unreachable.
4
- import { uuid as uuidV7 } from '@ultimat3/core';
5
- import { BARE, column, GENERATED_UUID, makeColumn, makeTimestamp } from './column';
6
- import { invariantViolated } from './errors';
7
- const reject = (rule, detail) => {
8
- throw invariantViolated('column', rule, detail);
9
- };
10
- /** uuid v7: time-ordered, so a primary key index stays append-friendly. */
11
- export const newId = () => uuidV7();
12
- const UUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
13
- const parseUuid = (value) => typeof value === 'string' && UUID.test(value)
14
- ? value
15
- : reject('format', `expected a uuid, got ${String(value)}`);
16
- export const uuid = () => ({
17
- ...makeColumn({ ...BARE, kind: 'uuid' }, parseUuid, false),
18
- // Narrower than the generic chain: a uuid key is generated when omitted, so it is the one
19
- // primary key an insert may leave out.
20
- primaryKey: () => makeColumn({ ...BARE, kind: 'uuid', primaryKey: true, default: GENERATED_UUID }, parseUuid, true),
21
- });
22
- export const text = (options = {}) => column('text', (value) => typeof value === 'string' ? value : reject('type', `expected a string, got ${typeof value}`), options.max === undefined
23
- ? {}
24
- : { length: options.max, check: (name) => `char_length(${name}) <= ${options.max}` });
25
- export const integer = () => column('integer', (value) => typeof value === 'number' && Number.isSafeInteger(value)
26
- ? value
27
- : reject('type', `expected a safe integer, got ${String(value)}`));
28
- export const boolean = () => column('boolean', (value) => typeof value === 'boolean' ? value : reject('type', `expected a boolean, got ${typeof value}`));
29
- const parseInstant = (value) => {
30
- if (value instanceof Date && !Number.isNaN(value.getTime()))
31
- return value;
32
- if (typeof value === 'string' || typeof value === 'number') {
33
- const parsed = new Date(value);
34
- if (!Number.isNaN(parsed.getTime()))
35
- return parsed;
36
- }
37
- return reject('format', `expected a UTC instant, got ${String(value)}`);
38
- };
39
- /** Always `timestamptz`. UTC storage is not a per-table decision. */
40
- export const timestamp = () => makeTimestamp({ ...BARE, kind: 'timestamptz' }, parseInstant, false);
41
- const quote = (value) => `'${value.replaceAll("'", "''")}'`;
42
- const oneOf = (values) => (name) => `${name} in (${values.map(quote).join(', ')})`;
43
- /**
44
- * A closed set of strings, emitted as a CHECK rather than a Postgres `ENUM` type: adding a
45
- * variant is then a one-line migration instead of `ALTER TYPE`, which cannot run inside a
46
- * transaction on older servers.
47
- */
48
- export const enumerated = (values) => {
49
- const allowed = new Set(values);
50
- return column('text', (value) => typeof value === 'string' && allowed.has(value)
51
- ? value
52
- : reject('enum', `expected one of ${values.join(' | ')}, got ${String(value)}`), { values, check: oneOf(values) });
53
- };
54
- /**
55
- * An absolute http(s) URL, validated on write rather than on render: a bad URL stored once is
56
- * served to every reader, and `<img src>` fails silently in the browser.
57
- */
58
- export const url = () => column('text', (value) => {
59
- if (typeof value === 'string') {
60
- try {
61
- const parsed = new URL(value);
62
- if (parsed.protocol === 'http:' || parsed.protocol === 'https:')
63
- return value;
64
- }
65
- catch {
66
- // fall through to the shared rejection so the error names the rule
67
- }
68
- }
69
- return reject('format', `expected an absolute http(s) URL, got ${String(value)}`);
70
- }, { check: (name) => `${name} ~ '^https?://'` });
71
- const isIanaZone = (value) => {
72
- try {
73
- new Intl.DateTimeFormat('en', { timeZone: value }).format(0);
74
- return true;
75
- }
76
- catch {
77
- return false;
78
- }
79
- };
80
- /**
81
- * IANA identifiers, checked against `Intl` when the column is declared — a typo or a UTC offset
82
- * is a startup error rather than a row nobody can format. An offset is wrong twice a year.
83
- */
84
- export const tz = (zones) => {
85
- for (const zone of zones) {
86
- if (!isIanaZone(zone))
87
- reject('iana-tz', `${zone} is not an IANA time zone`);
88
- }
89
- const allowed = new Set(zones);
90
- return column('text', (value) => typeof value === 'string' && allowed.has(value)
91
- ? value
92
- : reject('iana-tz', `expected one of ${zones.join(' | ')}, got ${String(value)}`), { values: zones, check: oneOf(zones) });
93
- };
94
- const BCP47 = /^[a-z]{2,3}(-[A-Za-z0-9]{2,8})*$/;
95
- export const locale = (locales) => {
96
- for (const tag of locales) {
97
- if (!BCP47.test(tag))
98
- reject('bcp-47', `${tag} is not a BCP-47 language tag`);
99
- }
100
- const allowed = new Set(locales);
101
- return column('text', (value) => typeof value === 'string' && allowed.has(value)
102
- ? value
103
- : reject('bcp-47', `expected one of ${locales.join(' | ')}, got ${String(value)}`), { values: locales, check: oneOf(locales) });
104
- };
105
- const parseMinor = (value) => {
106
- if (typeof value === 'bigint')
107
- return value;
108
- if (typeof value === 'number') {
109
- if (!Number.isInteger(value)) {
110
- return reject('money-minor-units', `got the float ${value}; money is integer minor units — 12.34 EUR is 1234n, not 12.34`);
111
- }
112
- return BigInt(value);
113
- }
114
- if (typeof value === 'string' && /^-?\d+$/.test(value))
115
- return BigInt(value);
116
- return reject('money-minor-units', `expected integer minor units, got ${String(value)}`);
117
- };
118
- const parseCurrency = (value) => typeof value === 'string' && /^[A-Z]{3}$/.test(value)
119
- ? value
120
- : reject('iso-4217', `expected a 3-letter ISO-4217 code, got ${String(value)}`);
121
- const parseMoney = (value) => {
122
- if (typeof value !== 'object' || value === null) {
123
- return reject('money', `expected { minor, currency }, got ${String(value)}`);
124
- }
125
- const input = value;
126
- return { minor: parseMinor(input.minor), currency: parseCurrency(input.currency) };
127
- };
128
- /**
129
- * One property, two physical columns: `<name>_minor bigint` and `<name>_currency char(3)`.
130
- * A single implied currency is a migration nobody wants to write later, and a float is a
131
- * rounding bug nobody wants to debug.
132
- */
133
- export const money = () => column('money', parseMoney);
134
- /** The CHECK that stops a psql session writing a currency the app would refuse. */
135
- export const currencyCheck = (currencyColumn) => `${currencyColumn} ~ '^[A-Z]{3}$'`;
136
- //# sourceMappingURL=columns.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"columns.js","sourceRoot":"","sources":["columns.ts"],"names":[],"mappings":"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"}
package/src/database.d.ts DELETED
@@ -1,21 +0,0 @@
1
- import type { EntityCore } from './entity';
2
- import type { Table } from './query';
3
- import type { Repo } from './repo';
4
- export type EntitySet = Readonly<Record<string, EntityCore>>;
5
- export type Database<E extends EntitySet> = {
6
- readonly [K in keyof E]: Table<E[K]['$row'], E[K]['$columns']>;
7
- };
8
- /** Where rows actually live. Postgres in production, memory in tests and before migrations. */
9
- export interface Driver {
10
- repo<Row>(entity: EntityCore<Row>): Repo<Row>;
11
- }
12
- export interface DatabaseOptions {
13
- readonly driver?: Driver;
14
- }
15
- /**
16
- * The default driver: correct semantics, no database, so `x dev` and every test run before
17
- * the first migration exists.
18
- */
19
- export declare const memoryDriver: () => Driver;
20
- export declare const database: <E extends EntitySet>(entities: E, options?: DatabaseOptions) => Database<E>;
21
- //# sourceMappingURL=database.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"database.d.ts","sourceRoot":"","sources":["database.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAC3C,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAErC,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAGnC,MAAM,MAAM,SAAS,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC,CAAC;AAE7D,MAAM,MAAM,QAAQ,CAAC,CAAC,SAAS,SAAS,IAAI;IAC1C,QAAQ,EAAE,CAAC,IAAI,MAAM,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC;CAC/D,CAAC;AAEF,+FAA+F;AAC/F,MAAM,WAAW,MAAM;IACrB,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,UAAU,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC;CAC/C;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED;;;GAGG;AACH,eAAO,MAAM,YAAY,QAAO,MAa/B,CAAC;AASF,eAAO,MAAM,QAAQ,GAAI,CAAC,SAAS,SAAS,YAChC,CAAC,YACF,eAAe,KACvB,QAAQ,CAAC,CAAC,CAQZ,CAAC"}
package/src/database.js DELETED
@@ -1,38 +0,0 @@
1
- // The one typed database handle. `db.posts` exists because `posts` was declared — nobody
2
- // writes a repository class per entity, and nobody can reach a table that is not in the set.
3
- import { tableFor } from './query';
4
- import { memoryRepo } from './repo';
5
- /**
6
- * The default driver: correct semantics, no database, so `x dev` and every test run before
7
- * the first migration exists.
8
- */
9
- export const memoryDriver = () => {
10
- const repos = new Map();
11
- return {
12
- repo(entity) {
13
- const existing = repos.get(entity.$name);
14
- // Keyed by entity name and only ever written from that same entity, so the row type a
15
- // caller asks for is the one that was stored.
16
- if (existing !== undefined)
17
- return existing;
18
- const created = memoryRepo(entity);
19
- repos.set(entity.$name, created);
20
- return created;
21
- },
22
- };
23
- };
24
- let shared;
25
- const defaultDriver = () => {
26
- shared ??= memoryDriver();
27
- return shared;
28
- };
29
- export const database = (entities, options = {}) => {
30
- const driver = options.driver ?? defaultDriver();
31
- const tables = {};
32
- for (const [key, entity] of Object.entries(entities)) {
33
- tables[key] = tableFor(entity, driver.repo(entity));
34
- }
35
- // Built key by key from `entities`, so each table is the one `Database<E>` names.
36
- return tables;
37
- };
38
- //# sourceMappingURL=database.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"database.js","sourceRoot":"","sources":["database.ts"],"names":[],"mappings":"AAAA,yFAAyF;AACzF,6FAA6F;AAI7F,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAEnC,OAAO,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AAiBpC;;;GAGG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,GAAW,EAAE;IACvC,MAAM,KAAK,GAAG,IAAI,GAAG,EAAmB,CAAC;IACzC,OAAO;QACL,IAAI,CAAM,MAAuB;YAC/B,MAAM,QAAQ,GAAG,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YACzC,sFAAsF;YACtF,8CAA8C;YAC9C,IAAI,QAAQ,KAAK,SAAS;gBAAE,OAAO,QAAqB,CAAC;YACzD,MAAM,OAAO,GAAG,UAAU,CAAM,MAAM,CAAC,CAAC;YACxC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;YACjC,OAAO,OAAO,CAAC;QACjB,CAAC;KACF,CAAC;AACJ,CAAC,CAAC;AAEF,IAAI,MAA0B,CAAC;AAE/B,MAAM,aAAa,GAAG,GAAW,EAAE;IACjC,MAAM,KAAK,YAAY,EAAE,CAAC;IAC1B,OAAO,MAAM,CAAC;AAChB,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,QAAQ,GAAG,CACtB,QAAW,EACX,OAAO,GAAoB,EAAE,EAChB,EAAE;IACf,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,aAAa,EAAE,CAAC;IACjD,MAAM,MAAM,GAA4B,EAAE,CAAC;IAC3C,KAAK,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC;QACrD,MAAM,CAAC,GAAG,CAAC,GAAG,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;IACtD,CAAC;IACD,kFAAkF;IAClF,OAAO,MAAqB,CAAC;AAC/B,CAAC,CAAC"}
package/src/describe.d.ts DELETED
@@ -1,16 +0,0 @@
1
- import type { Invariant } from './invariants';
2
- import type { EntityDescription } from './registry';
3
- import type { AnyColumn, IndexDef } from './types';
4
- export interface DescribeInput<Row> {
5
- readonly name: string;
6
- readonly columns: readonly (readonly [string, AnyColumn])[];
7
- readonly primaryKey: readonly string[];
8
- readonly invariants: readonly Invariant<Row>[];
9
- readonly indexes: readonly IndexDef[];
10
- readonly tags: readonly string[];
11
- readonly cacheTag: string;
12
- readonly softDelete: boolean;
13
- readonly tenantColumn: string | null;
14
- }
15
- export declare const describeEntity: <Row>(input: DescribeInput<Row>) => EntityDescription;
16
- //# sourceMappingURL=describe.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"describe.d.ts","sourceRoot":"","sources":["describe.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,KAAK,EAAqB,iBAAiB,EAAE,MAAM,YAAY,CAAC;AACvE,OAAO,KAAK,EAAE,SAAS,EAAc,QAAQ,EAAE,MAAM,SAAS,CAAC;AAE/D,MAAM,WAAW,aAAa,CAAC,GAAG;IAChC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,SAAS,CAAC,SAAS,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC,EAAE,CAAC;IAC5D,QAAQ,CAAC,UAAU,EAAE,SAAS,MAAM,EAAE,CAAC;IACvC,QAAQ,CAAC,UAAU,EAAE,SAAS,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC;IAC/C,QAAQ,CAAC,OAAO,EAAE,SAAS,QAAQ,EAAE,CAAC;IACtC,QAAQ,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,CAAC;IACjC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC;IAC7B,QAAQ,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;CACtC;AA8DD,eAAO,MAAM,cAAc,GAAI,GAAG,SAAS,aAAa,CAAC,GAAG,CAAC,KAAG,iBAmB9D,CAAC"}
package/src/describe.js DELETED
@@ -1,79 +0,0 @@
1
- // The projection an entity hands the rest of the toolchain: `x.manifest.json`, the migration
2
- // generator, the admin dashboard and `x entities`. It is a plain data snapshot on purpose —
3
- // a consumer must be able to read the whole domain without importing a single schema module.
4
- //
5
- // Money is the one place the projection is not one-to-one: one property becomes the two
6
- // physical columns that back it.
7
- import { bindingOf, snake } from './column';
8
- import { currencyCheck } from './columns';
9
- import { invariantViolated } from './errors';
10
- const referenceOf = (entityName, property, meta) => {
11
- if (meta.references === undefined)
12
- return null;
13
- const target = bindingOf(meta.references());
14
- if (target === undefined) {
15
- throw invariantViolated(entityName, property, 'references a column that belongs to no entity — pass a column of an entity() result');
16
- }
17
- return `${target.table}.${target.name}`;
18
- };
19
- const describeColumn = (input, property, meta) => {
20
- const physical = snake(property);
21
- if (meta.kind === 'money') {
22
- const currency = `${physical}_currency`;
23
- const shared = {
24
- notNull: meta.notNull,
25
- primaryKey: false,
26
- unique: false,
27
- hasDefault: false,
28
- references: null,
29
- };
30
- return [
31
- {
32
- property: `${property}Minor`,
33
- column: `${physical}_minor`,
34
- kind: 'bigint',
35
- check: null,
36
- ...shared,
37
- },
38
- {
39
- property: `${property}Currency`,
40
- column: currency,
41
- kind: 'char',
42
- check: currencyCheck(currency),
43
- ...shared,
44
- },
45
- ];
46
- }
47
- return [
48
- {
49
- property,
50
- column: physical,
51
- kind: meta.kind,
52
- notNull: meta.notNull,
53
- primaryKey: meta.primaryKey || input.primaryKey.includes(property),
54
- unique: meta.unique,
55
- hasDefault: meta.default !== undefined,
56
- check: meta.check?.(physical) ?? null,
57
- references: referenceOf(input.name, property, meta),
58
- },
59
- ];
60
- };
61
- export const describeEntity = (input) => ({
62
- name: input.name,
63
- table: input.name,
64
- primaryKey: input.primaryKey.map((property) => snake(property)),
65
- columns: input.columns.flatMap(([property, column]) => describeColumn(input, property, column.$meta)),
66
- invariants: input.invariants.map((inv) => ({
67
- name: inv.name,
68
- kind: inv.kind,
69
- message: inv.message,
70
- sql: inv.sql,
71
- where: inv.where ?? null,
72
- })),
73
- indexes: input.indexes.map((index) => index.name),
74
- tags: input.tags,
75
- cacheTag: input.cacheTag,
76
- softDelete: input.softDelete,
77
- orgScoped: input.tenantColumn !== null,
78
- });
79
- //# sourceMappingURL=describe.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"describe.js","sourceRoot":"","sources":["describe.ts"],"names":[],"mappings":"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"}
package/src/entity.d.ts DELETED
@@ -1,58 +0,0 @@
1
- import type { StandardSchemaV1 } from '@ultimat3/schema';
2
- import type { Expr, InvariantColumns } from './expr';
3
- import type { Invariant, InvariantDef } from './invariants';
4
- import type { EntityDescription } from './registry';
5
- import type { ColumnMap, IndexDef, RowOf } from './types';
6
- /** Presence of this column is what makes an entity soft-deletable — not a flag. */
7
- export declare const SOFT_DELETE_COLUMN = "deletedAt";
8
- export interface IndexInit<C extends ColumnMap> {
9
- readonly on: readonly (keyof C & string)[];
10
- readonly order?: 'asc' | 'desc';
11
- readonly unique?: boolean;
12
- /** Partial index predicate, written in the same language as an invariant. */
13
- readonly where?: (columns: InvariantColumns) => Expr;
14
- }
15
- export interface EntityInit<C extends ColumnMap> {
16
- readonly columns: C;
17
- /** Composite keys only — a single key is `uuid().primaryKey()` on the column itself. */
18
- readonly primaryKey?: readonly (keyof C & string)[];
19
- readonly invariants?: readonly InvariantDef[];
20
- readonly indexes?: readonly IndexInit<C>[];
21
- /** Extra cache tags this entity participates in, beyond its own. */
22
- readonly tags?: readonly string[];
23
- }
24
- /**
25
- * The row-shaped half of an entity. Consumers that must name "some entity" without naming its
26
- * row use `EntityCore`; `Entity` adds the columns themselves, so `orgs.id` is a column
27
- * reference and `typeof orgs.$row` is the derived row type.
28
- */
29
- export interface EntityCore<Row = unknown, C extends ColumnMap = ColumnMap> {
30
- readonly $name: string;
31
- readonly $table: string;
32
- readonly $columns: C;
33
- readonly $primaryKey: readonly string[];
34
- readonly $indexes: readonly IndexDef[];
35
- readonly $invariants: readonly Invariant<Row>[];
36
- readonly $tags: readonly string[];
37
- /** `entity:<name>`. `@ultimat3/cache` invalidates by this string. */
38
- readonly $cacheTag: string;
39
- readonly $softDelete: boolean;
40
- /** Property key of the tenant column, or `null`. Presence is what turns tenancy on. */
41
- readonly $tenantColumn: string | null;
42
- /** Phantom: `type Post = typeof posts.$row`. Reading it at runtime throws. */
43
- readonly $row: Row;
44
- /** The Standard Schema the columns already describe — forms and actions hand input to it. */
45
- readonly $schema: StandardSchemaV1<unknown, Row>;
46
- /** `entity:<name>:<id>` — row-level invalidation for live queries. */
47
- $tagFor(id: string): string;
48
- /** Fills declared defaults, then validates every column. Throws on a bad value. */
49
- $parse(value: unknown): Row;
50
- /** Runs every invariant. Called by the repository on insert and update. */
51
- $assert(row: Row): void;
52
- /** The CHECK/UNIQUE statements the migration emits for this entity. */
53
- $migration(): string;
54
- $describe(): EntityDescription;
55
- }
56
- export type Entity<Row, C extends ColumnMap = ColumnMap> = EntityCore<Row, C> & C;
57
- export declare const entity: <const C extends ColumnMap>(name: string, init: EntityInit<C>) => Entity<RowOf<C>, C>;
58
- //# sourceMappingURL=entity.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"entity.d.ts","sourceRoot":"","sources":["entity.ts"],"names":[],"mappings":"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"}