kysely-rizzolver 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (36) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +147 -0
  3. package/dist/cjs/fetch-result-factory.d.ts +52 -0
  4. package/dist/cjs/fetch-result-factory.js +88 -0
  5. package/dist/cjs/fetch-result.d.ts +111 -0
  6. package/dist/cjs/fetch-result.js +117 -0
  7. package/dist/cjs/index.d.ts +10 -0
  8. package/dist/cjs/index.js +21 -0
  9. package/dist/cjs/kysely-rizzolver.d.ts +138 -0
  10. package/dist/cjs/kysely-rizzolver.js +147 -0
  11. package/dist/cjs/model-collection.d.ts +26 -0
  12. package/dist/cjs/model-collection.js +24 -0
  13. package/dist/cjs/query-builder.d.ts +156 -0
  14. package/dist/cjs/query-builder.js +92 -0
  15. package/dist/cjs/selector.d.ts +72 -0
  16. package/dist/cjs/selector.js +45 -0
  17. package/dist/cjs/type-helpers.d.ts +11 -0
  18. package/dist/cjs/type-helpers.js +2 -0
  19. package/dist/esm/fetch-result-factory.js +85 -0
  20. package/dist/esm/fetch-result.js +105 -0
  21. package/dist/esm/index.js +5 -0
  22. package/dist/esm/kysely-rizzolver.js +143 -0
  23. package/dist/esm/model-collection.js +21 -0
  24. package/dist/esm/package.json +1 -0
  25. package/dist/esm/query-builder.js +89 -0
  26. package/dist/esm/selector.js +42 -0
  27. package/dist/esm/type-helpers.js +1 -0
  28. package/dist/types/fetch-result-factory.d.ts +52 -0
  29. package/dist/types/fetch-result.d.ts +111 -0
  30. package/dist/types/index.d.ts +10 -0
  31. package/dist/types/kysely-rizzolver.d.ts +138 -0
  32. package/dist/types/model-collection.d.ts +26 -0
  33. package/dist/types/query-builder.d.ts +156 -0
  34. package/dist/types/selector.d.ts +72 -0
  35. package/dist/types/type-helpers.d.ts +11 -0
  36. package/package.json +32 -0
@@ -0,0 +1,45 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.newSelector = newSelector;
4
+ function newSelector(rizzolver, tableName, alias, keys) {
5
+ const effectiveKeys = (keys ?? rizzolver.fields[tableName]);
6
+ const tableAlias = `${tableName} as ${alias}`;
7
+ const fields = effectiveKeys.map((field) => `${alias}.${field} as _${alias}_${field}`);
8
+ function _rowToModel(result) {
9
+ if (!result || !result[`_${alias}_id`]) {
10
+ return undefined;
11
+ }
12
+ const model = {};
13
+ for (const field of effectiveKeys) {
14
+ const aliasedField = `_${alias}_${field}`;
15
+ model[field] = result[aliasedField] ?? undefined;
16
+ }
17
+ return model;
18
+ }
19
+ const selector = {
20
+ input: {
21
+ table: tableName,
22
+ alias,
23
+ tableFields: effectiveKeys
24
+ },
25
+ selectTable: tableAlias,
26
+ selectFields: fields,
27
+ field(field) {
28
+ return {
29
+ str: `_${alias}_${field}`,
30
+ from(table) {
31
+ return `${table}._${alias}_${field}`;
32
+ }
33
+ };
34
+ },
35
+ select(rows) {
36
+ const data = [];
37
+ for (const row of rows) {
38
+ const model = _rowToModel(row);
39
+ data.push({ row, model });
40
+ }
41
+ return data;
42
+ }
43
+ };
44
+ return selector;
45
+ }
@@ -0,0 +1,11 @@
1
+ /**
2
+ * I can't explain this.
3
+ *
4
+ * I badgered ChatGPT until it worked. it probably just referenced type-fest.
5
+ */
6
+ type LastInUnion<U> = (U extends any ? () => U : never) extends infer F ? (F extends any ? (k: F) => void : never) extends (k: infer I) => void ? I extends () => infer R ? R : never : never : never;
7
+ /**
8
+ * Recursively converts a union type to a tuple by splitting it into its head and tail.
9
+ */
10
+ export type UnionToTuple<U, Last = LastInUnion<U>> = [U] extends [never] ? [] : [...UnionToTuple<Exclude<U, Last>>, Last];
11
+ export {};
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,85 @@
1
+ import { assertIsFetchOneResult, assertIsFetchOneXResult, assertIsFetchSomeResult, isFetchOneResult, isFetchOneXResult, isFetchSomeResult, newFetchOneResult, newFetchOneXResult, newFetchSomeResult } from './fetch-result.js';
2
+ import { newModelCollection } from './model-collection.js';
3
+ export function newFetchResultFactory() {
4
+ return {
5
+ /**
6
+ * Creates a new {@link FetchOneResult} instance.
7
+ */
8
+ newFetchOne(table, result, models) {
9
+ models ??= newModelCollection();
10
+ if (result) {
11
+ models.add(table, result);
12
+ }
13
+ return newFetchOneResult(table, result, models);
14
+ },
15
+ /**
16
+ * Creates a new {@link FetchOneXResult} instance.
17
+ *
18
+ * Note: it may be counterintuitive, but this function accepts `undefined` as
19
+ * input. I found it is way more convenient to assert the type once in this
20
+ * funciton rather than in every caller.
21
+ */
22
+ newFetchOneX(table, result, models) {
23
+ models ??= newModelCollection();
24
+ if (result) {
25
+ models.add(table, result);
26
+ }
27
+ return newFetchOneXResult(table, result, models);
28
+ },
29
+ /**
30
+ * Creates a new {@link FetchSomeResult} instance.
31
+ */
32
+ newFetchSome(table, result, models) {
33
+ models ??= newModelCollection();
34
+ for (const item of result) {
35
+ models.add(table, item);
36
+ }
37
+ return newFetchSomeResult(table, result, models);
38
+ },
39
+ /**
40
+ * Checks if a {@link FetchResult} is a {@link FetchOneResult}.
41
+ */
42
+ isFetchOne(table, result) {
43
+ return isFetchOneResult(result) && result.table === table;
44
+ },
45
+ /**
46
+ * Checks if a {@link FetchResult} is a {@link FetchOneXResult}.
47
+ */
48
+ isFetchOneX(table, result) {
49
+ return isFetchOneXResult(result) && result.table === table;
50
+ },
51
+ /**
52
+ * Checks if a {@link FetchResult} is a {@link FetchSomeResult}.
53
+ */
54
+ isFetchSome(table, result) {
55
+ return isFetchSomeResult(result) && result.table === table;
56
+ },
57
+ /**
58
+ * Asserts that a {@link FetchResult} is a {@link FetchOneResult}.
59
+ */
60
+ assertIsFetchOne(table, result) {
61
+ assertIsFetchOneResult(result);
62
+ if (result.table !== table) {
63
+ throw new Error(`Expected a fetchOne result for table ${table}`);
64
+ }
65
+ },
66
+ /**
67
+ * Asserts that a {@link FetchResult} is a {@link FetchOneXResult}.
68
+ */
69
+ assertIsFetchOneX(table, result) {
70
+ assertIsFetchOneXResult(result);
71
+ if (result.table !== table) {
72
+ throw new Error(`Expected a fetchOne result with a non-null non for table ${table}`);
73
+ }
74
+ },
75
+ /**
76
+ * Asserts that a {@link FetchResult} is a {@link FetchSomeResult}.
77
+ */
78
+ assertIsFetchSome(table, result) {
79
+ assertIsFetchSomeResult(result);
80
+ if (result.table !== table) {
81
+ throw new Error(`Expected a fetchSome result for table ${table}`);
82
+ }
83
+ }
84
+ };
85
+ }
@@ -0,0 +1,105 @@
1
+ /**
2
+ * Creates a new {@link FetchOneResult} instance.
3
+ */
4
+ export function newFetchOneResult(table, result, models) {
5
+ const ref = { value: null };
6
+ const me = {
7
+ fetchType: 'fetchOne',
8
+ table,
9
+ result,
10
+ models,
11
+ asFetchOneX() {
12
+ if (!me.result) {
13
+ throw new Error('Expected a fetchOneX result');
14
+ }
15
+ return ref.value;
16
+ }
17
+ };
18
+ ref.value = me;
19
+ return me;
20
+ }
21
+ /**
22
+ * Creates a new {@link FetchOneXResult} instance.
23
+ *
24
+ * Note: it may be counterintuitive, but this function accepts `undefined` as
25
+ * input. I found it is way more convenient to assert the type once in this
26
+ * funciton rather than in every caller.
27
+ */
28
+ export function newFetchOneXResult(table, result, models) {
29
+ if (!result) {
30
+ throw new Error('Expected a fetchOneX result');
31
+ }
32
+ const ref = { value: null };
33
+ const me = {
34
+ fetchType: 'fetchOne',
35
+ table,
36
+ result,
37
+ models,
38
+ asFetchOneX() {
39
+ return ref.value;
40
+ }
41
+ };
42
+ ref.value = me;
43
+ return me;
44
+ }
45
+ /**
46
+ * Creates a new {@link FetchSomeResult} instance.
47
+ */
48
+ export function newFetchSomeResult(table, result, models) {
49
+ return {
50
+ fetchType: 'fetchSome',
51
+ table,
52
+ result,
53
+ models
54
+ };
55
+ }
56
+ export function isFetchResult(result) {
57
+ return (!!result &&
58
+ typeof result === 'object' &&
59
+ 'fetchType' in result &&
60
+ !!result.fetchType &&
61
+ typeof result.fetchType === 'string' &&
62
+ 'table' in result &&
63
+ !!result.table &&
64
+ typeof result.table === 'string' &&
65
+ 'result' in result &&
66
+ (result.result === undefined ||
67
+ typeof result.result === 'object' ||
68
+ (Array.isArray(result.result) && result.result.every((r) => !!r && typeof r === 'object'))));
69
+ }
70
+ export function isFetchOneResult(value) {
71
+ return isFetchResult(value) && value.fetchType === 'fetchOne' && !Array.isArray(value.result);
72
+ }
73
+ export function isFetchOneXResult(value) {
74
+ return (isFetchResult(value) &&
75
+ value.fetchType === 'fetchOne' &&
76
+ !Array.isArray(value.result) &&
77
+ !!value.result);
78
+ }
79
+ export function isFetchSomeResult(value) {
80
+ return isFetchResult(value) && value.fetchType === 'fetchSome' && Array.isArray(value.result);
81
+ }
82
+ /**
83
+ * Asserts that `value` is a {@link FetchOneResult}.
84
+ */
85
+ export function assertIsFetchOneResult(value) {
86
+ if (!isFetchOneResult(value)) {
87
+ throw new Error('Expected a fetchOne result');
88
+ }
89
+ }
90
+ /**
91
+ * Asserts that `value` is a {@link FetchOneXResult}.
92
+ */
93
+ export function assertIsFetchOneXResult(value) {
94
+ if (!isFetchOneXResult(value)) {
95
+ throw new Error('Expected a fetchOne result with a non-null, non undefined result');
96
+ }
97
+ }
98
+ /**
99
+ * Asserts that `value` is a {@link FetchSomeResult}.
100
+ */
101
+ export function assertIsFetchSomeResult(value) {
102
+ if (!isFetchSomeResult(value)) {
103
+ throw new Error('Expected a fetchSome result');
104
+ }
105
+ }
@@ -0,0 +1,5 @@
1
+ export { KyselyRizzolver } from './kysely-rizzolver.js';
2
+ export { assertIsFetchOneResult, assertIsFetchOneXResult, assertIsFetchSomeResult, isFetchOneResult, isFetchOneXResult, isFetchSomeResult, newFetchOneResult, newFetchOneXResult, newFetchSomeResult } from './fetch-result.js';
3
+ export { newSelector } from './selector.js';
4
+ export { newQueryBuilder } from './query-builder.js';
5
+ export { newModelCollection } from './model-collection.js';
@@ -0,0 +1,143 @@
1
+ import { newFetchResultFactory } from './fetch-result-factory.js';
2
+ import { newQueryBuilder as kyNewQueryBuilder } from './query-builder.js';
3
+ import { newSelector as kyNewSelector } from './selector.js';
4
+ import { newModelCollection as kyNewModelCollection } from './model-collection.js';
5
+ /**
6
+ * A {@link KyselyRizzolver} is a class that is used to define the structure of
7
+ * a database schema.
8
+ *
9
+ * It streamlines instatiating type-safe {@link QueryBuilder}s,
10
+ * {@link Selector}s, {@link ModelCollection}s and {@link FetchResult}s.
11
+ *
12
+ * Define a new {@link KyselyRizzolver} using the
13
+ * {@link KyselyRizzolver.builder|.builderForSchema()} or
14
+ * {@link KyselyRizzolver.builderNoSchema|.builderNoSchema()}.
15
+ */
16
+ export class KyselyRizzolver {
17
+ fields;
18
+ fetches;
19
+ constructor(fields) {
20
+ this.fields = fields;
21
+ this.fetches = newFetchResultFactory();
22
+ }
23
+ /**
24
+ * Intantiates a new {@link Selector} for the given table.
25
+ */
26
+ newSelector(table, alias) {
27
+ return kyNewSelector(this, table, alias);
28
+ }
29
+ /**
30
+ * Instantiates a new {@link QueryBuilder}.
31
+ */
32
+ newQueryBuilder() {
33
+ return kyNewQueryBuilder(this);
34
+ }
35
+ /**
36
+ * Instantiates a new {@link ModelCollection}.
37
+ */
38
+ newModelCollection() {
39
+ return kyNewModelCollection();
40
+ }
41
+ /**
42
+ * Starts building a new {@link KyselyRizzolver} using a builder pattern for
43
+ * a schema.
44
+ *
45
+ * Call {@link KyselyRizzolverBuilderForSchema.table|.table()} for each
46
+ * table that exists on the `DB` type parameter with all of their column
47
+ * names as a const array. After all tables have been added, call
48
+ * {@link KyselyRizzolverBuilderForSchema.build|.build()} to get a new
49
+ * {@link KyselyRizzolver} instance.
50
+ *
51
+ * Example:
52
+ * ```
53
+ * const rizzolver = KyselyRizzolver.builderForSchema<DB>()
54
+ * .table('user', ['id', 'name', 'email'] as const)
55
+ * .table('post', ['id', 'title', 'content', 'authorId'] as const)
56
+ * .build();
57
+ * ```
58
+ *
59
+ * Note: The `as const` assertion is necessary for correct type inference.
60
+ */
61
+ static builderForSchema() {
62
+ return _newKyselyRizzolverBuilderForSchema({});
63
+ }
64
+ /**
65
+ * Starts building a new {@link KyselyRizzolver} using a builder pattern
66
+ * without a schema.
67
+ *
68
+ * Call {@link KyselyRizzolverBuilderNoSchema.table|.table()} for each
69
+ * table with all of their column names as a const array.
70
+ *
71
+ * Example:
72
+ * ```
73
+ * const rizzolver = KyselyRizzolver.builder()
74
+ * .table('user', ['id', 'name', 'email'] as const) // note `as const` is necessary
75
+ * .table('post', ['id', 'title', 'content', 'authorId'] as const)
76
+ * .build();
77
+ * ```
78
+ *
79
+ * Since this version of builder is schemaless, it cannot infer the value
80
+ * types for the columns. The `user` type will be `{ id: unknown, name:
81
+ * unknown, email: unknown }`.
82
+ *
83
+ * You may call
84
+ * {@link KyselyRizzolverBuilderNoSchema.asModel|.asModel\<M\>()}
85
+ * immediately after the .table() call to provide the types, where `M` is an
86
+ * type like `{ column1: type1, column2: type2, ... }`.
87
+ *
88
+ * Example:
89
+ * ```
90
+ * const rizzolver = KyselyRizzolver.builder()
91
+ * .table('user', ['id', 'name', 'email'] as const)
92
+ * .asModel<{id: number, name: string, email: string}>()
93
+ * .table('post', ['id', 'title', 'content', 'authorId'] as const)
94
+ * .asModel<{id: number, title: string, content: string, authorId: number}>()
95
+ * .build();
96
+ * ```
97
+ *
98
+ * p.s. if your .table() and .asModel() columns differ, it will let you know
99
+ * at compile time ;)
100
+ *
101
+ * Once all tables have been added, call
102
+ * {@link KyselyRizzolverBuilderNoSchema.build|.build()} to get a new
103
+ * {@link KyselyRizzolver} instance.
104
+ */
105
+ static builderNoSchema() {
106
+ return _newKyselyRizzolverBuilderNoSchema({}, null);
107
+ }
108
+ }
109
+ function _newKyselyRizzolverBuilderForSchema(fields) {
110
+ return {
111
+ table(tableName, tableFields) {
112
+ return _newKyselyRizzolverBuilderForSchema({
113
+ ...fields,
114
+ [tableName]: tableFields
115
+ });
116
+ },
117
+ build() {
118
+ return new KyselyRizzolver(fields);
119
+ }
120
+ };
121
+ }
122
+ function _newKyselyRizzolverBuilderNoSchema(fields, last) {
123
+ return {
124
+ table(tableName, tableFields) {
125
+ return _newKyselyRizzolverBuilderNoSchema({
126
+ ...fields,
127
+ [tableName]: {
128
+ model: null,
129
+ columns: tableFields
130
+ }
131
+ }, tableName);
132
+ },
133
+ asModel() {
134
+ if (!last) {
135
+ throw new Error('asModel() must be called after table()');
136
+ }
137
+ return _newKyselyRizzolverBuilderNoSchema(fields, null);
138
+ },
139
+ build() {
140
+ return new KyselyRizzolver(Object.fromEntries(Object.entries(fields).map((entry) => [entry[0], entry[1].columns])));
141
+ }
142
+ };
143
+ }
@@ -0,0 +1,21 @@
1
+ export function newModelCollection(init = {}) {
2
+ const collection = { ...init };
3
+ return {
4
+ add(table, selectable) {
5
+ if (!selectable ||
6
+ !('id' in selectable) ||
7
+ !selectable.id ||
8
+ typeof selectable.id !== 'number') {
9
+ return this;
10
+ }
11
+ if (!(table in collection)) {
12
+ collection[table] = {};
13
+ }
14
+ collection[table][selectable.id] = selectable;
15
+ return this;
16
+ },
17
+ get collection() {
18
+ return collection;
19
+ }
20
+ };
21
+ }
@@ -0,0 +1 @@
1
+ {"type": "module"}
@@ -0,0 +1,89 @@
1
+ import { newFetchOneResult, newFetchOneXResult, newFetchSomeResult } from './fetch-result.js';
2
+ import { newSelector } from './selector.js';
3
+ import { newModelCollection } from './model-collection.js';
4
+ export function newQueryBuilder(rizzolver) {
5
+ const selectors = {};
6
+ return {
7
+ selectors,
8
+ table(tableAlias) {
9
+ return selectors[tableAlias].selectTable;
10
+ },
11
+ allFields: Object.values(selectors)
12
+ .map((selector) => selector.selectFields)
13
+ .flat(),
14
+ fieldsOf(...tableAliases) {
15
+ return tableAliases.map((alias) => selectors[alias].selectFields).flat();
16
+ },
17
+ field(field) {
18
+ const [t, f] = field.split('.');
19
+ const alias = `_${t}_${f}`;
20
+ return {
21
+ value: alias,
22
+ from(a) {
23
+ return `${a}.${alias}`;
24
+ }
25
+ };
26
+ },
27
+ add(selectorOrTable, alias, keys) {
28
+ let selector;
29
+ if (typeof selectorOrTable === 'string') {
30
+ if (!alias) {
31
+ throw new Error('Must provide an alias when calling QueryBuilder.add with a table name');
32
+ }
33
+ selector = newSelector(rizzolver, selectorOrTable, alias, (keys ?? rizzolver.fields[selectorOrTable]));
34
+ }
35
+ else {
36
+ if (alias || keys) {
37
+ throw new Error('Must not provide an alias or keys when calling QueryBuilder.add with a selector');
38
+ }
39
+ selector = selectorOrTable;
40
+ }
41
+ selectors[selector.input.alias] = selector;
42
+ return this;
43
+ },
44
+ run(rowsOrCallback) {
45
+ const promise = (async () => {
46
+ const rows = Array.isArray(rowsOrCallback) ? rowsOrCallback : await rowsOrCallback(this);
47
+ const modelCollection = newModelCollection();
48
+ const selectorResults = {};
49
+ for (const [alias, selector] of Object.entries(selectors)) {
50
+ const selectorResult = selector.select(rows);
51
+ for (const { model } of selectorResult) {
52
+ if (!model) {
53
+ continue;
54
+ }
55
+ modelCollection.add(selector.input.table, model);
56
+ }
57
+ selectorResults[alias] = selectorResult;
58
+ }
59
+ const result = [];
60
+ for (let i = 0; i < rows.length; i++) {
61
+ const row = rows[i];
62
+ const selectedModels = {};
63
+ for (const [alias, selectorResult] of Object.entries(selectorResults)) {
64
+ selectedModels[alias] = selectorResult[i].model;
65
+ }
66
+ result.push({ row, selectors: selectedModels });
67
+ }
68
+ return {
69
+ first: result.length ? result[0] : undefined,
70
+ rows: result,
71
+ models: modelCollection,
72
+ newFetchOneResult(selectorAlias) {
73
+ return newFetchOneResult(selectors[selectorAlias].input.table, (result.length ? result[0] : undefined)?.selectors[selectorAlias], modelCollection);
74
+ },
75
+ newFetchOneXResult(selectorAlias) {
76
+ return newFetchOneXResult(selectors[selectorAlias].input.table, (result.length ? result[0] : undefined)?.selectors[selectorAlias], modelCollection);
77
+ },
78
+ newFetchSomeResult(selectorAlias) {
79
+ return newFetchSomeResult(selectors[selectorAlias].input.table, result.map((r) => r.selectors[selectorAlias]).filter((r) => !!r), modelCollection);
80
+ }
81
+ };
82
+ })();
83
+ promise.newFetchOneResult = (selectorAlias) => promise.then((result) => result.newFetchOneResult(selectorAlias));
84
+ promise.newFetchOneXResult = (selectorAlias) => promise.then((result) => result.newFetchOneXResult(selectorAlias));
85
+ promise.newFetchSomeResult = (selectorAlias) => promise.then((result) => result.newFetchSomeResult(selectorAlias));
86
+ return promise;
87
+ }
88
+ };
89
+ }
@@ -0,0 +1,42 @@
1
+ export function newSelector(rizzolver, tableName, alias, keys) {
2
+ const effectiveKeys = (keys ?? rizzolver.fields[tableName]);
3
+ const tableAlias = `${tableName} as ${alias}`;
4
+ const fields = effectiveKeys.map((field) => `${alias}.${field} as _${alias}_${field}`);
5
+ function _rowToModel(result) {
6
+ if (!result || !result[`_${alias}_id`]) {
7
+ return undefined;
8
+ }
9
+ const model = {};
10
+ for (const field of effectiveKeys) {
11
+ const aliasedField = `_${alias}_${field}`;
12
+ model[field] = result[aliasedField] ?? undefined;
13
+ }
14
+ return model;
15
+ }
16
+ const selector = {
17
+ input: {
18
+ table: tableName,
19
+ alias,
20
+ tableFields: effectiveKeys
21
+ },
22
+ selectTable: tableAlias,
23
+ selectFields: fields,
24
+ field(field) {
25
+ return {
26
+ str: `_${alias}_${field}`,
27
+ from(table) {
28
+ return `${table}._${alias}_${field}`;
29
+ }
30
+ };
31
+ },
32
+ select(rows) {
33
+ const data = [];
34
+ for (const row of rows) {
35
+ const model = _rowToModel(row);
36
+ data.push({ row, model });
37
+ }
38
+ return data;
39
+ }
40
+ };
41
+ return selector;
42
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,52 @@
1
+ import type { Selectable } from 'kysely';
2
+ import { type FetchOneResult, type FetchOneXResult, type FetchSomeResult } from './fetch-result.js';
3
+ import { type ModelCollection } from './model-collection.js';
4
+ /**
5
+ * A {@link FetchResultFactory} exposes variants of fetch-related functions, but
6
+ * with the `DB` type parameter already set.
7
+ *
8
+ * This makes it less verbose to work with fetch results in a type-safe way.
9
+ */
10
+ export type FetchResultFactory<DB> = ReturnType<typeof newFetchResultFactory<DB>>;
11
+ export declare function newFetchResultFactory<DB>(): {
12
+ /**
13
+ * Creates a new {@link FetchOneResult} instance.
14
+ */
15
+ newFetchOne<K extends keyof DB & string>(table: K, result: Selectable<DB[K]> | undefined, models?: ModelCollection<DB>): FetchOneResult<DB, K, Selectable<DB[K]>>;
16
+ /**
17
+ * Creates a new {@link FetchOneXResult} instance.
18
+ *
19
+ * Note: it may be counterintuitive, but this function accepts `undefined` as
20
+ * input. I found it is way more convenient to assert the type once in this
21
+ * funciton rather than in every caller.
22
+ */
23
+ newFetchOneX<K extends keyof DB & string>(table: K, result: Selectable<DB[K]> | undefined, models?: ModelCollection<DB>): FetchOneXResult<DB, K, Selectable<DB[K]>>;
24
+ /**
25
+ * Creates a new {@link FetchSomeResult} instance.
26
+ */
27
+ newFetchSome<K extends keyof DB & string>(table: K, result: Selectable<DB[K]>[], models?: ModelCollection<DB>): FetchSomeResult<DB, K, Selectable<DB[K]>>;
28
+ /**
29
+ * Checks if a {@link FetchResult} is a {@link FetchOneResult}.
30
+ */
31
+ isFetchOne<K extends keyof DB & string>(table: K, result: unknown): result is FetchOneResult<DB, K, Selectable<DB[K]>>;
32
+ /**
33
+ * Checks if a {@link FetchResult} is a {@link FetchOneXResult}.
34
+ */
35
+ isFetchOneX<K extends keyof DB & string>(table: K, result: unknown): result is FetchOneXResult<DB, K, Selectable<DB[K]>>;
36
+ /**
37
+ * Checks if a {@link FetchResult} is a {@link FetchSomeResult}.
38
+ */
39
+ isFetchSome<K extends keyof DB & string>(table: K, result: unknown): result is FetchSomeResult<DB, K, Selectable<DB[K]>>;
40
+ /**
41
+ * Asserts that a {@link FetchResult} is a {@link FetchOneResult}.
42
+ */
43
+ assertIsFetchOne<K extends keyof DB & string>(table: K, result: unknown): asserts result is FetchOneResult<DB, K, Selectable<DB[K]>>;
44
+ /**
45
+ * Asserts that a {@link FetchResult} is a {@link FetchOneXResult}.
46
+ */
47
+ assertIsFetchOneX<K extends keyof DB & string>(table: K, result: unknown): asserts result is FetchOneXResult<DB, K, Selectable<DB[K]>>;
48
+ /**
49
+ * Asserts that a {@link FetchResult} is a {@link FetchSomeResult}.
50
+ */
51
+ assertIsFetchSome<K extends keyof DB & string>(table: K, result: unknown): asserts result is FetchSomeResult<DB, K, Selectable<DB[K]>>;
52
+ };