@assemora/data 0.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.
- package/LICENSE +202 -0
- package/README.md +13 -0
- package/dist/columns.d.ts +121 -0
- package/dist/columns.d.ts.map +1 -0
- package/dist/columns.js +101 -0
- package/dist/columns.js.map +1 -0
- package/dist/index.d.ts +41 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +41 -0
- package/dist/index.js.map +1 -0
- package/dist/instance.d.ts +46 -0
- package/dist/instance.d.ts.map +1 -0
- package/dist/instance.js +158 -0
- package/dist/instance.js.map +1 -0
- package/dist/model.d.ts +73 -0
- package/dist/model.d.ts.map +1 -0
- package/dist/model.js +272 -0
- package/dist/model.js.map +1 -0
- package/dist/module.d.ts +19 -0
- package/dist/module.d.ts.map +1 -0
- package/dist/module.js +29 -0
- package/dist/module.js.map +1 -0
- package/dist/pivot.d.ts +86 -0
- package/dist/pivot.d.ts.map +1 -0
- package/dist/pivot.js +145 -0
- package/dist/pivot.js.map +1 -0
- package/dist/query.d.ts +170 -0
- package/dist/query.d.ts.map +1 -0
- package/dist/query.js +307 -0
- package/dist/query.js.map +1 -0
- package/dist/relations.d.ts +64 -0
- package/dist/relations.d.ts.map +1 -0
- package/dist/relations.js +26 -0
- package/dist/relations.js.map +1 -0
- package/dist/runtime.d.ts +28 -0
- package/dist/runtime.d.ts.map +1 -0
- package/dist/runtime.js +149 -0
- package/dist/runtime.js.map +1 -0
- package/dist/slow-queries.d.ts +55 -0
- package/dist/slow-queries.d.ts.map +1 -0
- package/dist/slow-queries.js +96 -0
- package/dist/slow-queries.js.map +1 -0
- package/package.json +40 -0
package/dist/pivot.d.ts
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pivot operations (SPEC.md §24).
|
|
3
|
+
*
|
|
4
|
+
* `belongsToMany` is the one relation that stores nothing on either table it links, so
|
|
5
|
+
* `user.roles` is the only handle there is on the join table. It is an array carrying
|
|
6
|
+
* three verbs: the array is what a read loaded, the verbs write to the join table
|
|
7
|
+
* whether or not anything was loaded, and both are true of the same value at once.
|
|
8
|
+
*
|
|
9
|
+
* The verbs are non-enumerable, so `Object.keys(user)`, `{ ...user }` and
|
|
10
|
+
* `JSON.stringify(user)` see exactly what they saw before there were any. Every write is
|
|
11
|
+
* an ordinary insert, delete or select through the Query AST, against the table
|
|
12
|
+
* `@assemora/database` derives — no adapter method and no operation is added for a
|
|
13
|
+
* pivot, because a link table is a table (ADR-0001, ADR-0013).
|
|
14
|
+
*/
|
|
15
|
+
import type { RelationDescriptor, TableDescriptor } from '@assemora/database';
|
|
16
|
+
import type { Fields } from './query.js';
|
|
17
|
+
/**
|
|
18
|
+
* What a key column holds.
|
|
19
|
+
*
|
|
20
|
+
* A relation's target type is erased so that two models may reference each other
|
|
21
|
+
* (ADR-0010), so an id cannot be typed as the target's primary key. This is as narrow
|
|
22
|
+
* as it can honestly be — every column type a primary key is declared with — and it
|
|
23
|
+
* still refuses `null`, `undefined` and an object that was meant to be its own id.
|
|
24
|
+
*/
|
|
25
|
+
export type RelatedKey = string | number | bigint;
|
|
26
|
+
/**
|
|
27
|
+
* One side of a many-to-many, as SPEC.md §24 writes it:
|
|
28
|
+
*
|
|
29
|
+
* ```ts
|
|
30
|
+
* await user.roles.attach(roleId)
|
|
31
|
+
* await user.roles.detach(roleId)
|
|
32
|
+
* await user.roles.sync([adminId, editorId])
|
|
33
|
+
* ```
|
|
34
|
+
*
|
|
35
|
+
* The rows are what `.with('roles')` returned — rows, not instances, because the type
|
|
36
|
+
* of the other side is erased (ADR-0010). `readonly` on purpose: pushing into this
|
|
37
|
+
* array would look like attaching and would write nothing.
|
|
38
|
+
*/
|
|
39
|
+
export type PivotRelation<Row = Record<string, unknown>> = readonly Row[] & {
|
|
40
|
+
/**
|
|
41
|
+
* Whether these rows came from a read that nothing has moved since.
|
|
42
|
+
*
|
|
43
|
+
* Without it an empty array would mean both "this row is linked to nothing" and
|
|
44
|
+
* "nobody asked", which are different facts. A write puts it back to `false` — on
|
|
45
|
+
* every array this relation has handed out, the ones a caller is still holding
|
|
46
|
+
* included — because what was read is no longer what is stored, and a stale view
|
|
47
|
+
* that still called itself loaded would be the same lie one step later.
|
|
48
|
+
*/
|
|
49
|
+
readonly isLoaded: boolean;
|
|
50
|
+
/** Links these, ignoring the ones already linked. */
|
|
51
|
+
attach(ids: RelatedKey | readonly RelatedKey[]): Promise<void>;
|
|
52
|
+
/** Unlinks these. Unlinking something that was never linked is not an error. */
|
|
53
|
+
detach(ids: RelatedKey | readonly RelatedKey[]): Promise<void>;
|
|
54
|
+
/** The links become exactly these and nothing else, in one transaction. */
|
|
55
|
+
sync(ids: readonly RelatedKey[]): Promise<void>;
|
|
56
|
+
};
|
|
57
|
+
/**
|
|
58
|
+
* The relations a join table stores, which are the only ones with pivot verbs.
|
|
59
|
+
*
|
|
60
|
+
* Matched on `kind` rather than on `Relation<'belongsToMany'>` so that a column, which
|
|
61
|
+
* has no `kind` at all, is excluded by the same test.
|
|
62
|
+
*/
|
|
63
|
+
export type PivotFields<F extends Fields> = {
|
|
64
|
+
readonly [K in keyof F as F[K] extends {
|
|
65
|
+
readonly kind: 'belongsToMany';
|
|
66
|
+
} ? K : never]: PivotRelation;
|
|
67
|
+
};
|
|
68
|
+
/** What a pivot needs to reach its join table, resolved at the moment it is used. */
|
|
69
|
+
export type PivotContext = {
|
|
70
|
+
readonly owner: TableDescriptor;
|
|
71
|
+
readonly relation: RelationDescriptor;
|
|
72
|
+
/**
|
|
73
|
+
* The row the links belong to. The live instance, not a copy: `create()` builds one
|
|
74
|
+
* before it has an id, and the address has to be taken against what it holds now.
|
|
75
|
+
*/
|
|
76
|
+
readonly row: Readonly<Record<string, unknown>>;
|
|
77
|
+
readonly related: () => Readonly<Record<string, TableDescriptor>>;
|
|
78
|
+
};
|
|
79
|
+
/**
|
|
80
|
+
* Puts `user.roles` on a model instance (SPEC.md §24).
|
|
81
|
+
*
|
|
82
|
+
* Takes over whatever a read left under the relation's name, so the loaded rows and the
|
|
83
|
+
* verbs are one value rather than two ways of spelling the same relation.
|
|
84
|
+
*/
|
|
85
|
+
export declare const definePivot: (target: object, context: PivotContext) => void;
|
|
86
|
+
//# sourceMappingURL=pivot.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pivot.d.ts","sourceRoot":"","sources":["../src/pivot.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,OAAO,KAAK,EAAgB,kBAAkB,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAA;AAG3F,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAA;AAGxC;;;;;;;GAOG;AACH,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,CAAA;AAEjD;;;;;;;;;;;;GAYG;AACH,MAAM,MAAM,aAAa,CAAC,GAAG,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI,SAAS,GAAG,EAAE,GAAG;IAC1E;;;;;;;;OAQG;IACH,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAA;IAC1B,qDAAqD;IACrD,MAAM,CAAC,GAAG,EAAE,UAAU,GAAG,SAAS,UAAU,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAC9D,gFAAgF;IAChF,MAAM,CAAC,GAAG,EAAE,UAAU,GAAG,SAAS,UAAU,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAC9D,2EAA2E;IAC3E,IAAI,CAAC,GAAG,EAAE,SAAS,UAAU,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;CAChD,CAAA;AAED;;;;;GAKG;AACH,MAAM,MAAM,WAAW,CAAC,CAAC,SAAS,MAAM,IAAI;IAC1C,QAAQ,EAAE,CAAC,IAAI,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS;QAAE,QAAQ,CAAC,IAAI,EAAE,eAAe,CAAA;KAAE,GACrE,CAAC,GACD,KAAK,GAAG,aAAa;CAC1B,CAAA;AAED,qFAAqF;AACrF,MAAM,MAAM,YAAY,GAAG;IACzB,QAAQ,CAAC,KAAK,EAAE,eAAe,CAAA;IAC/B,QAAQ,CAAC,QAAQ,EAAE,kBAAkB,CAAA;IACrC;;;OAGG;IACH,QAAQ,CAAC,GAAG,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAA;IAC/C,QAAQ,CAAC,OAAO,EAAE,MAAM,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC,CAAA;CAClE,CAAA;AA0BD;;;;;GAKG;AACH,eAAO,MAAM,WAAW,WAAY,MAAM,WAAW,YAAY,KAAG,IA6JnE,CAAA"}
|
package/dist/pivot.js
ADDED
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import { comparison, emptyQuery, pivotAddress } from '@assemora/database';
|
|
2
|
+
import { execute, transaction } from './runtime.js';
|
|
3
|
+
/**
|
|
4
|
+
* Compared as text, because a key that came back from the database may be a number
|
|
5
|
+
* where the caller wrote a string, and two links to the same record are one link.
|
|
6
|
+
*/
|
|
7
|
+
const keyOf = (value) => String(value);
|
|
8
|
+
/** The same id twice is one link, so it is asked for once. */
|
|
9
|
+
const distinct = (ids) => [
|
|
10
|
+
...new Map(ids.map((id) => [keyOf(id), id])).values(),
|
|
11
|
+
];
|
|
12
|
+
/** One id or several: a key is a primitive, so anything else is the list of them. */
|
|
13
|
+
const asKeys = (ids) => typeof ids === 'object' ? distinct(ids) : [ids];
|
|
14
|
+
/**
|
|
15
|
+
* What a read left on the row for this relation.
|
|
16
|
+
*
|
|
17
|
+
* Cast rather than inferred: an adapter answers with rows of the target table, and
|
|
18
|
+
* naming that type here would need the target's type, which ADR-0010 erases.
|
|
19
|
+
*/
|
|
20
|
+
const loadedRows = (value) => Array.isArray(value) ? value : undefined;
|
|
21
|
+
/**
|
|
22
|
+
* Puts `user.roles` on a model instance (SPEC.md §24).
|
|
23
|
+
*
|
|
24
|
+
* Takes over whatever a read left under the relation's name, so the loaded rows and the
|
|
25
|
+
* verbs are one value rather than two ways of spelling the same relation.
|
|
26
|
+
*/
|
|
27
|
+
export const definePivot = (target, context) => {
|
|
28
|
+
const name = context.relation.name;
|
|
29
|
+
const initial = loadedRows(target[name]);
|
|
30
|
+
let loaded = initial !== undefined;
|
|
31
|
+
/**
|
|
32
|
+
* Puts one array — the rows, carrying the three verbs — under the relation's name.
|
|
33
|
+
*
|
|
34
|
+
* Every array it ever publishes keeps the verbs and reads `isLoaded` off the same
|
|
35
|
+
* flag, so a caller holding an older one can still write through it and is still
|
|
36
|
+
* told that what it holds has been overtaken.
|
|
37
|
+
*/
|
|
38
|
+
const publish = (rows) => {
|
|
39
|
+
const items = [...rows];
|
|
40
|
+
Object.defineProperties(items, {
|
|
41
|
+
isLoaded: { enumerable: false, configurable: true, get: () => loaded },
|
|
42
|
+
attach: { enumerable: false, configurable: true, value: verbs.attach },
|
|
43
|
+
detach: { enumerable: false, configurable: true, value: verbs.detach },
|
|
44
|
+
sync: { enumerable: false, configurable: true, value: verbs.sync },
|
|
45
|
+
});
|
|
46
|
+
Object.defineProperty(target, name, {
|
|
47
|
+
// Enumerable exactly when it holds what a read returned, so `Object.keys(user)`
|
|
48
|
+
// and `{ ...user }` show a loaded relation and nothing more — which is what they
|
|
49
|
+
// showed before this relation had verbs to carry.
|
|
50
|
+
enumerable: loaded,
|
|
51
|
+
configurable: true,
|
|
52
|
+
writable: false,
|
|
53
|
+
value: items,
|
|
54
|
+
});
|
|
55
|
+
};
|
|
56
|
+
/**
|
|
57
|
+
* A write makes the loaded view a claim about a state the database has left.
|
|
58
|
+
*
|
|
59
|
+
* The rows are replaced rather than emptied where they lie. `user.roles` is an array
|
|
60
|
+
* the caller may already be holding — `for (const role of user.roles) await
|
|
61
|
+
* user.roles.detach(role.id)` binds it once — and truncating it mid-iteration ended
|
|
62
|
+
* that loop after its first row with the rest still linked and nothing thrown. A
|
|
63
|
+
* value handed out is the caller's; what a write invalidates is the answer to the
|
|
64
|
+
* next read of `user.roles`, and `isLoaded`, which goes false on every array at once.
|
|
65
|
+
*
|
|
66
|
+
* Unconditional, even where the write turned out to change nothing: whether a delete
|
|
67
|
+
* matched a row is not part of the adapter contract, and a view that is sometimes
|
|
68
|
+
* still loaded after `attach` would be a rule nobody could state.
|
|
69
|
+
*/
|
|
70
|
+
const invalidate = () => {
|
|
71
|
+
loaded = false;
|
|
72
|
+
publish([]);
|
|
73
|
+
};
|
|
74
|
+
const address = () => pivotAddress(context.owner, context.relation, context.row, context.related()[context.relation.target]);
|
|
75
|
+
/** The keys this row is already linked to, narrowed to `only` when one is given. */
|
|
76
|
+
const linked = async (pivot, only) => {
|
|
77
|
+
const rows = await execute({
|
|
78
|
+
...emptyQuery(pivot.table.name),
|
|
79
|
+
where: [
|
|
80
|
+
comparison(pivot.ownerColumn, '=', pivot.ownerValue),
|
|
81
|
+
...(only === undefined ? [] : [comparison(pivot.relatedColumn, 'in', only)]),
|
|
82
|
+
],
|
|
83
|
+
}, { table: pivot.table });
|
|
84
|
+
return new Map(rows.map((row) => [keyOf(row[pivot.relatedColumn]), row[pivot.relatedColumn]]));
|
|
85
|
+
};
|
|
86
|
+
const link = (pivot, id) => execute({
|
|
87
|
+
...emptyQuery(pivot.table.name, 'insert'),
|
|
88
|
+
data: { [pivot.ownerColumn]: pivot.ownerValue, [pivot.relatedColumn]: id },
|
|
89
|
+
}, { table: pivot.table });
|
|
90
|
+
const unlink = (pivot, ids) => execute({
|
|
91
|
+
...emptyQuery(pivot.table.name, 'delete'),
|
|
92
|
+
where: [
|
|
93
|
+
comparison(pivot.ownerColumn, '=', pivot.ownerValue),
|
|
94
|
+
comparison(pivot.relatedColumn, 'in', ids),
|
|
95
|
+
],
|
|
96
|
+
}, { table: pivot.table });
|
|
97
|
+
const verbs = {
|
|
98
|
+
async attach(ids) {
|
|
99
|
+
const wanted = asKeys(ids);
|
|
100
|
+
if (wanted.length === 0)
|
|
101
|
+
return;
|
|
102
|
+
// Read first rather than let the unique constraint refuse the second row: only
|
|
103
|
+
// one adapter holds constraints, and both have to answer the same way (ADR-0013).
|
|
104
|
+
// The transaction is for the writes that follow, not for the read — two callers
|
|
105
|
+
// attaching at once still race, and the constraint is what settles that.
|
|
106
|
+
await transaction(async () => {
|
|
107
|
+
const pivot = address();
|
|
108
|
+
const held = await linked(pivot, wanted);
|
|
109
|
+
for (const id of wanted) {
|
|
110
|
+
if (!held.has(keyOf(id)))
|
|
111
|
+
await link(pivot, id);
|
|
112
|
+
}
|
|
113
|
+
});
|
|
114
|
+
invalidate();
|
|
115
|
+
},
|
|
116
|
+
async detach(ids) {
|
|
117
|
+
const going = asKeys(ids);
|
|
118
|
+
if (going.length === 0)
|
|
119
|
+
return;
|
|
120
|
+
// One statement, so it is already one act. Deleting rows that are not there
|
|
121
|
+
// deletes nothing, which is what detaching something unattached should mean.
|
|
122
|
+
await unlink(address(), going);
|
|
123
|
+
invalidate();
|
|
124
|
+
},
|
|
125
|
+
async sync(ids) {
|
|
126
|
+
const wanted = distinct(ids);
|
|
127
|
+
// No early return on an empty list: `sync([])` says the links are now none.
|
|
128
|
+
await transaction(async () => {
|
|
129
|
+
const pivot = address();
|
|
130
|
+
const held = await linked(pivot);
|
|
131
|
+
const keep = new Set(wanted.map(keyOf));
|
|
132
|
+
const going = [...held].filter(([key]) => !keep.has(key)).map(([, value]) => value);
|
|
133
|
+
if (going.length > 0)
|
|
134
|
+
await unlink(pivot, going);
|
|
135
|
+
for (const id of wanted) {
|
|
136
|
+
if (!held.has(keyOf(id)))
|
|
137
|
+
await link(pivot, id);
|
|
138
|
+
}
|
|
139
|
+
});
|
|
140
|
+
invalidate();
|
|
141
|
+
},
|
|
142
|
+
};
|
|
143
|
+
publish(initial ?? []);
|
|
144
|
+
};
|
|
145
|
+
//# sourceMappingURL=pivot.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pivot.js","sourceRoot":"","sources":["../src/pivot.ts"],"names":[],"mappings":"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"}
|
package/dist/query.d.ts
ADDED
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
import type { ComparisonOperator, Condition, Order, QueryAst, RelationLoad, SortDirection, TableDescriptor } from '@assemora/database';
|
|
2
|
+
import type { AnyColumn, ColumnValue } from './columns.js';
|
|
3
|
+
import type { Relation } from './relations.js';
|
|
4
|
+
export type Fields = Readonly<Record<string, AnyColumn | Relation>>;
|
|
5
|
+
type ColumnFields<F extends Fields> = {
|
|
6
|
+
[K in keyof F as F[K] extends {
|
|
7
|
+
readonly node: 'column';
|
|
8
|
+
} ? K : never]: F[K];
|
|
9
|
+
};
|
|
10
|
+
type RelationFields<F extends Fields> = {
|
|
11
|
+
[K in keyof F as F[K] extends {
|
|
12
|
+
readonly node: 'relation';
|
|
13
|
+
} ? K : never]: F[K];
|
|
14
|
+
};
|
|
15
|
+
/** The names a `where` may address. */
|
|
16
|
+
export type FieldName<F extends Fields> = keyof ColumnFields<F> & string;
|
|
17
|
+
/** The names a `with` may load. */
|
|
18
|
+
export type RelationName<F extends Fields> = keyof RelationFields<F> & string;
|
|
19
|
+
export type FieldValue<F extends Fields, K extends FieldName<F>> = ColumnValue<ColumnFields<F>[K]>;
|
|
20
|
+
/** The names a pattern match may address: `like` is meaningless off a string. */
|
|
21
|
+
export type TextFieldName<F extends Fields> = keyof {
|
|
22
|
+
[K in keyof ColumnFields<F> as ColumnFields<F>[K] extends {
|
|
23
|
+
readonly schema: {
|
|
24
|
+
parse(value: unknown): {
|
|
25
|
+
ok: true;
|
|
26
|
+
value: string;
|
|
27
|
+
} | {
|
|
28
|
+
ok: false;
|
|
29
|
+
};
|
|
30
|
+
};
|
|
31
|
+
} ? K : never]: true;
|
|
32
|
+
} & string;
|
|
33
|
+
/** The names a JSON operator may address (SPEC.md §38). */
|
|
34
|
+
export type JsonFieldName<F extends Fields> = keyof {
|
|
35
|
+
[K in keyof ColumnFields<F> as ColumnFields<F>[K] extends {
|
|
36
|
+
readonly isJson: true;
|
|
37
|
+
} ? K : never]: true;
|
|
38
|
+
} & string;
|
|
39
|
+
/** The record a model produces (SPEC.md §18). */
|
|
40
|
+
export type InferRecord<F extends Fields> = {
|
|
41
|
+
[K in keyof ColumnFields<F>]: ColumnValue<ColumnFields<F>[K]>;
|
|
42
|
+
};
|
|
43
|
+
/** A relation to load: a declared name, optionally followed by a nested path. */
|
|
44
|
+
export type RelationPath<F extends Fields> = RelationName<F> | `${RelationName<F>}.${string}`;
|
|
45
|
+
export type Cursor<T> = {
|
|
46
|
+
readonly data: readonly T[];
|
|
47
|
+
/** Pass back as `after` to fetch the next page; `null` at the end. */
|
|
48
|
+
readonly nextCursor: unknown;
|
|
49
|
+
};
|
|
50
|
+
export type Page<T> = {
|
|
51
|
+
readonly data: readonly T[];
|
|
52
|
+
readonly total: number;
|
|
53
|
+
readonly page: number;
|
|
54
|
+
readonly perPage: number;
|
|
55
|
+
readonly lastPage: number;
|
|
56
|
+
};
|
|
57
|
+
export type QueryState = {
|
|
58
|
+
/**
|
|
59
|
+
* Resolved lazily: two models may reference each other, so a relation's target
|
|
60
|
+
* must not be touched while the models are still being declared.
|
|
61
|
+
*/
|
|
62
|
+
readonly table: () => TableDescriptor;
|
|
63
|
+
readonly where: readonly Condition[];
|
|
64
|
+
readonly order: readonly Order[];
|
|
65
|
+
readonly load: readonly RelationLoad[];
|
|
66
|
+
readonly limit: number | undefined;
|
|
67
|
+
readonly offset: number | undefined;
|
|
68
|
+
readonly trashed: 'without' | 'with' | 'only';
|
|
69
|
+
/**
|
|
70
|
+
* Which language this reads in (SPEC.md §131).
|
|
71
|
+
*
|
|
72
|
+
* `'context'` is the language of the operation, which is the default and the whole
|
|
73
|
+
* point: an application whose every query had to name a language is one where
|
|
74
|
+
* forgetting to is a page in the wrong one. Ignored entirely on a model that is not
|
|
75
|
+
* translatable.
|
|
76
|
+
*/
|
|
77
|
+
readonly locale: 'context' | 'all' | {
|
|
78
|
+
readonly code: string;
|
|
79
|
+
};
|
|
80
|
+
/**
|
|
81
|
+
* Whether a row with no translation is answered in the default language instead.
|
|
82
|
+
*
|
|
83
|
+
* On, because a catalogue that showed a hundred dishes in Ukrainian and twenty in
|
|
84
|
+
* Russian is not a Russian catalogue. The row that comes back carries its own
|
|
85
|
+
* `locale`, so the answer already says which language it is actually in.
|
|
86
|
+
*/
|
|
87
|
+
readonly fallback: boolean;
|
|
88
|
+
};
|
|
89
|
+
export type QueryRuntime<Row> = {
|
|
90
|
+
readonly related: () => Readonly<Record<string, TableDescriptor>>;
|
|
91
|
+
readonly hydrate: (row: Record<string, unknown>) => Row;
|
|
92
|
+
readonly scopes: Readonly<Record<string, (query: never) => unknown>>;
|
|
93
|
+
};
|
|
94
|
+
export interface Query<F extends Fields, SN extends string = never, Row = InferRecord<F>> extends PromiseLike<Row[]> {
|
|
95
|
+
where<K extends FieldName<F>>(field: K, value: FieldValue<F, K>): ScopedQuery<F, SN, Row>;
|
|
96
|
+
where<K extends FieldName<F>>(field: K, operator: ComparisonOperator, value: FieldValue<F, K>): ScopedQuery<F, SN, Row>;
|
|
97
|
+
where(filters: Partial<InferRecord<F>>): ScopedQuery<F, SN, Row>;
|
|
98
|
+
where(build: (query: ScopedQuery<F, SN, Row>) => ScopedQuery<F, SN, Row>): ScopedQuery<F, SN, Row>;
|
|
99
|
+
orWhere<K extends FieldName<F>>(field: K, value: FieldValue<F, K>): ScopedQuery<F, SN, Row>;
|
|
100
|
+
orWhere<K extends FieldName<F>>(field: K, operator: ComparisonOperator, value: FieldValue<F, K>): ScopedQuery<F, SN, Row>;
|
|
101
|
+
orWhere(build: (query: ScopedQuery<F, SN, Row>) => ScopedQuery<F, SN, Row>): ScopedQuery<F, SN, Row>;
|
|
102
|
+
whereIn<K extends FieldName<F>>(field: K, values: readonly FieldValue<F, K>[]): ScopedQuery<F, SN, Row>;
|
|
103
|
+
whereNotIn<K extends FieldName<F>>(field: K, values: readonly FieldValue<F, K>[]): ScopedQuery<F, SN, Row>;
|
|
104
|
+
whereNull<K extends FieldName<F>>(field: K): ScopedQuery<F, SN, Row>;
|
|
105
|
+
whereNotNull<K extends FieldName<F>>(field: K): ScopedQuery<F, SN, Row>;
|
|
106
|
+
whereBetween<K extends FieldName<F>>(field: K, range: readonly [FieldValue<F, K>, FieldValue<F, K>]): ScopedQuery<F, SN, Row>;
|
|
107
|
+
whereLike(field: TextFieldName<F>, pattern: string): ScopedQuery<F, SN, Row>;
|
|
108
|
+
/**
|
|
109
|
+
* Compares a key inside a JSON document: `whereJson('metadata', 'source', 'import')`.
|
|
110
|
+
*
|
|
111
|
+
* A dotted path reaches deeper — `'origin.system'`. An empty path compares the
|
|
112
|
+
* whole document, which is occasionally what you want and is why it is spelled out
|
|
113
|
+
* here rather than left to be discovered.
|
|
114
|
+
*/
|
|
115
|
+
whereJson(field: JsonFieldName<F>, path: string, value: unknown): ScopedQuery<F, SN, Row>;
|
|
116
|
+
/** Asks whether a JSON document includes the given fragment. */
|
|
117
|
+
whereJsonContains(field: JsonFieldName<F>, fragment: unknown): ScopedQuery<F, SN, Row>;
|
|
118
|
+
/** Pattern-matches a key inside a JSON document, which is how search reaches it. */
|
|
119
|
+
whereJsonLike(field: JsonFieldName<F>, path: string, pattern: string): ScopedQuery<F, SN, Row>;
|
|
120
|
+
orWhereJsonLike(field: JsonFieldName<F>, path: string, pattern: string): ScopedQuery<F, SN, Row>;
|
|
121
|
+
orderBy<K extends FieldName<F>>(field: K, direction?: SortDirection): ScopedQuery<F, SN, Row>;
|
|
122
|
+
/**
|
|
123
|
+
* Newest first, by `createdAt` unless another column is named — the Eloquent
|
|
124
|
+
* shorthand SPEC.md §19 and §128 ask for. A model without `createdAt` has to name
|
|
125
|
+
* one, and says so.
|
|
126
|
+
*/
|
|
127
|
+
latest(field?: FieldName<F>): ScopedQuery<F, SN, Row>;
|
|
128
|
+
oldest(field?: FieldName<F>): ScopedQuery<F, SN, Row>;
|
|
129
|
+
limit(count: number): ScopedQuery<F, SN, Row>;
|
|
130
|
+
offset(count: number): ScopedQuery<F, SN, Row>;
|
|
131
|
+
take(count: number): ScopedQuery<F, SN, Row>;
|
|
132
|
+
with(...relations: RelationPath<F>[]): ScopedQuery<F, SN, Row>;
|
|
133
|
+
withTrashed(): ScopedQuery<F, SN, Row>;
|
|
134
|
+
onlyTrashed(): ScopedQuery<F, SN, Row>;
|
|
135
|
+
/**
|
|
136
|
+
* Reads in a named language instead of the one the operation is in (SPEC.md §131).
|
|
137
|
+
*
|
|
138
|
+
* ```ts
|
|
139
|
+
* await Article.published().get() // the language of the request
|
|
140
|
+
* await Article.inLocale('de').get() // German, whatever the request is in
|
|
141
|
+
* ```
|
|
142
|
+
*/
|
|
143
|
+
inLocale(code: string): ScopedQuery<F, SN, Row>;
|
|
144
|
+
/** Every translation of every row, in every language. */
|
|
145
|
+
allLocales(): ScopedQuery<F, SN, Row>;
|
|
146
|
+
/**
|
|
147
|
+
* Answers only what is written in this language, rather than falling back.
|
|
148
|
+
*
|
|
149
|
+
* What a translator's screen asks: "which of these has not been done yet" is a
|
|
150
|
+
* question the fallback exists to hide from everybody else.
|
|
151
|
+
*/
|
|
152
|
+
withoutFallback(): ScopedQuery<F, SN, Row>;
|
|
153
|
+
get(): Promise<Row[]>;
|
|
154
|
+
first(): Promise<Row | null>;
|
|
155
|
+
firstOrFail(): Promise<Row>;
|
|
156
|
+
count(): Promise<number>;
|
|
157
|
+
exists(): Promise<boolean>;
|
|
158
|
+
paginate(page?: number, perPage?: number): Promise<Page<Row>>;
|
|
159
|
+
/** Keyset pagination over the primary key — stable while rows are inserted. */
|
|
160
|
+
cursorPaginate(perPage?: number, after?: unknown): Promise<Cursor<Row>>;
|
|
161
|
+
/** The query as data. The stable contract of SPEC.md §30. */
|
|
162
|
+
toAst(): QueryAst;
|
|
163
|
+
}
|
|
164
|
+
export type ScopeMethods<F extends Fields, SN extends string, Row> = {
|
|
165
|
+
[K in SN]: () => ScopedQuery<F, SN, Row>;
|
|
166
|
+
};
|
|
167
|
+
export type ScopedQuery<F extends Fields, SN extends string = never, Row = InferRecord<F>> = Query<F, SN, Row> & ScopeMethods<F, SN, Row>;
|
|
168
|
+
export declare const createQuery: <F extends Fields, SN extends string, Row>(state: QueryState, runtime: QueryRuntime<Row>) => ScopedQuery<F, SN, Row>;
|
|
169
|
+
export {};
|
|
170
|
+
//# sourceMappingURL=query.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"query.d.ts","sourceRoot":"","sources":["../src/query.ts"],"names":[],"mappings":"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"}
|