@burojs/pocketbase 0.2.0 → 0.5.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/dist/index.js CHANGED
@@ -1,297 +1,355 @@
1
- import { defineDataProvider } from '@burojs/core';
2
-
3
- // src/data-provider.ts
1
+ import { defineDataProvider } from "@burojs/core";
2
+ //#region src/data-provider.ts
4
3
  function lit(value) {
5
- return `"${String(value).replace(/\\/g, "\\\\").replace(/"/g, '\\"')}"`;
4
+ return `"${String(value).replace(/\\/g, "\\\\").replace(/"/g, "\\\"")}"`;
6
5
  }
7
- var FILTER_OPERATOR_UNSUPPORTED_CODE = "filter-operator-unsupported";
6
+ const FILTER_OPERATOR_UNSUPPORTED_CODE = "filter-operator-unsupported";
8
7
  function unsupportedOperator(field, op) {
9
- return {
10
- kind: "capability",
11
- code: FILTER_OPERATOR_UNSUPPORTED_CODE,
12
- message: `@burojs/pocketbase does not support the filter operator '${op}' (on '${field}').`
13
- };
8
+ return {
9
+ kind: "capability",
10
+ code: FILTER_OPERATOR_UNSUPPORTED_CODE,
11
+ message: `@burojs/pocketbase does not support the filter operator '${op}' (on '${field}').`
12
+ };
14
13
  }
15
- var DROP = { kind: "drop" };
16
- var constant = (value) => ({ kind: "const", value });
17
- var MATCHES_NO_RECORD = '(id="" && id!="")';
14
+ const DROP = { kind: "drop" };
15
+ const constant = (value) => ({
16
+ kind: "const",
17
+ value
18
+ });
19
+ const MATCHES_NO_RECORD = "(id=\"\" && id!=\"\")";
18
20
  function combine(branches, op) {
19
- if (branches.length === 0) return constant(op === "and");
20
- const absorbing = op === "or";
21
- const nodes = branches.map(translateFilter);
22
- if (nodes.some((node) => node.kind === "const" && node.value === absorbing)) {
23
- return constant(absorbing);
24
- }
25
- const parts = nodes.flatMap((node) => node.kind === "expr" ? [node.text] : []);
26
- if (parts.length > 0)
27
- return { kind: "expr", text: `(${parts.join(op === "and" ? " && " : " || ")})` };
28
- return nodes.some((node) => node.kind === "const") ? constant(!absorbing) : DROP;
21
+ if (branches.length === 0) return constant(op === "and");
22
+ const absorbing = op === "or";
23
+ const nodes = branches.map(translateFilter);
24
+ if (nodes.some((node) => node.kind === "const" && node.value === absorbing)) return constant(absorbing);
25
+ const parts = nodes.flatMap((node) => node.kind === "expr" ? [node.text] : []);
26
+ if (parts.length > 0) return {
27
+ kind: "expr",
28
+ text: `(${parts.join(op === "and" ? " && " : " || ")})`
29
+ };
30
+ return nodes.some((node) => node.kind === "const") ? constant(!absorbing) : DROP;
29
31
  }
30
32
  function translateFilter(filter) {
31
- if (filter === null || typeof filter !== "object") return DROP;
32
- const candidate = filter;
33
- if (Array.isArray(candidate.and)) return combine(candidate.and, "and");
34
- if (Array.isArray(candidate.or)) return combine(candidate.or, "or");
35
- if ("not" in candidate) {
36
- const inner = translateFilter(candidate.not);
37
- if (inner.kind === "drop") return DROP;
38
- if (inner.kind === "const") return constant(!inner.value);
39
- return { kind: "expr", text: `!(${inner.text})` };
40
- }
41
- if (typeof candidate.field !== "string" || typeof candidate.op !== "string") return DROP;
42
- const { field, op, value } = candidate;
43
- if (op === "isNull") return { kind: "expr", text: `${field}=null` };
44
- if (op === "isNotNull") return { kind: "expr", text: `${field}!=null` };
45
- if (!("value" in candidate) || value === void 0) return DROP;
46
- const chain = (join, term, empty) => {
47
- if (!Array.isArray(value)) return DROP;
48
- if (value.length === 0) return constant(empty);
49
- return { kind: "expr", text: `(${value.map(term).join(join)})` };
50
- };
51
- switch (op) {
52
- case "eq":
53
- return { kind: "expr", text: `${field}=${lit(value)}` };
54
- case "neq":
55
- return { kind: "expr", text: `${field}!=${lit(value)}` };
56
- case "contains":
57
- return { kind: "expr", text: `${field}~${lit(value)}` };
58
- case "startsWith":
59
- return { kind: "expr", text: `${field}~${lit(`${String(value)}%`)}` };
60
- case "endsWith":
61
- return { kind: "expr", text: `${field}~${lit(`%${String(value)}`)}` };
62
- case "gt":
63
- return { kind: "expr", text: `${field}>${lit(value)}` };
64
- case "gte":
65
- return { kind: "expr", text: `${field}>=${lit(value)}` };
66
- case "lt":
67
- return { kind: "expr", text: `${field}<${lit(value)}` };
68
- case "lte":
69
- return { kind: "expr", text: `${field}<=${lit(value)}` };
70
- case "in":
71
- return chain(" || ", (entry) => `${field}=${lit(entry)}`, false);
72
- case "notIn":
73
- return chain(" && ", (entry) => `${field}!=${lit(entry)}`, true);
74
- case "has":
75
- return { kind: "expr", text: `${field}~${lit(value)}` };
76
- case "hasAny":
77
- return chain(" || ", (entry) => `${field}~${lit(entry)}`, false);
78
- case "hasAll":
79
- return chain(" && ", (entry) => `${field}~${lit(entry)}`, true);
80
- // An operator this provider cannot express fails LOUDLY, and with the same
81
- // `kind` and `code` `@burojs/hasura` uses. It used to return DROP, i.e. "no
82
- // constraint" — so an unknown operator quietly matched every record here
83
- // while the sibling quietly turned it into `_eq`. Two silent, DIFFERENT
84
- // wrong answers for one input is the same defect class as the branchless
85
- // combinators, one hop out.
86
- default:
87
- throw unsupportedOperator(field, op);
88
- }
33
+ if (filter === null || typeof filter !== "object") return DROP;
34
+ const candidate = filter;
35
+ if (Array.isArray(candidate.and)) return combine(candidate.and, "and");
36
+ if (Array.isArray(candidate.or)) return combine(candidate.or, "or");
37
+ if ("not" in candidate) {
38
+ const inner = translateFilter(candidate.not);
39
+ if (inner.kind === "drop") return DROP;
40
+ if (inner.kind === "const") return constant(!inner.value);
41
+ return {
42
+ kind: "expr",
43
+ text: `!(${inner.text})`
44
+ };
45
+ }
46
+ if (typeof candidate.field !== "string" || typeof candidate.op !== "string") return DROP;
47
+ const { field, op, value } = candidate;
48
+ if (field.includes(".")) throw {
49
+ kind: "capability",
50
+ code: FILTER_OPERATOR_UNSUPPORTED_CODE,
51
+ message: `@burojs/pocketbase cannot express a filter across a relation ('${field}'): PocketBase's traversal syntax depends on the relation's kind and direction, which nothing on the descriptor declares. Filter on a field of this collection.`
52
+ };
53
+ if (op === "isNull") return {
54
+ kind: "expr",
55
+ text: `${field}=null`
56
+ };
57
+ if (op === "isNotNull") return {
58
+ kind: "expr",
59
+ text: `${field}!=null`
60
+ };
61
+ if (!("value" in candidate) || value === void 0) return DROP;
62
+ const chain = (join, term, empty) => {
63
+ if (!Array.isArray(value)) return DROP;
64
+ if (value.length === 0) return constant(empty);
65
+ return {
66
+ kind: "expr",
67
+ text: `(${value.map(term).join(join)})`
68
+ };
69
+ };
70
+ switch (op) {
71
+ case "eq": return {
72
+ kind: "expr",
73
+ text: `${field}=${lit(value)}`
74
+ };
75
+ case "neq": return {
76
+ kind: "expr",
77
+ text: `${field}!=${lit(value)}`
78
+ };
79
+ case "contains": return {
80
+ kind: "expr",
81
+ text: `${field}~${lit(value)}`
82
+ };
83
+ case "startsWith": return {
84
+ kind: "expr",
85
+ text: `${field}~${lit(`${String(value)}%`)}`
86
+ };
87
+ case "endsWith": return {
88
+ kind: "expr",
89
+ text: `${field}~${lit(`%${String(value)}`)}`
90
+ };
91
+ case "gt": return {
92
+ kind: "expr",
93
+ text: `${field}>${lit(value)}`
94
+ };
95
+ case "gte": return {
96
+ kind: "expr",
97
+ text: `${field}>=${lit(value)}`
98
+ };
99
+ case "lt": return {
100
+ kind: "expr",
101
+ text: `${field}<${lit(value)}`
102
+ };
103
+ case "lte": return {
104
+ kind: "expr",
105
+ text: `${field}<=${lit(value)}`
106
+ };
107
+ case "in": return chain(" || ", (entry) => `${field}=${lit(entry)}`, false);
108
+ case "notIn": return chain(" && ", (entry) => `${field}!=${lit(entry)}`, true);
109
+ case "has": return {
110
+ kind: "expr",
111
+ text: `${field}~${lit(value)}`
112
+ };
113
+ case "hasAny": return chain(" || ", (entry) => `${field}~${lit(entry)}`, false);
114
+ case "hasAll": return chain(" && ", (entry) => `${field}~${lit(entry)}`, true);
115
+ default: throw unsupportedOperator(field, op);
116
+ }
89
117
  }
90
118
  function filterExpression(filter) {
91
- const node = translateFilter(filter);
92
- if (node.kind === "expr") return node.text;
93
- if (node.kind === "const") return node.value ? void 0 : MATCHES_NO_RECORD;
94
- return void 0;
119
+ const node = translateFilter(filter);
120
+ if (node.kind === "expr") return node.text;
121
+ if (node.kind === "const") return node.value ? void 0 : MATCHES_NO_RECORD;
95
122
  }
96
123
  function recordResult(record, idField) {
97
- if (record === null || typeof record !== "object") {
98
- throw {
99
- kind: "protocol",
100
- code: "invalid-record",
101
- message: "PocketBase returned a non-object record."
102
- };
103
- }
104
- const id = record[idField];
105
- if (typeof id !== "string" && (typeof id !== "number" || !Number.isFinite(id))) {
106
- throw {
107
- kind: "protocol",
108
- code: "invalid-record-id",
109
- message: `PocketBase record is missing a valid ${idField} field.`
110
- };
111
- }
112
- return { kind: "record", id, record, completeness: "full" };
124
+ if (record === null || typeof record !== "object") throw {
125
+ kind: "protocol",
126
+ code: "invalid-record",
127
+ message: "PocketBase returned a non-object record."
128
+ };
129
+ const id = record[idField];
130
+ if (typeof id !== "string" && (typeof id !== "number" || !Number.isFinite(id))) throw {
131
+ kind: "protocol",
132
+ code: "invalid-record-id",
133
+ message: `PocketBase record is missing a valid ${idField} field.`
134
+ };
135
+ return {
136
+ kind: "record",
137
+ id,
138
+ record,
139
+ completeness: "full"
140
+ };
141
+ }
142
+ function statusKind(status, write) {
143
+ if (status === 400) return write ? "validation" : "protocol";
144
+ if (status === 401) return "auth";
145
+ if (status === 403) return "forbidden";
146
+ if (status === 404) return "not-found";
147
+ if (status === 409) return "conflict";
148
+ if (status >= 500) return write ? "sent" : "transport";
149
+ return "transport";
113
150
  }
114
151
  function createPocketbaseDataProvider(opts) {
115
- const base = opts.baseUrl.replace(/\/+$/, "");
116
- const records = (resource) => `${base}/api/collections/${resource}/records`;
117
- async function call(url, init = {}, signal) {
118
- try {
119
- const token = opts.getToken();
120
- const headers = new Headers(init.headers);
121
- if (token) headers.set("authorization", token);
122
- if (init.body && !(init.body instanceof FormData))
123
- headers.set("content-type", "application/json");
124
- const response = await (opts.fetchImpl ?? fetch)(url, { ...init, headers, signal });
125
- const text = await response.text();
126
- let json = {};
127
- if (text) {
128
- try {
129
- json = JSON.parse(text);
130
- } catch {
131
- throw {
132
- kind: "protocol",
133
- code: "invalid-json",
134
- message: "PocketBase returned invalid JSON.",
135
- status: response.status
136
- };
137
- }
138
- }
139
- if (!response.ok) {
140
- throw {
141
- kind: "transport",
142
- code: "pocketbase-request-failed",
143
- message: typeof json.message === "string" ? json.message : `PocketBase error ${response.status}`,
144
- status: response.status,
145
- details: json
146
- };
147
- }
148
- return json;
149
- } catch (error) {
150
- if (error !== null && typeof error === "object" && "kind" in error) throw error;
151
- throw {
152
- kind: signal?.aborted ? "cancelled" : "transport",
153
- code: signal?.aborted ? "request-aborted" : "pocketbase-request-failed",
154
- message: error instanceof Error ? error.message : "PocketBase request failed.",
155
- cause: error
156
- };
157
- }
158
- }
159
- const body = (input) => input instanceof FormData ? input : JSON.stringify(input);
160
- return defineDataProvider({
161
- queries: {
162
- async list(descriptor, context) {
163
- const params = new URLSearchParams();
164
- if (descriptor.pagination?.kind === "offset") {
165
- params.set("page", String(descriptor.pagination.page));
166
- params.set("perPage", String(descriptor.pagination.pageSize));
167
- } else if (descriptor.pagination?.kind === "cursor") {
168
- throw {
169
- kind: "capability",
170
- code: "cursor-pagination-unsupported",
171
- message: "PocketBase provider supports offset pagination only."
172
- };
173
- }
174
- const filter = filterExpression(descriptor.filter);
175
- if (filter) params.set("filter", filter);
176
- if (descriptor.sort?.length) {
177
- params.set(
178
- "sort",
179
- descriptor.sort.map(({ field, direction }) => `${direction === "desc" ? "-" : "+"}${field}`).join(",")
180
- );
181
- }
182
- const json = await call(
183
- `${records(descriptor.resource)}?${params}`,
184
- {},
185
- context.signal
186
- );
187
- return {
188
- data: json.items ?? [],
189
- ...typeof json.totalItems === "number" ? { total: json.totalItems } : {}
190
- };
191
- },
192
- async one(descriptor, context) {
193
- return {
194
- data: await call(
195
- `${records(descriptor.resource)}/${encodeURIComponent(String(descriptor.id))}`,
196
- {},
197
- context.signal
198
- )
199
- };
200
- },
201
- async many(descriptor, context) {
202
- if (descriptor.ids.length === 0) return { data: [] };
203
- const filter = descriptor.ids.map((id) => `id=${lit(id)}`).join(" || ");
204
- const json = await call(
205
- `${records(descriptor.resource)}?filter=${encodeURIComponent(filter)}&perPage=${descriptor.ids.length}`,
206
- {},
207
- context.signal
208
- );
209
- return { data: json.items ?? [] };
210
- }
211
- },
212
- mutations: {
213
- async createOne(descriptor, context) {
214
- const record = await call(
215
- records(descriptor.resource),
216
- { method: "POST", body: body(descriptor.input) },
217
- context.signal
218
- );
219
- return recordResult(record, descriptor.idField);
220
- },
221
- async updateOne(descriptor, context) {
222
- const record = await call(
223
- `${records(descriptor.resource)}/${encodeURIComponent(String(descriptor.id))}`,
224
- { method: "PATCH", body: body(descriptor.input) },
225
- context.signal
226
- );
227
- return recordResult(record, descriptor.idField);
228
- },
229
- async deleteOne(descriptor, context) {
230
- await call(
231
- `${records(descriptor.resource)}/${encodeURIComponent(String(descriptor.id))}`,
232
- { method: "DELETE" },
233
- context.signal
234
- );
235
- return { kind: "identity", id: descriptor.id };
236
- }
237
- }
238
- });
152
+ const base = opts.baseUrl.replace(/\/+$/, "");
153
+ const records = (resource) => `${base}/api/collections/${resource}/records`;
154
+ async function call(url, init = {}, signal) {
155
+ const method = (init.method ?? "GET").toUpperCase();
156
+ let handedOver = false;
157
+ let answered = false;
158
+ try {
159
+ const token = opts.getToken();
160
+ const headers = new Headers(init.headers);
161
+ if (token) headers.set("authorization", token);
162
+ if (init.body && !(init.body instanceof FormData)) headers.set("content-type", "application/json");
163
+ handedOver = true;
164
+ const response = await (opts.fetchImpl ?? fetch)(url, {
165
+ ...init,
166
+ headers,
167
+ signal
168
+ });
169
+ answered = true;
170
+ const write = method !== "GET";
171
+ if (!response.ok) {
172
+ const kind = statusKind(response.status, write);
173
+ let json = {};
174
+ try {
175
+ const parsed = JSON.parse(await response.text());
176
+ if (parsed !== null && typeof parsed === "object") json = parsed;
177
+ } catch {}
178
+ throw {
179
+ kind,
180
+ code: kind === "sent" ? "pocketbase-answer-lost" : "pocketbase-request-failed",
181
+ message: typeof json.message === "string" ? json.message : `PocketBase error ${response.status}`,
182
+ status: response.status,
183
+ ...kind === "sent" ? { retryable: false } : {},
184
+ details: json
185
+ };
186
+ }
187
+ const unreadable = (cause) => write ? {
188
+ kind: "sent",
189
+ code: "pocketbase-answer-unreadable",
190
+ message: "PocketBase answered a write with a body that could not be read; it may have been applied.",
191
+ status: response.status,
192
+ retryable: false,
193
+ cause
194
+ } : {
195
+ kind: "protocol",
196
+ code: "invalid-json",
197
+ message: "PocketBase returned invalid JSON.",
198
+ status: response.status,
199
+ cause
200
+ };
201
+ let text;
202
+ try {
203
+ text = await response.text();
204
+ } catch (cause) {
205
+ if (signal?.aborted) throw cause;
206
+ throw unreadable(cause);
207
+ }
208
+ if (!text && write && method !== "DELETE") throw unreadable(void 0);
209
+ let json = {};
210
+ if (text) try {
211
+ json = JSON.parse(text);
212
+ } catch (cause) {
213
+ throw unreadable(cause);
214
+ }
215
+ return json;
216
+ } catch (error) {
217
+ if (error !== null && typeof error === "object" && "kind" in error) throw error;
218
+ if (handedOver && !answered && method !== "GET" && !signal?.aborted) throw {
219
+ kind: "sent",
220
+ code: "pocketbase-request-sent",
221
+ message: "PocketBase did not answer a write request; it may have been applied.",
222
+ retryable: false,
223
+ cause: error
224
+ };
225
+ throw {
226
+ kind: signal?.aborted ? "cancelled" : "transport",
227
+ code: signal?.aborted ? "request-aborted" : "pocketbase-request-failed",
228
+ message: error instanceof Error ? error.message : "PocketBase request failed.",
229
+ cause: error
230
+ };
231
+ }
232
+ }
233
+ const body = (input) => input instanceof FormData ? input : JSON.stringify(input);
234
+ return defineDataProvider({
235
+ queries: {
236
+ async list(descriptor, context) {
237
+ const params = new URLSearchParams();
238
+ if (descriptor.pagination?.kind === "offset") {
239
+ params.set("page", String(descriptor.pagination.page));
240
+ params.set("perPage", String(descriptor.pagination.pageSize));
241
+ } else if (descriptor.pagination?.kind === "cursor") throw {
242
+ kind: "capability",
243
+ code: "cursor-pagination-unsupported",
244
+ message: "PocketBase provider supports offset pagination only."
245
+ };
246
+ const filter = filterExpression(descriptor.filter);
247
+ if (filter) params.set("filter", filter);
248
+ if (descriptor.sort?.length) params.set("sort", descriptor.sort.map(({ field, direction }) => `${direction === "desc" ? "-" : "+"}${field}`).join(","));
249
+ const json = await call(`${records(descriptor.resource)}?${params}`, {}, context.signal);
250
+ return {
251
+ data: json.items ?? [],
252
+ ...typeof json.totalItems === "number" ? { total: json.totalItems } : {}
253
+ };
254
+ },
255
+ async one(descriptor, context) {
256
+ return { data: await call(`${records(descriptor.resource)}/${encodeURIComponent(String(descriptor.id))}`, {}, context.signal) };
257
+ },
258
+ async many(descriptor, context) {
259
+ if (descriptor.ids.length === 0) return { data: [] };
260
+ const filter = descriptor.ids.map((id) => `id=${lit(id)}`).join(" || ");
261
+ return { data: (await call(`${records(descriptor.resource)}?filter=${encodeURIComponent(filter)}&perPage=${descriptor.ids.length}`, {}, context.signal)).items ?? [] };
262
+ }
263
+ },
264
+ mutations: {
265
+ async createOne(descriptor, context) {
266
+ return recordResult(await call(records(descriptor.resource), {
267
+ method: "POST",
268
+ body: body(descriptor.input)
269
+ }, context.signal), descriptor.idField);
270
+ },
271
+ async updateOne(descriptor, context) {
272
+ return recordResult(await call(`${records(descriptor.resource)}/${encodeURIComponent(String(descriptor.id))}`, {
273
+ method: "PATCH",
274
+ body: body(descriptor.input)
275
+ }, context.signal), descriptor.idField);
276
+ },
277
+ async deleteOne(descriptor, context) {
278
+ await call(`${records(descriptor.resource)}/${encodeURIComponent(String(descriptor.id))}`, { method: "DELETE" }, context.signal);
279
+ return {
280
+ kind: "identity",
281
+ id: descriptor.id
282
+ };
283
+ }
284
+ }
285
+ });
239
286
  }
240
-
241
- // src/auth-provider.ts
287
+ //#endregion
288
+ //#region src/auth-provider.ts
242
289
  function createPocketbaseAuthProvider(opts) {
243
- const base = opts.baseUrl.replace(/\/+$/, "");
244
- const key = opts.storageKey ?? "buro-example-vite-auth";
245
- const read = () => {
246
- try {
247
- const raw = localStorage.getItem(key);
248
- if (!raw) return null;
249
- const parsed = JSON.parse(raw);
250
- if (!parsed || typeof parsed.token !== "string" || typeof parsed.record?.id !== "string") {
251
- return null;
252
- }
253
- return parsed;
254
- } catch {
255
- return null;
256
- }
257
- };
258
- return {
259
- getToken: () => read()?.token ?? null,
260
- async login(params) {
261
- const { email, password } = params;
262
- const fetchImpl = opts.fetchImpl ?? fetch;
263
- const res = await fetchImpl(`${base}/api/collections/users/auth-with-password`, {
264
- method: "POST",
265
- headers: { "content-type": "application/json" },
266
- body: JSON.stringify({ identity: email, password })
267
- });
268
- if (!res.ok) {
269
- return {
270
- success: false,
271
- error: { kind: "auth", code: "invalid-credentials", message: "Invalid credentials" }
272
- };
273
- }
274
- localStorage.setItem(key, JSON.stringify(await res.json()));
275
- return { success: true };
276
- },
277
- async logout() {
278
- localStorage.removeItem(key);
279
- return { success: true };
280
- },
281
- async check() {
282
- return read() ? { authenticated: true } : { authenticated: false, reason: "signed-out" };
283
- },
284
- async onError(error) {
285
- return { action: "propagate", error };
286
- },
287
- async getIdentity() {
288
- const session = read();
289
- if (!session) return null;
290
- return { id: session.record.id, name: session.record.name ?? session.record.email };
291
- }
292
- };
290
+ const base = opts.baseUrl.replace(/\/+$/, "");
291
+ const key = opts.storageKey ?? "buro-example-vite-auth";
292
+ const read = () => {
293
+ try {
294
+ const raw = localStorage.getItem(key);
295
+ if (!raw) return null;
296
+ const parsed = JSON.parse(raw);
297
+ if (!parsed || typeof parsed.token !== "string" || typeof parsed.record?.id !== "string") return null;
298
+ return parsed;
299
+ } catch {
300
+ return null;
301
+ }
302
+ };
303
+ return {
304
+ getToken: () => read()?.token ?? null,
305
+ async login(params) {
306
+ const { email, password } = params;
307
+ const res = await (opts.fetchImpl ?? fetch)(`${base}/api/collections/users/auth-with-password`, {
308
+ method: "POST",
309
+ headers: { "content-type": "application/json" },
310
+ body: JSON.stringify({
311
+ identity: email,
312
+ password
313
+ })
314
+ });
315
+ if (!res.ok) return {
316
+ success: false,
317
+ error: {
318
+ kind: "auth",
319
+ code: "invalid-credentials",
320
+ message: "Invalid credentials"
321
+ }
322
+ };
323
+ localStorage.setItem(key, JSON.stringify(await res.json()));
324
+ return { success: true };
325
+ },
326
+ async logout() {
327
+ localStorage.removeItem(key);
328
+ return { success: true };
329
+ },
330
+ async check() {
331
+ return read() ? { authenticated: true } : {
332
+ authenticated: false,
333
+ reason: "signed-out"
334
+ };
335
+ },
336
+ async onError(error) {
337
+ return {
338
+ action: "propagate",
339
+ error
340
+ };
341
+ },
342
+ async getIdentity() {
343
+ const session = read();
344
+ if (!session) return null;
345
+ return {
346
+ id: session.record.id,
347
+ name: session.record.name ?? session.record.email
348
+ };
349
+ }
350
+ };
293
351
  }
294
-
352
+ //#endregion
295
353
  export { FILTER_OPERATOR_UNSUPPORTED_CODE, createPocketbaseAuthProvider, createPocketbaseDataProvider, filterExpression };
296
- //# sourceMappingURL=index.js.map
354
+
297
355
  //# sourceMappingURL=index.js.map