@ultimat3/entity 1.0.0 → 1.2.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.
- package/package.json +4 -4
- package/src/column.d.ts +0 -28
- package/src/column.d.ts.map +0 -1
- package/src/column.js +0 -75
- package/src/column.js.map +0 -1
- package/src/columns.d.ts +0 -39
- package/src/columns.d.ts.map +0 -1
- package/src/columns.js +0 -136
- package/src/columns.js.map +0 -1
- package/src/database.d.ts +0 -21
- package/src/database.d.ts.map +0 -1
- package/src/database.js +0 -38
- package/src/database.js.map +0 -1
- package/src/describe.d.ts +0 -16
- package/src/describe.d.ts.map +0 -1
- package/src/describe.js +0 -79
- package/src/describe.js.map +0 -1
- package/src/entity.d.ts +0 -58
- package/src/entity.d.ts.map +0 -1
- package/src/entity.js +0 -160
- package/src/entity.js.map +0 -1
- package/src/errors.d.ts +0 -18
- package/src/errors.d.ts.map +0 -1
- package/src/errors.js +0 -59
- package/src/errors.js.map +0 -1
- package/src/expr.d.ts +0 -41
- package/src/expr.d.ts.map +0 -1
- package/src/expr.js +0 -94
- package/src/expr.js.map +0 -1
- package/src/index.d.ts +0 -23
- package/src/index.d.ts.map +0 -1
- package/src/index.js +0 -12
- package/src/index.js.map +0 -1
- package/src/invariants.d.ts +0 -36
- package/src/invariants.d.ts.map +0 -1
- package/src/invariants.js +0 -53
- package/src/invariants.js.map +0 -1
- package/src/query.d.ts +0 -30
- package/src/query.d.ts.map +0 -1
- package/src/query.js +0 -74
- package/src/query.js.map +0 -1
- package/src/registry.d.ts +0 -45
- package/src/registry.d.ts.map +0 -1
- package/src/registry.js +0 -26
- package/src/registry.js.map +0 -1
- package/src/repo.d.ts +0 -54
- package/src/repo.d.ts.map +0 -1
- package/src/repo.js +0 -203
- package/src/repo.js.map +0 -1
- package/src/seed.d.ts +0 -20
- package/src/seed.d.ts.map +0 -1
- package/src/seed.js +0 -43
- package/src/seed.js.map +0 -1
- package/src/tenancy.d.ts +0 -41
- package/src/tenancy.d.ts.map +0 -1
- package/src/tenancy.js +0 -57
- package/src/tenancy.js.map +0 -1
- package/src/types.d.ts +0 -99
- package/src/types.d.ts.map +0 -1
- package/src/types.js +0 -8
- package/src/types.js.map +0 -1
package/src/query.js
DELETED
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
// The chainable read. Every chain terminates in a cursor page — `page()` returns rows plus the
|
|
2
|
-
// cursor for the next one, and `all()`/`one()` are that page's rows. There is no `offset()` and
|
|
3
|
-
// there will not be one: under concurrent writes an insert before the offset shifts every later
|
|
4
|
-
// page, so a client silently skips and repeats rows.
|
|
5
|
-
const EMPTY = { where: [], orderBy: [], limit: 50, cursor: null, select: undefined };
|
|
6
|
-
const asRecord = (value) => typeof value === 'object' && value !== null ? value : {};
|
|
7
|
-
const builder = (entity, repo, state, pick) => {
|
|
8
|
-
const next = (patch) => builder(entity, repo, { ...state, ...patch }, pick);
|
|
9
|
-
const args = () => ({
|
|
10
|
-
where: state.where,
|
|
11
|
-
orderBy: state.orderBy,
|
|
12
|
-
limit: state.limit,
|
|
13
|
-
cursor: state.cursor,
|
|
14
|
-
...(state.select === undefined ? {} : { select: state.select }),
|
|
15
|
-
});
|
|
16
|
-
return {
|
|
17
|
-
where: (filter) => next({
|
|
18
|
-
where: [
|
|
19
|
-
...state.where,
|
|
20
|
-
...Object.entries(asRecord(filter)).map(([column, value]) => ({ column, op: 'eq', value })),
|
|
21
|
-
],
|
|
22
|
-
}),
|
|
23
|
-
andWhere: (column, op, value) => next({ where: [...state.where, { column, op, value }] }),
|
|
24
|
-
orderBy: (column, direction = 'asc') => next({ orderBy: [...state.orderBy, { column, direction }] }),
|
|
25
|
-
limit: (rows) => next({ limit: rows }),
|
|
26
|
-
after: (cursor) => next({ cursor }),
|
|
27
|
-
select(fields) {
|
|
28
|
-
// The predicate is what carries the literal key type through `Object.keys`.
|
|
29
|
-
const keys = Object.keys(fields).filter((key) => Object.hasOwn(fields, key));
|
|
30
|
-
return builder(entity, repo, { ...state, select: keys }, (row) => {
|
|
31
|
-
const source = pick(row);
|
|
32
|
-
const picked = {};
|
|
33
|
-
for (const key of keys)
|
|
34
|
-
picked[key] = source[key];
|
|
35
|
-
return picked;
|
|
36
|
-
});
|
|
37
|
-
},
|
|
38
|
-
page: async () => {
|
|
39
|
-
const result = await repo.findMany(args());
|
|
40
|
-
return { rows: result.rows.map(pick), nextCursor: result.nextCursor };
|
|
41
|
-
},
|
|
42
|
-
all: async () => (await repo.findMany(args())).rows.map(pick),
|
|
43
|
-
one: async () => {
|
|
44
|
-
const { rows } = await repo.findMany({ ...args(), limit: 1 });
|
|
45
|
-
const row = rows[0];
|
|
46
|
-
return row === undefined ? null : pick(row);
|
|
47
|
-
},
|
|
48
|
-
count: () => repo.count(args()),
|
|
49
|
-
plan: () => ({
|
|
50
|
-
entity: entity.$name,
|
|
51
|
-
where: state.where,
|
|
52
|
-
orderBy: state.orderBy,
|
|
53
|
-
limit: state.limit,
|
|
54
|
-
...(state.cursor === null ? {} : { cursor: state.cursor }),
|
|
55
|
-
...(state.select === undefined ? {} : { select: state.select }),
|
|
56
|
-
}),
|
|
57
|
-
};
|
|
58
|
-
};
|
|
59
|
-
/** Columns declared `onUpdateNow()` are written by the framework, never by the caller. */
|
|
60
|
-
const touch = (entity, patch) => {
|
|
61
|
-
const stamped = {};
|
|
62
|
-
for (const [property, column] of Object.entries(entity.$columns)) {
|
|
63
|
-
if (column.$meta.onUpdate !== undefined)
|
|
64
|
-
stamped[property] = new Date();
|
|
65
|
-
}
|
|
66
|
-
return Object.assign({}, patch, stamped);
|
|
67
|
-
};
|
|
68
|
-
export const tableFor = (entity, repo) => ({
|
|
69
|
-
...builder(entity, repo, EMPTY, (row) => row),
|
|
70
|
-
insert: (values, options) => repo.insert(entity.$parse(values), options),
|
|
71
|
-
update: (id, patch, options) => repo.update(id, touch(entity, patch), options),
|
|
72
|
-
delete: (id, options) => repo.delete(id, options),
|
|
73
|
-
});
|
|
74
|
-
//# sourceMappingURL=query.js.map
|
package/src/query.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"query.js","sourceRoot":"","sources":["query.ts"],"names":[],"mappings":"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"}
|
package/src/registry.d.ts
DELETED
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
import type { InvariantKind } from './invariants';
|
|
2
|
-
export interface ColumnDescription {
|
|
3
|
-
readonly property: string;
|
|
4
|
-
readonly column: string;
|
|
5
|
-
readonly kind: string;
|
|
6
|
-
readonly notNull: boolean;
|
|
7
|
-
readonly primaryKey: boolean;
|
|
8
|
-
readonly unique: boolean;
|
|
9
|
-
readonly hasDefault: boolean;
|
|
10
|
-
readonly check: string | null;
|
|
11
|
-
readonly references: string | null;
|
|
12
|
-
}
|
|
13
|
-
export interface InvariantDescription {
|
|
14
|
-
readonly name: string;
|
|
15
|
-
readonly kind: InvariantKind;
|
|
16
|
-
readonly message: string;
|
|
17
|
-
/** `null` for an `assert`: a JS predicate the database was never told about. */
|
|
18
|
-
readonly sql: string | null;
|
|
19
|
-
readonly where: string | null;
|
|
20
|
-
}
|
|
21
|
-
export interface EntityDescription {
|
|
22
|
-
readonly name: string;
|
|
23
|
-
readonly table: string;
|
|
24
|
-
readonly primaryKey: readonly string[];
|
|
25
|
-
readonly columns: readonly ColumnDescription[];
|
|
26
|
-
readonly invariants: readonly InvariantDescription[];
|
|
27
|
-
readonly indexes: readonly string[];
|
|
28
|
-
readonly tags: readonly string[];
|
|
29
|
-
readonly cacheTag: string;
|
|
30
|
-
readonly softDelete: boolean;
|
|
31
|
-
readonly orgScoped: boolean;
|
|
32
|
-
}
|
|
33
|
-
export interface RegistryEntry {
|
|
34
|
-
readonly name: string;
|
|
35
|
-
readonly tableName: string;
|
|
36
|
-
describe(): EntityDescription;
|
|
37
|
-
}
|
|
38
|
-
export declare const registerEntity: <E extends RegistryEntry>(entry: E) => E;
|
|
39
|
-
export declare const getEntity: (name: string) => RegistryEntry | undefined;
|
|
40
|
-
export declare const entityNames: () => readonly string[];
|
|
41
|
-
/** Deterministic order: the manifest is a build artefact and must diff cleanly. */
|
|
42
|
-
export declare const describeEntities: () => readonly EntityDescription[];
|
|
43
|
-
/** Test seam. Production code never unregisters an entity. */
|
|
44
|
-
export declare const clearRegistry: () => void;
|
|
45
|
-
//# sourceMappingURL=registry.d.ts.map
|
package/src/registry.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["registry.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAElD,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC;IAC7B,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC;IAC7B,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CACpC;AAED,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAC;IAC7B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,gFAAgF;IAChF,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CAC/B;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,UAAU,EAAE,SAAS,MAAM,EAAE,CAAC;IACvC,QAAQ,CAAC,OAAO,EAAE,SAAS,iBAAiB,EAAE,CAAC;IAC/C,QAAQ,CAAC,UAAU,EAAE,SAAS,oBAAoB,EAAE,CAAC;IACrD,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;IACpC,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,SAAS,EAAE,OAAO,CAAC;CAC7B;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,IAAI,iBAAiB,CAAC;CAC/B;AAID,eAAO,MAAM,cAAc,GAAI,CAAC,SAAS,aAAa,SAAS,CAAC,KAAG,CAOlE,CAAC;AAEF,eAAO,MAAM,SAAS,SAAU,MAAM,KAAG,aAAa,GAAG,SAA+B,CAAC;AAEzF,eAAO,MAAM,WAAW,QAAO,SAAS,MAAM,EAAiC,CAAC;AAEhF,mFAAmF;AACnF,eAAO,MAAM,gBAAgB,QAAO,SAAS,iBAAiB,EAK1D,CAAC;AAEL,8DAA8D;AAC9D,eAAO,MAAM,aAAa,QAAO,IAAwB,CAAC"}
|
package/src/registry.js
DELETED
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
// The entity registry. Every `entity()` call registers here, which is what makes
|
|
2
|
-
// `x.manifest.json`, the admin dashboard generator and the migration emitter able to see the
|
|
3
|
-
// whole domain without importing it — and what makes a duplicate name a build error rather
|
|
4
|
-
// than a silent last-one-wins.
|
|
5
|
-
import { entityDuplicate } from './errors';
|
|
6
|
-
const entities = new Map();
|
|
7
|
-
export const registerEntity = (entry) => {
|
|
8
|
-
const existing = entities.get(entry.name);
|
|
9
|
-
if (existing !== undefined && existing !== entry) {
|
|
10
|
-
throw entityDuplicate(entry.name, existing.tableName);
|
|
11
|
-
}
|
|
12
|
-
entities.set(entry.name, entry);
|
|
13
|
-
return entry;
|
|
14
|
-
};
|
|
15
|
-
export const getEntity = (name) => entities.get(name);
|
|
16
|
-
export const entityNames = () => [...entities.keys()].sort();
|
|
17
|
-
/** Deterministic order: the manifest is a build artefact and must diff cleanly. */
|
|
18
|
-
export const describeEntities = () => entityNames().map((name) => {
|
|
19
|
-
const entry = entities.get(name);
|
|
20
|
-
if (entry === undefined)
|
|
21
|
-
throw entityDuplicate(name, 'unknown');
|
|
22
|
-
return entry.describe();
|
|
23
|
-
});
|
|
24
|
-
/** Test seam. Production code never unregisters an entity. */
|
|
25
|
-
export const clearRegistry = () => entities.clear();
|
|
26
|
-
//# sourceMappingURL=registry.js.map
|
package/src/registry.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"registry.js","sourceRoot":"","sources":["registry.ts"],"names":[],"mappings":"AAAA,iFAAiF;AACjF,6FAA6F;AAC7F,2FAA2F;AAC3F,+BAA+B;AAE/B,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AA2C3C,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAyB,CAAC;AAElD,MAAM,CAAC,MAAM,cAAc,GAAG,CAA0B,KAAQ,EAAK,EAAE;IACrE,MAAM,QAAQ,GAAG,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC1C,IAAI,QAAQ,KAAK,SAAS,IAAI,QAAQ,KAAK,KAAK,EAAE,CAAC;QACjD,MAAM,eAAe,CAAC,KAAK,CAAC,IAAI,EAAE,QAAQ,CAAC,SAAS,CAAC,CAAC;IACxD,CAAC;IACD,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IAChC,OAAO,KAAK,CAAC;AACf,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,IAAY,EAA6B,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;AAEzF,MAAM,CAAC,MAAM,WAAW,GAAG,GAAsB,EAAE,CAAC,CAAC,GAAG,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;AAEhF,mFAAmF;AACnF,MAAM,CAAC,MAAM,gBAAgB,GAAG,GAAiC,EAAE,CACjE,WAAW,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;IACzB,MAAM,KAAK,GAAG,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IACjC,IAAI,KAAK,KAAK,SAAS;QAAE,MAAM,eAAe,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;IAChE,OAAO,KAAK,CAAC,QAAQ,EAAE,CAAC;AAC1B,CAAC,CAAC,CAAC;AAEL,8DAA8D;AAC9D,MAAM,CAAC,MAAM,aAAa,GAAG,GAAS,EAAE,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC"}
|
package/src/repo.d.ts
DELETED
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
import type { EntityCore } from './entity';
|
|
2
|
-
import type { Predicate, SortKey } from './tenancy';
|
|
3
|
-
export interface Tx {
|
|
4
|
-
readonly id: string;
|
|
5
|
-
/** Registered by drivers so a failed transaction can undo in-memory effects. */
|
|
6
|
-
onRollback(undo: () => void): void;
|
|
7
|
-
}
|
|
8
|
-
export interface RepoOptions {
|
|
9
|
-
readonly tx?: Tx;
|
|
10
|
-
/** Required for tenant-scoped entities; the guard throws without it. */
|
|
11
|
-
readonly orgId?: string;
|
|
12
|
-
}
|
|
13
|
-
export interface FindManyArgs extends RepoOptions {
|
|
14
|
-
readonly where?: readonly Predicate[];
|
|
15
|
-
readonly orderBy?: readonly SortKey[];
|
|
16
|
-
readonly limit?: number;
|
|
17
|
-
readonly cursor?: string | null;
|
|
18
|
-
readonly includeDeleted?: boolean;
|
|
19
|
-
readonly select?: readonly string[];
|
|
20
|
-
}
|
|
21
|
-
export interface Page<T> {
|
|
22
|
-
readonly rows: readonly T[];
|
|
23
|
-
/** Pass back as `cursor`. `null` means this was the last page. */
|
|
24
|
-
readonly nextCursor: string | null;
|
|
25
|
-
}
|
|
26
|
-
/**
|
|
27
|
-
* `T` defaults to `unknown` so a row-agnostic consumer (the generated admin, the manifest
|
|
28
|
-
* emitter) can name the shape without knowing the entity.
|
|
29
|
-
*/
|
|
30
|
-
export interface Repo<T = unknown> {
|
|
31
|
-
findById(id: string, options?: RepoOptions): Promise<T | null>;
|
|
32
|
-
findMany(args?: FindManyArgs): Promise<Page<T>>;
|
|
33
|
-
insert(values: T, options?: RepoOptions): Promise<T>;
|
|
34
|
-
update(id: string, patch: Partial<T>, options?: RepoOptions): Promise<T>;
|
|
35
|
-
delete(id: string, options?: RepoOptions): Promise<void>;
|
|
36
|
-
count(args?: FindManyArgs): Promise<number>;
|
|
37
|
-
}
|
|
38
|
-
export interface Transactor {
|
|
39
|
-
run<R>(work: (tx: Tx) => Promise<R>): Promise<R>;
|
|
40
|
-
}
|
|
41
|
-
export declare const encodeCursor: (key: string, id: string) => string;
|
|
42
|
-
export declare const decodeCursor: (cursor: string) => {
|
|
43
|
-
key: string;
|
|
44
|
-
id: string;
|
|
45
|
-
} | null;
|
|
46
|
-
/**
|
|
47
|
-
* The default driver: correct semantics, no database. `x dev` uses it before the first
|
|
48
|
-
* migration and tests use it everywhere. Postgres is the production driver and implements
|
|
49
|
-
* this same interface.
|
|
50
|
-
*/
|
|
51
|
-
export declare const memoryRepo: <Row>(entity: EntityCore<Row>, seed?: readonly Row[]) => Repo<Row>;
|
|
52
|
-
/** In-memory transactor: undo closures registered by drivers run on failure. */
|
|
53
|
-
export declare const memoryTransactor: () => Transactor;
|
|
54
|
-
//# sourceMappingURL=repo.d.ts.map
|
package/src/repo.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"repo.d.ts","sourceRoot":"","sources":["repo.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAE3C,OAAO,KAAK,EAAE,SAAS,EAAa,OAAO,EAAE,MAAM,WAAW,CAAC;AAG/D,MAAM,WAAW,EAAE;IACjB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,gFAAgF;IAChF,UAAU,CAAC,IAAI,EAAE,MAAM,IAAI,GAAG,IAAI,CAAC;CACpC;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;IACjB,wEAAwE;IACxE,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,YAAa,SAAQ,WAAW;IAC/C,QAAQ,CAAC,KAAK,CAAC,EAAE,SAAS,SAAS,EAAE,CAAC;IACtC,QAAQ,CAAC,OAAO,CAAC,EAAE,SAAS,OAAO,EAAE,CAAC;IACtC,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,QAAQ,CAAC,cAAc,CAAC,EAAE,OAAO,CAAC;IAClC,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CACrC;AAED,MAAM,WAAW,IAAI,CAAC,CAAC;IACrB,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC,EAAE,CAAC;IAC5B,kEAAkE;IAClE,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CACpC;AAED;;;GAGG;AACH,MAAM,WAAW,IAAI,CAAC,CAAC,GAAG,OAAO;IAC/B,QAAQ,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;IAC/D,QAAQ,CAAC,IAAI,CAAC,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;IAChD,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;IACrD,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;IACzE,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACzD,KAAK,CAAC,IAAI,CAAC,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;CAC7C;AAED,MAAM,WAAW,UAAU;IACzB,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,EAAE,EAAE,KAAK,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;CAClD;AAED,eAAO,MAAM,YAAY,QAAS,MAAM,MAAM,MAAM,KAAG,MACjB,CAAC;AAEvC,eAAO,MAAM,YAAY,WAAY,MAAM,KAAG;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,GAAG,IAS3E,CAAC;AAiDF;;;;GAIG;AACH,eAAO,MAAM,UAAU,GAAI,GAAG,UAAU,UAAU,CAAC,GAAG,CAAC,SAAQ,SAAS,GAAG,EAAE,KAAQ,IAAI,CAAC,GAAG,CAoI5F,CAAC;AAIF,gFAAgF;AAChF,eAAO,MAAM,gBAAgB,QAAO,UAYlC,CAAC"}
|
package/src/repo.js
DELETED
|
@@ -1,203 +0,0 @@
|
|
|
1
|
-
// The repository seam. Two rules are structural rather than advisory:
|
|
2
|
-
//
|
|
3
|
-
// 1. `tx` is an explicit parameter on every write, so the transactional outbox can join the
|
|
4
|
-
// request's transaction instead of opening its own and losing atomicity.
|
|
5
|
-
// 2. Pagination is cursor-only. OFFSET is wrong under concurrent writes: a row inserted or
|
|
6
|
-
// deleted before the offset shifts every later page, so a client paging through a live
|
|
7
|
-
// table silently skips and repeats rows. A keyset cursor is stable because it names a
|
|
8
|
-
// position in the sort order, not a row count.
|
|
9
|
-
import { invariantViolated, notFound } from './errors';
|
|
10
|
-
import { assertScoped } from './tenancy';
|
|
11
|
-
export const encodeCursor = (key, id) => btoa(JSON.stringify({ k: key, id }));
|
|
12
|
-
export const decodeCursor = (cursor) => {
|
|
13
|
-
try {
|
|
14
|
-
const parsed = JSON.parse(atob(cursor));
|
|
15
|
-
return typeof parsed.k === 'string' && typeof parsed.id === 'string'
|
|
16
|
-
? { key: parsed.k, id: parsed.id }
|
|
17
|
-
: null;
|
|
18
|
-
}
|
|
19
|
-
catch {
|
|
20
|
-
return null;
|
|
21
|
-
}
|
|
22
|
-
};
|
|
23
|
-
const field = (row, property) => typeof row === 'object' && row !== null ? row[property] : undefined;
|
|
24
|
-
const matches = (row, predicate) => {
|
|
25
|
-
const actual = field(row, predicate.column);
|
|
26
|
-
switch (predicate.op) {
|
|
27
|
-
case 'eq':
|
|
28
|
-
return actual === predicate.value;
|
|
29
|
-
case 'neq':
|
|
30
|
-
return actual !== predicate.value;
|
|
31
|
-
case 'in':
|
|
32
|
-
return Array.isArray(predicate.value) && predicate.value.includes(actual);
|
|
33
|
-
case 'gt':
|
|
34
|
-
return compare(actual, predicate.value) > 0;
|
|
35
|
-
case 'gte':
|
|
36
|
-
return compare(actual, predicate.value) >= 0;
|
|
37
|
-
case 'lt':
|
|
38
|
-
return compare(actual, predicate.value) < 0;
|
|
39
|
-
case 'lte':
|
|
40
|
-
return compare(actual, predicate.value) <= 0;
|
|
41
|
-
case 'like':
|
|
42
|
-
return String(actual).includes(String(predicate.value).replaceAll('%', ''));
|
|
43
|
-
case 'is-null':
|
|
44
|
-
return actual === null || actual === undefined;
|
|
45
|
-
case 'is-not-null':
|
|
46
|
-
return actual !== null && actual !== undefined;
|
|
47
|
-
}
|
|
48
|
-
};
|
|
49
|
-
const compare = (left, right) => {
|
|
50
|
-
if (left instanceof Date && right instanceof Date)
|
|
51
|
-
return left.getTime() - right.getTime();
|
|
52
|
-
if (typeof left === 'number' && typeof right === 'number')
|
|
53
|
-
return left - right;
|
|
54
|
-
if (typeof left === 'bigint' && typeof right === 'bigint') {
|
|
55
|
-
return left < right ? -1 : left > right ? 1 : 0;
|
|
56
|
-
}
|
|
57
|
-
const [a, b] = [String(left), String(right)];
|
|
58
|
-
return a < b ? -1 : a > b ? 1 : 0;
|
|
59
|
-
};
|
|
60
|
-
const sortKey = (row, plan) => plan.orderBy
|
|
61
|
-
.map((entry) => {
|
|
62
|
-
const value = field(row, entry.column);
|
|
63
|
-
return value instanceof Date ? value.toISOString() : String(value);
|
|
64
|
-
})
|
|
65
|
-
.join(' ');
|
|
66
|
-
/**
|
|
67
|
-
* The default driver: correct semantics, no database. `x dev` uses it before the first
|
|
68
|
-
* migration and tests use it everywhere. Postgres is the production driver and implements
|
|
69
|
-
* this same interface.
|
|
70
|
-
*/
|
|
71
|
-
export const memoryRepo = (entity, seed = []) => {
|
|
72
|
-
const keyOf = (row) => entity.$primaryKey.map((property) => String(field(row, property))).join('');
|
|
73
|
-
const rows = new Map(seed.map((row) => [keyOf(row), row]));
|
|
74
|
-
const singleKey = (operation) => {
|
|
75
|
-
const [only] = entity.$primaryKey;
|
|
76
|
-
if (entity.$primaryKey.length !== 1 || only === undefined) {
|
|
77
|
-
throw invariantViolated(entity.$name, operation, `${entity.$name} has a composite primary key (${entity.$primaryKey.join(', ')}) — ` +
|
|
78
|
-
'use findMany({ where }) instead of an id');
|
|
79
|
-
}
|
|
80
|
-
return only;
|
|
81
|
-
};
|
|
82
|
-
const planFor = (args) => {
|
|
83
|
-
const scoped = args.orgId === undefined || entity.$tenantColumn === null
|
|
84
|
-
? []
|
|
85
|
-
: [{ column: entity.$tenantColumn, op: 'eq', value: args.orgId }];
|
|
86
|
-
const ordered = args.orderBy ?? [];
|
|
87
|
-
return {
|
|
88
|
-
entity: entity.$name,
|
|
89
|
-
where: [...(args.where ?? []), ...scoped],
|
|
90
|
-
// The primary key is always the final sort key: a cursor needs a total order, or two
|
|
91
|
-
// rows with the same sort value straddle a page boundary.
|
|
92
|
-
orderBy: [
|
|
93
|
-
...ordered,
|
|
94
|
-
...entity.$primaryKey
|
|
95
|
-
.filter((property) => !ordered.some((entry) => entry.column === property))
|
|
96
|
-
.map((property) => ({ column: property, direction: 'asc' })),
|
|
97
|
-
],
|
|
98
|
-
limit: args.limit ?? 50,
|
|
99
|
-
...(args.cursor === undefined || args.cursor === null ? {} : { cursor: args.cursor }),
|
|
100
|
-
...(args.select === undefined ? {} : { select: args.select }),
|
|
101
|
-
};
|
|
102
|
-
};
|
|
103
|
-
const select = (args, operation) => {
|
|
104
|
-
const plan = planFor(args);
|
|
105
|
-
assertScoped(entity.$name, entity.$tenantColumn, operation, plan);
|
|
106
|
-
const visible = (row) => !entity.$softDelete ||
|
|
107
|
-
args.includeDeleted === true ||
|
|
108
|
-
field(row, 'deletedAt') === null ||
|
|
109
|
-
field(row, 'deletedAt') === undefined;
|
|
110
|
-
const found = [...rows.values()]
|
|
111
|
-
.filter((row) => plan.where.every((predicate) => matches(row, predicate)))
|
|
112
|
-
.filter(visible)
|
|
113
|
-
.sort((left, right) => {
|
|
114
|
-
for (const entry of plan.orderBy) {
|
|
115
|
-
const order = compare(field(left, entry.column), field(right, entry.column));
|
|
116
|
-
if (order !== 0)
|
|
117
|
-
return entry.direction === 'desc' ? -order : order;
|
|
118
|
-
}
|
|
119
|
-
return 0;
|
|
120
|
-
});
|
|
121
|
-
return { plan, found };
|
|
122
|
-
};
|
|
123
|
-
const write = (row, options) => {
|
|
124
|
-
entity.$assert(row);
|
|
125
|
-
const key = keyOf(row);
|
|
126
|
-
const previous = rows.get(key);
|
|
127
|
-
options?.tx?.onRollback(() => {
|
|
128
|
-
if (previous === undefined)
|
|
129
|
-
rows.delete(key);
|
|
130
|
-
else
|
|
131
|
-
rows.set(key, previous);
|
|
132
|
-
});
|
|
133
|
-
rows.set(key, row);
|
|
134
|
-
return row;
|
|
135
|
-
};
|
|
136
|
-
const byId = (id) => {
|
|
137
|
-
const current = rows.get(id);
|
|
138
|
-
if (current === undefined)
|
|
139
|
-
throw notFound(entity.$name, id);
|
|
140
|
-
return current;
|
|
141
|
-
};
|
|
142
|
-
// Every method is async: a repository call that fails must reject, never throw
|
|
143
|
-
// synchronously, or half the call sites would need two error paths.
|
|
144
|
-
return {
|
|
145
|
-
async findById(id, options) {
|
|
146
|
-
const property = singleKey('findById');
|
|
147
|
-
const { found } = select({ ...options, where: [{ column: property, op: 'eq', value: id }] }, 'findById');
|
|
148
|
-
return found[0] ?? null;
|
|
149
|
-
},
|
|
150
|
-
async findMany(args = {}) {
|
|
151
|
-
const { plan, found } = select(args, 'findMany');
|
|
152
|
-
const decoded = plan.cursor === undefined ? null : decodeCursor(plan.cursor);
|
|
153
|
-
const start = decoded === null ? 0 : found.findIndex((row) => keyOf(row) === decoded.id) + 1;
|
|
154
|
-
const page = found.slice(start, start + plan.limit);
|
|
155
|
-
const last = page.at(-1);
|
|
156
|
-
const more = start + page.length < found.length;
|
|
157
|
-
return {
|
|
158
|
-
rows: page,
|
|
159
|
-
nextCursor: more && last !== undefined ? encodeCursor(sortKey(last, plan), keyOf(last)) : null,
|
|
160
|
-
};
|
|
161
|
-
},
|
|
162
|
-
async insert(values, options) {
|
|
163
|
-
return write(values, options);
|
|
164
|
-
},
|
|
165
|
-
async update(id, patch, options) {
|
|
166
|
-
singleKey('update');
|
|
167
|
-
return write(Object.assign({}, byId(id), patch), options);
|
|
168
|
-
},
|
|
169
|
-
async delete(id, options) {
|
|
170
|
-
singleKey('delete');
|
|
171
|
-
const current = byId(id);
|
|
172
|
-
// Soft delete hides the row without losing it; the column's presence is the switch.
|
|
173
|
-
if (entity.$softDelete) {
|
|
174
|
-
write(Object.assign({}, current, { deletedAt: new Date() }), options);
|
|
175
|
-
return;
|
|
176
|
-
}
|
|
177
|
-
const key = keyOf(current);
|
|
178
|
-
options?.tx?.onRollback(() => rows.set(key, current));
|
|
179
|
-
rows.delete(key);
|
|
180
|
-
},
|
|
181
|
-
async count(args = {}) {
|
|
182
|
-
return select(args, 'count').found.length;
|
|
183
|
-
},
|
|
184
|
-
};
|
|
185
|
-
};
|
|
186
|
-
let txCounter = 0;
|
|
187
|
-
/** In-memory transactor: undo closures registered by drivers run on failure. */
|
|
188
|
-
export const memoryTransactor = () => ({
|
|
189
|
-
async run(work) {
|
|
190
|
-
const undos = [];
|
|
191
|
-
txCounter += 1;
|
|
192
|
-
const tx = { id: `tx-${txCounter}`, onRollback: (undo) => undos.push(undo) };
|
|
193
|
-
try {
|
|
194
|
-
return await work(tx);
|
|
195
|
-
}
|
|
196
|
-
catch (error) {
|
|
197
|
-
for (const undo of undos.reverse())
|
|
198
|
-
undo();
|
|
199
|
-
throw error;
|
|
200
|
-
}
|
|
201
|
-
},
|
|
202
|
-
});
|
|
203
|
-
//# sourceMappingURL=repo.js.map
|
package/src/repo.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"repo.js","sourceRoot":"","sources":["repo.ts"],"names":[],"mappings":"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"}
|
package/src/seed.d.ts
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import type { Driver } from './database';
|
|
2
|
-
import type { EntityCore } from './entity';
|
|
3
|
-
import type { ColumnMap, Insertable } from './types';
|
|
4
|
-
/** RFC 4122 v5: SHA-1 of namespace + name, with the version and variant bits pinned. */
|
|
5
|
-
export declare const seedId: (label: string) => string;
|
|
6
|
-
export interface SeedContext {
|
|
7
|
-
insert<Row, C extends ColumnMap>(entity: EntityCore<Row, C>, rows: readonly Insertable<C>[]): Promise<void>;
|
|
8
|
-
/** Deterministic id for a label. Same label, same uuid, every run. */
|
|
9
|
-
id(label: string): string;
|
|
10
|
-
}
|
|
11
|
-
export interface SeedOptions {
|
|
12
|
-
/** Defaults to a fresh in-memory driver, so a seed runs with no database at all. */
|
|
13
|
-
readonly driver?: Driver;
|
|
14
|
-
}
|
|
15
|
-
export interface Seed {
|
|
16
|
-
readonly name: string;
|
|
17
|
-
run(options?: SeedOptions): Promise<void>;
|
|
18
|
-
}
|
|
19
|
-
export declare const defineSeed: (name: string, build: (context: SeedContext) => Promise<void>) => Seed;
|
|
20
|
-
//# sourceMappingURL=seed.d.ts.map
|
package/src/seed.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"seed.d.ts","sourceRoot":"","sources":["seed.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAEzC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAC3C,OAAO,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAQrD,wFAAwF;AACxF,eAAO,MAAM,MAAM,UAAW,MAAM,KAAG,MAiBtC,CAAC;AAEF,MAAM,WAAW,WAAW;IAC1B,MAAM,CAAC,GAAG,EAAE,CAAC,SAAS,SAAS,EAC7B,MAAM,EAAE,UAAU,CAAC,GAAG,EAAE,CAAC,CAAC,EAC1B,IAAI,EAAE,SAAS,UAAU,CAAC,CAAC,CAAC,EAAE,GAC7B,OAAO,CAAC,IAAI,CAAC,CAAC;IACjB,sEAAsE;IACtE,EAAE,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,WAAW;IAC1B,oFAAoF;IACpF,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,IAAI;IACnB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,GAAG,CAAC,OAAO,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC3C;AAED,eAAO,MAAM,UAAU,SAAU,MAAM,SAAS,CAAC,OAAO,EAAE,WAAW,KAAK,OAAO,CAAC,IAAI,CAAC,KAAG,IAYxF,CAAC"}
|
package/src/seed.js
DELETED
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
// A seed is the fixture graph, written once and replayed anywhere. `id('post:tenancy')` is a
|
|
2
|
-
// UUID v5 of the label, so the same row gets the same id on every machine and a bug reproduced
|
|
3
|
-
// locally reproduces in CI. Rows go through `entity.$parse` and the invariants, which makes a
|
|
4
|
-
// seed a test of the schema as well as data for one.
|
|
5
|
-
import { createHash } from 'node:crypto';
|
|
6
|
-
import { memoryDriver } from './database';
|
|
7
|
-
/** Framework namespace for seed labels. Fixed forever: changing it moves every seeded id. */
|
|
8
|
-
const NAMESPACE = 'a3c1f0d6-5c2b-4a3e-9f1b-6d4e7c8a9b02';
|
|
9
|
-
const bytesOf = (uuid) => Uint8Array.from((uuid.replaceAll('-', '').match(/../g) ?? []).map((pair) => parseInt(pair, 16)));
|
|
10
|
-
/** RFC 4122 v5: SHA-1 of namespace + name, with the version and variant bits pinned. */
|
|
11
|
-
export const seedId = (label) => {
|
|
12
|
-
const name = new TextEncoder().encode(label);
|
|
13
|
-
const input = new Uint8Array(16 + name.length);
|
|
14
|
-
input.set(bytesOf(NAMESPACE));
|
|
15
|
-
input.set(name, 16);
|
|
16
|
-
const digest = new Uint8Array(createHash('sha1').update(input).digest());
|
|
17
|
-
const bytes = digest.slice(0, 16);
|
|
18
|
-
bytes[6] = ((bytes[6] ?? 0) & 0x0f) | 0x50;
|
|
19
|
-
bytes[8] = ((bytes[8] ?? 0) & 0x3f) | 0x80;
|
|
20
|
-
const hex = [...bytes].map((byte) => byte.toString(16).padStart(2, '0')).join('');
|
|
21
|
-
return [
|
|
22
|
-
hex.slice(0, 8),
|
|
23
|
-
hex.slice(8, 12),
|
|
24
|
-
hex.slice(12, 16),
|
|
25
|
-
hex.slice(16, 20),
|
|
26
|
-
hex.slice(20, 32),
|
|
27
|
-
].join('-');
|
|
28
|
-
};
|
|
29
|
-
export const defineSeed = (name, build) => ({
|
|
30
|
-
name,
|
|
31
|
-
run: async (options = {}) => {
|
|
32
|
-
const driver = options.driver ?? memoryDriver();
|
|
33
|
-
await build({
|
|
34
|
-
insert: async (entity, rows) => {
|
|
35
|
-
const repo = driver.repo(entity);
|
|
36
|
-
for (const row of rows)
|
|
37
|
-
await repo.insert(entity.$parse(row));
|
|
38
|
-
},
|
|
39
|
-
id: seedId,
|
|
40
|
-
});
|
|
41
|
-
},
|
|
42
|
-
});
|
|
43
|
-
//# sourceMappingURL=seed.js.map
|
package/src/seed.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"seed.js","sourceRoot":"","sources":["seed.ts"],"names":[],"mappings":"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"}
|
package/src/tenancy.d.ts
DELETED
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
import type { ColumnMap } from './types';
|
|
2
|
-
export type Operator = 'eq' | 'neq' | 'in' | 'gt' | 'gte' | 'lt' | 'lte' | 'like' | 'is-null' | 'is-not-null';
|
|
3
|
-
export interface Predicate {
|
|
4
|
-
readonly column: string;
|
|
5
|
-
readonly op: Operator;
|
|
6
|
-
readonly value?: unknown;
|
|
7
|
-
}
|
|
8
|
-
export type SortDirection = 'asc' | 'desc';
|
|
9
|
-
export interface SortKey {
|
|
10
|
-
readonly column: string;
|
|
11
|
-
readonly direction: SortDirection;
|
|
12
|
-
}
|
|
13
|
-
export interface QueryPlan {
|
|
14
|
-
readonly entity: string;
|
|
15
|
-
readonly where: readonly Predicate[];
|
|
16
|
-
readonly orderBy: readonly SortKey[];
|
|
17
|
-
readonly limit: number;
|
|
18
|
-
/** Keyset position. There is no `offset` and there will not be one — see `repo.ts`. */
|
|
19
|
-
readonly cursor?: string;
|
|
20
|
-
readonly select?: readonly string[];
|
|
21
|
-
}
|
|
22
|
-
/** The property key a tenant column takes when it is not marked explicitly. */
|
|
23
|
-
export declare const ORG_COLUMN = "orgId";
|
|
24
|
-
/**
|
|
25
|
-
* `.tenant()` is the switch; a column literally named `orgId` counts too, so an entity cannot
|
|
26
|
-
* become unscoped by forgetting one call.
|
|
27
|
-
*/
|
|
28
|
-
export declare const tenantColumnOf: (columns: ColumnMap) => string | null;
|
|
29
|
-
export declare const isOrgScoped: (columns: ColumnMap) => boolean;
|
|
30
|
-
export declare const emptyPlan: (entity: string, limit?: number) => QueryPlan;
|
|
31
|
-
export declare const hasOrgPredicate: (plan: QueryPlan, column?: string) => boolean;
|
|
32
|
-
/** Adds the org predicate exactly once; calling it twice is not an error. */
|
|
33
|
-
export declare const orgScoped: (plan: QueryPlan, orgId: string, column?: string) => QueryPlan;
|
|
34
|
-
/**
|
|
35
|
-
* Called by every repository operation. Runtime here, and a build-time check in `x verify`
|
|
36
|
-
* that no query for a tenant-scoped entity is constructed without it.
|
|
37
|
-
*/
|
|
38
|
-
export declare const assertScoped: (entityName: string, tenantColumn: string | null, operation: string, plan: QueryPlan) => void;
|
|
39
|
-
/** Debug and `x db explain` rendering. Values stay out: a plan is safe to log. */
|
|
40
|
-
export declare const describePlan: (plan: QueryPlan) => string;
|
|
41
|
-
//# sourceMappingURL=tenancy.d.ts.map
|
package/src/tenancy.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"tenancy.d.ts","sourceRoot":"","sources":["tenancy.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAEzC,MAAM,MAAM,QAAQ,GAChB,IAAI,GACJ,KAAK,GACL,IAAI,GACJ,IAAI,GACJ,KAAK,GACL,IAAI,GACJ,KAAK,GACL,MAAM,GACN,SAAS,GACT,aAAa,CAAC;AAElB,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,EAAE,EAAE,QAAQ,CAAC;IACtB,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED,MAAM,MAAM,aAAa,GAAG,KAAK,GAAG,MAAM,CAAC;AAE3C,MAAM,WAAW,OAAO;IACtB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,SAAS,EAAE,aAAa,CAAC;CACnC;AAED,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,KAAK,EAAE,SAAS,SAAS,EAAE,CAAC;IACrC,QAAQ,CAAC,OAAO,EAAE,SAAS,OAAO,EAAE,CAAC;IACrC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,uFAAuF;IACvF,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CACrC;AAED,+EAA+E;AAC/E,eAAO,MAAM,UAAU,UAAU,CAAC;AAElC;;;GAGG;AACH,eAAO,MAAM,cAAc,YAAa,SAAS,KAAG,MAAM,GAAG,IAK5D,CAAC;AAEF,eAAO,MAAM,WAAW,YAAa,SAAS,KAAG,OAA2C,CAAC;AAE7F,eAAO,MAAM,SAAS,WAAY,MAAM,qBAAe,SAKrD,CAAC;AAEH,eAAO,MAAM,eAAe,SAAU,SAAS,WAAU,MAAM,KAAgB,OAClB,CAAC;AAE9D,6EAA6E;AAC7E,eAAO,MAAM,SAAS,SACd,SAAS,SACR,MAAM,WACL,MAAM,KACb,SAG0E,CAAC;AAE9E;;;GAGG;AACH,eAAO,MAAM,YAAY,eACX,MAAM,gBACJ,MAAM,GAAG,IAAI,aAChB,MAAM,QACX,SAAS,KACd,IAIF,CAAC;AAEF,kFAAkF;AAClF,eAAO,MAAM,YAAY,SAAU,SAAS,KAAG,MAc9C,CAAC"}
|
package/src/tenancy.js
DELETED
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
// Multi-tenancy is a guard, not a convention. An entity with a tenant column can only be read
|
|
2
|
-
// through a plan that carries an org predicate; building one without it throws
|
|
3
|
-
// `X_TENANCY_UNSCOPED` at the seam instead of leaking another tenant's rows.
|
|
4
|
-
import { tenancyUnscoped } from './errors';
|
|
5
|
-
/** The property key a tenant column takes when it is not marked explicitly. */
|
|
6
|
-
export const ORG_COLUMN = 'orgId';
|
|
7
|
-
/**
|
|
8
|
-
* `.tenant()` is the switch; a column literally named `orgId` counts too, so an entity cannot
|
|
9
|
-
* become unscoped by forgetting one call.
|
|
10
|
-
*/
|
|
11
|
-
export const tenantColumnOf = (columns) => {
|
|
12
|
-
for (const [property, column] of Object.entries(columns)) {
|
|
13
|
-
if (column.$meta.tenant)
|
|
14
|
-
return property;
|
|
15
|
-
}
|
|
16
|
-
return Object.hasOwn(columns, ORG_COLUMN) ? ORG_COLUMN : null;
|
|
17
|
-
};
|
|
18
|
-
export const isOrgScoped = (columns) => tenantColumnOf(columns) !== null;
|
|
19
|
-
export const emptyPlan = (entity, limit = 50) => ({
|
|
20
|
-
entity,
|
|
21
|
-
where: [],
|
|
22
|
-
orderBy: [],
|
|
23
|
-
limit,
|
|
24
|
-
});
|
|
25
|
-
export const hasOrgPredicate = (plan, column = ORG_COLUMN) => plan.where.some((predicate) => predicate.column === column);
|
|
26
|
-
/** Adds the org predicate exactly once; calling it twice is not an error. */
|
|
27
|
-
export const orgScoped = (plan, orgId, column = ORG_COLUMN) => hasOrgPredicate(plan, column)
|
|
28
|
-
? plan
|
|
29
|
-
: { ...plan, where: [...plan.where, { column, op: 'eq', value: orgId }] };
|
|
30
|
-
/**
|
|
31
|
-
* Called by every repository operation. Runtime here, and a build-time check in `x verify`
|
|
32
|
-
* that no query for a tenant-scoped entity is constructed without it.
|
|
33
|
-
*/
|
|
34
|
-
export const assertScoped = (entityName, tenantColumn, operation, plan) => {
|
|
35
|
-
if (tenantColumn === null)
|
|
36
|
-
return;
|
|
37
|
-
if (hasOrgPredicate(plan, tenantColumn))
|
|
38
|
-
return;
|
|
39
|
-
throw tenancyUnscoped(entityName, operation);
|
|
40
|
-
};
|
|
41
|
-
/** Debug and `x db explain` rendering. Values stay out: a plan is safe to log. */
|
|
42
|
-
export const describePlan = (plan) => {
|
|
43
|
-
const where = plan.where
|
|
44
|
-
.map((predicate) => `${predicate.column} ${predicate.op} ?`)
|
|
45
|
-
.join(' and ');
|
|
46
|
-
const order = plan.orderBy.map((entry) => `${entry.column} ${entry.direction}`).join(', ');
|
|
47
|
-
return [
|
|
48
|
-
`from ${plan.entity}`,
|
|
49
|
-
where === '' ? null : `where ${where}`,
|
|
50
|
-
order === '' ? null : `order by ${order}`,
|
|
51
|
-
`limit ${plan.limit}`,
|
|
52
|
-
plan.cursor === undefined ? null : 'after cursor',
|
|
53
|
-
]
|
|
54
|
-
.filter((part) => part !== null)
|
|
55
|
-
.join(' ');
|
|
56
|
-
};
|
|
57
|
-
//# sourceMappingURL=tenancy.js.map
|
package/src/tenancy.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"tenancy.js","sourceRoot":"","sources":["tenancy.ts"],"names":[],"mappings":"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"}
|