@rebasepro/server 0.13.0 → 0.13.1-canary.g18cfeb7
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/{admin_block-CcSGdH7M.js → admin_block-CLeUMG8G.js} +3 -1
- package/dist/admin_block-CLeUMG8G.js.map +1 -0
- package/dist/api/errors.d.ts +0 -6
- package/dist/api/openapi-generator.d.ts +14 -0
- package/dist/api/rest/idempotency.d.ts +41 -4
- package/dist/api/rest/write-validation.d.ts +12 -5
- package/dist/auth/index.d.ts +1 -1
- package/dist/auth/jwt.d.ts +12 -0
- package/dist/{auth-CuC9M2x6.js → auth-CtxXQYV_.js} +20 -39
- package/dist/auth-CtxXQYV_.js.map +1 -0
- package/dist/{backup-CVggVhR2.js → backup-BJiY_mM-.js} +2 -2
- package/dist/{backup-CVggVhR2.js.map → backup-BJiY_mM-.js.map} +1 -1
- package/dist/boot/boot.d.ts +19 -0
- package/dist/{contract-routes-Dj8i5AiM.js → contract-routes-FSt0Nyfk.js} +2 -2
- package/dist/{contract-routes-Dj8i5AiM.js.map → contract-routes-FSt0Nyfk.js.map} +1 -1
- package/dist/cron/cron-scheduler.d.ts +8 -3
- package/dist/cron/define-cron.d.ts +5 -3
- package/dist/{cron-routes-CrQ0tK-_.js → cron-routes-D5a9v1HY.js} +2 -2
- package/dist/{cron-routes-CrQ0tK-_.js.map → cron-routes-D5a9v1HY.js.map} +1 -1
- package/dist/{cron-scheduler-B3RFt0HS.js → cron-scheduler-CsQtYLMq.js} +28 -3
- package/dist/cron-scheduler-CsQtYLMq.js.map +1 -0
- package/dist/{cron-store-BywZsyfZ.js → cron-store-CHH7zrif.js} +16 -3
- package/dist/cron-store-CHH7zrif.js.map +1 -0
- package/dist/{errors-CgkCzoj7.js → errors-BpudWAVU.js} +2 -10
- package/dist/errors-BpudWAVU.js.map +1 -0
- package/dist/functions/define-function.d.ts +1 -1
- package/dist/index.es.js +673 -232
- package/dist/index.es.js.map +1 -1
- package/dist/internal-tables-57VaN3o1.js +105 -0
- package/dist/internal-tables-57VaN3o1.js.map +1 -0
- package/dist/{jwt-DD6EtpGj.js → jwt-CzeviDcB.js} +17 -2
- package/dist/{jwt-DD6EtpGj.js.map → jwt-CzeviDcB.js.map} +1 -1
- package/dist/{openapi-generator-BEwyiaAr.js → openapi-generator-CSlEZh7-.js} +306 -128
- package/dist/openapi-generator-CSlEZh7-.js.map +1 -0
- package/dist/{schema-editor-routes-CbF20Mf1.js → schema-editor-routes-BqjzvvWU.js} +4 -4
- package/dist/{schema-editor-routes-CbF20Mf1.js.map → schema-editor-routes-BqjzvvWU.js.map} +1 -1
- package/dist/{src-_qQ3RNCK.js → src-Ca6NhxKs.js} +79 -2
- package/dist/src-Ca6NhxKs.js.map +1 -0
- package/dist/{src-Cum9kox5.js → src-CvaxLgnM.js} +115 -34
- package/dist/src-CvaxLgnM.js.map +1 -0
- package/dist/utils/logging.d.ts +0 -4
- package/dist/utils/sql.d.ts +11 -6
- package/package.json +6 -6
- package/dist/admin_block-CcSGdH7M.js.map +0 -1
- package/dist/auth-CuC9M2x6.js.map +0 -1
- package/dist/backend-CIxN4FVm.js +0 -15
- package/dist/backend-CIxN4FVm.js.map +0 -1
- package/dist/cron-scheduler-B3RFt0HS.js.map +0 -1
- package/dist/cron-store-BywZsyfZ.js.map +0 -1
- package/dist/errors-CgkCzoj7.js.map +0 -1
- package/dist/openapi-generator-BEwyiaAr.js.map +0 -1
- package/dist/src-Cum9kox5.js.map +0 -1
- package/dist/src-_qQ3RNCK.js.map +0 -1
|
@@ -2,7 +2,7 @@ import { createRequire as __createRequire } from "module";
|
|
|
2
2
|
import "process";
|
|
3
3
|
__createRequire(import.meta.url);
|
|
4
4
|
import { r as __require, t as __commonJSMin } from "./rolldown-runtime-DSJWtz9O.js";
|
|
5
|
-
import {
|
|
5
|
+
import { a as getDeclaredSubcollections, d as NULL_OPS, f as REST_TO_CANONICAL, l as getDataSourceCapabilities, o as isPostgresCollectionConfig, p as toCanonicalOp, s as isRelationalCollectionConfig, u as CANONICAL_TO_REST } from "./src-Ca6NhxKs.js";
|
|
6
6
|
//#region ../types/src/types/entities.ts
|
|
7
7
|
/**
|
|
8
8
|
* Class used to create a reference to a entity in a different path.
|
|
@@ -129,7 +129,7 @@ var Vector = class {
|
|
|
129
129
|
//#endregion
|
|
130
130
|
//#region ../types/src/types/policy.ts
|
|
131
131
|
/**
|
|
132
|
-
* The id a request without a logged-in user reports as `
|
|
132
|
+
* The id a request without a logged-in user reports as `rebase.uid()`.
|
|
133
133
|
*
|
|
134
134
|
* A user-context request always sets `app.uid`: blank would read back as
|
|
135
135
|
* `NULL`, and `NULL` is how the trusted server context is recognised, so an
|
|
@@ -137,7 +137,7 @@ var Vector = class {
|
|
|
137
137
|
* therefore substitutes this sentinel at the single chokepoint where the GUC
|
|
138
138
|
* is set.
|
|
139
139
|
*
|
|
140
|
-
* The consequence for policy authors is that **`
|
|
140
|
+
* The consequence for policy authors is that **`rebase.uid() IS NOT NULL` is a
|
|
141
141
|
* tautology on the user path** — it is true for anonymous visitors too. Use
|
|
142
142
|
* {@link policy.authenticated} to mean "signed in", and
|
|
143
143
|
* {@link policy.serverContext} to mean "the trusted server context". Do not
|
|
@@ -154,7 +154,7 @@ var ANONYMOUS_USER_ID = "anonymous";
|
|
|
154
154
|
* JavaScript evaluator and the linter were all built on
|
|
155
155
|
* {@link ANONYMOUS_USER_ID}, while the request path scoped unauthenticated
|
|
156
156
|
* callers as `'anon'` — so `policy.authenticated()`, which compiled to
|
|
157
|
-
* `
|
|
157
|
+
* `rebase.uid() <> 'anonymous'`, was *true* for an anonymous visitor. The
|
|
158
158
|
* sanctioned way to write "signed in" granted to everyone, and the linter
|
|
159
159
|
* flagged the spelling that actually worked as a foreign convention.
|
|
160
160
|
*
|
|
@@ -235,6 +235,27 @@ var policy = {
|
|
|
235
235
|
authUid: () => ({ kind: "authUid" }),
|
|
236
236
|
authRoles: () => ({ kind: "authRoles" })
|
|
237
237
|
};
|
|
238
|
+
/** Hard ceiling clamped onto any client-supplied `limit`, on every surface. */
|
|
239
|
+
var MAX_LIST_LIMIT = 1e3;
|
|
240
|
+
/**
|
|
241
|
+
* Resolve a client-supplied list `limit` into a safe, always-defined value.
|
|
242
|
+
*
|
|
243
|
+
* - A provided limit is coerced to an integer and clamped to `[1, maxLimit]`,
|
|
244
|
+
* so `0`, negatives, and absurd values can never bypass the cap.
|
|
245
|
+
* - An absent / blank / non-numeric limit falls back to the mode default:
|
|
246
|
+
* `vectorDefaultLimit` for a vector search, otherwise `defaultLimit`.
|
|
247
|
+
*
|
|
248
|
+
* The return is never `undefined` — no ingress that routes its client limit
|
|
249
|
+
* through this can produce an unbounded read.
|
|
250
|
+
*/
|
|
251
|
+
function resolveClientListLimit(rawLimit, opts = {}) {
|
|
252
|
+
const maxLimit = opts.maxLimit ?? 1e3;
|
|
253
|
+
if (rawLimit != null && String(rawLimit).trim() !== "") {
|
|
254
|
+
const parsed = typeof rawLimit === "number" ? rawLimit : parseInt(String(rawLimit), 10);
|
|
255
|
+
if (Number.isFinite(parsed)) return Math.min(Math.max(1, Math.floor(parsed)), maxLimit);
|
|
256
|
+
}
|
|
257
|
+
return opts.vectorSearch ? opts.vectorDefaultLimit ?? 10 : opts.defaultLimit ?? 50;
|
|
258
|
+
}
|
|
238
259
|
(/* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
239
260
|
(function(e) {
|
|
240
261
|
var t;
|
|
@@ -1382,10 +1403,21 @@ function singularizeForKey(name) {
|
|
|
1382
1403
|
* have `id` and `path` fields — these are relation-shaped objects from
|
|
1383
1404
|
* edge cases in the data pipeline (REST fallback, stale cache, custom data source).
|
|
1384
1405
|
*
|
|
1406
|
+
* When `targetPath` is given, also accepts a bare id. A relation column is a
|
|
1407
|
+
* foreign key, and the REST layer returns it as the scalar it is; only some
|
|
1408
|
+
* fetch paths hydrate it into an object. Which form a caller sees therefore
|
|
1409
|
+
* depends on how the row was loaded, and a caller that only accepted objects
|
|
1410
|
+
* reported half of its own data as a type error. The declared target is the
|
|
1411
|
+
* missing half: with it, an id is a relation that has not been fetched yet.
|
|
1412
|
+
*
|
|
1385
1413
|
* Returns null if the value cannot be coerced.
|
|
1386
1414
|
*/
|
|
1387
|
-
function normalizeToEntityRelation(value, propertyType) {
|
|
1415
|
+
function normalizeToEntityRelation(value, propertyType, targetPath) {
|
|
1388
1416
|
if (value instanceof EntityRelation) return value;
|
|
1417
|
+
if (targetPath && (typeof value === "string" || typeof value === "number")) {
|
|
1418
|
+
if (value === "") return null;
|
|
1419
|
+
return new EntityRelation(value, targetPath);
|
|
1420
|
+
}
|
|
1389
1421
|
if (!value || typeof value !== "object" || Array.isArray(value)) return null;
|
|
1390
1422
|
const obj = value;
|
|
1391
1423
|
if (!(obj.__type === "relation" || obj.__type === "reference" || typeof obj.isEntityRelation === "function" && obj.isEntityRelation() || typeof obj.isEntityReference === "function" && obj.isEntityReference() || propertyType === "relation" && typeof obj.id !== "undefined" && typeof obj.path === "string")) return null;
|
|
@@ -2941,6 +2973,30 @@ var RebasePaginationError = class RebasePaginationError extends Error {
|
|
|
2941
2973
|
Object.setPrototypeOf(this, RebasePaginationError.prototype);
|
|
2942
2974
|
}
|
|
2943
2975
|
};
|
|
2976
|
+
/**
|
|
2977
|
+
* Resolve `limit`/`offset`/`page` into the window a read will actually use.
|
|
2978
|
+
*
|
|
2979
|
+
* Lives here, next to the walk, for the reason at the top of this file: every
|
|
2980
|
+
* transport has to mean the same thing by "page two". Four of them did not —
|
|
2981
|
+
* the REST layer strode by {@link DEFAULT_LIST_LIMIT}, the local-first
|
|
2982
|
+
* evaluator by {@link DEFAULT_PAGE_SIZE}, the in-process accessor by 20, and
|
|
2983
|
+
* the published type documented a fourth number. Pages that overlap or skip
|
|
2984
|
+
* rows are the mildest of those outcomes.
|
|
2985
|
+
*
|
|
2986
|
+
* `page` wins over `offset`, as {@link FindParams} documents. `driverOffset`
|
|
2987
|
+
* is the value to hand a driver: it stays `undefined` when the caller named no
|
|
2988
|
+
* offset, because keyset pagination seeks with a `where` clause and must not
|
|
2989
|
+
* look like it is paging by offset.
|
|
2990
|
+
*/
|
|
2991
|
+
function resolveFindWindow(params) {
|
|
2992
|
+
const limit = params?.limit ?? 50;
|
|
2993
|
+
const offset = params?.page != null ? Math.max(0, (params.page - 1) * limit) : params?.offset ?? 0;
|
|
2994
|
+
return {
|
|
2995
|
+
limit,
|
|
2996
|
+
offset,
|
|
2997
|
+
driverOffset: params?.page != null ? offset : params?.offset
|
|
2998
|
+
};
|
|
2999
|
+
}
|
|
2944
3000
|
function normalizePageSize(raw) {
|
|
2945
3001
|
if (raw === void 0 || !Number.isFinite(raw)) return 200;
|
|
2946
3002
|
return Math.max(1, Math.floor(raw));
|
|
@@ -3251,18 +3307,8 @@ function serializeLogicalCondition(cond) {
|
|
|
3251
3307
|
}
|
|
3252
3308
|
return `${cond.column}.${restOp}.${stringifyValue(cond.value)}`;
|
|
3253
3309
|
}
|
|
3254
|
-
|
|
3255
|
-
|
|
3256
|
-
* `LogicalCondition` or `FilterCondition`.
|
|
3257
|
-
*
|
|
3258
|
-
* @example
|
|
3259
|
-
* deserializeLogicalCondition("status.eq.active")
|
|
3260
|
-
* // → { column: "status", operator: "==", value: "active" }
|
|
3261
|
-
*
|
|
3262
|
-
* deserializeLogicalCondition("or(status.eq.active,age.gte.18)")
|
|
3263
|
-
* // → { type: "or", conditions: [...] }
|
|
3264
|
-
*/
|
|
3265
|
-
function deserializeLogicalCondition(str) {
|
|
3310
|
+
function deserializeLogicalCondition(str, nesting = 0) {
|
|
3311
|
+
if (nesting > 32) throw new Error(`Filter groups nest more than 32 levels deep. Flatten the condition — \`or(a,or(b,c))\` is \`or(a,b,c)\`.`);
|
|
3266
3312
|
const logicalMatch = str.match(/^(and|or)\((.+)\)$/);
|
|
3267
3313
|
if (logicalMatch) {
|
|
3268
3314
|
const type = logicalMatch[1];
|
|
@@ -3273,10 +3319,10 @@ function deserializeLogicalCondition(str) {
|
|
|
3273
3319
|
for (let i = 0; i < innerStr.length; i++) if (innerStr[i] === "(") depth++;
|
|
3274
3320
|
else if (innerStr[i] === ")") depth--;
|
|
3275
3321
|
else if (innerStr[i] === "," && depth === 0) {
|
|
3276
|
-
conditions.push(deserializeLogicalCondition(innerStr.slice(start, i)));
|
|
3322
|
+
conditions.push(deserializeLogicalCondition(innerStr.slice(start, i), nesting + 1));
|
|
3277
3323
|
start = i + 1;
|
|
3278
3324
|
}
|
|
3279
|
-
conditions.push(deserializeLogicalCondition(innerStr.slice(start)));
|
|
3325
|
+
conditions.push(deserializeLogicalCondition(innerStr.slice(start), nesting + 1));
|
|
3280
3326
|
return {
|
|
3281
3327
|
type,
|
|
3282
3328
|
conditions
|
|
@@ -3390,21 +3436,22 @@ function createDriverAccessor(driver, slug, getPks = () => []) {
|
|
|
3390
3436
|
const accessor = {
|
|
3391
3437
|
async find(params) {
|
|
3392
3438
|
const filter = params?.where ? deserializeFilter(params.where) : void 0;
|
|
3393
|
-
const limit = params
|
|
3394
|
-
const offset = params?.offset ?? 0;
|
|
3439
|
+
const { limit, offset, driverOffset } = resolveFindWindow(params);
|
|
3395
3440
|
const fetchService = driver.restFetchService;
|
|
3396
3441
|
const rows = fetchService ? await fetchService.fetchCollectionForRest(slug, {
|
|
3397
3442
|
filter,
|
|
3398
|
-
|
|
3399
|
-
|
|
3443
|
+
logical: params?.logical,
|
|
3444
|
+
limit,
|
|
3445
|
+
offset: driverOffset,
|
|
3400
3446
|
orderBy: params?.orderBy?.[0],
|
|
3401
3447
|
order: params?.orderBy?.[1],
|
|
3402
3448
|
searchString: params?.searchString
|
|
3403
3449
|
}, params?.include) : await driver.fetchCollection({
|
|
3404
3450
|
path: slug,
|
|
3405
|
-
limit
|
|
3406
|
-
offset:
|
|
3451
|
+
limit,
|
|
3452
|
+
offset: driverOffset,
|
|
3407
3453
|
filter,
|
|
3454
|
+
logical: params?.logical,
|
|
3408
3455
|
orderBy: params?.orderBy?.[0],
|
|
3409
3456
|
order: params?.orderBy?.[1],
|
|
3410
3457
|
searchString: params?.searchString
|
|
@@ -3414,7 +3461,9 @@ function createDriverAccessor(driver, slug, getPks = () => []) {
|
|
|
3414
3461
|
if (driver.count) {
|
|
3415
3462
|
total = await driver.count({
|
|
3416
3463
|
path: slug,
|
|
3417
|
-
filter
|
|
3464
|
+
filter,
|
|
3465
|
+
logical: params?.logical,
|
|
3466
|
+
searchString: params?.searchString
|
|
3418
3467
|
});
|
|
3419
3468
|
hasMore = offset + rows.length < total;
|
|
3420
3469
|
}
|
|
@@ -3466,22 +3515,39 @@ function createDriverAccessor(driver, slug, getPks = () => []) {
|
|
|
3466
3515
|
values: {}
|
|
3467
3516
|
} });
|
|
3468
3517
|
},
|
|
3518
|
+
updateMany: driver.updateMany ? async (updates) => {
|
|
3519
|
+
return (await driver.updateMany({
|
|
3520
|
+
path: slug,
|
|
3521
|
+
updates: updates.map((u) => ({
|
|
3522
|
+
id: u.id,
|
|
3523
|
+
values: u.data
|
|
3524
|
+
}))
|
|
3525
|
+
})).map((row) => rowToEntity(row, slug, getPks()));
|
|
3526
|
+
} : void 0,
|
|
3527
|
+
deleteMany: driver.deleteMany ? async (ids) => {
|
|
3528
|
+
await driver.deleteMany({
|
|
3529
|
+
path: slug,
|
|
3530
|
+
ids
|
|
3531
|
+
});
|
|
3532
|
+
} : void 0,
|
|
3469
3533
|
count: driver.count ? async (params) => {
|
|
3470
3534
|
const filter = params?.where ? deserializeFilter(params.where) : void 0;
|
|
3471
3535
|
return driver.count({
|
|
3472
3536
|
path: slug,
|
|
3473
|
-
filter
|
|
3537
|
+
filter,
|
|
3538
|
+
logical: params?.logical,
|
|
3539
|
+
searchString: params?.searchString
|
|
3474
3540
|
});
|
|
3475
3541
|
} : void 0,
|
|
3476
3542
|
listen: driver.listenCollection ? (params, onUpdate, onError) => {
|
|
3477
|
-
const limit = params
|
|
3478
|
-
const offset = params?.offset ?? 0;
|
|
3543
|
+
const { limit, offset, driverOffset } = resolveFindWindow(params);
|
|
3479
3544
|
const normalize = driver.restFetchService ? inlineRelationRefs : (row) => row;
|
|
3480
3545
|
return driver.listenCollection({
|
|
3481
3546
|
path: slug,
|
|
3482
|
-
limit
|
|
3483
|
-
offset:
|
|
3547
|
+
limit,
|
|
3548
|
+
offset: driverOffset,
|
|
3484
3549
|
filter: params?.where,
|
|
3550
|
+
logical: params?.logical,
|
|
3485
3551
|
orderBy: params?.orderBy?.[0],
|
|
3486
3552
|
order: params?.orderBy?.[1],
|
|
3487
3553
|
searchString: params?.searchString,
|
|
@@ -3489,7 +3555,7 @@ function createDriverAccessor(driver, slug, getPks = () => []) {
|
|
|
3489
3555
|
onUpdate({
|
|
3490
3556
|
data: entities.map((row) => rowToEntity(normalize(row), slug, getPks())),
|
|
3491
3557
|
meta: {
|
|
3492
|
-
total: entities.length,
|
|
3558
|
+
total: offset + entities.length,
|
|
3493
3559
|
limit,
|
|
3494
3560
|
offset,
|
|
3495
3561
|
hasMore: entities.length >= limit
|
|
@@ -3666,9 +3732,24 @@ function toSdkCollectionClient(snap, slug = "collection") {
|
|
|
3666
3732
|
async update(id, data) {
|
|
3667
3733
|
return entityToRow(await snap.update(id, data));
|
|
3668
3734
|
},
|
|
3735
|
+
async updateMany(updates) {
|
|
3736
|
+
if (!Array.isArray(updates)) throw new TypeError("updateMany expects an array of { id, data } entries.");
|
|
3737
|
+
if (updates.length === 0) return [];
|
|
3738
|
+
if (!snap.updateMany) throw new Error("Bulk updates are not supported by this collection's data source. Fall back to update() per record.");
|
|
3739
|
+
return (await snap.updateMany(updates.map((u) => ({
|
|
3740
|
+
id: u.id,
|
|
3741
|
+
data: u.data
|
|
3742
|
+
})))).map(entityToRow);
|
|
3743
|
+
},
|
|
3669
3744
|
delete(id) {
|
|
3670
3745
|
return snap.delete(id);
|
|
3671
3746
|
},
|
|
3747
|
+
async deleteMany(ids) {
|
|
3748
|
+
if (!Array.isArray(ids)) throw new TypeError("deleteMany expects an array of ids.");
|
|
3749
|
+
if (ids.length === 0) return;
|
|
3750
|
+
if (!snap.deleteMany) throw new Error("Bulk deletes are not supported by this collection's data source. Fall back to delete() per record.");
|
|
3751
|
+
await snap.deleteMany(ids);
|
|
3752
|
+
},
|
|
3672
3753
|
count: snap.count ? (params) => snap.count(params) : void 0,
|
|
3673
3754
|
listen: snap.listen ? (params, onUpdate, onError) => snap.listen(params, (res) => onUpdate({
|
|
3674
3755
|
data: res.data.map(entityToRow),
|
|
@@ -3772,6 +3853,6 @@ function buildRoutedRebaseData({ defaultData, sources, resolveKey }) {
|
|
|
3772
3853
|
} });
|
|
3773
3854
|
}
|
|
3774
3855
|
//#endregion
|
|
3775
|
-
export { Vector as S,
|
|
3856
|
+
export { EntityReference as C, Vector as E, isAnonymousUid as S, GeoPoint as T, resolvePrimaryKeys as _, serializeFilter as a, resolveClientListLimit as b, paginateFind as c, createDataSourceRegistry as d, resolveDataSource as f, buildCompositeId as g, resolveCollectionRelations as h, deserializeLogicalCondition as i, resolveFindWindow as l, findRelation as m, buildSdkData as n, serializeLogicalCondition as o, getEffectiveSecurityRules as p, deserializeFilter as r, collectAllPages as s, buildRoutedRebaseData as t, CollectionRegistry as u, toSnakeCase as v, EntityRelation as w, ANONYMOUS_USER_ID as x, MAX_LIST_LIMIT as y };
|
|
3776
3857
|
|
|
3777
|
-
//# sourceMappingURL=src-
|
|
3858
|
+
//# sourceMappingURL=src-CvaxLgnM.js.map
|