lazypock 0.1.3 → 0.1.6
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/README.md +96 -38
- package/dist/{chunk-3MZJ5HCD.js → chunk-Y6PMBL2S.js} +7 -5
- package/dist/{chunk-3MZJ5HCD.js.map → chunk-Y6PMBL2S.js.map} +1 -1
- package/dist/cli.cjs +6 -4
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.global.js +6 -4
- package/dist/cli.global.js.map +1 -1
- package/dist/cli.js +1 -1
- package/dist/index.cjs +344 -138
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +212 -84
- package/dist/index.d.ts +212 -84
- package/dist/index.global.js +340 -138
- package/dist/index.global.js.map +1 -1
- package/dist/index.js +335 -135
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/codegen.ts +6 -4
- package/src/collection.ts +69 -10
- package/src/collections.ts +200 -0
- package/src/files.ts +75 -0
- package/src/http.ts +120 -8
- package/src/index.ts +5 -0
- package/src/lazypock.ts +50 -171
- package/src/types.ts +30 -1
package/dist/index.cjs
CHANGED
|
@@ -23,7 +23,9 @@ __export(index_exports, {
|
|
|
23
23
|
ApiError: () => ApiError,
|
|
24
24
|
AuthStore: () => AuthStore,
|
|
25
25
|
CollectionService: () => CollectionService,
|
|
26
|
+
CollectionsService: () => CollectionsService,
|
|
26
27
|
FilesService: () => FilesService,
|
|
28
|
+
HttpClient: () => HttpClient,
|
|
27
29
|
LazypockClient: () => LazypockClient,
|
|
28
30
|
RealtimeService: () => RealtimeService,
|
|
29
31
|
TypedClient: () => TypedClient,
|
|
@@ -33,6 +35,8 @@ __export(index_exports, {
|
|
|
33
35
|
fieldTypeScriptType: () => fieldTypeScriptType,
|
|
34
36
|
generateTypes: () => generateTypes,
|
|
35
37
|
getFileUrl: () => getFileUrl,
|
|
38
|
+
getScaleUrl: () => getScaleUrl,
|
|
39
|
+
getThumbUrl: () => getThumbUrl,
|
|
36
40
|
schemaFieldType: () => schemaFieldType,
|
|
37
41
|
wsUrlFromBaseUrl: () => wsUrlFromBaseUrl
|
|
38
42
|
});
|
|
@@ -40,21 +44,33 @@ module.exports = __toCommonJS(index_exports);
|
|
|
40
44
|
|
|
41
45
|
// src/types.ts
|
|
42
46
|
var ApiError = class extends Error {
|
|
43
|
-
constructor(message, data, status) {
|
|
47
|
+
constructor(message, data, status, isAbort = false) {
|
|
44
48
|
super(message);
|
|
45
49
|
this.name = "ApiError";
|
|
46
50
|
this.data = data;
|
|
47
51
|
this.status = status;
|
|
52
|
+
this.isAbort = isAbort;
|
|
48
53
|
}
|
|
49
54
|
};
|
|
50
55
|
|
|
51
56
|
// src/http.ts
|
|
57
|
+
function isAbortError(err) {
|
|
58
|
+
return err instanceof Error && (err.name === "AbortError" || err.message === "Aborted");
|
|
59
|
+
}
|
|
52
60
|
var HttpClient = class {
|
|
53
61
|
/**
|
|
54
62
|
* @param baseUrl The API base URL (e.g. `http://localhost:4000/api`). Trailing slash stripped.
|
|
55
63
|
* @param authStore The auth store providing the token for Authorization headers.
|
|
56
64
|
*/
|
|
57
65
|
constructor(baseUrl, authStore) {
|
|
66
|
+
/**
|
|
67
|
+
* Abort controllers for in-flight requests, keyed by their cancellation key
|
|
68
|
+
* (default `METHOD path`). A new request with the same key aborts the
|
|
69
|
+
* previous one — PocketBase-style auto-cancellation of duplicated requests.
|
|
70
|
+
*/
|
|
71
|
+
this.cancelControllers = {};
|
|
72
|
+
/** Global toggle for the auto-cancellation behaviour (default: on). */
|
|
73
|
+
this.enableAutoCancellation = true;
|
|
58
74
|
this.baseUrl = baseUrl.replace(/\/+$/, "");
|
|
59
75
|
this.authStore = authStore;
|
|
60
76
|
this.defaultFetch = globalThis.fetch.bind(globalThis);
|
|
@@ -91,20 +107,73 @@ var HttpClient = class {
|
|
|
91
107
|
return null;
|
|
92
108
|
}
|
|
93
109
|
}
|
|
110
|
+
/**
|
|
111
|
+
* Globally enable or disable auto-cancellation of duplicated pending requests.
|
|
112
|
+
* Fluent — returns `this` for chaining.
|
|
113
|
+
*/
|
|
114
|
+
autoCancellation(enable) {
|
|
115
|
+
this.enableAutoCancellation = !!enable;
|
|
116
|
+
return this;
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Abort a pending request identified by its cancellation key
|
|
120
|
+
* (default `METHOD path`, e.g. `"GET /api/posts"`). No-op if not pending.
|
|
121
|
+
*/
|
|
122
|
+
cancelRequest(requestKey) {
|
|
123
|
+
const controller = this.cancelControllers[requestKey];
|
|
124
|
+
if (controller) {
|
|
125
|
+
controller.abort();
|
|
126
|
+
delete this.cancelControllers[requestKey];
|
|
127
|
+
}
|
|
128
|
+
return this;
|
|
129
|
+
}
|
|
130
|
+
/** Abort all pending requests. */
|
|
131
|
+
cancelAllRequests() {
|
|
132
|
+
for (const key in this.cancelControllers) {
|
|
133
|
+
this.cancelControllers[key].abort();
|
|
134
|
+
}
|
|
135
|
+
this.cancelControllers = {};
|
|
136
|
+
return this;
|
|
137
|
+
}
|
|
94
138
|
/**
|
|
95
139
|
* Make an HTTP request with automatic auth token injection and optional auto-refresh.
|
|
96
140
|
*
|
|
141
|
+
* Auto-cancellation: a request keyed by `options.requestKey` (default
|
|
142
|
+
* `METHOD path`) aborts any previous pending request with the same key,
|
|
143
|
+
* so only the last duplicate executes. Set `requestKey: null` or
|
|
144
|
+
* `autoCancel: false` to opt out per request.
|
|
145
|
+
*
|
|
97
146
|
* @param method HTTP method.
|
|
98
147
|
* @param path URL path (appended to baseUrl).
|
|
99
148
|
* @param body JSON-serializable body, or FormData for file uploads.
|
|
100
149
|
* @param options Optional request options.
|
|
101
150
|
* @returns Parsed JSON response, or null for 204 No Content.
|
|
102
|
-
* @throws {ApiError} On non-2xx responses
|
|
151
|
+
* @throws {ApiError} On non-2xx responses or when the request is aborted
|
|
152
|
+
* (aborted requests throw an `ApiError` with `isAbort === true`).
|
|
103
153
|
*/
|
|
104
154
|
async request(method, path, body, options) {
|
|
105
155
|
if (this.authStore.isExpired && this.authStore.collectionName) {
|
|
106
156
|
await this.refreshAuth();
|
|
107
157
|
}
|
|
158
|
+
let requestKey = options?.requestKey === void 0 ? options?.cancelKey ?? `${method} ${path}` : options.requestKey;
|
|
159
|
+
if (options?.autoCancel === false) requestKey = null;
|
|
160
|
+
let controller = null;
|
|
161
|
+
const externalSignal = options?.signal;
|
|
162
|
+
if (requestKey !== null) {
|
|
163
|
+
if (this.enableAutoCancellation) {
|
|
164
|
+
this.cancelRequest(requestKey);
|
|
165
|
+
}
|
|
166
|
+
controller = new AbortController();
|
|
167
|
+
this.cancelControllers[requestKey] = controller;
|
|
168
|
+
if (externalSignal?.aborted) {
|
|
169
|
+
controller.abort();
|
|
170
|
+
} else if (externalSignal) {
|
|
171
|
+
externalSignal.addEventListener("abort", () => controller?.abort(), {
|
|
172
|
+
once: true
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
const signal = controller?.signal ?? externalSignal;
|
|
108
177
|
let url = this.baseUrl + path;
|
|
109
178
|
if (options?.params) {
|
|
110
179
|
const qs = new URLSearchParams(options.params).toString();
|
|
@@ -124,7 +193,7 @@ var HttpClient = class {
|
|
|
124
193
|
const init = {
|
|
125
194
|
method,
|
|
126
195
|
headers,
|
|
127
|
-
signal
|
|
196
|
+
signal
|
|
128
197
|
};
|
|
129
198
|
if (body != null && method !== "GET" && method !== "DELETE") {
|
|
130
199
|
if (body instanceof FormData) {
|
|
@@ -133,8 +202,25 @@ var HttpClient = class {
|
|
|
133
202
|
init.body = JSON.stringify(body);
|
|
134
203
|
}
|
|
135
204
|
}
|
|
205
|
+
let res = null;
|
|
136
206
|
const fetcher = options?.fetch ?? this.defaultFetch;
|
|
137
|
-
|
|
207
|
+
try {
|
|
208
|
+
res = await fetcher(url, init);
|
|
209
|
+
} catch (err) {
|
|
210
|
+
if (isAbortError(err)) {
|
|
211
|
+
throw new ApiError(
|
|
212
|
+
"The request was aborted (most likely auto-cancelled by a newer request with the same requestKey)",
|
|
213
|
+
{},
|
|
214
|
+
0,
|
|
215
|
+
true
|
|
216
|
+
);
|
|
217
|
+
}
|
|
218
|
+
throw err;
|
|
219
|
+
} finally {
|
|
220
|
+
if (requestKey !== null && this.cancelControllers[requestKey] === controller) {
|
|
221
|
+
delete this.cancelControllers[requestKey];
|
|
222
|
+
}
|
|
223
|
+
}
|
|
138
224
|
if (res.status === 204) return null;
|
|
139
225
|
let bodyText = "";
|
|
140
226
|
let data = {};
|
|
@@ -353,17 +439,68 @@ var CollectionService = class {
|
|
|
353
439
|
return encodeURIComponent(id);
|
|
354
440
|
}
|
|
355
441
|
/**
|
|
356
|
-
*
|
|
357
|
-
*
|
|
358
|
-
* @param
|
|
442
|
+
* Fetch a paginated list of records (PocketBase `getList`).
|
|
443
|
+
*
|
|
444
|
+
* @param page Page number (default 1).
|
|
445
|
+
* @param perPage Records per page (default 30).
|
|
446
|
+
* @param options Query params (`filter`, `sort`, `expand`, `fields`) + request options.
|
|
359
447
|
*/
|
|
360
|
-
|
|
361
|
-
const
|
|
448
|
+
getList(page = 1, perPage = 30, options) {
|
|
449
|
+
const { requestKey, autoCancel, cancelKey, ...rest } = options ?? {};
|
|
450
|
+
const qs = new URLSearchParams(
|
|
451
|
+
Object.fromEntries(
|
|
452
|
+
Object.entries({
|
|
453
|
+
page: String(page),
|
|
454
|
+
perPage: String(perPage),
|
|
455
|
+
...rest
|
|
456
|
+
}).map(([k, v]) => [k, String(v)])
|
|
457
|
+
)
|
|
458
|
+
).toString();
|
|
362
459
|
return this.http.get(
|
|
363
|
-
"/" + this.encodeId(this.collectionName) + qs,
|
|
364
|
-
|
|
460
|
+
"/" + this.encodeId(this.collectionName) + "?" + qs,
|
|
461
|
+
{ requestKey, autoCancel, cancelKey }
|
|
365
462
|
);
|
|
366
463
|
}
|
|
464
|
+
/**
|
|
465
|
+
* Fetch all records at once (auto-paginates). Mirrors PocketBase's
|
|
466
|
+
* `pb.collection(name).getFullList()`.
|
|
467
|
+
*
|
|
468
|
+
* @param options Query params (`sort`, `filter`, `batch`, etc.) + request options.
|
|
469
|
+
*/
|
|
470
|
+
async getFullList(options) {
|
|
471
|
+
const { batch = 1e3, ...rest } = options ?? {};
|
|
472
|
+
const items = [];
|
|
473
|
+
let page = 1;
|
|
474
|
+
for (; ; ) {
|
|
475
|
+
const res = await this.getList(
|
|
476
|
+
page,
|
|
477
|
+
batch,
|
|
478
|
+
{
|
|
479
|
+
// disable auto-cancellation across pages — each page request is unique
|
|
480
|
+
...rest,
|
|
481
|
+
requestKey: null
|
|
482
|
+
}
|
|
483
|
+
);
|
|
484
|
+
if (!res || !res.items || res.items.length === 0) break;
|
|
485
|
+
items.push(...res.items);
|
|
486
|
+
if (page >= (res.totalPages ?? page)) break;
|
|
487
|
+
page += 1;
|
|
488
|
+
}
|
|
489
|
+
return items;
|
|
490
|
+
}
|
|
491
|
+
/**
|
|
492
|
+
* Fetch the first record matching a filter (PocketBase `getFirstListItem`).
|
|
493
|
+
*
|
|
494
|
+
* @param filter Filter expression (e.g. `title = 'x'`).
|
|
495
|
+
* @param options Optional request options.
|
|
496
|
+
*/
|
|
497
|
+
async getFirstListItem(filter, options) {
|
|
498
|
+
const res = await this.getList(1, 1, {
|
|
499
|
+
...options,
|
|
500
|
+
filter
|
|
501
|
+
});
|
|
502
|
+
return res?.items?.[0] ?? null;
|
|
503
|
+
}
|
|
367
504
|
/**
|
|
368
505
|
* Get a single record by ID.
|
|
369
506
|
* @param id Record ID.
|
|
@@ -748,6 +885,12 @@ var RealtimeService = class {
|
|
|
748
885
|
function getFileUrl(baseUrl, fileId) {
|
|
749
886
|
return baseUrl.replace(/\/+$/, "") + "/files/" + encodeURIComponent(fileId);
|
|
750
887
|
}
|
|
888
|
+
function getThumbUrl(baseUrl, fileId, size) {
|
|
889
|
+
return baseUrl.replace(/\/+$/, "") + "/files/" + encodeURIComponent(fileId) + "/thumbs/" + encodeURIComponent(size);
|
|
890
|
+
}
|
|
891
|
+
function getScaleUrl(baseUrl, fileId, size) {
|
|
892
|
+
return baseUrl.replace(/\/+$/, "") + "/files/" + encodeURIComponent(fileId) + "/scale/" + encodeURIComponent(size);
|
|
893
|
+
}
|
|
751
894
|
var FilesService = class {
|
|
752
895
|
constructor(http) {
|
|
753
896
|
this.http = http;
|
|
@@ -779,6 +922,25 @@ var FilesService = class {
|
|
|
779
922
|
);
|
|
780
923
|
return data;
|
|
781
924
|
}
|
|
925
|
+
/**
|
|
926
|
+
* List uploaded files (newest first), with optional filters.
|
|
927
|
+
*
|
|
928
|
+
* @param options Filters and pagination.
|
|
929
|
+
*/
|
|
930
|
+
async list(options) {
|
|
931
|
+
const params = {};
|
|
932
|
+
if (options?.page !== void 0) params["page"] = String(options.page);
|
|
933
|
+
if (options?.perPage !== void 0) params["perPage"] = String(options.perPage);
|
|
934
|
+
if (options?.collectionName) params["collectionName"] = options.collectionName;
|
|
935
|
+
if (options?.fieldName) params["fieldName"] = options.fieldName;
|
|
936
|
+
if (options?.mime) params["mime"] = options.mime;
|
|
937
|
+
const data = await this.http.request("GET", "/files", void 0, { params });
|
|
938
|
+
return data ?? { items: [], page: 1, perPage: 50, total: 0 };
|
|
939
|
+
}
|
|
940
|
+
/**
|
|
941
|
+
* Fetch file metadata including URL.
|
|
942
|
+
* @param fileId The file ID.
|
|
943
|
+
*/
|
|
782
944
|
/**
|
|
783
945
|
* Fetch file metadata including URL.
|
|
784
946
|
* @param fileId The file ID.
|
|
@@ -808,6 +970,135 @@ var FilesService = class {
|
|
|
808
970
|
}
|
|
809
971
|
};
|
|
810
972
|
|
|
973
|
+
// src/collections.ts
|
|
974
|
+
var REGISTRY_TOPIC = "collections";
|
|
975
|
+
var CollectionsService = class {
|
|
976
|
+
/** @internal */
|
|
977
|
+
constructor(http, realtime) {
|
|
978
|
+
this.http = http;
|
|
979
|
+
this.realtime = realtime;
|
|
980
|
+
}
|
|
981
|
+
/**
|
|
982
|
+
* Fetch a paginated list of collections (admin).
|
|
983
|
+
*
|
|
984
|
+
* @param params Optional query params (`page`, `perPage`, `filter`, `sort`).
|
|
985
|
+
* @param options Optional request options.
|
|
986
|
+
*/
|
|
987
|
+
async getList(params, options) {
|
|
988
|
+
const qs = params ? "?" + new URLSearchParams(
|
|
989
|
+
Object.fromEntries(
|
|
990
|
+
Object.entries(params).map(([k, v]) => [k, String(v)])
|
|
991
|
+
)
|
|
992
|
+
).toString() : "";
|
|
993
|
+
return this.http?.get("/collections" + qs, options) ?? null;
|
|
994
|
+
}
|
|
995
|
+
/**
|
|
996
|
+
* Fetch all collections at once (auto-paginates). Mirrors PocketBase's
|
|
997
|
+
* `pb.collections.getFullList()` — defaults to listing everything.
|
|
998
|
+
*
|
|
999
|
+
* @param options Query params (`sort`, `batch`, etc.) or request options.
|
|
1000
|
+
*/
|
|
1001
|
+
async getFullList(options) {
|
|
1002
|
+
if (!this.http) return [];
|
|
1003
|
+
const { batch = 1e3, ...rest } = options ?? {};
|
|
1004
|
+
const items = [];
|
|
1005
|
+
let page = 1;
|
|
1006
|
+
for (; ; ) {
|
|
1007
|
+
const res = await this.getList({
|
|
1008
|
+
...rest,
|
|
1009
|
+
page,
|
|
1010
|
+
perPage: batch
|
|
1011
|
+
});
|
|
1012
|
+
if (!res || !res.items || res.items.length === 0) break;
|
|
1013
|
+
items.push(...res.items);
|
|
1014
|
+
if (page >= (res.totalPages ?? page)) break;
|
|
1015
|
+
page += 1;
|
|
1016
|
+
}
|
|
1017
|
+
return items;
|
|
1018
|
+
}
|
|
1019
|
+
/**
|
|
1020
|
+
* Get a single collection by ID or name (admin).
|
|
1021
|
+
*
|
|
1022
|
+
* @param id Collection ID or name.
|
|
1023
|
+
* @param options Optional request options.
|
|
1024
|
+
*/
|
|
1025
|
+
async getOne(id, options) {
|
|
1026
|
+
return this.http?.get("/collections/" + encodeURIComponent(id), options) ?? null;
|
|
1027
|
+
}
|
|
1028
|
+
/**
|
|
1029
|
+
* Create a new collection (admin).
|
|
1030
|
+
*
|
|
1031
|
+
* @param data Collection definition (name, type, fields, options, rules, etc.).
|
|
1032
|
+
* @param options Optional request options.
|
|
1033
|
+
*/
|
|
1034
|
+
async create(data, options) {
|
|
1035
|
+
return this.http?.post("/collections", data, options) ?? null;
|
|
1036
|
+
}
|
|
1037
|
+
/**
|
|
1038
|
+
* Update an existing collection (admin).
|
|
1039
|
+
*
|
|
1040
|
+
* @param id Collection ID or name.
|
|
1041
|
+
* @param data Updated collection fields.
|
|
1042
|
+
* @param options Optional request options.
|
|
1043
|
+
*/
|
|
1044
|
+
async update(id, data, options) {
|
|
1045
|
+
return this.http?.patch(
|
|
1046
|
+
"/collections/" + encodeURIComponent(id),
|
|
1047
|
+
data,
|
|
1048
|
+
options
|
|
1049
|
+
) ?? null;
|
|
1050
|
+
}
|
|
1051
|
+
/**
|
|
1052
|
+
* Delete a collection (admin).
|
|
1053
|
+
*
|
|
1054
|
+
* @param id Collection ID or name.
|
|
1055
|
+
* @param options Optional request options.
|
|
1056
|
+
*/
|
|
1057
|
+
async delete(id, options) {
|
|
1058
|
+
const res = this.http?.delete(
|
|
1059
|
+
"/collections/" + encodeURIComponent(id),
|
|
1060
|
+
options
|
|
1061
|
+
);
|
|
1062
|
+
return res == null ? false : true;
|
|
1063
|
+
}
|
|
1064
|
+
/**
|
|
1065
|
+
* Subscribe to collection registry changes.
|
|
1066
|
+
*
|
|
1067
|
+
* @param callback Received on every collection create/update/delete.
|
|
1068
|
+
* @returns A function that unsubscribes this callback.
|
|
1069
|
+
*/
|
|
1070
|
+
subscribe(callback) {
|
|
1071
|
+
if (!this.realtime) {
|
|
1072
|
+
console.warn("[lazypock] No realtime service configured.");
|
|
1073
|
+
return () => {
|
|
1074
|
+
};
|
|
1075
|
+
}
|
|
1076
|
+
const handler = (raw) => {
|
|
1077
|
+
callback({
|
|
1078
|
+
action: normalizeAction2(raw.event),
|
|
1079
|
+
collection: raw.payload ?? {},
|
|
1080
|
+
topic: raw.topic
|
|
1081
|
+
});
|
|
1082
|
+
};
|
|
1083
|
+
this.realtime.ensureConnected();
|
|
1084
|
+
this.realtime.subscribe(REGISTRY_TOPIC, handler);
|
|
1085
|
+
return () => this.realtime?.unsubscribe(REGISTRY_TOPIC, handler);
|
|
1086
|
+
}
|
|
1087
|
+
/**
|
|
1088
|
+
* Unsubscribe all callbacks from the registry channel.
|
|
1089
|
+
*/
|
|
1090
|
+
unsubscribe() {
|
|
1091
|
+
this.realtime?.unsubscribe(REGISTRY_TOPIC);
|
|
1092
|
+
}
|
|
1093
|
+
};
|
|
1094
|
+
function normalizeAction2(event) {
|
|
1095
|
+
const e = event.toLowerCase();
|
|
1096
|
+
if (e === "create") return "create";
|
|
1097
|
+
if (e === "update") return "update";
|
|
1098
|
+
if (e === "delete") return "delete";
|
|
1099
|
+
return "update";
|
|
1100
|
+
}
|
|
1101
|
+
|
|
811
1102
|
// src/typegen.ts
|
|
812
1103
|
function fieldTypeScriptType(field, fallback = "unknown") {
|
|
813
1104
|
const opts = field.options ?? {};
|
|
@@ -968,11 +1259,13 @@ export function createClient(options: LazypockClientOptions): TypedClient {
|
|
|
968
1259
|
}
|
|
969
1260
|
|
|
970
1261
|
export class TypedClient extends LazypockClient {
|
|
971
|
-
override collection<
|
|
972
|
-
|
|
973
|
-
|
|
1262
|
+
override collection<T extends string>(name: T): T extends keyof LazypockCollections
|
|
1263
|
+
? CollectionService<LazypockCollections[T]>
|
|
1264
|
+
: CollectionService<unknown> {
|
|
1265
|
+
return super.collection(name) as T extends keyof LazypockCollections ? CollectionService<LazypockCollections[T]> : CollectionService<unknown>;
|
|
974
1266
|
}
|
|
975
|
-
}
|
|
1267
|
+
}
|
|
1268
|
+
`);
|
|
976
1269
|
return sections.join("\n\n") + "\n";
|
|
977
1270
|
}
|
|
978
1271
|
function renderInterface(opts) {
|
|
@@ -1006,6 +1299,7 @@ var LazypockClient = class {
|
|
|
1006
1299
|
this.realtime.setUrl(wsUrlFromBaseUrl(baseUrl));
|
|
1007
1300
|
}
|
|
1008
1301
|
this.files = new FilesService(this.http);
|
|
1302
|
+
this.collections = new CollectionsService(this.http, this.realtime);
|
|
1009
1303
|
if (options.types?.schemas) {
|
|
1010
1304
|
this.schemaByName = new Map(
|
|
1011
1305
|
options.types.schemas.map((s) => [s.name, s])
|
|
@@ -1055,6 +1349,37 @@ var LazypockClient = class {
|
|
|
1055
1349
|
const schemas = this.schemaByName ? [...this.schemaByName.values()] : [];
|
|
1056
1350
|
return generateTypes(schemas, options);
|
|
1057
1351
|
}
|
|
1352
|
+
// ── Auto-cancellation (PocketBase `autoCancellation` parity) ──
|
|
1353
|
+
/**
|
|
1354
|
+
* Globally enable or disable auto-cancellation of duplicated pending requests.
|
|
1355
|
+
*
|
|
1356
|
+
* When enabled (default), a new request whose `requestKey` (default
|
|
1357
|
+
* `HTTP_METHOD + path`) matches a still-pending request aborts the previous
|
|
1358
|
+
* one — only the last duplicate executes.
|
|
1359
|
+
*
|
|
1360
|
+
* @example
|
|
1361
|
+
* ```ts
|
|
1362
|
+
* client.autoCancellation(false); // keep every request
|
|
1363
|
+
* ```
|
|
1364
|
+
*/
|
|
1365
|
+
autoCancellation(enable) {
|
|
1366
|
+
this.http.autoCancellation(enable);
|
|
1367
|
+
return this;
|
|
1368
|
+
}
|
|
1369
|
+
/**
|
|
1370
|
+
* Abort a single pending request by its cancellation key
|
|
1371
|
+
* (default `HTTP_METHOD + path`, e.g. `"GET /api/posts?page=1"`).
|
|
1372
|
+
* The request rejects with an `ApiError` whose `isAbort` is `true`.
|
|
1373
|
+
*/
|
|
1374
|
+
cancelRequest(requestKey) {
|
|
1375
|
+
this.http.cancelRequest(requestKey);
|
|
1376
|
+
return this;
|
|
1377
|
+
}
|
|
1378
|
+
/** Abort all pending requests. */
|
|
1379
|
+
cancelAllRequests() {
|
|
1380
|
+
this.http.cancelAllRequests();
|
|
1381
|
+
return this;
|
|
1382
|
+
}
|
|
1058
1383
|
// ── Auth ──
|
|
1059
1384
|
/** Check whether any superuser exists (for login vs setup screen routing). */
|
|
1060
1385
|
async checkSuperuser() {
|
|
@@ -1166,129 +1491,6 @@ var LazypockClient = class {
|
|
|
1166
1491
|
health(options) {
|
|
1167
1492
|
return this.http.get("/health", options);
|
|
1168
1493
|
}
|
|
1169
|
-
// ── Collection Management (admin) ──
|
|
1170
|
-
/**
|
|
1171
|
-
* List all collections (admin).
|
|
1172
|
-
* @param q URL query string (e.g. `page=1&perPage=200`).
|
|
1173
|
-
* @param options Optional request options.
|
|
1174
|
-
*/
|
|
1175
|
-
listCollections(q, options) {
|
|
1176
|
-
return this.http.get(
|
|
1177
|
-
"/collections" + (q ? "?" + q : ""),
|
|
1178
|
-
options
|
|
1179
|
-
);
|
|
1180
|
-
}
|
|
1181
|
-
/**
|
|
1182
|
-
* Get a single collection by ID or name.
|
|
1183
|
-
* @param id Collection ID or name.
|
|
1184
|
-
* @param options Optional request options.
|
|
1185
|
-
*/
|
|
1186
|
-
getCollection(id, options) {
|
|
1187
|
-
return this.http.get(
|
|
1188
|
-
"/collections/" + encodeURIComponent(id),
|
|
1189
|
-
options
|
|
1190
|
-
);
|
|
1191
|
-
}
|
|
1192
|
-
/**
|
|
1193
|
-
* Create a new collection (admin).
|
|
1194
|
-
* @param data Collection definition (name, type, fields, options, rules, etc.).
|
|
1195
|
-
* @param options Optional request options.
|
|
1196
|
-
*/
|
|
1197
|
-
createCollection(data, options) {
|
|
1198
|
-
return this.http.post("/collections", data, options);
|
|
1199
|
-
}
|
|
1200
|
-
/**
|
|
1201
|
-
* Update an existing collection (admin).
|
|
1202
|
-
* @param id Collection ID or name.
|
|
1203
|
-
* @param data Updated collection fields.
|
|
1204
|
-
* @param options Optional request options.
|
|
1205
|
-
*/
|
|
1206
|
-
updateCollection(id, data, options) {
|
|
1207
|
-
return this.http.patch(
|
|
1208
|
-
"/collections/" + encodeURIComponent(id),
|
|
1209
|
-
data,
|
|
1210
|
-
options
|
|
1211
|
-
);
|
|
1212
|
-
}
|
|
1213
|
-
/**
|
|
1214
|
-
* Delete a collection (admin).
|
|
1215
|
-
* @param id Collection ID or name.
|
|
1216
|
-
* @param options Optional request options.
|
|
1217
|
-
*/
|
|
1218
|
-
deleteCollection(id, options) {
|
|
1219
|
-
return this.http.delete("/collections/" + encodeURIComponent(id), options);
|
|
1220
|
-
}
|
|
1221
|
-
// ── Records (dynamic collection) ──
|
|
1222
|
-
/**
|
|
1223
|
-
* List records from a dynamic collection with optional filter/sort/pagination.
|
|
1224
|
-
*
|
|
1225
|
-
* @param coll Collection name.
|
|
1226
|
-
* @param params Query parameters including:
|
|
1227
|
-
* - `filter` — PocketBase filter syntax (e.g. `title~'hello' && published=true`)
|
|
1228
|
-
* - `sort` — Comma-separated, `-` prefix for DESC (e.g. `-created,title`)
|
|
1229
|
-
* - `page` — Page number (default: 1)
|
|
1230
|
-
* - `perPage` — Items per page (default: 30, max: 200)
|
|
1231
|
-
* - `expand` — Comma-separated relation fields (e.g. `author,category`)
|
|
1232
|
-
* @param options Optional request options.
|
|
1233
|
-
*/
|
|
1234
|
-
listRecords(coll, params, options) {
|
|
1235
|
-
const qs = params ? "?" + new URLSearchParams(params).toString() : "";
|
|
1236
|
-
return this.http.get(
|
|
1237
|
-
"/" + encodeURIComponent(coll) + qs,
|
|
1238
|
-
options
|
|
1239
|
-
);
|
|
1240
|
-
}
|
|
1241
|
-
/**
|
|
1242
|
-
* Get a single record by ID.
|
|
1243
|
-
* @param coll Collection name.
|
|
1244
|
-
* @param id Record ID.
|
|
1245
|
-
* @param options Optional request options.
|
|
1246
|
-
*/
|
|
1247
|
-
getRecord(coll, id, options) {
|
|
1248
|
-
return this.http.get(
|
|
1249
|
-
"/" + encodeURIComponent(coll) + "/" + encodeURIComponent(id),
|
|
1250
|
-
options
|
|
1251
|
-
);
|
|
1252
|
-
}
|
|
1253
|
-
/**
|
|
1254
|
-
* Create a record in a dynamic collection.
|
|
1255
|
-
* @param coll Collection name.
|
|
1256
|
-
* @param data Record fields.
|
|
1257
|
-
* @param options Optional request options.
|
|
1258
|
-
*/
|
|
1259
|
-
createRecord(coll, data, options) {
|
|
1260
|
-
return this.http.post(
|
|
1261
|
-
"/" + encodeURIComponent(coll),
|
|
1262
|
-
data,
|
|
1263
|
-
options
|
|
1264
|
-
);
|
|
1265
|
-
}
|
|
1266
|
-
/**
|
|
1267
|
-
* Update a record in a dynamic collection.
|
|
1268
|
-
* @param coll Collection name.
|
|
1269
|
-
* @param id Record ID.
|
|
1270
|
-
* @param data Updated record fields.
|
|
1271
|
-
* @param options Optional request options.
|
|
1272
|
-
*/
|
|
1273
|
-
updateRecord(coll, id, data, options) {
|
|
1274
|
-
return this.http.patch(
|
|
1275
|
-
"/" + encodeURIComponent(coll) + "/" + encodeURIComponent(id),
|
|
1276
|
-
data,
|
|
1277
|
-
options
|
|
1278
|
-
);
|
|
1279
|
-
}
|
|
1280
|
-
/**
|
|
1281
|
-
* Delete a record from a dynamic collection.
|
|
1282
|
-
* @param coll Collection name.
|
|
1283
|
-
* @param id Record ID.
|
|
1284
|
-
* @param options Optional request options.
|
|
1285
|
-
*/
|
|
1286
|
-
deleteRecord(coll, id, options) {
|
|
1287
|
-
return this.http.delete(
|
|
1288
|
-
"/" + encodeURIComponent(coll) + "/" + encodeURIComponent(id),
|
|
1289
|
-
options
|
|
1290
|
-
);
|
|
1291
|
-
}
|
|
1292
1494
|
};
|
|
1293
1495
|
|
|
1294
1496
|
// src/client.ts
|
|
@@ -1305,7 +1507,9 @@ function createClient(options) {
|
|
|
1305
1507
|
ApiError,
|
|
1306
1508
|
AuthStore,
|
|
1307
1509
|
CollectionService,
|
|
1510
|
+
CollectionsService,
|
|
1308
1511
|
FilesService,
|
|
1512
|
+
HttpClient,
|
|
1309
1513
|
LazypockClient,
|
|
1310
1514
|
RealtimeService,
|
|
1311
1515
|
TypedClient,
|
|
@@ -1315,6 +1519,8 @@ function createClient(options) {
|
|
|
1315
1519
|
fieldTypeScriptType,
|
|
1316
1520
|
generateTypes,
|
|
1317
1521
|
getFileUrl,
|
|
1522
|
+
getScaleUrl,
|
|
1523
|
+
getThumbUrl,
|
|
1318
1524
|
schemaFieldType,
|
|
1319
1525
|
wsUrlFromBaseUrl
|
|
1320
1526
|
});
|