@rebasepro/server 0.21.2-canary.g1ea48be → 0.23.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.
Files changed (115) hide show
  1. package/dist/{GCSStorageController-CLIJXwGS.js → GCSStorageController-CjrA4PMo.js} +37 -23
  2. package/dist/GCSStorageController-CjrA4PMo.js.map +1 -0
  3. package/dist/{S3StorageController-Dcuf8lMA.js → S3StorageController-B6pKDNVj.js} +2 -2
  4. package/dist/{S3StorageController-Dcuf8lMA.js.map → S3StorageController-B6pKDNVj.js.map} +1 -1
  5. package/dist/api/ast-schema-editor.d.ts +35 -0
  6. package/dist/api/live-schema-routes.d.ts +14 -0
  7. package/dist/api/rest/api-generator.d.ts +117 -35
  8. package/dist/api/rest/auth-collection-writes.d.ts +85 -0
  9. package/dist/api/rest/field-access-query.d.ts +6 -2
  10. package/dist/api/rest/idempotency.d.ts +7 -1
  11. package/dist/api/rest/nested-write-access.d.ts +46 -0
  12. package/dist/api/rest/write-validation.d.ts +32 -0
  13. package/dist/{ast-schema-editor-CslO8Oje.js → ast-schema-editor-Mvr50v_S.js} +104 -4
  14. package/dist/ast-schema-editor-Mvr50v_S.js.map +1 -0
  15. package/dist/auth/address-ownership.d.ts +53 -0
  16. package/dist/auth/admin-user-ops.d.ts +35 -2
  17. package/dist/auth/auth-hooks.d.ts +4 -0
  18. package/dist/auth/captcha.d.ts +5 -0
  19. package/dist/auth/interfaces.d.ts +36 -6
  20. package/dist/auth/jwt.d.ts +17 -0
  21. package/dist/auth/oauth-signin-policy.d.ts +25 -8
  22. package/dist/auth/rate-limiter.d.ts +31 -1
  23. package/dist/auth/session-routes.d.ts +7 -0
  24. package/dist/auth/token-revocation.d.ts +4 -1
  25. package/dist/{auth-DZXQRmYD.js → auth-B-GIMpDG.js} +643 -230
  26. package/dist/auth-B-GIMpDG.js.map +1 -0
  27. package/dist/backend-DTAOsLQc.js +30 -0
  28. package/dist/backend-DTAOsLQc.js.map +1 -0
  29. package/dist/backup/backup-common.d.ts +19 -0
  30. package/dist/{backup-DzI9jLwc.js → backup-D7YR94N3.js} +69 -8
  31. package/dist/backup-D7YR94N3.js.map +1 -0
  32. package/dist/boot/driver.d.ts +10 -0
  33. package/dist/boot/env.d.ts +2 -2
  34. package/dist/boot/fetch-bundle.d.ts +18 -1
  35. package/dist/boot/rls-audit-option.d.ts +26 -0
  36. package/dist/boot/sources.d.ts +1 -0
  37. package/dist/{contract-routes-eLxV0le1.js → contract-routes-CbFjuBwa.js} +2 -2
  38. package/dist/{contract-routes-eLxV0le1.js.map → contract-routes-CbFjuBwa.js.map} +1 -1
  39. package/dist/cron/cron-routes.d.ts +7 -2
  40. package/dist/cron/cron-scheduler.d.ts +128 -8
  41. package/dist/cron/cron-store.d.ts +72 -8
  42. package/dist/cron/index.d.ts +1 -1
  43. package/dist/{cron-loader-CQjvjpEw.js → cron-loader-DfTj2Hbi.js} +2 -2
  44. package/dist/{cron-loader-CQjvjpEw.js.map → cron-loader-DfTj2Hbi.js.map} +1 -1
  45. package/dist/{cron-routes-cv0hSd-O.js → cron-routes-eE8nif_b.js} +33 -12
  46. package/dist/cron-routes-eE8nif_b.js.map +1 -0
  47. package/dist/{cron-scheduler-COPQxlEq.js → cron-scheduler-B0pLfAix.js} +394 -68
  48. package/dist/cron-scheduler-B0pLfAix.js.map +1 -0
  49. package/dist/{cron-store-Bdm7JqFB.js → cron-store-TcoGz-xS.js} +133 -12
  50. package/dist/cron-store-TcoGz-xS.js.map +1 -0
  51. package/dist/{ddl-bootstrap-CfNvxMuK.js → ddl-bootstrap-C6mo0Kmz.js} +2 -25
  52. package/dist/ddl-bootstrap-C6mo0Kmz.js.map +1 -0
  53. package/dist/email/link-base.d.ts +5 -4
  54. package/dist/email/smtp-email-service.d.ts +13 -1
  55. package/dist/email/templates.d.ts +9 -0
  56. package/dist/email/types.d.ts +3 -2
  57. package/dist/env.d.ts +24 -5
  58. package/dist/{history-recorder-CYfkqP2X.js → history-recorder-B4MpJfJK.js} +8 -6
  59. package/dist/history-recorder-B4MpJfJK.js.map +1 -0
  60. package/dist/{history-store-B1CBwLfi.js → history-store-BhxWOuz9.js} +2 -2
  61. package/dist/{history-store-B1CBwLfi.js.map → history-store-BhxWOuz9.js.map} +1 -1
  62. package/dist/index.d.ts +6 -2
  63. package/dist/index.es.js +2769 -878
  64. package/dist/index.es.js.map +1 -1
  65. package/dist/init/docs.d.ts +5 -2
  66. package/dist/init/global-callbacks.d.ts +21 -0
  67. package/dist/init/shutdown.d.ts +8 -3
  68. package/dist/jobs/index.d.ts +2 -2
  69. package/dist/jobs/job-queue.d.ts +23 -2
  70. package/dist/jobs/job-store.d.ts +37 -5
  71. package/dist/jobs/types.d.ts +8 -6
  72. package/dist/{jobs-2fO2BI8P.js → jobs-CazMYhyy.js} +305 -166
  73. package/dist/jobs-CazMYhyy.js.map +1 -0
  74. package/dist/{jwt-C4OW-DNq.js → jwt-DnQHNFCl.js} +77 -25
  75. package/dist/{jwt-C4OW-DNq.js.map → jwt-DnQHNFCl.js.map} +1 -1
  76. package/dist/{keys-Qfc4XieN.js → keys-CogCQpxG.js} +18 -3
  77. package/dist/{keys-Qfc4XieN.js.map → keys-CogCQpxG.js.map} +1 -1
  78. package/dist/{logs-routes-3EEzPjhl.js → logs-routes-Bj4TYYUl.js} +7 -4
  79. package/dist/{logs-routes-3EEzPjhl.js.map → logs-routes-Bj4TYYUl.js.map} +1 -1
  80. package/dist/mcp/mcp-routes.d.ts +38 -2
  81. package/dist/mcp/mcp-tools.d.ts +7 -1
  82. package/dist/mcp/oauth-routes.d.ts +27 -0
  83. package/dist/mcp/oauth-store.d.ts +29 -13
  84. package/dist/metrics/history-recorder.d.ts +1 -1
  85. package/dist/{openapi-generator-D8ZIN_ss.js → openapi-generator-O_O24MAT.js} +34 -12
  86. package/dist/openapi-generator-O_O24MAT.js.map +1 -0
  87. package/dist/{query-parser-CoIOmflr.js → query-parser-DGRVFNM3.js} +39 -30
  88. package/dist/query-parser-DGRVFNM3.js.map +1 -0
  89. package/dist/rls-audit/index.d.ts +4 -0
  90. package/dist/{schema-editor-routes-DdLihzp0.js → schema-editor-routes-C5-lh_jO.js} +2 -2
  91. package/dist/{schema-editor-routes-DdLihzp0.js.map → schema-editor-routes-C5-lh_jO.js.map} +1 -1
  92. package/dist/{src-BYax9_rm.js → src-pmvW7BFx.js} +189 -14
  93. package/dist/src-pmvW7BFx.js.map +1 -0
  94. package/dist/{src-Br6ARbs6.js → src-vkcwKXbT.js} +2 -27
  95. package/dist/{src-Br6ARbs6.js.map → src-vkcwKXbT.js.map} +1 -1
  96. package/dist/storage/GCSStorageController.d.ts +11 -1
  97. package/dist/storage/keys.d.ts +12 -0
  98. package/dist/storage/rendition-cache.d.ts +11 -1
  99. package/dist/storage/request-keys.d.ts +67 -0
  100. package/dist/storage/types.d.ts +17 -1
  101. package/dist/types-BfKcm9do.js.map +1 -1
  102. package/package.json +9 -9
  103. package/dist/GCSStorageController-CLIJXwGS.js.map +0 -1
  104. package/dist/ast-schema-editor-CslO8Oje.js.map +0 -1
  105. package/dist/auth-DZXQRmYD.js.map +0 -1
  106. package/dist/backup-DzI9jLwc.js.map +0 -1
  107. package/dist/cron-routes-cv0hSd-O.js.map +0 -1
  108. package/dist/cron-scheduler-COPQxlEq.js.map +0 -1
  109. package/dist/cron-store-Bdm7JqFB.js.map +0 -1
  110. package/dist/ddl-bootstrap-CfNvxMuK.js.map +0 -1
  111. package/dist/history-recorder-CYfkqP2X.js.map +0 -1
  112. package/dist/jobs-2fO2BI8P.js.map +0 -1
  113. package/dist/openapi-generator-D8ZIN_ss.js.map +0 -1
  114. package/dist/query-parser-CoIOmflr.js.map +0 -1
  115. package/dist/src-BYax9_rm.js.map +0 -1
@@ -3,7 +3,7 @@ import __rebaseProcess from "process";
3
3
  globalThis.process ??= __rebaseProcess;
4
4
  __rebaseCreateRequire(import.meta.url);
5
5
  import { r as __require, t as __commonJSMin } from "./rolldown-runtime-dW7B1o5h.js";
6
- import { A as LIST_OPS, C as getDeclaredSubcollections, D as getDataSourceCapabilities, F as sortKeyToString, I as toCanonicalOp, M as REST_TO_CANONICAL, N as isRelationAggregateSort, O as ALL_WHERE_FILTER_OPS, T as isRelationalCollectionConfig, j as NULL_OPS, k as CANONICAL_TO_REST, p as resolveResourceRefs, w as isPostgresCollectionConfig, x as rewriteLegacyRlsFunctions } from "./src-Br6ARbs6.js";
6
+ import { A as NULL_OPS, C as isPostgresCollectionConfig, D as ALL_WHERE_FILTER_OPS, E as getDataSourceCapabilities, F as toCanonicalOp, M as isRelationAggregateSort, O as CANONICAL_TO_REST, P as sortKeyToString, S as getDeclaredSubcollections, b as rewriteLegacyRlsFunctions, f as resolveResourceRefs, j as REST_TO_CANONICAL, k as LIST_OPS, w as isRelationalCollectionConfig } from "./src-vkcwKXbT.js";
7
7
  //#region ../types/src/errors.ts
8
8
  /**
9
9
  * The single error type thrown across the entire Rebase client surface —
@@ -261,6 +261,10 @@ var Vector = class {
261
261
  */
262
262
  var JUNCTION_PIVOT_KEY = "_pivot";
263
263
  /** @group Models */
264
+ function hasForeignKeyOnTarget(relation) {
265
+ return relation.kind === "hasOne" || relation.kind === "hasMany";
266
+ }
267
+ /** @group Models */
264
268
  function isManyToMany(relation) {
265
269
  return relation.kind === "manyToMany";
266
270
  }
@@ -1528,6 +1532,42 @@ function suggestNearMiss(known, key) {
1528
1532
  return known.find((candidate) => isNearMiss(candidate, key));
1529
1533
  }
1530
1534
  /**
1535
+ * The terms a user meant when they typed into a search box.
1536
+ *
1537
+ * A search box is not a substring box. Typing `sebastian melendez` on a
1538
+ * collection whose name is split across `first_name` and `last_name` has to
1539
+ * find the row, and matching the whole string against each field separately
1540
+ * cannot: no single column holds both words. Splitting on whitespace and
1541
+ * requiring *every* term to match *some* field is what does, and it is what
1542
+ * `websearch_to_tsquery` already does for collections that declared a `search`
1543
+ * block — so this is also what keeps the two search paths answering the same
1544
+ * question.
1545
+ *
1546
+ * It fixes the trailing space too: `sebastian ` matched nothing at all, because
1547
+ * the space was part of the pattern.
1548
+ *
1549
+ * A double-quoted run is one term, again matching the full-text path, so a
1550
+ * caller who really does want the phrase can ask for it. An unbalanced quote is
1551
+ * stripped rather than honoured — the alternative is that everything after a
1552
+ * stray `"` silently becomes one long term that matches nothing.
1553
+ *
1554
+ * Returns an empty array for a string with no terms in it at all (whitespace,
1555
+ * or nothing but quotes); the caller decides what an empty search means, since
1556
+ * only it knows whether "no constraint" or "no rows" is the safe reading.
1557
+ */
1558
+ function splitSearchTerms(searchString, maxTerms = 8) {
1559
+ const terms = [];
1560
+ const pattern = /"([^"]*)"|(\S+)/g;
1561
+ let match;
1562
+ while ((match = pattern.exec(searchString)) !== null) {
1563
+ const term = (match[1] ?? match[2].replace(/"/g, "")).trim();
1564
+ if (!term) continue;
1565
+ terms.push(term);
1566
+ if (terms.length >= maxTerms) break;
1567
+ }
1568
+ return terms;
1569
+ }
1570
+ /**
1531
1571
  * Deep clone a value, preserving function references and class instances.
1532
1572
  * Unlike structuredClone, this handles objects that contain functions
1533
1573
  * (e.g. CollectionConfig with target(), childCollections(), callbacks).
@@ -3230,6 +3270,7 @@ var REBASE_INTERNAL_TABLES = [
3230
3270
  "api_keys",
3231
3271
  "cron_logs",
3232
3272
  "cron_claims",
3273
+ "cron_job_state",
3233
3274
  "jobs",
3234
3275
  "rate_limit_hits",
3235
3276
  "idempotency_keys",
@@ -4190,6 +4231,37 @@ var CollectionRegistry = class {
4190
4231
  };
4191
4232
  }
4192
4233
  };
4234
+ //#endregion
4235
+ //#region ../common/src/collections/engine-support.ts
4236
+ /**
4237
+ * Refuse a `beforeQuery` hook on a collection Postgres does not serve.
4238
+ *
4239
+ * `beforeQuery` narrows a read *before it is compiled*, which means compiling
4240
+ * a declarative filter into the query the engine is about to run. Only
4241
+ * `@rebasepro/server-postgres` does that today. On any other engine the hook
4242
+ * would look configured and do nothing — and for a hook whose whole purpose is
4243
+ * to restrict which rows come back, "nothing" means every row served to
4244
+ * everybody.
4245
+ *
4246
+ * So it is a boot failure, named. The alternative — declaring the hook only on
4247
+ * `PostgresCollectionConfig`, the way `search` is — is not available:
4248
+ * `callbacks` is one engine-agnostic type shared by every collection, and
4249
+ * splitting it would fork `afterRead` and the five write hooks along with it.
4250
+ *
4251
+ * Lives here rather than in either driver because both have to run it: the
4252
+ * Postgres schema planner sees every collection in a mixed app, and a
4253
+ * Mongo-only app never boots a Postgres planner at all.
4254
+ *
4255
+ * Called with *every* collection, before an engine filters any out.
4256
+ */
4257
+ var assertBeforeQueryIsPostgresOnly = (collections) => {
4258
+ for (const collection of collections) {
4259
+ if (isPostgresCollectionConfig(collection)) continue;
4260
+ if (!collection.callbacks?.beforeQuery) continue;
4261
+ const engine = collection.engine ?? "non-postgres";
4262
+ throw new Error(`${collection.slug}.callbacks.beforeQuery: narrowing a read before it is compiled is a Postgres feature, and this collection is served by \`${engine}\`. Remove the hook — it would otherwise look configured while every read kept returning every row the engine allows. Redaction that works on every engine is \`afterRead\`.`);
4263
+ }
4264
+ };
4193
4265
  /**
4194
4266
  * What a property's access rules actually are, with `excludeFromApi` expanded.
4195
4267
  *
@@ -4250,18 +4322,36 @@ function canWriteField(property, viewer) {
4250
4322
  * who knows the table can send `password_hash` as readily as `passwordHash`, and
4251
4323
  * a rule that only knew the wire name would be one rename away from useless.
4252
4324
  *
4325
+ * A restricted to-one relation takes its foreign key with it. `bandId: 7` names
4326
+ * the band exactly as `band: { id: 7 }` does, and the row carries the column
4327
+ * beside the relation — so a rule on the relation that left the key alone
4328
+ * withheld the value from the row and still let `?bandId=7` ask for it.
4329
+ *
4253
4330
  * `kind` picks which half of the rule is read; nothing else differs.
4254
4331
  */
4255
4332
  function restrictedFieldNames(collection, viewer, kind) {
4256
4333
  const declared = [];
4257
4334
  const refused = /* @__PURE__ */ new Set();
4258
4335
  const allowed = kind === "read" ? canReadField : canWriteField;
4259
- for (const [name, property] of Object.entries(collection.properties ?? {})) {
4260
- if (allowed(property, viewer)) continue;
4261
- declared.push(name);
4336
+ const properties = collection.properties ?? {};
4337
+ let relations;
4338
+ const restrict = (name) => {
4339
+ if (name in properties && !declared.includes(name)) declared.push(name);
4262
4340
  refused.add(name);
4341
+ };
4342
+ for (const [name, property] of Object.entries(properties)) {
4343
+ if (allowed(property, viewer)) continue;
4344
+ restrict(name);
4263
4345
  const columnName = property.columnName;
4264
4346
  if (columnName) refused.add(columnName);
4347
+ if (property.type === "relation") {
4348
+ relations ??= resolveCollectionRelations(collection);
4349
+ const relation = findRelation(relations, name);
4350
+ if (relation?.kind === "belongsTo") {
4351
+ restrict(fieldKeyForColumn(collection, relation.localKey));
4352
+ refused.add(relation.localKey);
4353
+ }
4354
+ }
4265
4355
  }
4266
4356
  return {
4267
4357
  declared,
@@ -5027,19 +5117,23 @@ function normalizeMaxRows(raw) {
5027
5117
  * @param label the collection name, so an error says which walk failed
5028
5118
  */
5029
5119
  async function* paginateFind(find, params, label = "collection") {
5030
- const { pageSize, cursor, maxPages, ...rest } = params ?? {};
5120
+ const { pageSize, cursor, maxPages, after: startAfter, offset: startOffset, page: startPage, ...rest } = params ?? {};
5031
5121
  const findParams = { ...rest };
5032
5122
  const size = normalizePageSize(pageSize);
5033
5123
  const pageCap = normalizeMaxPages(maxPages);
5034
- const seekRequested = cursor !== void 0 && cursor !== null;
5035
- if (seekRequested) {
5124
+ const seekRequested = cursor !== void 0 && cursor !== null || !!startAfter;
5125
+ if (cursor !== void 0 && cursor !== null) {
5036
5126
  const field = typeof cursor === "string" ? cursor : cursor.field;
5037
5127
  const requested = typeof cursor === "object" && cursor !== null ? cursor.direction : void 0;
5038
5128
  if (!normalizeOrderBy(findParams.orderBy)) findParams.orderBy = [field, requested ?? "asc"];
5039
5129
  }
5040
- let offset = 0;
5130
+ let offset = resolveFindWindow({
5131
+ limit: size,
5132
+ offset: startOffset,
5133
+ page: startPage
5134
+ }).offset;
5041
5135
  let pages = 0;
5042
- let after;
5136
+ let after = startAfter || void 0;
5043
5137
  for (;;) {
5044
5138
  if (pages >= pageCap) throw new RebasePaginationError("max-pages", `Iterating "${label}" made ${pages} requests without the server reporting the end of the collection. Stopping rather than looping forever — raise \`maxPages\` if the walk is genuinely this long, or check that the backend sets \`meta.hasMore\`.`);
5045
5139
  const pageParams = {
@@ -5104,9 +5198,16 @@ async function collectAllPages(find, params, label = "collection") {
5104
5198
  * Relation values (`EntityRelation` instances or `{ __type: "relation", id, path }`
5105
5199
  * objects) are serialized as their raw id — the wire format only carries the
5106
5200
  * value to compare against the FK column.
5201
+ *
5202
+ * A `Date` is its ISO 8601 instant — what JSON makes of it on the socket and
5203
+ * in-process, so one filter names one instant through every door. `String()`
5204
+ * gave the viewer's local zone, no milliseconds and a parenthesised zone name
5205
+ * Postgres cannot parse. An invalid date keeps its "Invalid Date" spelling for
5206
+ * the server to refuse, rather than throwing a `RangeError` from here.
5107
5207
  */
5108
5208
  function stringifyValue(value) {
5109
5209
  if (value === null) return "null";
5210
+ if (value instanceof Date && !Number.isNaN(value.getTime())) return value.toISOString();
5110
5211
  const relation = normalizeToEntityRelation(value);
5111
5212
  if (relation) return String(relation.id);
5112
5213
  return String(value);
@@ -5164,6 +5265,41 @@ function unescapeWireValue(value) {
5164
5265
  return result;
5165
5266
  }
5166
5267
  /**
5268
+ * Whether a scalar, sent raw as a query parameter's operand, would be read
5269
+ * back as something other than itself.
5270
+ *
5271
+ * A query parameter owns its whole value, so its scalar goes out unescaped —
5272
+ * `eq.a,b`, `eq.C:\x` — and the decoder returns it verbatim. Two shapes break
5273
+ * that. A parenthesised operand is a list for every operator (so that
5274
+ * `["==", ["a","b"]]` on an array column stays a list), so raw, the scalar
5275
+ * `"(deleted)"` would arrive as `["deleted"]`: an `==` matching nothing, a
5276
+ * `!=` returning the very rows it excludes. Such a scalar is sent escaped,
5277
+ * `eq.\(deleted\)`. And that spelling has to be told apart from a raw value
5278
+ * that looks the same, so a scalar of *that* shape is escaped in turn.
5279
+ *
5280
+ * Everything else stays raw, so a value an older client sends decodes as it
5281
+ * always has — unless it is exactly the escaped spelling of such a scalar,
5282
+ * which decodes to the scalar it spells.
5283
+ */
5284
+ function scalarNeedsEscape(value) {
5285
+ if (value.startsWith("(") && value.endsWith(")")) return true;
5286
+ return decodeEscapedScalar(value) !== void 0;
5287
+ }
5288
+ /**
5289
+ * The scalar an operand is the escaped spelling of, when it is one.
5290
+ *
5291
+ * Exact on purpose: only an operand that {@link escapeWireValue} produces from
5292
+ * a scalar that {@link scalarNeedsEscape} is decoded. Any other operand —
5293
+ * including a raw backslash an older client sent, like `\\server\share` — is
5294
+ * left verbatim. Terminates because an operand that matches contains an
5295
+ * escape pair, so the value is strictly shorter than it.
5296
+ */
5297
+ function decodeEscapedScalar(operand) {
5298
+ if (!operand.startsWith("\\")) return void 0;
5299
+ const value = unescapeWireValue(operand);
5300
+ return escapeWireValue(value) === operand && scalarNeedsEscape(value) ? value : void 0;
5301
+ }
5302
+ /**
5167
5303
  * Split a parenthesized list string on unescaped commas.
5168
5304
  * Input is the content between `(` and `)`.
5169
5305
  *
@@ -5408,6 +5544,42 @@ function readTuple(field, raw) {
5408
5544
  if (isOperatorShaped(op)) throw new UnknownFilterOperatorError(field, op);
5409
5545
  }
5410
5546
  /**
5547
+ * The query-parameter names a REST listing reads as something other than a
5548
+ * field filter: pagination, sorting, includes, projection, search, the logical
5549
+ * groups, the JSON `where` dialect, an aggregate's `select`/`groupBy`, and the
5550
+ * soft-delete switches.
5551
+ *
5552
+ * One list for both ends. The server skips these names when it collects
5553
+ * `?<field>=<op>.<value>` filters, and the SDK sends a filter on a column with
5554
+ * one of these names inside `?where=` instead — a collection is free to have a
5555
+ * `page`, `select` or `hard` column, and a filter on it sent as its own
5556
+ * parameter was read as the parameter and never applied.
5557
+ */
5558
+ var RESERVED_QUERY_KEYS = /* @__PURE__ */ new Set([
5559
+ "limit",
5560
+ "offset",
5561
+ "page",
5562
+ "after",
5563
+ "orderBy",
5564
+ "include",
5565
+ "fields",
5566
+ "distinct",
5567
+ "searchString",
5568
+ "searchExplain",
5569
+ "vector_search",
5570
+ "vector",
5571
+ "vector_distance",
5572
+ "vector_threshold",
5573
+ "or",
5574
+ "and",
5575
+ "not",
5576
+ "where",
5577
+ "select",
5578
+ "groupBy",
5579
+ "deleted",
5580
+ "hard"
5581
+ ]);
5582
+ /**
5411
5583
  * Encode the `<op>.<value>` half of a wire condition.
5412
5584
  *
5413
5585
  * This is the single leaf encoder. Both wire positions that carry a condition
@@ -5435,7 +5607,7 @@ function serializeOperatorAndValue(op, value, { escapeScalar, where }) {
5435
5607
  return `${restOp}.(${value.map((v) => escapeWireValue(stringifyValue(v))).join(",")})`;
5436
5608
  }
5437
5609
  const scalar = stringifyValue(value);
5438
- return `${restOp}.${escapeScalar ? escapeWireValue(scalar) : scalar}`;
5610
+ return `${restOp}.${escapeScalar || !LIST_OPS.has(op) && scalarNeedsEscape(scalar) ? escapeWireValue(scalar) : scalar}`;
5439
5611
  }
5440
5612
  /**
5441
5613
  * Serialize a single canonical condition tuple to a PostgREST dot-string.
@@ -5531,7 +5703,10 @@ var NULL_OPERANDS = /* @__PURE__ */ new Set([
5531
5703
  * operand: only {@link NULL_OPERANDS}. `notnull.reason` is the value
5532
5704
  * `"notnull.reason"`, not "reason is not null".
5533
5705
  * - **Everything else** takes one scalar, and any remainder is one — including
5534
- * the empty string, so `eq.` really is "equals the empty string".
5706
+ * the empty string, so `eq.` really is "equals the empty string". A
5707
+ * parenthesised remainder is a list for these too (`eq.(a,b)` is array
5708
+ * equality); a scalar that is itself parenthesised arrives escaped,
5709
+ * `eq.\(none\)`, and is decoded here — see {@link scalarNeedsEscape}.
5535
5710
  *
5536
5711
  * ### The one ambiguity that remains, and how to write past it
5537
5712
  *
@@ -5566,7 +5741,7 @@ function deserializeSingle(raw) {
5566
5741
  return [canonicalOp, inner === EMPTY_LIST_TOKEN ? [] : splitListItems(inner)];
5567
5742
  }
5568
5743
  if (LIST_OPS.has(canonicalOp)) return ["==", raw];
5569
- return [canonicalOp, rest];
5744
+ return [canonicalOp, decodeEscapedScalar(rest) ?? rest];
5570
5745
  }
5571
5746
  /**
5572
5747
  * Convert a PostgREST-style querystring record to `FilterValues`.
@@ -6508,6 +6683,6 @@ function buildRoutedRebaseData({ defaultData, sources, resolveKey }) {
6508
6683
  }
6509
6684
  new Set(REBASE_INTERNAL_TABLES);
6510
6685
  //#endregion
6511
- export { resolveClientListLimit as $, isRelationalCollection as A, findRelation as B, decodeCursor as C, restrictedFieldNames as D, effectiveAccess as E, getJunctionConfigForRelation as F, buildCompositeId as G, isRelationRequired as H, getEffectiveSecurityRules as I, suggestNearMiss as J, resolvePrimaryKeys as K, getTenantConfig as L, authSecretsMissingExclusion as M, REBASE_USER_ROLE as N, CollectionRegistry as O, revokeInternalTableSql as P, MAX_LIST_LIMIT as Q, securityRuleToConditions as R, cursorToStartAfter as S, canWriteField as T, resolveCollectionRelations as U, getTableName as V, enumToObjectEntries as W, unref as X, toSnakeCase as Y, ListLimitError as Z, OrderBySpecError as _, deserializeLogicalCondition as a, isAnonymousUid as at, CursorError as b, collectAllPages as c, isToMany as ct, IncludeSpecError as d, GeoPoint as dt, BATCH_REF_KEY as et, deserializeInclude as f, Vector as ft, topLevelIncludeNames as g, unsupportedMethod as gt, serializeInclude as h, isUnsupported as ht, deserializeFilter as i, ANONYMOUS_USER_ID as it, resolveDataSource as j, createDataSourceRegistry as k, paginateFind as l, EntityReference as lt, normalizeInclude as m, RebaseClientError as mt, buildSdkData as n, hasFieldOperation as nt, serializeFilter as o, JUNCTION_PIVOT_KEY as ot, mergeIncludeSpecs as p, RebaseApiError as pt, hydrateRegExp as q, UnknownFilterOperatorError as r, isFieldOperation as rt, serializeLogicalCondition as s, isManyToMany as st, buildRoutedRebaseData as t, FIELD_OPERATORS as tt, resolveFindWindow as u, EntityRelation as ut, normalizeOrderBy as v, reconcileCursorOrder as w, CursorMismatchError as x, serializeOrderBy as y, fieldKeyForColumn as z };
6686
+ export { toSnakeCase as $, createDataSourceRegistry as A, fieldKeyForColumn as B, cursorToStartAfter as C, restrictedFieldNames as D, effectiveAccess as E, revokeInternalTableSql as F, resolveCollectionRelations as G, getTableName as H, getJunctionConfigForRelation as I, resolvePrimaryKeys as J, enumToObjectEntries as K, getEffectiveSecurityRules as L, resolveDataSource as M, authSecretsMissingExclusion as N, assertBeforeQueryIsPostgresOnly as O, REBASE_USER_ROLE as P, suggestNearMiss as Q, getTenantConfig as R, CursorMismatchError as S, reconcileCursorOrder as T, isRelationRequired as U, findRelation as V, relationDeclaringProperty as W, isObject as X, hydrateRegExp as Y, splitSearchTerms as Z, topLevelIncludeNames as _, Vector as _t, deserializeFilter as a, FIELD_OPERATORS as at, serializeOrderBy as b, isUnsupported as bt, serializeLogicalCondition as c, ANONYMOUS_USER_ID as ct, resolveFindWindow as d, hasForeignKeyOnTarget as dt, unref as et, IncludeSpecError as f, isManyToMany as ft, serializeInclude as g, GeoPoint as gt, normalizeInclude as h, EntityRelation as ht, UnknownFilterOperatorError as i, BATCH_REF_KEY as it, isRelationalCollection as j, CollectionRegistry as k, collectAllPages as l, isAnonymousUid as lt, mergeIncludeSpecs as m, EntityReference as mt, buildSdkData as n, MAX_LIST_LIMIT as nt, deserializeLogicalCondition as o, hasFieldOperation as ot, deserializeInclude as p, isToMany as pt, buildCompositeId as q, RESERVED_QUERY_KEYS as r, resolveClientListLimit as rt, serializeFilter as s, isFieldOperation as st, buildRoutedRebaseData as t, ListLimitError as tt, paginateFind as u, JUNCTION_PIVOT_KEY as ut, OrderBySpecError as v, RebaseApiError as vt, decodeCursor as w, CursorError as x, unsupportedMethod as xt, normalizeOrderBy as y, RebaseClientError as yt, securityRuleToConditions as z };
6512
6687
 
6513
- //# sourceMappingURL=src-BYax9_rm.js.map
6688
+ //# sourceMappingURL=src-pmvW7BFx.js.map