@motherbase/client 2.2.1 → 2.2.4
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/COMPATIBILITY.md +157 -0
- package/LICENSE +21 -21
- package/README.md +52 -4
- package/dist/admin/auth-admin-client.d.ts +43 -0
- package/dist/admin/auth-admin-client.d.ts.map +1 -0
- package/dist/admin/auth-admin-client.js +62 -0
- package/dist/admin/auth-admin-client.js.map +1 -0
- package/dist/admin/auth-admin-mfa-client.d.ts +22 -0
- package/dist/admin/auth-admin-mfa-client.d.ts.map +1 -0
- package/dist/admin/auth-admin-mfa-client.js +17 -0
- package/dist/admin/auth-admin-mfa-client.js.map +1 -0
- package/dist/admin/types.d.ts +85 -0
- package/dist/admin/types.d.ts.map +1 -0
- package/dist/admin/types.js +3 -0
- package/dist/admin/types.js.map +1 -0
- package/dist/auth/constants.d.ts +21 -0
- package/dist/auth/constants.d.ts.map +1 -0
- package/dist/auth/constants.js +34 -0
- package/dist/auth/constants.js.map +1 -0
- package/dist/auth/index.d.ts +5 -0
- package/dist/auth/index.d.ts.map +1 -0
- package/dist/auth/index.js +34 -0
- package/dist/auth/index.js.map +1 -0
- package/dist/auth/motherbase-plugin.d.ts +6 -0
- package/dist/auth/motherbase-plugin.d.ts.map +1 -0
- package/dist/auth/motherbase-plugin.js +80 -0
- package/dist/auth/motherbase-plugin.js.map +1 -0
- package/dist/auth/pkce.d.ts +19 -0
- package/dist/auth/pkce.d.ts.map +1 -0
- package/dist/auth/pkce.js +89 -0
- package/dist/auth/pkce.js.map +1 -0
- package/dist/auth/session-utils.d.ts +29 -0
- package/dist/auth/session-utils.d.ts.map +1 -0
- package/dist/auth/session-utils.js +123 -0
- package/dist/auth/session-utils.js.map +1 -0
- package/dist/auth/session.d.ts +51 -0
- package/dist/auth/session.d.ts.map +1 -0
- package/dist/auth/session.js +161 -0
- package/dist/auth/session.js.map +1 -0
- package/dist/auth/types.d.ts +341 -0
- package/dist/auth/types.d.ts.map +1 -0
- package/dist/auth/types.js +2 -0
- package/dist/auth/types.js.map +1 -0
- package/dist/auth/utils.d.ts +28 -0
- package/dist/auth/utils.d.ts.map +1 -0
- package/dist/auth/utils.js +70 -0
- package/dist/auth/utils.js.map +1 -0
- package/dist/auth.d.ts +3 -2
- package/dist/auth.d.ts.map +1 -1
- package/dist/auth.js +27 -11
- package/dist/auth.js.map +1 -1
- package/dist/channel.d.ts +11 -0
- package/dist/channel.d.ts.map +1 -1
- package/dist/channel.js +26 -2
- package/dist/channel.js.map +1 -1
- package/dist/cookies/cookie-storage.d.ts +12 -0
- package/dist/cookies/cookie-storage.d.ts.map +1 -0
- package/dist/cookies/cookie-storage.js +35 -0
- package/dist/cookies/cookie-storage.js.map +1 -0
- package/dist/cookies/index.d.ts +5 -0
- package/dist/cookies/index.d.ts.map +1 -0
- package/dist/cookies/index.js +5 -0
- package/dist/cookies/index.js.map +1 -0
- package/dist/cookies/server-cookie-storage.d.ts +20 -0
- package/dist/cookies/server-cookie-storage.d.ts.map +1 -0
- package/dist/cookies/server-cookie-storage.js +60 -0
- package/dist/cookies/server-cookie-storage.js.map +1 -0
- package/dist/cookies/types.d.ts +33 -0
- package/dist/cookies/types.d.ts.map +1 -0
- package/dist/cookies/types.js +8 -0
- package/dist/cookies/types.js.map +1 -0
- package/dist/cookies/utils.d.ts +23 -0
- package/dist/cookies/utils.d.ts.map +1 -0
- package/dist/cookies/utils.js +67 -0
- package/dist/cookies/utils.js.map +1 -0
- package/dist/database/database.d.ts +197 -0
- package/dist/database/database.d.ts.map +1 -0
- package/dist/database/database.js +2 -0
- package/dist/database/database.js.map +1 -0
- package/dist/database/facade.d.ts +218 -0
- package/dist/database/facade.d.ts.map +1 -0
- package/dist/database/facade.js +198 -0
- package/dist/database/facade.js.map +1 -0
- package/dist/database/query.d.ts +97 -0
- package/dist/database/query.d.ts.map +1 -0
- package/dist/database/query.js +94 -0
- package/dist/database/query.js.map +1 -0
- package/dist/database/types.d.ts +314 -0
- package/dist/database/types.d.ts.map +1 -0
- package/dist/database/types.js +2 -0
- package/dist/database/types.js.map +1 -0
- package/dist/functions/errors.d.ts +28 -0
- package/dist/functions/errors.d.ts.map +1 -0
- package/dist/functions/errors.js +37 -0
- package/dist/functions/errors.js.map +1 -0
- package/dist/functions/index.d.ts +9 -0
- package/dist/functions/index.d.ts.map +1 -0
- package/dist/functions/index.js +40 -0
- package/dist/functions/index.js.map +1 -0
- package/dist/functions/types.d.ts +25 -0
- package/dist/functions/types.d.ts.map +1 -0
- package/dist/functions/types.js +2 -0
- package/dist/functions/types.js.map +1 -0
- package/dist/http/backend-error.d.ts +17 -0
- package/dist/http/backend-error.d.ts.map +1 -0
- package/dist/http/backend-error.js +11 -0
- package/dist/http/backend-error.js.map +1 -0
- package/dist/http/index.d.ts +59 -0
- package/dist/http/index.d.ts.map +1 -0
- package/dist/http/index.js +175 -0
- package/dist/http/index.js.map +1 -0
- package/dist/http/types.d.ts +45 -0
- package/dist/http/types.d.ts.map +1 -0
- package/dist/http/types.js +2 -0
- package/dist/http/types.js.map +1 -0
- package/dist/http/utils.d.ts +14 -0
- package/dist/http/utils.d.ts.map +1 -0
- package/dist/http/utils.js +37 -0
- package/dist/http/utils.js.map +1 -0
- package/dist/http.d.ts.map +1 -1
- package/dist/http.js +2 -1
- package/dist/http.js.map +1 -1
- package/dist/index.d.ts +47 -77
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +58 -73
- package/dist/index.js.map +1 -1
- package/dist/pkce.js +4 -4
- package/dist/postgrest/index.d.ts +4 -0
- package/dist/postgrest/index.d.ts.map +1 -0
- package/dist/postgrest/index.js +4 -0
- package/dist/postgrest/index.js.map +1 -0
- package/dist/postgrest/query-builder.d.ts +224 -0
- package/dist/postgrest/query-builder.d.ts.map +1 -0
- package/dist/postgrest/query-builder.js +544 -0
- package/dist/postgrest/query-builder.js.map +1 -0
- package/dist/postgrest/rpc.d.ts +12 -0
- package/dist/postgrest/rpc.d.ts.map +1 -0
- package/dist/postgrest/rpc.js +42 -0
- package/dist/postgrest/rpc.js.map +1 -0
- package/dist/postgrest/types.d.ts +88 -0
- package/dist/postgrest/types.d.ts.map +1 -0
- package/dist/postgrest/types.js +2 -0
- package/dist/postgrest/types.js.map +1 -0
- package/dist/postgrest/utils.d.ts +23 -0
- package/dist/postgrest/utils.d.ts.map +1 -0
- package/dist/postgrest/utils.js +87 -0
- package/dist/postgrest/utils.js.map +1 -0
- package/dist/postgrest.d.ts +5 -1
- package/dist/postgrest.d.ts.map +1 -1
- package/dist/postgrest.js +17 -10
- package/dist/postgrest.js.map +1 -1
- package/dist/realtime/channel.d.ts +83 -0
- package/dist/realtime/channel.d.ts.map +1 -0
- package/dist/realtime/channel.js +240 -0
- package/dist/realtime/channel.js.map +1 -0
- package/dist/realtime/index.d.ts +94 -0
- package/dist/realtime/index.d.ts.map +1 -0
- package/dist/realtime/index.js +455 -0
- package/dist/realtime/index.js.map +1 -0
- package/dist/realtime/types.d.ts +120 -0
- package/dist/realtime/types.d.ts.map +1 -0
- package/dist/realtime/types.js +2 -0
- package/dist/realtime/types.js.map +1 -0
- package/dist/realtime.d.ts +1 -0
- package/dist/realtime.d.ts.map +1 -1
- package/dist/realtime.js +26 -1
- package/dist/realtime.js.map +1 -1
- package/dist/runtime.d.ts +13 -0
- package/dist/runtime.d.ts.map +1 -0
- package/dist/runtime.js +15 -0
- package/dist/runtime.js.map +1 -0
- package/dist/session.d.ts +2 -0
- package/dist/session.d.ts.map +1 -1
- package/dist/session.js +11 -2
- package/dist/session.js.map +1 -1
- package/dist/storage/bucket.d.ts +166 -0
- package/dist/storage/bucket.d.ts.map +1 -0
- package/dist/storage/bucket.js +294 -0
- package/dist/storage/bucket.js.map +1 -0
- package/dist/storage/index.d.ts +45 -0
- package/dist/storage/index.d.ts.map +1 -0
- package/dist/storage/index.js +55 -0
- package/dist/storage/index.js.map +1 -0
- package/dist/storage/types.d.ts +131 -0
- package/dist/storage/types.d.ts.map +1 -0
- package/dist/storage/types.js +2 -0
- package/dist/storage/types.js.map +1 -0
- package/dist/storage/utils.d.ts +27 -0
- package/dist/storage/utils.d.ts.map +1 -0
- package/dist/storage/utils.js +43 -0
- package/dist/storage/utils.js.map +1 -0
- package/dist/test.d.ts +2 -0
- package/dist/test.d.ts.map +1 -0
- package/dist/test.js +3 -0
- package/dist/test.js.map +1 -0
- package/dist/types.d.ts +14 -249
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/compat.d.ts +40 -0
- package/dist/utils/compat.d.ts.map +1 -0
- package/dist/utils/compat.js +100 -0
- package/dist/utils/compat.js.map +1 -0
- package/dist/utils/runtime.d.ts +13 -0
- package/dist/utils/runtime.d.ts.map +1 -0
- package/dist/utils/runtime.js +15 -0
- package/dist/utils/runtime.js.map +1 -0
- package/dist/utils/testing.d.ts +38 -0
- package/dist/utils/testing.d.ts.map +1 -0
- package/dist/utils/testing.js +50 -0
- package/dist/utils/testing.js.map +1 -0
- package/dist/utils/warn.d.ts +2 -0
- package/dist/utils/warn.d.ts.map +1 -0
- package/dist/utils/warn.js +23 -0
- package/dist/utils/warn.js.map +1 -0
- package/package.json +13 -11
- package/dist/devices.d.ts +0 -13
- package/dist/devices.d.ts.map +0 -1
- package/dist/devices.js +0 -13
- package/dist/devices.js.map +0 -1
- package/dist/profile.d.ts +0 -16
- package/dist/profile.d.ts.map +0 -1
- package/dist/profile.js +0 -26
- package/dist/profile.js.map +0 -1
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
const OPERATORS = new Set([
|
|
2
|
+
'equals', 'not', 'in', 'gt', 'gte', 'lt', 'lte', 'contains', 'startsWith', 'endsWith',
|
|
3
|
+
]);
|
|
4
|
+
/**
|
|
5
|
+
* An operator object, as opposed to a bare value. Every key must be an
|
|
6
|
+
* operator, so a json column compared to `{ theme: 'dark' }` stays a value.
|
|
7
|
+
*/
|
|
8
|
+
function isOperators(condition) {
|
|
9
|
+
if (typeof condition !== 'object' || condition === null || Array.isArray(condition))
|
|
10
|
+
return false;
|
|
11
|
+
const keys = Object.keys(condition);
|
|
12
|
+
return keys.length > 0 && keys.every(key => OPERATORS.has(key));
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Flatten a `where` into one filter per condition:
|
|
16
|
+
* `{ published: true, views: { gt: 1, lt: 9 } }` is three filters.
|
|
17
|
+
*
|
|
18
|
+
* An `undefined` value means "no filter", as in Prisma, so `{ author_id: maybeId }`
|
|
19
|
+
* reads naturally. `requireFilters` is what stops that from widening a write.
|
|
20
|
+
*/
|
|
21
|
+
export function filtersOf(where = {}) {
|
|
22
|
+
const filters = [];
|
|
23
|
+
for (const [column, condition] of Object.entries(where)) {
|
|
24
|
+
if (isOperators(condition)) {
|
|
25
|
+
for (const [operator, value] of Object.entries(condition)) {
|
|
26
|
+
filters.push({ column, operator: operator, value });
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
else {
|
|
30
|
+
filters.push({ column, operator: 'equals', value: condition });
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
return filters.filter(filter => filter.value !== undefined);
|
|
34
|
+
}
|
|
35
|
+
function applyFilter(query, { column, operator, value }) {
|
|
36
|
+
const v = value;
|
|
37
|
+
switch (operator) {
|
|
38
|
+
// SQL's `= NULL` matches nothing: a null comparison has to be `IS NULL`.
|
|
39
|
+
case 'equals':
|
|
40
|
+
if (value === null)
|
|
41
|
+
query.is(column, null);
|
|
42
|
+
else
|
|
43
|
+
query.eq(column, v);
|
|
44
|
+
return;
|
|
45
|
+
case 'not':
|
|
46
|
+
if (value === null)
|
|
47
|
+
query.not(column, 'is', null);
|
|
48
|
+
else
|
|
49
|
+
query.neq(column, v);
|
|
50
|
+
return;
|
|
51
|
+
case 'in':
|
|
52
|
+
query.in(column, v);
|
|
53
|
+
return;
|
|
54
|
+
case 'gt':
|
|
55
|
+
query.gt(column, v);
|
|
56
|
+
return;
|
|
57
|
+
case 'gte':
|
|
58
|
+
query.gte(column, v);
|
|
59
|
+
return;
|
|
60
|
+
case 'lt':
|
|
61
|
+
query.lt(column, v);
|
|
62
|
+
return;
|
|
63
|
+
case 'lte':
|
|
64
|
+
query.lte(column, v);
|
|
65
|
+
return;
|
|
66
|
+
// `*` is PostgREST's LIKE wildcard.
|
|
67
|
+
// ponytail: a `*` inside the value is a wildcard too; escape it if literal stars need matching.
|
|
68
|
+
case 'contains':
|
|
69
|
+
query.like(column, `*${v}*`);
|
|
70
|
+
return;
|
|
71
|
+
case 'startsWith':
|
|
72
|
+
query.like(column, `${v}*`);
|
|
73
|
+
return;
|
|
74
|
+
case 'endsWith':
|
|
75
|
+
query.like(column, `*${v}`);
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* A write with no filter touches every row. Prisma allows it; here it takes
|
|
81
|
+
* `client.from(table)` written out, so an id that was `undefined` at runtime
|
|
82
|
+
* cannot turn a targeted delete into a table wipe.
|
|
83
|
+
*/
|
|
84
|
+
function requireFilters(where, method) {
|
|
85
|
+
const filters = filtersOf(where);
|
|
86
|
+
if (!filters.length) {
|
|
87
|
+
throw new Error(`${method}(): where matched no column. Use client.from(table) to target every row.`);
|
|
88
|
+
}
|
|
89
|
+
return filters;
|
|
90
|
+
}
|
|
91
|
+
/** `query` narrowed by a `where` that must not be empty. */
|
|
92
|
+
function narrowed(query, where, method) {
|
|
93
|
+
for (const filter of requireFilters(where, method))
|
|
94
|
+
applyFilter(query, filter);
|
|
95
|
+
return query;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* A PATCH or DELETE matching nothing answers 404 here (under compat it
|
|
99
|
+
* resolves empty instead). Either way it means no row, not a failure.
|
|
100
|
+
*/
|
|
101
|
+
function noRows(error) {
|
|
102
|
+
if (error.status === 404)
|
|
103
|
+
return [];
|
|
104
|
+
throw error;
|
|
105
|
+
}
|
|
106
|
+
/** The read half: `findMany` arguments applied to a fresh builder. Exported for tests. */
|
|
107
|
+
export function applyFindArgs(query, args = {}) {
|
|
108
|
+
query.select(args.select ? Object.keys(args.select).join(',') : '*');
|
|
109
|
+
for (const filter of filtersOf(args.where))
|
|
110
|
+
applyFilter(query, filter);
|
|
111
|
+
for (const [column, direction] of Object.entries(args.orderBy ?? {})) {
|
|
112
|
+
query.order(column, { ascending: direction === 'asc' });
|
|
113
|
+
}
|
|
114
|
+
if (args.take !== undefined) {
|
|
115
|
+
const skip = args.skip ?? 0;
|
|
116
|
+
query.range(skip, skip + args.take - 1);
|
|
117
|
+
}
|
|
118
|
+
else if (args.skip !== undefined) {
|
|
119
|
+
throw new Error('findMany(): skip needs take, the builder only offsets through range().');
|
|
120
|
+
}
|
|
121
|
+
return query;
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* `data` of a query sent with `throwOnError()`. Such a query only resolves on
|
|
125
|
+
* success, so `data` is set, whatever the `{ data, error }` envelope type says.
|
|
126
|
+
*/
|
|
127
|
+
async function dataOf(query) {
|
|
128
|
+
return (await query).data;
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* One table's facade. `newQuery` returns a fresh builder for that table on
|
|
132
|
+
* every call. Every method is `async`, so a refused write rejects like a failed
|
|
133
|
+
* one instead of throwing synchronously.
|
|
134
|
+
*/
|
|
135
|
+
export function tableFacade(newQuery) {
|
|
136
|
+
async function createManyAndReturn({ data, skipDuplicates }) {
|
|
137
|
+
const rows = data;
|
|
138
|
+
const query = skipDuplicates ? newQuery().upsert(rows, { ignoreDuplicates: true }) : newQuery().insert(rows);
|
|
139
|
+
return dataOf(query.select().throwOnError());
|
|
140
|
+
}
|
|
141
|
+
return {
|
|
142
|
+
async findMany(args) {
|
|
143
|
+
return dataOf(applyFindArgs(newQuery(), args).throwOnError());
|
|
144
|
+
},
|
|
145
|
+
async findFirst(args) {
|
|
146
|
+
return dataOf(applyFindArgs(newQuery(), { ...args, take: 1 }).throwOnError().maybeSingle());
|
|
147
|
+
},
|
|
148
|
+
async findFirstOrThrow(args) {
|
|
149
|
+
return dataOf(applyFindArgs(newQuery(), { ...args, take: 1 }).throwOnError().single());
|
|
150
|
+
},
|
|
151
|
+
// Two rows are enough to tell a unique match from several, without reading them all.
|
|
152
|
+
async findUnique(args) {
|
|
153
|
+
requireFilters(args.where, 'findUnique');
|
|
154
|
+
return dataOf(applyFindArgs(newQuery(), { ...args, take: 2 }).throwOnError().maybeSingle());
|
|
155
|
+
},
|
|
156
|
+
async findUniqueOrThrow(args) {
|
|
157
|
+
requireFilters(args.where, 'findUniqueOrThrow');
|
|
158
|
+
return dataOf(applyFindArgs(newQuery(), { ...args, take: 2 }).throwOnError().single());
|
|
159
|
+
},
|
|
160
|
+
async count(args) {
|
|
161
|
+
const query = newQuery().select('*', { count: 'exact', head: true });
|
|
162
|
+
for (const filter of filtersOf(args?.where))
|
|
163
|
+
applyFilter(query, filter);
|
|
164
|
+
return (await query.throwOnError()).count ?? 0;
|
|
165
|
+
},
|
|
166
|
+
async create({ data }) {
|
|
167
|
+
return dataOf(newQuery().insert(data).select().throwOnError().single());
|
|
168
|
+
},
|
|
169
|
+
// The server sends no Content-Range on writes, so the count is of the rows sent back.
|
|
170
|
+
async createMany(args) {
|
|
171
|
+
return { count: (await createManyAndReturn(args)).length };
|
|
172
|
+
},
|
|
173
|
+
createManyAndReturn,
|
|
174
|
+
async update({ where, data }) {
|
|
175
|
+
const query = narrowed(newQuery().update(data), where, 'update').maxAffected(1);
|
|
176
|
+
return dataOf(query.select().throwOnError().single());
|
|
177
|
+
},
|
|
178
|
+
async updateMany({ where, data }) {
|
|
179
|
+
return dataOf(narrowed(newQuery().update(data), where, 'updateMany').select().throwOnError());
|
|
180
|
+
},
|
|
181
|
+
async delete({ where }) {
|
|
182
|
+
const query = narrowed(newQuery().delete(), where, 'delete').maxAffected(1);
|
|
183
|
+
return dataOf(query.select().throwOnError().single());
|
|
184
|
+
},
|
|
185
|
+
async deleteMany({ where }) {
|
|
186
|
+
return dataOf(narrowed(newQuery().delete(), where, 'deleteMany').select().throwOnError());
|
|
187
|
+
},
|
|
188
|
+
// ponytail: update, then insert if nothing matched. A concurrent insert in
|
|
189
|
+
// between fails on the unique constraint instead of merging; Prisma's own
|
|
190
|
+
// non-native upsert has the same gap.
|
|
191
|
+
async upsert({ where, create, update }) {
|
|
192
|
+
const query = narrowed(newQuery().update(update), where, 'upsert').maxAffected(1);
|
|
193
|
+
const [updated] = await dataOf(query.select().throwOnError()).catch(noRows);
|
|
194
|
+
return updated ?? dataOf(newQuery().insert(create).select().throwOnError().single());
|
|
195
|
+
},
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
//# sourceMappingURL=facade.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"facade.js","sourceRoot":"","sources":["../../src/database/facade.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* React Query / SWR glue: cache keys and fetchers for Motherbase queries.
|
|
3
|
+
*
|
|
4
|
+
* Every app that reaches for a data-fetching library writes the same two
|
|
5
|
+
* things, badly: a key convention, and a fetcher that remembers to throw on
|
|
6
|
+
* `{ error }` instead of caching it as data. The second one is the bug. A
|
|
7
|
+
* fetcher that returns `{ data: null, error }` resolves successfully as far as
|
|
8
|
+
* React Query is concerned, so the error is cached, `isError` stays false, and
|
|
9
|
+
* the UI renders an empty list forever.
|
|
10
|
+
*
|
|
11
|
+
* No dependency on React Query here, and none needed: the returned objects are
|
|
12
|
+
* plain `{ queryKey, queryFn }`, which is what `useQuery` takes. The same
|
|
13
|
+
* objects work with SWR by passing `queryKey` as the key and `queryFn` as the
|
|
14
|
+
* fetcher.
|
|
15
|
+
*/
|
|
16
|
+
import type { MotherbaseClient } from '../index.js';
|
|
17
|
+
import type { TypedQuery } from './types.js';
|
|
18
|
+
import type { PostgrestResponse } from '../postgrest/index.js';
|
|
19
|
+
/**
|
|
20
|
+
* The builder handed to a `build` callback: the same object `client.from()`
|
|
21
|
+
* returns, narrowed to the row type the helper was called with. Typed rather
|
|
22
|
+
* than `any`, so `.eq('athor', …)` is a compile error inside the callback and
|
|
23
|
+
* the editor completes the column names.
|
|
24
|
+
*/
|
|
25
|
+
export type QueryBuilderFor<Row extends object> = TypedQuery<Row, Partial<Row>, Partial<Row>>;
|
|
26
|
+
/**
|
|
27
|
+
* Any client, whatever `Database` it was created with.
|
|
28
|
+
*
|
|
29
|
+
* ponytail: the generic arguments are erased here because `from()`'s relation
|
|
30
|
+
* names are literal types that differ per `Database`, so no single parameter
|
|
31
|
+
* type accepts them all. The erasure stops at this boundary: everything the
|
|
32
|
+
* helpers hand back to the caller is typed through `Row`.
|
|
33
|
+
*/
|
|
34
|
+
type AnyClient = MotherbaseClient<any, any, any>;
|
|
35
|
+
/**
|
|
36
|
+
* Cache keys, hierarchical so invalidation can be coarse.
|
|
37
|
+
*
|
|
38
|
+
* `['motherbase', 'table', 'posts']` is a prefix of every key below it, so
|
|
39
|
+
* `invalidateQueries({ queryKey: keys.table('posts') })` reaches every list and
|
|
40
|
+
* every row of that table, which is what you want after a write. Anything
|
|
41
|
+
* narrower leaves a stale list on screen next to a fresh row.
|
|
42
|
+
*/
|
|
43
|
+
export declare const keys: {
|
|
44
|
+
all: readonly ["motherbase"];
|
|
45
|
+
table: (table: string) => readonly ["motherbase", "table", string];
|
|
46
|
+
list: (table: string, filters?: unknown) => readonly ["motherbase", "table", string, "list"] | readonly ["motherbase", "table", string, "list", {} | null];
|
|
47
|
+
row: (table: string, id: unknown) => readonly ["motherbase", "table", string, "row", unknown];
|
|
48
|
+
};
|
|
49
|
+
export interface QueryOptions<T> {
|
|
50
|
+
queryKey: readonly unknown[];
|
|
51
|
+
queryFn: () => Promise<T>;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* A list query.
|
|
55
|
+
*
|
|
56
|
+
* `build` receives the query builder so filters, ordering and column selection
|
|
57
|
+
* stay in the caller's hands; whatever it returns is awaited and unwrapped.
|
|
58
|
+
* Pass `filters` to make the key unique per filter set, or two different
|
|
59
|
+
* filtered lists of the same table will share one cache entry and overwrite
|
|
60
|
+
* each other.
|
|
61
|
+
*
|
|
62
|
+
* ```ts
|
|
63
|
+
* useQuery(listQuery(client, 'posts', {
|
|
64
|
+
* filters: { author },
|
|
65
|
+
* build: q => q.select('*').eq('author', author).order('created_at'),
|
|
66
|
+
* }))
|
|
67
|
+
* ```
|
|
68
|
+
*/
|
|
69
|
+
export declare function listQuery<Row extends object = Record<string, unknown>>(client: AnyClient, table: string, options?: {
|
|
70
|
+
filters?: unknown;
|
|
71
|
+
build?: (query: QueryBuilderFor<Row>) => PromiseLike<PostgrestResponse<Row[]>>;
|
|
72
|
+
}): QueryOptions<Row[]>;
|
|
73
|
+
/**
|
|
74
|
+
* One row by primary key (or by any unique column, through `column`).
|
|
75
|
+
*
|
|
76
|
+
* Resolves `null` rather than throwing when the row is not there: "not found"
|
|
77
|
+
* is an answer, and a cache library that receives it as an error retries it.
|
|
78
|
+
*/
|
|
79
|
+
export declare function rowQuery<Row extends object = Record<string, unknown>>(client: AnyClient, table: string, id: unknown, options?: {
|
|
80
|
+
column?: keyof Row & string;
|
|
81
|
+
columns?: string;
|
|
82
|
+
}): QueryOptions<Row | null>;
|
|
83
|
+
/**
|
|
84
|
+
* Every row, walked through `stream()` rather than capped at the server's
|
|
85
|
+
* `api.rest.maxRows`.
|
|
86
|
+
*
|
|
87
|
+
* Separate from `listQuery` on purpose: this issues one request per page, so it
|
|
88
|
+
* belongs to lists that are known to be small enough to hold in memory and
|
|
89
|
+
* large enough to exceed the cap. Anything unbounded wants real pagination.
|
|
90
|
+
*/
|
|
91
|
+
export declare function allRowsQuery<Row extends object = Record<string, unknown>>(client: AnyClient, table: string, options?: {
|
|
92
|
+
filters?: unknown;
|
|
93
|
+
pageSize?: number;
|
|
94
|
+
build?: (query: QueryBuilderFor<Row>) => QueryBuilderFor<Row>;
|
|
95
|
+
}): QueryOptions<Row[]>;
|
|
96
|
+
export {};
|
|
97
|
+
//# sourceMappingURL=query.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"query.d.ts","sourceRoot":"","sources":["../../src/database/query.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAE/D;;;;;GAKG;AACH,MAAM,MAAM,eAAe,CAAC,GAAG,SAAS,MAAM,IAAI,UAAU,CAAC,GAAG,EAAE,OAAO,CAAC,GAAG,CAAC,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC;AAE9F;;;;;;;GAOG;AACH,KAAK,SAAS,GAAG,gBAAgB,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;AAOjD;;;;;;;GAOG;AACH,eAAO,MAAM,IAAI;;mBAEA,MAAM;kBACP,MAAM,YAAY,OAAO;iBAI1B,MAAM,MAAM,OAAO;CACjC,CAAC;AASF,MAAM,WAAW,YAAY,CAAC,CAAC;IAC7B,QAAQ,EAAE,SAAS,OAAO,EAAE,CAAC;IAC7B,OAAO,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,CAAC;CAC3B;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,SAAS,CAAC,GAAG,SAAS,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACpE,MAAM,EAAE,SAAS,EACjB,KAAK,EAAE,MAAM,EACb,OAAO,GAAE;IACP,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,eAAe,CAAC,GAAG,CAAC,KAAK,WAAW,CAAC,iBAAiB,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;CAC3E,GACL,YAAY,CAAC,GAAG,EAAE,CAAC,CASrB;AAED;;;;;GAKG;AACH,wBAAgB,QAAQ,CAAC,GAAG,SAAS,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACnE,MAAM,EAAE,SAAS,EACjB,KAAK,EAAE,MAAM,EACb,EAAE,EAAE,OAAO,EACX,OAAO,GAAE;IAAE,MAAM,CAAC,EAAE,MAAM,GAAG,GAAG,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAO,GAC9D,YAAY,CAAC,GAAG,GAAG,IAAI,CAAC,CAc1B;AAED;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,GAAG,SAAS,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACvE,MAAM,EAAE,SAAS,EACjB,KAAK,EAAE,MAAM,EACb,OAAO,GAAE;IACP,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,eAAe,CAAC,GAAG,CAAC,KAAK,eAAe,CAAC,GAAG,CAAC,CAAC;CAC1D,GACL,YAAY,CAAC,GAAG,EAAE,CAAC,CAYrB"}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/** `from()` on an erased client, re-typed to the row the caller asked for. */
|
|
2
|
+
function queryFor(client, table) {
|
|
3
|
+
return client.from(table);
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* Cache keys, hierarchical so invalidation can be coarse.
|
|
7
|
+
*
|
|
8
|
+
* `['motherbase', 'table', 'posts']` is a prefix of every key below it, so
|
|
9
|
+
* `invalidateQueries({ queryKey: keys.table('posts') })` reaches every list and
|
|
10
|
+
* every row of that table, which is what you want after a write. Anything
|
|
11
|
+
* narrower leaves a stale list on screen next to a fresh row.
|
|
12
|
+
*/
|
|
13
|
+
export const keys = {
|
|
14
|
+
all: ['motherbase'],
|
|
15
|
+
table: (table) => ['motherbase', 'table', table],
|
|
16
|
+
list: (table, filters) => (filters === undefined
|
|
17
|
+
? ['motherbase', 'table', table, 'list']
|
|
18
|
+
: ['motherbase', 'table', table, 'list', filters]),
|
|
19
|
+
row: (table, id) => ['motherbase', 'table', table, 'row', id],
|
|
20
|
+
};
|
|
21
|
+
/** Unwrap a `{ data, error }` result the way a cache library needs: throw on error. */
|
|
22
|
+
async function unwrap(result) {
|
|
23
|
+
const { data, error } = await result;
|
|
24
|
+
if (error)
|
|
25
|
+
throw Object.assign(new Error(error.message), error);
|
|
26
|
+
return data;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* A list query.
|
|
30
|
+
*
|
|
31
|
+
* `build` receives the query builder so filters, ordering and column selection
|
|
32
|
+
* stay in the caller's hands; whatever it returns is awaited and unwrapped.
|
|
33
|
+
* Pass `filters` to make the key unique per filter set, or two different
|
|
34
|
+
* filtered lists of the same table will share one cache entry and overwrite
|
|
35
|
+
* each other.
|
|
36
|
+
*
|
|
37
|
+
* ```ts
|
|
38
|
+
* useQuery(listQuery(client, 'posts', {
|
|
39
|
+
* filters: { author },
|
|
40
|
+
* build: q => q.select('*').eq('author', author).order('created_at'),
|
|
41
|
+
* }))
|
|
42
|
+
* ```
|
|
43
|
+
*/
|
|
44
|
+
export function listQuery(client, table, options = {}) {
|
|
45
|
+
const { filters, build } = options;
|
|
46
|
+
return {
|
|
47
|
+
queryKey: keys.list(table, filters),
|
|
48
|
+
queryFn: () => {
|
|
49
|
+
const base = queryFor(client, table);
|
|
50
|
+
return unwrap(build ? build(base) : base.select('*'));
|
|
51
|
+
},
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* One row by primary key (or by any unique column, through `column`).
|
|
56
|
+
*
|
|
57
|
+
* Resolves `null` rather than throwing when the row is not there: "not found"
|
|
58
|
+
* is an answer, and a cache library that receives it as an error retries it.
|
|
59
|
+
*/
|
|
60
|
+
export function rowQuery(client, table, id, options = {}) {
|
|
61
|
+
const { column = 'id', columns = '*' } = options;
|
|
62
|
+
return {
|
|
63
|
+
queryKey: keys.row(table, id),
|
|
64
|
+
queryFn: () => unwrap(queryFor(client, table)
|
|
65
|
+
// `columns` is a runtime string, so it cannot be checked against the
|
|
66
|
+
// row the way a literal passed to `.select()` is.
|
|
67
|
+
.select(columns)
|
|
68
|
+
.eq(column, id)
|
|
69
|
+
.maybeSingle()),
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Every row, walked through `stream()` rather than capped at the server's
|
|
74
|
+
* `api.rest.maxRows`.
|
|
75
|
+
*
|
|
76
|
+
* Separate from `listQuery` on purpose: this issues one request per page, so it
|
|
77
|
+
* belongs to lists that are known to be small enough to hold in memory and
|
|
78
|
+
* large enough to exceed the cap. Anything unbounded wants real pagination.
|
|
79
|
+
*/
|
|
80
|
+
export function allRowsQuery(client, table, options = {}) {
|
|
81
|
+
const { filters, pageSize, build } = options;
|
|
82
|
+
return {
|
|
83
|
+
queryKey: [...keys.list(table, filters), 'all'],
|
|
84
|
+
queryFn: async () => {
|
|
85
|
+
const base = queryFor(client, table);
|
|
86
|
+
const query = build ? build(base) : base.select('*');
|
|
87
|
+
const rows = [];
|
|
88
|
+
for await (const row of query.stream({ pageSize }))
|
|
89
|
+
rows.push(row);
|
|
90
|
+
return rows;
|
|
91
|
+
},
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
//# sourceMappingURL=query.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"query.js","sourceRoot":"","sources":["../../src/database/query.ts"],"names":[],"mappings":"AAqCA,8EAA8E;AAC9E,SAAS,QAAQ,CAAqB,MAAiB,EAAE,KAAa;IACpE,OAAO,MAAM,CAAC,IAAI,CAAM,KAAc,CAAyB,CAAC;AAClE,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,IAAI,GAAG;IAClB,GAAG,EAAE,CAAC,YAAY,CAAU;IAC5B,KAAK,EAAE,CAAC,KAAa,EAAE,EAAE,CAAC,CAAC,YAAY,EAAE,OAAO,EAAE,KAAK,CAAU;IACjE,IAAI,EAAE,CAAC,KAAa,EAAE,OAAiB,EAAE,EAAE,CAC3C,CAAC,OAAO,KAAK,SAAS;QACpB,CAAC,CAAE,CAAC,YAAY,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,CAAW;QACnD,CAAC,CAAE,CAAC,YAAY,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,CAAW,CAAC;IAC/D,GAAG,EAAE,CAAC,KAAa,EAAE,EAAW,EAAE,EAAE,CAAC,CAAC,YAAY,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,CAAU;CACxF,CAAC;AAEF,uFAAuF;AACvF,KAAK,UAAU,MAAM,CAAI,MAAyC;IAChE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,MAAM,MAAM,CAAC;IACrC,IAAI,KAAK;QAAE,MAAM,MAAM,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,KAAK,CAAC,CAAC;IAChE,OAAO,IAAS,CAAC;AACnB,CAAC;AAOD;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,SAAS,CACvB,MAAiB,EACjB,KAAa,EACb,UAGI,EAAE;IAEN,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,GAAG,OAAO,CAAC;IACnC,OAAO;QACL,QAAQ,EAAE,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,OAAO,CAAC;QACnC,OAAO,EAAE,GAAG,EAAE;YACZ,MAAM,IAAI,GAAG,QAAQ,CAAM,MAAM,EAAE,KAAK,CAAC,CAAC;YAC1C,OAAO,MAAM,CAAQ,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAE,IAAI,CAAC,MAAM,CAAC,GAAG,CAA2C,CAAC,CAAC;QAC1G,CAAC;KACF,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,QAAQ,CACtB,MAAiB,EACjB,KAAa,EACb,EAAW,EACX,UAA6D,EAAE;IAE/D,MAAM,EAAE,MAAM,GAAG,IAA0B,EAAE,OAAO,GAAG,GAAG,EAAE,GAAG,OAAO,CAAC;IACvE,OAAO;QACL,QAAQ,EAAE,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,EAAE,CAAC;QAC7B,OAAO,EAAE,GAAG,EAAE,CACZ,MAAM,CACJ,QAAQ,CAAM,MAAM,EAAE,KAAK,CAAC;YAC1B,qEAAqE;YACrE,kDAAkD;aACjD,MAAM,CAAC,OAAc,CAAC;aACtB,EAAE,CAAC,MAAM,EAAE,EAAW,CAAC;aACvB,WAAW,EAAgD,CAC/D;KACJ,CAAC;AACJ,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,YAAY,CAC1B,MAAiB,EACjB,KAAa,EACb,UAII,EAAE;IAEN,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,GAAG,OAAO,CAAC;IAC7C,OAAO;QACL,QAAQ,EAAE,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,OAAO,CAAC,EAAE,KAAK,CAAC;QAC/C,OAAO,EAAE,KAAK,IAAI,EAAE;YAClB,MAAM,IAAI,GAAG,QAAQ,CAAM,MAAM,EAAE,KAAK,CAAC,CAAC;YAC1C,MAAM,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAE,IAAI,CAAC,MAAM,CAAC,GAAG,CAA0B,CAAC;YAC/E,MAAM,IAAI,GAAU,EAAE,CAAC;YACvB,IAAI,KAAK,EAAE,MAAM,GAAG,IAAI,KAAK,CAAC,MAAM,CAAC,EAAE,QAAQ,EAAE,CAAC;gBAAE,IAAI,CAAC,IAAI,CAAC,GAAU,CAAC,CAAC;YAC1E,OAAO,IAAI,CAAC;QACd,CAAC;KACF,CAAC;AACJ,CAAC"}
|