@rebasepro/server-postgres 0.10.1-canary.b1e3dbf → 0.10.1-canary.ff9ccd6

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.es.js CHANGED
@@ -1,6 +1,9 @@
1
1
  import { createRequire as __createRequire } from "module";
2
2
  import process from "process";
3
- const require = __createRequire(import.meta.url);
3
+ __createRequire(import.meta.url);
4
+ import { i as __toESM, n as __exportAll, r as __require, t as __commonJSMin } from "./chunk-DSJWtz9O.js";
5
+ import { a as isSchemaAdmin, i as isSQLAdmin, l as isPostgresCollectionConfig, m as Vector, n as getDataSourceCapabilities, o as ANONYMOUS_USER_ID, r as isChannelBusInstance } from "./src-CBgtrPhJ.js";
6
+ import { C as createRelationRefWithData, D as mergeDeep, E as getPolicyNamesForRule, O as camelCase, S as createRelationRef, T as updateDateAutoValues, _ as getTableVarName, a as getJunctionCollectionConfig, b as getDeclaredPrimaryKeys, c as getEffectiveSecurityRules, d as securityRuleToConditions, f as findAnonymousGrants, g as getTableName$1, h as getEnumVarName, i as CollectionRegistry, k as toSnakeCase, l as buildPropertyCallbacks, m as getColumnName, n as detectJunctionTables, o as getJunctionSecurityRules, p as findRelation, r as buildSdkData, s as resolveJunctionSpecs, t as classifyTable, u as policyToPostgres, v as resolveCollectionRelations, w as normalizeToEntityRelation, x as parseIdValues, y as buildCompositeId } from "./src-DG6ZsQQ3.js";
4
7
  import { Client, Pool } from "pg";
5
8
  import { drizzle } from "drizzle-orm/node-postgres";
6
9
  import { ApiError, createEmailService, extractUserFromToken, loadCollectionsFromDirectory, logger, safeCompare } from "@rebasepro/server";
@@ -31,4568 +34,174 @@ import { finished } from "node:stream/promises";
31
34
  import { Duplex, PassThrough, Readable, Transform, Writable, getDefaultHighWaterMark } from "node:stream";
32
35
  import { Buffer as Buffer$1 } from "node:buffer";
33
36
  import { fileURLToPath as fileURLToPath$1 } from "url";
34
- //#region \0rolldown/runtime.js
35
- var __create = Object.create;
36
- var __defProp = Object.defineProperty;
37
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
38
- var __getOwnPropNames = Object.getOwnPropertyNames;
39
- var __getProtoOf = Object.getPrototypeOf;
40
- var __hasOwnProp = Object.prototype.hasOwnProperty;
41
- var __commonJSMin = (cb, mod) => () => (mod || (cb((mod = { exports: {} }).exports, mod), cb = null), mod.exports);
42
- var __exportAll = (all, no_symbols) => {
43
- let target = {};
44
- for (var name in all) __defProp(target, name, {
45
- get: all[name],
46
- enumerable: true
47
- });
48
- if (!no_symbols) __defProp(target, Symbol.toStringTag, { value: "Module" });
49
- return target;
50
- };
51
- var __copyProps = (to, from, except, desc) => {
52
- if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
53
- key = keys[i];
54
- if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
55
- get: ((k) => from[k]).bind(null, key),
56
- enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
57
- });
58
- }
59
- return to;
60
- };
61
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
62
- value: mod,
63
- enumerable: true
64
- }) : target, mod));
65
- var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, { get: (a, b) => (typeof require !== "undefined" ? require : a)[b] }) : x)(function(x) {
66
- if (typeof require !== "undefined") return require.apply(this, arguments);
67
- throw Error("Calling `require` for \"" + x + "\" in an environment that doesn't expose the `require` function. See https://rolldown.rs/in-depth/bundling-cjs#require-external-modules for more details.");
68
- });
69
- //#endregion
70
37
  //#region src/connection.ts
71
- var connection_exports = /* @__PURE__ */ __exportAll({
72
- createDirectDatabaseConnection: () => createDirectDatabaseConnection,
73
- createPostgresDatabaseConnection: () => createPostgresDatabaseConnection,
74
- createReadReplicaConnection: () => createReadReplicaConnection,
75
- guardPoolAgainstDirtyRelease: () => guardPoolAgainstDirtyRelease
76
- });
77
- var DEFAULT_POOL = {
78
- max: 20,
79
- idleTimeoutMillis: 3e4,
80
- connectionTimeoutMillis: 1e4,
81
- queryTimeout: 6e4,
82
- statementTimeout: 3e4,
83
- keepAlive: true
84
- };
85
- /** ReadyForQuery status byte: `I` idle, `T` in transaction, `E` failed transaction. */
86
- var TX_IDLE = "I";
87
- /**
88
- * Destroy pool clients that are released while still inside a transaction.
89
- *
90
- * pg-pool returns a client to the idle list whenever `release()` is called
91
- * without an error — even if the connection is still mid-transaction (status
92
- * `T`/`E`). That happens in practice: drizzle's pool transaction releases in
93
- * a `finally` after attempting ROLLBACK, and if the ROLLBACK itself fails
94
- * (e.g. it was queued behind a statement that hit the client-side
95
- * query_timeout), the client goes back dirty. The next checkout then runs
96
- * its statements inside the zombie transaction — with the previous request's
97
- * `app.*` RLS GUCs still applied, which turns unrelated queries into
98
- * RLS-scoped ones (observed in production as registration failing with
99
- * SQLSTATE 42501 under a leaked anonymous context).
100
- *
101
- * pg-pool emits `release` before it consults its private `_expired` set, so
102
- * marking the client expired here makes `_release()` destroy it instead of
103
- * pooling it. Both `client._txStatus` (pg ≥ 8.16) and `pool._expired` are
104
- * private APIs — feature-detect and fall back to loud logging so an upstream
105
- * change degrades to observability, never to silent corruption.
106
- */
107
- function guardPoolAgainstDirtyRelease(pool, label) {
108
- pool.on("release", (err, client) => {
109
- if (err) return;
110
- const txStatus = client?._txStatus;
111
- if (typeof txStatus !== "string" || txStatus === TX_IDLE) return;
112
- const expired = pool._expired;
113
- if (expired && typeof expired.add === "function" && typeof expired.has === "function" && client && typeof client === "object") {
114
- expired.add(client);
115
- logger.error(`[${label}] Client released back to the pool while still in a transaction (status '${txStatus}') — destroying it so the open transaction and its session state (RLS GUCs) cannot leak into the next request.`);
116
- } else logger.error(`[${label}] Client released mid-transaction (status '${txStatus}') but the pool's internal expiry set is unavailable (pg-pool internals changed?). The connection may leak its open transaction into subsequent requests.`);
117
- });
118
- }
119
- /**
120
- * Create a Drizzle-backed Postgres connection with a production-grade
121
- * connection pool.
122
- *
123
- * @param connectionString Postgres connection URL
124
- * @param schema Optional Drizzle schema for the relational API
125
- * @param poolConfig Optional pool tuning (merged over defaults)
126
- *
127
- * @returns `{ db, pool, connectionString }` — the `pool` is exposed so
128
- * callers can register shutdown hooks (`pool.end()`) or monitor
129
- * pool metrics.
130
- */
131
- function createPostgresDatabaseConnection(connectionString, schema, poolConfig) {
132
- const opts = {
133
- ...DEFAULT_POOL,
134
- ...poolConfig
135
- };
136
- const pool = new Pool({
137
- connectionString,
138
- max: opts.max,
139
- idleTimeoutMillis: opts.idleTimeoutMillis,
140
- connectionTimeoutMillis: opts.connectionTimeoutMillis,
141
- query_timeout: opts.queryTimeout,
142
- statement_timeout: opts.statementTimeout,
143
- keepAlive: opts.keepAlive,
144
- keepAliveInitialDelayMillis: 0
145
- });
146
- pool.on("error", (err) => {
147
- logger.error("[pg-pool] Unexpected pool error", { detail: err.message });
148
- if (err.message.includes("ETIMEDOUT")) logger.warn("[pg-pool] Connection timeout detected — pool will auto-retry");
149
- });
150
- guardPoolAgainstDirtyRelease(pool, "pg-pool");
151
- return {
152
- db: schema ? drizzle(pool, { schema }) : drizzle(pool),
153
- pool,
154
- connectionString
155
- };
156
- }
157
- /**
158
- * Create a direct (non-pooled) connection for operations that require
159
- * session-level features incompatible with PgBouncer transaction mode,
160
- * such as LISTEN/NOTIFY, prepared statements, or advisory locks.
161
- *
162
- * Uses a smaller pool since this is only for specific use cases.
163
- */
164
- function createDirectDatabaseConnection(connectionString, schema, poolConfig) {
165
- const opts = {
166
- ...DEFAULT_POOL,
167
- max: 5,
168
- ...poolConfig
169
- };
170
- const pool = new Pool({
171
- connectionString,
172
- max: opts.max,
173
- idleTimeoutMillis: opts.idleTimeoutMillis,
174
- connectionTimeoutMillis: opts.connectionTimeoutMillis,
175
- query_timeout: opts.queryTimeout,
176
- statement_timeout: opts.statementTimeout,
177
- keepAlive: opts.keepAlive,
178
- keepAliveInitialDelayMillis: 0
179
- });
180
- pool.on("error", (err) => {
181
- logger.error("[pg-direct-pool] Unexpected pool error", { detail: err.message });
182
- });
183
- guardPoolAgainstDirtyRelease(pool, "pg-direct-pool");
184
- return {
185
- db: schema ? drizzle(pool, { schema }) : drizzle(pool),
186
- pool,
187
- connectionString
188
- };
189
- }
190
- /**
191
- * Create a read-only connection for routing read queries to replicas.
192
- * Uses a moderate pool size since reads are distributed across replicas.
193
- */
194
- function createReadReplicaConnection(connectionString, schema, poolConfig) {
195
- const opts = {
196
- ...DEFAULT_POOL,
197
- max: 10,
198
- ...poolConfig
199
- };
200
- const pool = new Pool({
201
- connectionString,
202
- max: opts.max,
203
- idleTimeoutMillis: opts.idleTimeoutMillis,
204
- connectionTimeoutMillis: opts.connectionTimeoutMillis,
205
- query_timeout: opts.queryTimeout,
206
- statement_timeout: opts.statementTimeout,
207
- keepAlive: opts.keepAlive,
208
- keepAliveInitialDelayMillis: 0
209
- });
210
- pool.on("error", (err) => {
211
- logger.error("[pg-replica-pool] Unexpected pool error", { detail: err.message });
212
- });
213
- guardPoolAgainstDirtyRelease(pool, "pg-replica-pool");
214
- return {
215
- db: schema ? drizzle(pool, { schema }) : drizzle(pool),
216
- pool,
217
- connectionString
218
- };
219
- }
220
- //#endregion
221
- //#region ../types/src/types/entities.ts
222
- /**
223
- * Class used to create a reference to a entity in a different path
224
- */
225
- var EntityRelation = class {
226
- __type = "relation";
227
- /**
228
- * ID of the entity
229
- */
230
- id;
231
- /**
232
- * A string representing the path of the referenced document (relative
233
- * to the root of the database).
234
- */
235
- path;
236
- /**
237
- * Pre-fetched data payload to eliminate N+1 queries.
238
- * When present, clients can use this directly instead of fetching.
239
- */
240
- data;
241
- constructor(id, path, data) {
242
- this.id = id;
243
- this.path = path;
244
- this.data = data;
245
- }
246
- get pathWithId() {
247
- return `${this.path}/${this.id}`;
248
- }
249
- isEntityReference() {
250
- return false;
251
- }
252
- isEntityRelation() {
253
- return true;
254
- }
255
- };
256
- var Vector = class {
257
- value;
258
- constructor(value) {
259
- this.value = value;
260
- }
261
- };
262
- //#endregion
263
- //#region ../types/src/types/filter-operators.ts
264
- /** Maps REST short-code operators to their canonical equivalents. */
265
- var REST_TO_CANONICAL = {
266
- "eq": "==",
267
- "neq": "!=",
268
- "gt": ">",
269
- "gte": ">=",
270
- "lt": "<",
271
- "lte": "<=",
272
- "in": "in",
273
- "nin": "not-in",
274
- "cs": "array-contains",
275
- "csa": "array-contains-any",
276
- "like": "like",
277
- "ilike": "ilike",
278
- "nlike": "not-like",
279
- "nilike": "not-ilike",
280
- "isnull": "is-null",
281
- "notnull": "is-not-null"
282
- };
283
- /**
284
- * Operators that test for null/not-null and therefore ignore their value.
285
- * Codecs normalize the value of these conditions to `null`.
286
- */
287
- var NULL_OPS = new Set(["is-null", "is-not-null"]);
288
- /**
289
- * Every canonical operator, in a stable order. Useful for engine capability
290
- * declarations ({@link DataSourceCapabilities.filterOperators}) and for
291
- * building operator subsets.
292
- * @group Models
293
- */
294
- var ALL_WHERE_FILTER_OPS = [
295
- "<",
296
- "<=",
297
- "==",
298
- "!=",
299
- ">=",
300
- ">",
301
- "in",
302
- "not-in",
303
- "array-contains",
304
- "array-contains-any",
305
- "like",
306
- "ilike",
307
- "not-like",
308
- "not-ilike",
309
- "is-null",
310
- "is-not-null"
311
- ];
312
- /** All canonical operator strings for runtime validation. */
313
- var CANONICAL_OPS = new Set(ALL_WHERE_FILTER_OPS);
314
- /**
315
- * Resolve any operator string (canonical or REST short-code) to its
316
- * canonical `WhereFilterOp` form. Returns `undefined` for unknown operators.
317
- *
318
- * @example
319
- * toCanonicalOp("==") // "=="
320
- * toCanonicalOp("eq") // "=="
321
- * toCanonicalOp("cs") // "array-contains"
322
- * toCanonicalOp("xyz") // undefined
323
- */
324
- function toCanonicalOp(op) {
325
- if (CANONICAL_OPS.has(op)) return op;
326
- return REST_TO_CANONICAL[op];
327
- }
328
- //#endregion
329
- //#region ../types/src/types/collections.ts
330
- /**
331
- * Type guard for PostgreSQL collections.
332
- * Returns true if the collection uses the Postgres engine (or the default engine).
333
- * @group Models
334
- */
335
- function isPostgresCollectionConfig(collection) {
336
- return !collection.engine || collection.engine === "postgres";
337
- }
338
- /**
339
- * Reads a collection's driver-declared subcollections thunk (the `subcollections`
340
- * field) independent of engine identity, so engine-agnostic code doesn't have to
341
- * type-guard against a specific driver. Returns `undefined` when the collection
342
- * declares none.
343
- *
344
- * Pair with `getDataSourceCapabilities(engine).supportsSubcollections` to decide
345
- * whether the engine honours subcollections at all before reading them.
346
- * @group Models
347
- */
348
- function getDeclaredSubcollections(collection) {
349
- return collection.subcollections;
350
- }
351
- //#endregion
352
- //#region ../types/src/types/policy.ts
353
- /**
354
- * The id a request without a logged-in user reports as `auth.uid()`.
355
- *
356
- * A user-context request always sets `app.uid`: blank would read back as
357
- * `NULL`, and `NULL` is how the trusted server context is recognised, so an
358
- * anonymous visitor would be promoted to server privileges. The driver
359
- * therefore substitutes this sentinel at the single chokepoint where the GUC
360
- * is set.
361
- *
362
- * The consequence for policy authors is that **`auth.uid() IS NOT NULL` is a
363
- * tautology on the user path** — it is true for anonymous visitors too. Use
364
- * {@link policy.authenticated} (or `auth.uid() <> 'anonymous'`) to mean "signed
365
- * in", and {@link policy.serverContext} to mean "the trusted server context".
366
- *
367
- * @group Models
368
- */
369
- var ANONYMOUS_USER_ID = "anonymous";
370
- /** @group Models */
371
- var policy = {
372
- true: () => ({ kind: "true" }),
373
- false: () => ({ kind: "false" }),
374
- and: (...operands) => ({
375
- kind: "and",
376
- operands
377
- }),
378
- or: (...operands) => ({
379
- kind: "or",
380
- operands
381
- }),
382
- not: (operand) => ({
383
- kind: "not",
384
- operand
385
- }),
386
- compare: (left, op, right) => ({
387
- kind: "compare",
388
- op,
389
- left,
390
- right
391
- }),
392
- rolesOverlap: (roles) => ({
393
- kind: "rolesOverlap",
394
- roles
395
- }),
396
- rolesContain: (roles) => ({
397
- kind: "rolesContain",
398
- roles
399
- }),
400
- authenticated: () => ({ kind: "authenticated" }),
401
- serverContext: () => ({ kind: "serverContext" }),
402
- existsIn: (args) => ({
403
- kind: "existsIn",
404
- collection: args.collection,
405
- where: args.where
406
- }),
407
- raw: (sql) => ({
408
- kind: "raw",
409
- sql
410
- }),
411
- field: (name) => ({
412
- kind: "field",
413
- name
414
- }),
415
- outerField: (name) => ({
416
- kind: "outerField",
417
- name
418
- }),
419
- literal: (value) => ({
420
- kind: "literal",
421
- value
422
- }),
423
- authUid: () => ({ kind: "authUid" }),
424
- authRoles: () => ({ kind: "authRoles" })
425
- };
426
- //#endregion
427
- //#region ../types/src/types/backend.ts
428
- /**
429
- * Type guard: does this admin support SQL operations?
430
- * @group Admin
431
- */
432
- function isSQLAdmin(admin) {
433
- return !!admin && typeof admin.executeSql === "function";
434
- }
435
- /**
436
- * Type guard: does this admin support schema management?
437
- * @group Admin
438
- */
439
- function isSchemaAdmin(admin) {
440
- return !!admin && (typeof admin.fetchUnmappedTables === "function" || typeof admin.fetchTableMetadata === "function");
441
- }
442
- //#endregion
443
- //#region ../types/src/types/channel_bus.ts
444
- /**
445
- * Whether `setting` is an already-constructed transport rather than a request
446
- * for a built-in one.
447
- *
448
- * Structural rather than nominal so that an instance from a *different copy* of
449
- * `@rebasepro/types` — an entirely normal outcome of a separately versioned
450
- * transport package — is still recognised.
451
- */
452
- function isChannelBusInstance(setting) {
453
- return typeof setting?.publish === "function";
454
- }
455
- /** @group Models */
456
- var POSTGRES_CAPABILITIES = {
457
- key: "postgres",
458
- label: "PostgreSQL",
459
- supportsRelations: true,
460
- supportsSubcollections: false,
461
- supportsRLS: true,
462
- supportsReferences: false,
463
- supportsColumnTypes: true,
464
- supportsRealtime: true,
465
- filterOperators: ALL_WHERE_FILTER_OPS,
466
- supportsSQLAdmin: true,
467
- supportsDocumentAdmin: false,
468
- supportsSchemaAdmin: true
469
- };
470
- /** @group Models */
471
- var FIREBASE_CAPABILITIES = {
472
- key: "firestore",
473
- label: "Firebase / Firestore",
474
- supportsRelations: false,
475
- supportsSubcollections: true,
476
- supportsRLS: false,
477
- supportsReferences: true,
478
- supportsColumnTypes: false,
479
- supportsRealtime: true,
480
- filterOperators: ALL_WHERE_FILTER_OPS.filter((op) => op !== "like" && op !== "ilike" && op !== "not-like" && op !== "not-ilike"),
481
- supportsSQLAdmin: false,
482
- supportsDocumentAdmin: false,
483
- supportsSchemaAdmin: false
484
- };
485
- /** @group Models */
486
- var MONGODB_CAPABILITIES = {
487
- key: "mongodb",
488
- label: "MongoDB",
489
- supportsRelations: false,
490
- supportsSubcollections: true,
491
- supportsRLS: false,
492
- supportsReferences: true,
493
- supportsColumnTypes: false,
494
- supportsRealtime: false,
495
- filterOperators: ALL_WHERE_FILTER_OPS,
496
- supportsSQLAdmin: false,
497
- supportsDocumentAdmin: true,
498
- supportsSchemaAdmin: true
499
- };
500
- /**
501
- * Fallback capabilities when the driver is unknown.
502
- * Enables everything so nothing is hidden unexpectedly.
503
- * @group Models
504
- */
505
- var DEFAULT_CAPABILITIES = {
506
- key: "(default)",
507
- label: "Default",
508
- supportsRelations: true,
509
- supportsSubcollections: true,
510
- supportsRLS: true,
511
- supportsReferences: true,
512
- supportsColumnTypes: true,
513
- supportsRealtime: true,
514
- filterOperators: ALL_WHERE_FILTER_OPS,
515
- supportsSQLAdmin: true,
516
- supportsDocumentAdmin: true,
517
- supportsSchemaAdmin: true
518
- };
519
- var CAPABILITIES_REGISTRY = {
520
- postgres: POSTGRES_CAPABILITIES,
521
- firestore: FIREBASE_CAPABILITIES,
522
- mongodb: MONGODB_CAPABILITIES,
523
- "(default)": DEFAULT_CAPABILITIES
524
- };
525
- /**
526
- * Look up capabilities for a given engine key.
527
- * If `engine` is undefined or not found, returns `DEFAULT_CAPABILITIES`.
528
- * @group Models
529
- */
530
- function getDataSourceCapabilities(engine) {
531
- if (!engine) return POSTGRES_CAPABILITIES;
532
- return CAPABILITIES_REGISTRY[engine] ?? DEFAULT_CAPABILITIES;
533
- }
534
- /**
535
- * Resolve a client-supplied list `limit` into a safe, always-defined value.
536
- *
537
- * - A provided limit is coerced to an integer and clamped to `[1, maxLimit]`,
538
- * so `0`, negatives, and absurd values can never bypass the cap.
539
- * - An absent / blank / non-numeric limit falls back to the mode default:
540
- * `vectorDefaultLimit` for a vector search, otherwise `defaultLimit`.
541
- *
542
- * The return is never `undefined` — no ingress that routes its client limit
543
- * through this can produce an unbounded read.
544
- */
545
- function resolveClientListLimit(rawLimit, opts = {}) {
546
- const maxLimit = opts.maxLimit ?? 1e3;
547
- if (rawLimit != null && String(rawLimit).trim() !== "") {
548
- const parsed = typeof rawLimit === "number" ? rawLimit : parseInt(String(rawLimit), 10);
549
- if (Number.isFinite(parsed)) return Math.min(Math.max(1, Math.floor(parsed)), maxLimit);
550
- }
551
- return opts.vectorSearch ? opts.vectorDefaultLimit ?? 10 : opts.defaultLimit ?? 50;
552
- }
553
- var snakeCaseRegex = /[A-Z]{2,}(?=[A-Z][a-z]|\b)|[A-Z]?[a-z]+|[0-9]+(?:[a-z](?![a-z]))?|[A-Z]/g;
554
- var toSnakeCase = (str) => {
555
- if (!str || typeof str !== "string") return "";
556
- const regExpMatchArray = str.match(snakeCaseRegex);
557
- if (!regExpMatchArray) return "";
558
- return regExpMatchArray.map((x) => x.toLowerCase()).join("_");
559
- };
560
- function camelCase(str) {
561
- if (!str) return "";
562
- if (str.length === 1) return str.toLowerCase();
563
- const parts = str.split(/[-_ ]+/).filter(Boolean);
564
- if (parts.length === 0) return "";
565
- return parts[0].toLowerCase() + parts.slice(1).map((part) => part.charAt(0).toUpperCase() + part.substring(1).toLowerCase()).join("");
566
- }
567
- (/* @__PURE__ */ __commonJSMin(((exports, module) => {
568
- (function(e) {
569
- var t;
570
- "object" == typeof exports ? module.exports = e() : "function" == typeof define && define.amd ? define(e) : ("undefined" != typeof window ? t = window : "undefined" != typeof global ? t = global : "undefined" != typeof self && (t = self), t.objectHash = e());
571
- })(function() {
572
- return function r(o, i, u) {
573
- function s(n, e) {
574
- if (!i[n]) {
575
- if (!o[n]) {
576
- var t = "function" == typeof __require && __require;
577
- if (!e && t) return t(n, !0);
578
- if (a) return a(n, !0);
579
- throw new Error("Cannot find module '" + n + "'");
580
- }
581
- e = i[n] = { exports: {} };
582
- o[n][0].call(e.exports, function(e) {
583
- var t = o[n][1][e];
584
- return s(t || e);
585
- }, e, e.exports, r, o, i, u);
586
- }
587
- return i[n].exports;
588
- }
589
- for (var a = "function" == typeof __require && __require, e = 0; e < u.length; e++) s(u[e]);
590
- return s;
591
- }({
592
- 1: [function(w, b, m) {
593
- (function(e, n, s, c, d, h, p, g, y) {
594
- "use strict";
595
- var r = w("crypto");
596
- function t(e, t) {
597
- t = u(e, t);
598
- var n;
599
- return void 0 === (n = "passthrough" !== t.algorithm ? r.createHash(t.algorithm) : new l()).write && (n.write = n.update, n.end = n.update), f(t, n).dispatch(e), n.update || n.end(""), n.digest ? n.digest("buffer" === t.encoding ? void 0 : t.encoding) : (e = n.read(), "buffer" !== t.encoding ? e.toString(t.encoding) : e);
600
- }
601
- (m = b.exports = t).sha1 = function(e) {
602
- return t(e);
603
- }, m.keys = function(e) {
604
- return t(e, {
605
- excludeValues: !0,
606
- algorithm: "sha1",
607
- encoding: "hex"
608
- });
609
- }, m.MD5 = function(e) {
610
- return t(e, {
611
- algorithm: "md5",
612
- encoding: "hex"
613
- });
614
- }, m.keysMD5 = function(e) {
615
- return t(e, {
616
- algorithm: "md5",
617
- encoding: "hex",
618
- excludeValues: !0
619
- });
620
- };
621
- var o = r.getHashes ? r.getHashes().slice() : ["sha1", "md5"], i = (o.push("passthrough"), [
622
- "buffer",
623
- "hex",
624
- "binary",
625
- "base64"
626
- ]);
627
- function u(e, t) {
628
- var n = {};
629
- if (n.algorithm = (t = t || {}).algorithm || "sha1", n.encoding = t.encoding || "hex", n.excludeValues = !!t.excludeValues, n.algorithm = n.algorithm.toLowerCase(), n.encoding = n.encoding.toLowerCase(), n.ignoreUnknown = !0 === t.ignoreUnknown, n.respectType = !1 !== t.respectType, n.respectFunctionNames = !1 !== t.respectFunctionNames, n.respectFunctionProperties = !1 !== t.respectFunctionProperties, n.unorderedArrays = !0 === t.unorderedArrays, n.unorderedSets = !1 !== t.unorderedSets, n.unorderedObjects = !1 !== t.unorderedObjects, n.replacer = t.replacer || void 0, n.excludeKeys = t.excludeKeys || void 0, void 0 === e) throw new Error("Object argument required.");
630
- for (var r = 0; r < o.length; ++r) o[r].toLowerCase() === n.algorithm.toLowerCase() && (n.algorithm = o[r]);
631
- if (-1 === o.indexOf(n.algorithm)) throw new Error("Algorithm \"" + n.algorithm + "\" not supported. supported values: " + o.join(", "));
632
- if (-1 === i.indexOf(n.encoding) && "passthrough" !== n.algorithm) throw new Error("Encoding \"" + n.encoding + "\" not supported. supported values: " + i.join(", "));
633
- return n;
634
- }
635
- function a(e) {
636
- if ("function" == typeof e) return null != /^function\s+\w*\s*\(\s*\)\s*{\s+\[native code\]\s+}$/i.exec(Function.prototype.toString.call(e));
637
- }
638
- function f(o, t, i) {
639
- i = i || [];
640
- function u(e) {
641
- return t.update ? t.update(e, "utf8") : t.write(e, "utf8");
642
- }
643
- return {
644
- dispatch: function(e) {
645
- return this["_" + (null === (e = o.replacer ? o.replacer(e) : e) ? "null" : typeof e)](e);
646
- },
647
- _object: function(t) {
648
- var n, e = Object.prototype.toString.call(t), r = /\[object (.*)\]/i.exec(e);
649
- r = (r = r ? r[1] : "unknown:[" + e + "]").toLowerCase();
650
- if (0 <= (e = i.indexOf(t))) return this.dispatch("[CIRCULAR:" + e + "]");
651
- if (i.push(t), void 0 !== s && s.isBuffer && s.isBuffer(t)) return u("buffer:"), u(t);
652
- if ("object" === r || "function" === r || "asyncfunction" === r) return e = Object.keys(t), o.unorderedObjects && (e = e.sort()), !1 === o.respectType || a(t) || e.splice(0, 0, "prototype", "__proto__", "constructor"), o.excludeKeys && (e = e.filter(function(e) {
653
- return !o.excludeKeys(e);
654
- })), u("object:" + e.length + ":"), n = this, e.forEach(function(e) {
655
- n.dispatch(e), u(":"), o.excludeValues || n.dispatch(t[e]), u(",");
656
- });
657
- if (!this["_" + r]) {
658
- if (o.ignoreUnknown) return u("[" + r + "]");
659
- throw new Error("Unknown object type \"" + r + "\"");
660
- }
661
- this["_" + r](t);
662
- },
663
- _array: function(e, t) {
664
- t = void 0 !== t ? t : !1 !== o.unorderedArrays;
665
- var n = this;
666
- if (u("array:" + e.length + ":"), !t || e.length <= 1) return e.forEach(function(e) {
667
- return n.dispatch(e);
668
- });
669
- var r = [], t = e.map(function(e) {
670
- var t = new l(), n = i.slice();
671
- return f(o, t, n).dispatch(e), r = r.concat(n.slice(i.length)), t.read().toString();
672
- });
673
- return i = i.concat(r), t.sort(), this._array(t, !1);
674
- },
675
- _date: function(e) {
676
- return u("date:" + e.toJSON());
677
- },
678
- _symbol: function(e) {
679
- return u("symbol:" + e.toString());
680
- },
681
- _error: function(e) {
682
- return u("error:" + e.toString());
683
- },
684
- _boolean: function(e) {
685
- return u("bool:" + e.toString());
686
- },
687
- _string: function(e) {
688
- u("string:" + e.length + ":"), u(e.toString());
689
- },
690
- _function: function(e) {
691
- u("fn:"), a(e) ? this.dispatch("[native]") : this.dispatch(e.toString()), !1 !== o.respectFunctionNames && this.dispatch("function-name:" + String(e.name)), o.respectFunctionProperties && this._object(e);
692
- },
693
- _number: function(e) {
694
- return u("number:" + e.toString());
695
- },
696
- _xml: function(e) {
697
- return u("xml:" + e.toString());
698
- },
699
- _null: function() {
700
- return u("Null");
701
- },
702
- _undefined: function() {
703
- return u("Undefined");
704
- },
705
- _regexp: function(e) {
706
- return u("regex:" + e.toString());
707
- },
708
- _uint8array: function(e) {
709
- return u("uint8array:"), this.dispatch(Array.prototype.slice.call(e));
710
- },
711
- _uint8clampedarray: function(e) {
712
- return u("uint8clampedarray:"), this.dispatch(Array.prototype.slice.call(e));
713
- },
714
- _int8array: function(e) {
715
- return u("int8array:"), this.dispatch(Array.prototype.slice.call(e));
716
- },
717
- _uint16array: function(e) {
718
- return u("uint16array:"), this.dispatch(Array.prototype.slice.call(e));
719
- },
720
- _int16array: function(e) {
721
- return u("int16array:"), this.dispatch(Array.prototype.slice.call(e));
722
- },
723
- _uint32array: function(e) {
724
- return u("uint32array:"), this.dispatch(Array.prototype.slice.call(e));
725
- },
726
- _int32array: function(e) {
727
- return u("int32array:"), this.dispatch(Array.prototype.slice.call(e));
728
- },
729
- _float32array: function(e) {
730
- return u("float32array:"), this.dispatch(Array.prototype.slice.call(e));
731
- },
732
- _float64array: function(e) {
733
- return u("float64array:"), this.dispatch(Array.prototype.slice.call(e));
734
- },
735
- _arraybuffer: function(e) {
736
- return u("arraybuffer:"), this.dispatch(new Uint8Array(e));
737
- },
738
- _url: function(e) {
739
- return u("url:" + e.toString());
740
- },
741
- _map: function(e) {
742
- u("map:");
743
- e = Array.from(e);
744
- return this._array(e, !1 !== o.unorderedSets);
745
- },
746
- _set: function(e) {
747
- u("set:");
748
- e = Array.from(e);
749
- return this._array(e, !1 !== o.unorderedSets);
750
- },
751
- _file: function(e) {
752
- return u("file:"), this.dispatch([
753
- e.name,
754
- e.size,
755
- e.type,
756
- e.lastModfied
757
- ]);
758
- },
759
- _blob: function() {
760
- if (o.ignoreUnknown) return u("[blob]");
761
- throw Error("Hashing Blob objects is currently not supported\n(see https://github.com/puleos/object-hash/issues/26)\nUse \"options.replacer\" or \"options.ignoreUnknown\"\n");
762
- },
763
- _domwindow: function() {
764
- return u("domwindow");
765
- },
766
- _bigint: function(e) {
767
- return u("bigint:" + e.toString());
768
- },
769
- _process: function() {
770
- return u("process");
771
- },
772
- _timer: function() {
773
- return u("timer");
774
- },
775
- _pipe: function() {
776
- return u("pipe");
777
- },
778
- _tcp: function() {
779
- return u("tcp");
780
- },
781
- _udp: function() {
782
- return u("udp");
783
- },
784
- _tty: function() {
785
- return u("tty");
786
- },
787
- _statwatcher: function() {
788
- return u("statwatcher");
789
- },
790
- _securecontext: function() {
791
- return u("securecontext");
792
- },
793
- _connection: function() {
794
- return u("connection");
795
- },
796
- _zlib: function() {
797
- return u("zlib");
798
- },
799
- _context: function() {
800
- return u("context");
801
- },
802
- _nodescript: function() {
803
- return u("nodescript");
804
- },
805
- _httpparser: function() {
806
- return u("httpparser");
807
- },
808
- _dataview: function() {
809
- return u("dataview");
810
- },
811
- _signal: function() {
812
- return u("signal");
813
- },
814
- _fsevent: function() {
815
- return u("fsevent");
816
- },
817
- _tlswrap: function() {
818
- return u("tlswrap");
819
- }
820
- };
821
- }
822
- function l() {
823
- return {
824
- buf: "",
825
- write: function(e) {
826
- this.buf += e;
827
- },
828
- end: function(e) {
829
- this.buf += e;
830
- },
831
- read: function() {
832
- return this.buf;
833
- }
834
- };
835
- }
836
- m.writeToStream = function(e, t, n) {
837
- return void 0 === n && (n = t, t = {}), f(t = u(e, t), n).dispatch(e);
838
- };
839
- }).call(this, w("lYpoI2"), "undefined" != typeof self ? self : "undefined" != typeof window ? window : {}, w("buffer").Buffer, arguments[3], arguments[4], arguments[5], arguments[6], "/fake_9a5aa49d.js", "/");
840
- }, {
841
- buffer: 3,
842
- crypto: 5,
843
- lYpoI2: 11
844
- }],
845
- 2: [function(e, t, f) {
846
- (function(e, t, n, r, o, i, u, s, a) {
847
- (function(e) {
848
- "use strict";
849
- var a = "undefined" != typeof Uint8Array ? Uint8Array : Array, t = "+".charCodeAt(0), n = "/".charCodeAt(0), r = "0".charCodeAt(0), o = "a".charCodeAt(0), i = "A".charCodeAt(0), u = "-".charCodeAt(0), s = "_".charCodeAt(0);
850
- function f(e) {
851
- e = e.charCodeAt(0);
852
- return e === t || e === u ? 62 : e === n || e === s ? 63 : e < r ? -1 : e < r + 10 ? e - r + 26 + 26 : e < i + 26 ? e - i : e < o + 26 ? e - o + 26 : void 0;
853
- }
854
- e.toByteArray = function(e) {
855
- var t, n;
856
- if (0 < e.length % 4) throw new Error("Invalid string. Length must be a multiple of 4");
857
- var r = e.length, r = "=" === e.charAt(r - 2) ? 2 : "=" === e.charAt(r - 1) ? 1 : 0, o = new a(3 * e.length / 4 - r), i = 0 < r ? e.length - 4 : e.length, u = 0;
858
- function s(e) {
859
- o[u++] = e;
860
- }
861
- for (t = 0; t < i; t += 4) s((16711680 & (n = f(e.charAt(t)) << 18 | f(e.charAt(t + 1)) << 12 | f(e.charAt(t + 2)) << 6 | f(e.charAt(t + 3)))) >> 16), s((65280 & n) >> 8), s(255 & n);
862
- return 2 == r ? s(255 & (n = f(e.charAt(t)) << 2 | f(e.charAt(t + 1)) >> 4)) : 1 == r && (s((n = f(e.charAt(t)) << 10 | f(e.charAt(t + 1)) << 4 | f(e.charAt(t + 2)) >> 2) >> 8 & 255), s(255 & n)), o;
863
- }, e.fromByteArray = function(e) {
864
- var t, n, r, o, i = e.length % 3, u = "";
865
- function s(e) {
866
- return "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".charAt(e);
867
- }
868
- for (t = 0, r = e.length - i; t < r; t += 3) n = (e[t] << 16) + (e[t + 1] << 8) + e[t + 2], u += s((o = n) >> 18 & 63) + s(o >> 12 & 63) + s(o >> 6 & 63) + s(63 & o);
869
- switch (i) {
870
- case 1:
871
- u = (u += s((n = e[e.length - 1]) >> 2)) + s(n << 4 & 63) + "==";
872
- break;
873
- case 2: u = (u = (u += s((n = (e[e.length - 2] << 8) + e[e.length - 1]) >> 10)) + s(n >> 4 & 63)) + s(n << 2 & 63) + "=";
874
- }
875
- return u;
876
- };
877
- })(void 0 === f ? this.base64js = {} : f);
878
- }).call(this, e("lYpoI2"), "undefined" != typeof self ? self : "undefined" != typeof window ? window : {}, e("buffer").Buffer, arguments[3], arguments[4], arguments[5], arguments[6], "/node_modules/gulp-browserify/node_modules/base64-js/lib/b64.js", "/node_modules/gulp-browserify/node_modules/base64-js/lib");
879
- }, {
880
- buffer: 3,
881
- lYpoI2: 11
882
- }],
883
- 3: [function(O, e, H) {
884
- (function(e, n, f, r, h, p, g, y, w) {
885
- var a = O("base64-js"), i = O("ieee754");
886
- function f(e, t, n) {
887
- if (!(this instanceof f)) return new f(e, t, n);
888
- var r, o, i, u, s = typeof e;
889
- if ("base64" === t && "string" == s) for (e = (u = e).trim ? u.trim() : u.replace(/^\s+|\s+$/g, ""); e.length % 4 != 0;) e += "=";
890
- if ("number" == s) r = j(e);
891
- else if ("string" == s) r = f.byteLength(e, t);
892
- else {
893
- if ("object" != s) throw new Error("First argument needs to be a number, array or string.");
894
- r = j(e.length);
895
- }
896
- if (f._useTypedArrays ? o = f._augment(new Uint8Array(r)) : ((o = this).length = r, o._isBuffer = !0), f._useTypedArrays && "number" == typeof e.byteLength) o._set(e);
897
- else if (C(u = e) || f.isBuffer(u) || u && "object" == typeof u && "number" == typeof u.length) for (i = 0; i < r; i++) f.isBuffer(e) ? o[i] = e.readUInt8(i) : o[i] = e[i];
898
- else if ("string" == s) o.write(e, 0, t);
899
- else if ("number" == s && !f._useTypedArrays && !n) for (i = 0; i < r; i++) o[i] = 0;
900
- return o;
901
- }
902
- function b(e, t, n, r) {
903
- return f._charsWritten = c(function(e) {
904
- for (var t = [], n = 0; n < e.length; n++) t.push(255 & e.charCodeAt(n));
905
- return t;
906
- }(t), e, n, r);
907
- }
908
- function m(e, t, n, r) {
909
- return f._charsWritten = c(function(e) {
910
- for (var t, n, r = [], o = 0; o < e.length; o++) n = e.charCodeAt(o), t = n >> 8, n = n % 256, r.push(n), r.push(t);
911
- return r;
912
- }(t), e, n, r);
913
- }
914
- function v(e, t, n) {
915
- var r = "";
916
- n = Math.min(e.length, n);
917
- for (var o = t; o < n; o++) r += String.fromCharCode(e[o]);
918
- return r;
919
- }
920
- function o(e, t, n, r) {
921
- r || (d("boolean" == typeof n, "missing or invalid endian"), d(null != t, "missing offset"), d(t + 1 < e.length, "Trying to read beyond buffer length"));
922
- var o, r = e.length;
923
- if (!(r <= t)) return n ? (o = e[t], t + 1 < r && (o |= e[t + 1] << 8)) : (o = e[t] << 8, t + 1 < r && (o |= e[t + 1])), o;
924
- }
925
- function u(e, t, n, r) {
926
- r || (d("boolean" == typeof n, "missing or invalid endian"), d(null != t, "missing offset"), d(t + 3 < e.length, "Trying to read beyond buffer length"));
927
- var o, r = e.length;
928
- if (!(r <= t)) return n ? (t + 2 < r && (o = e[t + 2] << 16), t + 1 < r && (o |= e[t + 1] << 8), o |= e[t], t + 3 < r && (o += e[t + 3] << 24 >>> 0)) : (t + 1 < r && (o = e[t + 1] << 16), t + 2 < r && (o |= e[t + 2] << 8), t + 3 < r && (o |= e[t + 3]), o += e[t] << 24 >>> 0), o;
929
- }
930
- function _(e, t, n, r) {
931
- if (r || (d("boolean" == typeof n, "missing or invalid endian"), d(null != t, "missing offset"), d(t + 1 < e.length, "Trying to read beyond buffer length")), !(e.length <= t)) return r = o(e, t, n, !0), 32768 & r ? -1 * (65535 - r + 1) : r;
932
- }
933
- function E(e, t, n, r) {
934
- if (r || (d("boolean" == typeof n, "missing or invalid endian"), d(null != t, "missing offset"), d(t + 3 < e.length, "Trying to read beyond buffer length")), !(e.length <= t)) return r = u(e, t, n, !0), 2147483648 & r ? -1 * (4294967295 - r + 1) : r;
935
- }
936
- function I(e, t, n, r) {
937
- return r || (d("boolean" == typeof n, "missing or invalid endian"), d(t + 3 < e.length, "Trying to read beyond buffer length")), i.read(e, t, n, 23, 4);
938
- }
939
- function A(e, t, n, r) {
940
- return r || (d("boolean" == typeof n, "missing or invalid endian"), d(t + 7 < e.length, "Trying to read beyond buffer length")), i.read(e, t, n, 52, 8);
941
- }
942
- function s(e, t, n, r, o) {
943
- o || (d(null != t, "missing value"), d("boolean" == typeof r, "missing or invalid endian"), d(null != n, "missing offset"), d(n + 1 < e.length, "trying to write beyond buffer length"), Y(t, 65535));
944
- o = e.length;
945
- if (!(o <= n)) for (var i = 0, u = Math.min(o - n, 2); i < u; i++) e[n + i] = (t & 255 << 8 * (r ? i : 1 - i)) >>> 8 * (r ? i : 1 - i);
946
- }
947
- function l(e, t, n, r, o) {
948
- o || (d(null != t, "missing value"), d("boolean" == typeof r, "missing or invalid endian"), d(null != n, "missing offset"), d(n + 3 < e.length, "trying to write beyond buffer length"), Y(t, 4294967295));
949
- o = e.length;
950
- if (!(o <= n)) for (var i = 0, u = Math.min(o - n, 4); i < u; i++) e[n + i] = t >>> 8 * (r ? i : 3 - i) & 255;
951
- }
952
- function B(e, t, n, r, o) {
953
- o || (d(null != t, "missing value"), d("boolean" == typeof r, "missing or invalid endian"), d(null != n, "missing offset"), d(n + 1 < e.length, "Trying to write beyond buffer length"), F(t, 32767, -32768)), e.length <= n || s(e, 0 <= t ? t : 65535 + t + 1, n, r, o);
954
- }
955
- function L(e, t, n, r, o) {
956
- o || (d(null != t, "missing value"), d("boolean" == typeof r, "missing or invalid endian"), d(null != n, "missing offset"), d(n + 3 < e.length, "Trying to write beyond buffer length"), F(t, 2147483647, -2147483648)), e.length <= n || l(e, 0 <= t ? t : 4294967295 + t + 1, n, r, o);
957
- }
958
- function U(e, t, n, r, o) {
959
- o || (d(null != t, "missing value"), d("boolean" == typeof r, "missing or invalid endian"), d(null != n, "missing offset"), d(n + 3 < e.length, "Trying to write beyond buffer length"), D(t, 34028234663852886e22, -34028234663852886e22)), e.length <= n || i.write(e, t, n, r, 23, 4);
960
- }
961
- function x(e, t, n, r, o) {
962
- o || (d(null != t, "missing value"), d("boolean" == typeof r, "missing or invalid endian"), d(null != n, "missing offset"), d(n + 7 < e.length, "Trying to write beyond buffer length"), D(t, 17976931348623157e292, -17976931348623157e292)), e.length <= n || i.write(e, t, n, r, 52, 8);
963
- }
964
- H.Buffer = f, H.SlowBuffer = f, H.INSPECT_MAX_BYTES = 50, f.poolSize = 8192, f._useTypedArrays = function() {
965
- try {
966
- var t = new Uint8Array(/* @__PURE__ */ new ArrayBuffer(0));
967
- return t.foo = function() {
968
- return 42;
969
- }, 42 === t.foo() && "function" == typeof t.subarray;
970
- } catch (e) {
971
- return !1;
972
- }
973
- }(), f.isEncoding = function(e) {
974
- switch (String(e).toLowerCase()) {
975
- case "hex":
976
- case "utf8":
977
- case "utf-8":
978
- case "ascii":
979
- case "binary":
980
- case "base64":
981
- case "raw":
982
- case "ucs2":
983
- case "ucs-2":
984
- case "utf16le":
985
- case "utf-16le": return !0;
986
- default: return !1;
987
- }
988
- }, f.isBuffer = function(e) {
989
- return !(null == e || !e._isBuffer);
990
- }, f.byteLength = function(e, t) {
991
- var n;
992
- switch (e += "", t || "utf8") {
993
- case "hex":
994
- n = e.length / 2;
995
- break;
996
- case "utf8":
997
- case "utf-8":
998
- n = T(e).length;
999
- break;
1000
- case "ascii":
1001
- case "binary":
1002
- case "raw":
1003
- n = e.length;
1004
- break;
1005
- case "base64":
1006
- n = M(e).length;
1007
- break;
1008
- case "ucs2":
1009
- case "ucs-2":
1010
- case "utf16le":
1011
- case "utf-16le":
1012
- n = 2 * e.length;
1013
- break;
1014
- default: throw new Error("Unknown encoding");
1015
- }
1016
- return n;
1017
- }, f.concat = function(e, t) {
1018
- if (d(C(e), "Usage: Buffer.concat(list, [totalLength])\nlist should be an Array."), 0 === e.length) return new f(0);
1019
- if (1 === e.length) return e[0];
1020
- if ("number" != typeof t) for (o = t = 0; o < e.length; o++) t += e[o].length;
1021
- for (var n = new f(t), r = 0, o = 0; o < e.length; o++) {
1022
- var i = e[o];
1023
- i.copy(n, r), r += i.length;
1024
- }
1025
- return n;
1026
- }, f.prototype.write = function(e, t, n, r) {
1027
- isFinite(t) ? isFinite(n) || (r = n, n = void 0) : (a = r, r = t, t = n, n = a), t = Number(t) || 0;
1028
- var o, i, u, s, a = this.length - t;
1029
- switch ((!n || a < (n = Number(n))) && (n = a), r = String(r || "utf8").toLowerCase()) {
1030
- case "hex":
1031
- o = function(e, t, n, r) {
1032
- n = Number(n) || 0;
1033
- var o = e.length - n;
1034
- (!r || o < (r = Number(r))) && (r = o), d((o = t.length) % 2 == 0, "Invalid hex string"), o / 2 < r && (r = o / 2);
1035
- for (var i = 0; i < r; i++) {
1036
- var u = parseInt(t.substr(2 * i, 2), 16);
1037
- d(!isNaN(u), "Invalid hex string"), e[n + i] = u;
1038
- }
1039
- return f._charsWritten = 2 * i, i;
1040
- }(this, e, t, n);
1041
- break;
1042
- case "utf8":
1043
- case "utf-8":
1044
- i = this, u = t, s = n, o = f._charsWritten = c(T(e), i, u, s);
1045
- break;
1046
- case "ascii":
1047
- case "binary":
1048
- o = b(this, e, t, n);
1049
- break;
1050
- case "base64":
1051
- i = this, u = t, s = n, o = f._charsWritten = c(M(e), i, u, s);
1052
- break;
1053
- case "ucs2":
1054
- case "ucs-2":
1055
- case "utf16le":
1056
- case "utf-16le":
1057
- o = m(this, e, t, n);
1058
- break;
1059
- default: throw new Error("Unknown encoding");
1060
- }
1061
- return o;
1062
- }, f.prototype.toString = function(e, t, n) {
1063
- var r, o, i, u, s = this;
1064
- if (e = String(e || "utf8").toLowerCase(), t = Number(t) || 0, (n = void 0 !== n ? Number(n) : s.length) === t) return "";
1065
- switch (e) {
1066
- case "hex":
1067
- r = function(e, t, n) {
1068
- var r = e.length;
1069
- (!t || t < 0) && (t = 0);
1070
- (!n || n < 0 || r < n) && (n = r);
1071
- for (var o = "", i = t; i < n; i++) o += k(e[i]);
1072
- return o;
1073
- }(s, t, n);
1074
- break;
1075
- case "utf8":
1076
- case "utf-8":
1077
- r = function(e, t, n) {
1078
- var r = "", o = "";
1079
- n = Math.min(e.length, n);
1080
- for (var i = t; i < n; i++) e[i] <= 127 ? (r += N(o) + String.fromCharCode(e[i]), o = "") : o += "%" + e[i].toString(16);
1081
- return r + N(o);
1082
- }(s, t, n);
1083
- break;
1084
- case "ascii":
1085
- case "binary":
1086
- r = v(s, t, n);
1087
- break;
1088
- case "base64":
1089
- o = s, u = n, r = 0 === (i = t) && u === o.length ? a.fromByteArray(o) : a.fromByteArray(o.slice(i, u));
1090
- break;
1091
- case "ucs2":
1092
- case "ucs-2":
1093
- case "utf16le":
1094
- case "utf-16le":
1095
- r = function(e, t, n) {
1096
- for (var r = e.slice(t, n), o = "", i = 0; i < r.length; i += 2) o += String.fromCharCode(r[i] + 256 * r[i + 1]);
1097
- return o;
1098
- }(s, t, n);
1099
- break;
1100
- default: throw new Error("Unknown encoding");
1101
- }
1102
- return r;
1103
- }, f.prototype.toJSON = function() {
1104
- return {
1105
- type: "Buffer",
1106
- data: Array.prototype.slice.call(this._arr || this, 0)
1107
- };
1108
- }, f.prototype.copy = function(e, t, n, r) {
1109
- if (t = t || 0, (r = r || 0 === r ? r : this.length) !== (n = n || 0) && 0 !== e.length && 0 !== this.length) {
1110
- d(n <= r, "sourceEnd < sourceStart"), d(0 <= t && t < e.length, "targetStart out of bounds"), d(0 <= n && n < this.length, "sourceStart out of bounds"), d(0 <= r && r <= this.length, "sourceEnd out of bounds"), r > this.length && (r = this.length);
1111
- var o = (r = e.length - t < r - n ? e.length - t + n : r) - n;
1112
- if (o < 100 || !f._useTypedArrays) for (var i = 0; i < o; i++) e[i + t] = this[i + n];
1113
- else e._set(this.subarray(n, n + o), t);
1114
- }
1115
- }, f.prototype.slice = function(e, t) {
1116
- var n = this.length;
1117
- if (e = S(e, n, 0), t = S(t, n, n), f._useTypedArrays) return f._augment(this.subarray(e, t));
1118
- for (var r = t - e, o = new f(r, void 0, !0), i = 0; i < r; i++) o[i] = this[i + e];
1119
- return o;
1120
- }, f.prototype.get = function(e) {
1121
- return console.log(".get() is deprecated. Access using array indexes instead."), this.readUInt8(e);
1122
- }, f.prototype.set = function(e, t) {
1123
- return console.log(".set() is deprecated. Access using array indexes instead."), this.writeUInt8(e, t);
1124
- }, f.prototype.readUInt8 = function(e, t) {
1125
- if (t || (d(null != e, "missing offset"), d(e < this.length, "Trying to read beyond buffer length")), !(e >= this.length)) return this[e];
1126
- }, f.prototype.readUInt16LE = function(e, t) {
1127
- return o(this, e, !0, t);
1128
- }, f.prototype.readUInt16BE = function(e, t) {
1129
- return o(this, e, !1, t);
1130
- }, f.prototype.readUInt32LE = function(e, t) {
1131
- return u(this, e, !0, t);
1132
- }, f.prototype.readUInt32BE = function(e, t) {
1133
- return u(this, e, !1, t);
1134
- }, f.prototype.readInt8 = function(e, t) {
1135
- if (t || (d(null != e, "missing offset"), d(e < this.length, "Trying to read beyond buffer length")), !(e >= this.length)) return 128 & this[e] ? -1 * (255 - this[e] + 1) : this[e];
1136
- }, f.prototype.readInt16LE = function(e, t) {
1137
- return _(this, e, !0, t);
1138
- }, f.prototype.readInt16BE = function(e, t) {
1139
- return _(this, e, !1, t);
1140
- }, f.prototype.readInt32LE = function(e, t) {
1141
- return E(this, e, !0, t);
1142
- }, f.prototype.readInt32BE = function(e, t) {
1143
- return E(this, e, !1, t);
1144
- }, f.prototype.readFloatLE = function(e, t) {
1145
- return I(this, e, !0, t);
1146
- }, f.prototype.readFloatBE = function(e, t) {
1147
- return I(this, e, !1, t);
1148
- }, f.prototype.readDoubleLE = function(e, t) {
1149
- return A(this, e, !0, t);
1150
- }, f.prototype.readDoubleBE = function(e, t) {
1151
- return A(this, e, !1, t);
1152
- }, f.prototype.writeUInt8 = function(e, t, n) {
1153
- n || (d(null != e, "missing value"), d(null != t, "missing offset"), d(t < this.length, "trying to write beyond buffer length"), Y(e, 255)), t >= this.length || (this[t] = e);
1154
- }, f.prototype.writeUInt16LE = function(e, t, n) {
1155
- s(this, e, t, !0, n);
1156
- }, f.prototype.writeUInt16BE = function(e, t, n) {
1157
- s(this, e, t, !1, n);
1158
- }, f.prototype.writeUInt32LE = function(e, t, n) {
1159
- l(this, e, t, !0, n);
1160
- }, f.prototype.writeUInt32BE = function(e, t, n) {
1161
- l(this, e, t, !1, n);
1162
- }, f.prototype.writeInt8 = function(e, t, n) {
1163
- n || (d(null != e, "missing value"), d(null != t, "missing offset"), d(t < this.length, "Trying to write beyond buffer length"), F(e, 127, -128)), t >= this.length || (0 <= e ? this.writeUInt8(e, t, n) : this.writeUInt8(255 + e + 1, t, n));
1164
- }, f.prototype.writeInt16LE = function(e, t, n) {
1165
- B(this, e, t, !0, n);
1166
- }, f.prototype.writeInt16BE = function(e, t, n) {
1167
- B(this, e, t, !1, n);
1168
- }, f.prototype.writeInt32LE = function(e, t, n) {
1169
- L(this, e, t, !0, n);
1170
- }, f.prototype.writeInt32BE = function(e, t, n) {
1171
- L(this, e, t, !1, n);
1172
- }, f.prototype.writeFloatLE = function(e, t, n) {
1173
- U(this, e, t, !0, n);
1174
- }, f.prototype.writeFloatBE = function(e, t, n) {
1175
- U(this, e, t, !1, n);
1176
- }, f.prototype.writeDoubleLE = function(e, t, n) {
1177
- x(this, e, t, !0, n);
1178
- }, f.prototype.writeDoubleBE = function(e, t, n) {
1179
- x(this, e, t, !1, n);
1180
- }, f.prototype.fill = function(e, t, n) {
1181
- if (t = t || 0, n = n || this.length, d("number" == typeof (e = "string" == typeof (e = e || 0) ? e.charCodeAt(0) : e) && !isNaN(e), "value is not a number"), d(t <= n, "end < start"), n !== t && 0 !== this.length) {
1182
- d(0 <= t && t < this.length, "start out of bounds"), d(0 <= n && n <= this.length, "end out of bounds");
1183
- for (var r = t; r < n; r++) this[r] = e;
1184
- }
1185
- }, f.prototype.inspect = function() {
1186
- for (var e = [], t = this.length, n = 0; n < t; n++) if (e[n] = k(this[n]), n === H.INSPECT_MAX_BYTES) {
1187
- e[n + 1] = "...";
1188
- break;
1189
- }
1190
- return "<Buffer " + e.join(" ") + ">";
1191
- }, f.prototype.toArrayBuffer = function() {
1192
- if ("undefined" == typeof Uint8Array) throw new Error("Buffer.toArrayBuffer not supported in this browser");
1193
- if (f._useTypedArrays) return new f(this).buffer;
1194
- for (var e = new Uint8Array(this.length), t = 0, n = e.length; t < n; t += 1) e[t] = this[t];
1195
- return e.buffer;
1196
- };
1197
- var t = f.prototype;
1198
- function S(e, t, n) {
1199
- return "number" != typeof e ? n : t <= (e = ~~e) ? t : 0 <= e || 0 <= (e += t) ? e : 0;
1200
- }
1201
- function j(e) {
1202
- return (e = ~~Math.ceil(+e)) < 0 ? 0 : e;
1203
- }
1204
- function C(e) {
1205
- return (Array.isArray || function(e) {
1206
- return "[object Array]" === Object.prototype.toString.call(e);
1207
- })(e);
1208
- }
1209
- function k(e) {
1210
- return e < 16 ? "0" + e.toString(16) : e.toString(16);
1211
- }
1212
- function T(e) {
1213
- for (var t = [], n = 0; n < e.length; n++) {
1214
- var r = e.charCodeAt(n);
1215
- if (r <= 127) t.push(e.charCodeAt(n));
1216
- else for (var o = n, i = (55296 <= r && r <= 57343 && n++, encodeURIComponent(e.slice(o, n + 1)).substr(1).split("%")), u = 0; u < i.length; u++) t.push(parseInt(i[u], 16));
1217
- }
1218
- return t;
1219
- }
1220
- function M(e) {
1221
- return a.toByteArray(e);
1222
- }
1223
- function c(e, t, n, r) {
1224
- for (var o = 0; o < r && !(o + n >= t.length || o >= e.length); o++) t[o + n] = e[o];
1225
- return o;
1226
- }
1227
- function N(e) {
1228
- try {
1229
- return decodeURIComponent(e);
1230
- } catch (e) {
1231
- return String.fromCharCode(65533);
1232
- }
1233
- }
1234
- function Y(e, t) {
1235
- d("number" == typeof e, "cannot write a non-number as a number"), d(0 <= e, "specified a negative value for writing an unsigned value"), d(e <= t, "value is larger than maximum value for type"), d(Math.floor(e) === e, "value has a fractional component");
1236
- }
1237
- function F(e, t, n) {
1238
- d("number" == typeof e, "cannot write a non-number as a number"), d(e <= t, "value larger than maximum allowed value"), d(n <= e, "value smaller than minimum allowed value"), d(Math.floor(e) === e, "value has a fractional component");
1239
- }
1240
- function D(e, t, n) {
1241
- d("number" == typeof e, "cannot write a non-number as a number"), d(e <= t, "value larger than maximum allowed value"), d(n <= e, "value smaller than minimum allowed value");
1242
- }
1243
- function d(e, t) {
1244
- if (!e) throw new Error(t || "Failed assertion");
1245
- }
1246
- f._augment = function(e) {
1247
- return e._isBuffer = !0, e._get = e.get, e._set = e.set, e.get = t.get, e.set = t.set, e.write = t.write, e.toString = t.toString, e.toLocaleString = t.toString, e.toJSON = t.toJSON, e.copy = t.copy, e.slice = t.slice, e.readUInt8 = t.readUInt8, e.readUInt16LE = t.readUInt16LE, e.readUInt16BE = t.readUInt16BE, e.readUInt32LE = t.readUInt32LE, e.readUInt32BE = t.readUInt32BE, e.readInt8 = t.readInt8, e.readInt16LE = t.readInt16LE, e.readInt16BE = t.readInt16BE, e.readInt32LE = t.readInt32LE, e.readInt32BE = t.readInt32BE, e.readFloatLE = t.readFloatLE, e.readFloatBE = t.readFloatBE, e.readDoubleLE = t.readDoubleLE, e.readDoubleBE = t.readDoubleBE, e.writeUInt8 = t.writeUInt8, e.writeUInt16LE = t.writeUInt16LE, e.writeUInt16BE = t.writeUInt16BE, e.writeUInt32LE = t.writeUInt32LE, e.writeUInt32BE = t.writeUInt32BE, e.writeInt8 = t.writeInt8, e.writeInt16LE = t.writeInt16LE, e.writeInt16BE = t.writeInt16BE, e.writeInt32LE = t.writeInt32LE, e.writeInt32BE = t.writeInt32BE, e.writeFloatLE = t.writeFloatLE, e.writeFloatBE = t.writeFloatBE, e.writeDoubleLE = t.writeDoubleLE, e.writeDoubleBE = t.writeDoubleBE, e.fill = t.fill, e.inspect = t.inspect, e.toArrayBuffer = t.toArrayBuffer, e;
1248
- };
1249
- }).call(this, O("lYpoI2"), "undefined" != typeof self ? self : "undefined" != typeof window ? window : {}, O("buffer").Buffer, arguments[3], arguments[4], arguments[5], arguments[6], "/node_modules/gulp-browserify/node_modules/buffer/index.js", "/node_modules/gulp-browserify/node_modules/buffer");
1250
- }, {
1251
- "base64-js": 2,
1252
- buffer: 3,
1253
- ieee754: 10,
1254
- lYpoI2: 11
1255
- }],
1256
- 4: [function(c, d, e) {
1257
- (function(e, t, a, n, r, o, i, u, s) {
1258
- var a = c("buffer").Buffer, f = 4, l = new a(f);
1259
- l.fill(0);
1260
- d.exports = { hash: function(e, t, n, r) {
1261
- for (var o = t(function(e, t) {
1262
- e.length % f != 0 && (n = e.length + (f - e.length % f), e = a.concat([e, l], n));
1263
- for (var n, r = [], o = t ? e.readInt32BE : e.readInt32LE, i = 0; i < e.length; i += f) r.push(o.call(e, i));
1264
- return r;
1265
- }(e = a.isBuffer(e) ? e : new a(e), r), 8 * e.length), t = r, i = new a(n), u = t ? i.writeInt32BE : i.writeInt32LE, s = 0; s < o.length; s++) u.call(i, o[s], 4 * s, !0);
1266
- return i;
1267
- } };
1268
- }).call(this, c("lYpoI2"), "undefined" != typeof self ? self : "undefined" != typeof window ? window : {}, c("buffer").Buffer, arguments[3], arguments[4], arguments[5], arguments[6], "/node_modules/gulp-browserify/node_modules/crypto-browserify/helpers.js", "/node_modules/gulp-browserify/node_modules/crypto-browserify");
1269
- }, {
1270
- buffer: 3,
1271
- lYpoI2: 11
1272
- }],
1273
- 5: [function(v, e, _) {
1274
- (function(l, c, u, d, h, p, g, y, w) {
1275
- var u = v("buffer").Buffer, e = v("./sha"), t = v("./sha256"), n = v("./rng"), b = {
1276
- sha1: e,
1277
- sha256: t,
1278
- md5: v("./md5")
1279
- }, s = 64, a = new u(s);
1280
- function r(e, n) {
1281
- var r = b[e = e || "sha1"], o = [];
1282
- return r || i("algorithm:", e, "is not yet supported"), {
1283
- update: function(e) {
1284
- return u.isBuffer(e) || (e = new u(e)), o.push(e), e.length, this;
1285
- },
1286
- digest: function(e) {
1287
- var t = u.concat(o), t = n ? function(e, t, n) {
1288
- u.isBuffer(t) || (t = new u(t)), u.isBuffer(n) || (n = new u(n)), t.length > s ? t = e(t) : t.length < s && (t = u.concat([t, a], s));
1289
- for (var r = new u(s), o = new u(s), i = 0; i < s; i++) r[i] = 54 ^ t[i], o[i] = 92 ^ t[i];
1290
- return n = e(u.concat([r, n])), e(u.concat([o, n]));
1291
- }(r, n, t) : r(t);
1292
- return o = null, e ? t.toString(e) : t;
1293
- }
1294
- };
1295
- }
1296
- function i() {
1297
- var e = [].slice.call(arguments).join(" ");
1298
- throw new Error([
1299
- e,
1300
- "we accept pull requests",
1301
- "http://github.com/dominictarr/crypto-browserify"
1302
- ].join("\n"));
1303
- }
1304
- a.fill(0), _.createHash = function(e) {
1305
- return r(e);
1306
- }, _.createHmac = r, _.randomBytes = function(e, t) {
1307
- if (!t || !t.call) return new u(n(e));
1308
- try {
1309
- t.call(this, void 0, new u(n(e)));
1310
- } catch (e) {
1311
- t(e);
1312
- }
1313
- };
1314
- var o, f = [
1315
- "createCredentials",
1316
- "createCipher",
1317
- "createCipheriv",
1318
- "createDecipher",
1319
- "createDecipheriv",
1320
- "createSign",
1321
- "createVerify",
1322
- "createDiffieHellman",
1323
- "pbkdf2"
1324
- ], m = function(e) {
1325
- _[e] = function() {
1326
- i("sorry,", e, "is not implemented yet");
1327
- };
1328
- };
1329
- for (o in f) m(f[o], o);
1330
- }).call(this, v("lYpoI2"), "undefined" != typeof self ? self : "undefined" != typeof window ? window : {}, v("buffer").Buffer, arguments[3], arguments[4], arguments[5], arguments[6], "/node_modules/gulp-browserify/node_modules/crypto-browserify/index.js", "/node_modules/gulp-browserify/node_modules/crypto-browserify");
1331
- }, {
1332
- "./md5": 6,
1333
- "./rng": 7,
1334
- "./sha": 8,
1335
- "./sha256": 9,
1336
- buffer: 3,
1337
- lYpoI2: 11
1338
- }],
1339
- 6: [function(w, b, e) {
1340
- (function(e, r, o, i, u, a, f, l, y) {
1341
- var t = w("./helpers");
1342
- function n(e, t) {
1343
- e[t >> 5] |= 128 << t % 32, e[14 + (t + 64 >>> 9 << 4)] = t;
1344
- for (var n = 1732584193, r = -271733879, o = -1732584194, i = 271733878, u = 0; u < e.length; u += 16) {
1345
- var s = n, a = r, f = o, l = i, n = c(n, r, o, i, e[u + 0], 7, -680876936), i = c(i, n, r, o, e[u + 1], 12, -389564586), o = c(o, i, n, r, e[u + 2], 17, 606105819), r = c(r, o, i, n, e[u + 3], 22, -1044525330);
1346
- n = c(n, r, o, i, e[u + 4], 7, -176418897), i = c(i, n, r, o, e[u + 5], 12, 1200080426), o = c(o, i, n, r, e[u + 6], 17, -1473231341), r = c(r, o, i, n, e[u + 7], 22, -45705983), n = c(n, r, o, i, e[u + 8], 7, 1770035416), i = c(i, n, r, o, e[u + 9], 12, -1958414417), o = c(o, i, n, r, e[u + 10], 17, -42063), r = c(r, o, i, n, e[u + 11], 22, -1990404162), n = c(n, r, o, i, e[u + 12], 7, 1804603682), i = c(i, n, r, o, e[u + 13], 12, -40341101), o = c(o, i, n, r, e[u + 14], 17, -1502002290), n = d(n, r = c(r, o, i, n, e[u + 15], 22, 1236535329), o, i, e[u + 1], 5, -165796510), i = d(i, n, r, o, e[u + 6], 9, -1069501632), o = d(o, i, n, r, e[u + 11], 14, 643717713), r = d(r, o, i, n, e[u + 0], 20, -373897302), n = d(n, r, o, i, e[u + 5], 5, -701558691), i = d(i, n, r, o, e[u + 10], 9, 38016083), o = d(o, i, n, r, e[u + 15], 14, -660478335), r = d(r, o, i, n, e[u + 4], 20, -405537848), n = d(n, r, o, i, e[u + 9], 5, 568446438), i = d(i, n, r, o, e[u + 14], 9, -1019803690), o = d(o, i, n, r, e[u + 3], 14, -187363961), r = d(r, o, i, n, e[u + 8], 20, 1163531501), n = d(n, r, o, i, e[u + 13], 5, -1444681467), i = d(i, n, r, o, e[u + 2], 9, -51403784), o = d(o, i, n, r, e[u + 7], 14, 1735328473), n = h(n, r = d(r, o, i, n, e[u + 12], 20, -1926607734), o, i, e[u + 5], 4, -378558), i = h(i, n, r, o, e[u + 8], 11, -2022574463), o = h(o, i, n, r, e[u + 11], 16, 1839030562), r = h(r, o, i, n, e[u + 14], 23, -35309556), n = h(n, r, o, i, e[u + 1], 4, -1530992060), i = h(i, n, r, o, e[u + 4], 11, 1272893353), o = h(o, i, n, r, e[u + 7], 16, -155497632), r = h(r, o, i, n, e[u + 10], 23, -1094730640), n = h(n, r, o, i, e[u + 13], 4, 681279174), i = h(i, n, r, o, e[u + 0], 11, -358537222), o = h(o, i, n, r, e[u + 3], 16, -722521979), r = h(r, o, i, n, e[u + 6], 23, 76029189), n = h(n, r, o, i, e[u + 9], 4, -640364487), i = h(i, n, r, o, e[u + 12], 11, -421815835), o = h(o, i, n, r, e[u + 15], 16, 530742520), n = p(n, r = h(r, o, i, n, e[u + 2], 23, -995338651), o, i, e[u + 0], 6, -198630844), i = p(i, n, r, o, e[u + 7], 10, 1126891415), o = p(o, i, n, r, e[u + 14], 15, -1416354905), r = p(r, o, i, n, e[u + 5], 21, -57434055), n = p(n, r, o, i, e[u + 12], 6, 1700485571), i = p(i, n, r, o, e[u + 3], 10, -1894986606), o = p(o, i, n, r, e[u + 10], 15, -1051523), r = p(r, o, i, n, e[u + 1], 21, -2054922799), n = p(n, r, o, i, e[u + 8], 6, 1873313359), i = p(i, n, r, o, e[u + 15], 10, -30611744), o = p(o, i, n, r, e[u + 6], 15, -1560198380), r = p(r, o, i, n, e[u + 13], 21, 1309151649), n = p(n, r, o, i, e[u + 4], 6, -145523070), i = p(i, n, r, o, e[u + 11], 10, -1120210379), o = p(o, i, n, r, e[u + 2], 15, 718787259), r = p(r, o, i, n, e[u + 9], 21, -343485551), n = g(n, s), r = g(r, a), o = g(o, f), i = g(i, l);
1347
- }
1348
- return Array(n, r, o, i);
1349
- }
1350
- function s(e, t, n, r, o, i) {
1351
- return g((t = g(g(t, e), g(r, i))) << o | t >>> 32 - o, n);
1352
- }
1353
- function c(e, t, n, r, o, i, u) {
1354
- return s(t & n | ~t & r, e, t, o, i, u);
1355
- }
1356
- function d(e, t, n, r, o, i, u) {
1357
- return s(t & r | n & ~r, e, t, o, i, u);
1358
- }
1359
- function h(e, t, n, r, o, i, u) {
1360
- return s(t ^ n ^ r, e, t, o, i, u);
1361
- }
1362
- function p(e, t, n, r, o, i, u) {
1363
- return s(n ^ (t | ~r), e, t, o, i, u);
1364
- }
1365
- function g(e, t) {
1366
- var n = (65535 & e) + (65535 & t);
1367
- return (e >> 16) + (t >> 16) + (n >> 16) << 16 | 65535 & n;
1368
- }
1369
- b.exports = function(e) {
1370
- return t.hash(e, n, 16);
1371
- };
1372
- }).call(this, w("lYpoI2"), "undefined" != typeof self ? self : "undefined" != typeof window ? window : {}, w("buffer").Buffer, arguments[3], arguments[4], arguments[5], arguments[6], "/node_modules/gulp-browserify/node_modules/crypto-browserify/md5.js", "/node_modules/gulp-browserify/node_modules/crypto-browserify");
1373
- }, {
1374
- "./helpers": 4,
1375
- buffer: 3,
1376
- lYpoI2: 11
1377
- }],
1378
- 7: [function(e, l, t) {
1379
- (function(e, t, n, r, o, i, u, s, f) {
1380
- var a;
1381
- l.exports = a || function(e) {
1382
- for (var t, n = new Array(e), r = 0; r < e; r++) 0 == (3 & r) && (t = 4294967296 * Math.random()), n[r] = t >>> ((3 & r) << 3) & 255;
1383
- return n;
1384
- };
1385
- }).call(this, e("lYpoI2"), "undefined" != typeof self ? self : "undefined" != typeof window ? window : {}, e("buffer").Buffer, arguments[3], arguments[4], arguments[5], arguments[6], "/node_modules/gulp-browserify/node_modules/crypto-browserify/rng.js", "/node_modules/gulp-browserify/node_modules/crypto-browserify");
1386
- }, {
1387
- buffer: 3,
1388
- lYpoI2: 11
1389
- }],
1390
- 8: [function(c, d, e) {
1391
- (function(e, t, n, r, o, s, a, f, l) {
1392
- var i = c("./helpers");
1393
- function u(l, c) {
1394
- l[c >> 5] |= 128 << 24 - c % 32, l[15 + (c + 64 >> 9 << 4)] = c;
1395
- for (var e, t, n, r = Array(80), o = 1732584193, i = -271733879, u = -1732584194, s = 271733878, d = -1009589776, h = 0; h < l.length; h += 16) {
1396
- for (var p = o, g = i, y = u, w = s, b = d, a = 0; a < 80; a++) {
1397
- r[a] = a < 16 ? l[h + a] : v(r[a - 3] ^ r[a - 8] ^ r[a - 14] ^ r[a - 16], 1);
1398
- var f = m(m(v(o, 5), (f = i, t = u, n = s, (e = a) < 20 ? f & t | ~f & n : !(e < 40) && e < 60 ? f & t | f & n | t & n : f ^ t ^ n)), m(m(d, r[a]), (e = a) < 20 ? 1518500249 : e < 40 ? 1859775393 : e < 60 ? -1894007588 : -899497514)), d = s, s = u, u = v(i, 30), i = o, o = f;
1399
- }
1400
- o = m(o, p), i = m(i, g), u = m(u, y), s = m(s, w), d = m(d, b);
1401
- }
1402
- return Array(o, i, u, s, d);
1403
- }
1404
- function m(e, t) {
1405
- var n = (65535 & e) + (65535 & t);
1406
- return (e >> 16) + (t >> 16) + (n >> 16) << 16 | 65535 & n;
1407
- }
1408
- function v(e, t) {
1409
- return e << t | e >>> 32 - t;
1410
- }
1411
- d.exports = function(e) {
1412
- return i.hash(e, u, 20, !0);
1413
- };
1414
- }).call(this, c("lYpoI2"), "undefined" != typeof self ? self : "undefined" != typeof window ? window : {}, c("buffer").Buffer, arguments[3], arguments[4], arguments[5], arguments[6], "/node_modules/gulp-browserify/node_modules/crypto-browserify/sha.js", "/node_modules/gulp-browserify/node_modules/crypto-browserify");
1415
- }, {
1416
- "./helpers": 4,
1417
- buffer: 3,
1418
- lYpoI2: 11
1419
- }],
1420
- 9: [function(c, d, e) {
1421
- (function(e, t, n, r, u, s, a, f, l) {
1422
- function b(e, t) {
1423
- var n = (65535 & e) + (65535 & t);
1424
- return (e >> 16) + (t >> 16) + (n >> 16) << 16 | 65535 & n;
1425
- }
1426
- function o(e, l) {
1427
- var c, d = new Array(1116352408, 1899447441, 3049323471, 3921009573, 961987163, 1508970993, 2453635748, 2870763221, 3624381080, 310598401, 607225278, 1426881987, 1925078388, 2162078206, 2614888103, 3248222580, 3835390401, 4022224774, 264347078, 604807628, 770255983, 1249150122, 1555081692, 1996064986, 2554220882, 2821834349, 2952996808, 3210313671, 3336571891, 3584528711, 113926993, 338241895, 666307205, 773529912, 1294757372, 1396182291, 1695183700, 1986661051, 2177026350, 2456956037, 2730485921, 2820302411, 3259730800, 3345764771, 3516065817, 3600352804, 4094571909, 275423344, 430227734, 506948616, 659060556, 883997877, 958139571, 1322822218, 1537002063, 1747873779, 1955562222, 2024104815, 2227730452, 2361852424, 2428436474, 2756734187, 3204031479, 3329325298), t = new Array(1779033703, 3144134277, 1013904242, 2773480762, 1359893119, 2600822924, 528734635, 1541459225), n = new Array(64);
1428
- e[l >> 5] |= 128 << 24 - l % 32, e[15 + (l + 64 >> 9 << 4)] = l;
1429
- for (var r, o, h = 0; h < e.length; h += 16) {
1430
- for (var i = t[0], u = t[1], s = t[2], p = t[3], a = t[4], g = t[5], y = t[6], w = t[7], f = 0; f < 64; f++) n[f] = f < 16 ? e[f + h] : b(b(b((o = n[f - 2], m(o, 17) ^ m(o, 19) ^ v(o, 10)), n[f - 7]), (o = n[f - 15], m(o, 7) ^ m(o, 18) ^ v(o, 3))), n[f - 16]), c = b(b(b(b(w, m(o = a, 6) ^ m(o, 11) ^ m(o, 25)), a & g ^ ~a & y), d[f]), n[f]), r = b(m(r = i, 2) ^ m(r, 13) ^ m(r, 22), i & u ^ i & s ^ u & s), w = y, y = g, g = a, a = b(p, c), p = s, s = u, u = i, i = b(c, r);
1431
- t[0] = b(i, t[0]), t[1] = b(u, t[1]), t[2] = b(s, t[2]), t[3] = b(p, t[3]), t[4] = b(a, t[4]), t[5] = b(g, t[5]), t[6] = b(y, t[6]), t[7] = b(w, t[7]);
1432
- }
1433
- return t;
1434
- }
1435
- var i = c("./helpers"), m = function(e, t) {
1436
- return e >>> t | e << 32 - t;
1437
- }, v = function(e, t) {
1438
- return e >>> t;
1439
- };
1440
- d.exports = function(e) {
1441
- return i.hash(e, o, 32, !0);
1442
- };
1443
- }).call(this, c("lYpoI2"), "undefined" != typeof self ? self : "undefined" != typeof window ? window : {}, c("buffer").Buffer, arguments[3], arguments[4], arguments[5], arguments[6], "/node_modules/gulp-browserify/node_modules/crypto-browserify/sha256.js", "/node_modules/gulp-browserify/node_modules/crypto-browserify");
1444
- }, {
1445
- "./helpers": 4,
1446
- buffer: 3,
1447
- lYpoI2: 11
1448
- }],
1449
- 10: [function(e, t, f) {
1450
- (function(e, t, n, r, o, i, u, s, a) {
1451
- f.read = function(e, t, n, r, o) {
1452
- var i, u, l = 8 * o - r - 1, c = (1 << l) - 1, d = c >> 1, s = -7, a = n ? o - 1 : 0, f = n ? -1 : 1, o = e[t + a];
1453
- for (a += f, i = o & (1 << -s) - 1, o >>= -s, s += l; 0 < s; i = 256 * i + e[t + a], a += f, s -= 8);
1454
- for (u = i & (1 << -s) - 1, i >>= -s, s += r; 0 < s; u = 256 * u + e[t + a], a += f, s -= 8);
1455
- if (0 === i) i = 1 - d;
1456
- else {
1457
- if (i === c) return u ? NaN : Infinity * (o ? -1 : 1);
1458
- u += Math.pow(2, r), i -= d;
1459
- }
1460
- return (o ? -1 : 1) * u * Math.pow(2, i - r);
1461
- }, f.write = function(e, t, l, n, r, c) {
1462
- var o, i, u = 8 * c - r - 1, s = (1 << u) - 1, a = s >> 1, d = 23 === r ? Math.pow(2, -24) - Math.pow(2, -77) : 0, f = n ? 0 : c - 1, h = n ? 1 : -1, c = t < 0 || 0 === t && 1 / t < 0 ? 1 : 0;
1463
- for (t = Math.abs(t), isNaN(t) || t === Infinity ? (i = isNaN(t) ? 1 : 0, o = s) : (o = Math.floor(Math.log(t) / Math.LN2), t * (n = Math.pow(2, -o)) < 1 && (o--, n *= 2), 2 <= (t += 1 <= o + a ? d / n : d * Math.pow(2, 1 - a)) * n && (o++, n /= 2), s <= o + a ? (i = 0, o = s) : 1 <= o + a ? (i = (t * n - 1) * Math.pow(2, r), o += a) : (i = t * Math.pow(2, a - 1) * Math.pow(2, r), o = 0)); 8 <= r; e[l + f] = 255 & i, f += h, i /= 256, r -= 8);
1464
- for (o = o << r | i, u += r; 0 < u; e[l + f] = 255 & o, f += h, o /= 256, u -= 8);
1465
- e[l + f - h] |= 128 * c;
1466
- };
1467
- }).call(this, e("lYpoI2"), "undefined" != typeof self ? self : "undefined" != typeof window ? window : {}, e("buffer").Buffer, arguments[3], arguments[4], arguments[5], arguments[6], "/node_modules/gulp-browserify/node_modules/ieee754/index.js", "/node_modules/gulp-browserify/node_modules/ieee754");
1468
- }, {
1469
- buffer: 3,
1470
- lYpoI2: 11
1471
- }],
1472
- 11: [function(e, h, t) {
1473
- (function(e, t, n, r, o, f, l, c, d) {
1474
- var i, u, s;
1475
- function a() {}
1476
- (e = h.exports = {}).nextTick = (u = "undefined" != typeof window && window.setImmediate, s = "undefined" != typeof window && window.postMessage && window.addEventListener, u ? function(e) {
1477
- return window.setImmediate(e);
1478
- } : s ? (i = [], window.addEventListener("message", function(e) {
1479
- var t = e.source;
1480
- t !== window && null !== t || "process-tick" !== e.data || (e.stopPropagation(), 0 < i.length && i.shift()());
1481
- }, !0), function(e) {
1482
- i.push(e), window.postMessage("process-tick", "*");
1483
- }) : function(e) {
1484
- setTimeout(e, 0);
1485
- }), e.title = "browser", e.browser = !0, e.env = {}, e.argv = [], e.on = a, e.addListener = a, e.once = a, e.off = a, e.removeListener = a, e.removeAllListeners = a, e.emit = a, e.binding = function(e) {
1486
- throw new Error("process.binding is not supported");
1487
- }, e.cwd = function() {
1488
- return "/";
1489
- }, e.chdir = function(e) {
1490
- throw new Error("process.chdir is not supported");
1491
- };
1492
- }).call(this, e("lYpoI2"), "undefined" != typeof self ? self : "undefined" != typeof window ? window : {}, e("buffer").Buffer, arguments[3], arguments[4], arguments[5], arguments[6], "/node_modules/gulp-browserify/node_modules/process/browser.js", "/node_modules/gulp-browserify/node_modules/process");
1493
- }, {
1494
- buffer: 3,
1495
- lYpoI2: 11
1496
- }]
1497
- }, {}, [1])(1);
1498
- });
1499
- })))();
1500
- /**
1501
- * Deep clone a value, preserving function references and class instances.
1502
- * Unlike structuredClone, this handles objects that contain functions
1503
- * (e.g. CollectionConfig with target(), childCollections(), callbacks).
1504
- */
1505
- function deepClone(value) {
1506
- if (value === null || value === void 0) return value;
1507
- if (typeof value === "function") return value;
1508
- if (typeof value !== "object") return value;
1509
- if (Array.isArray(value)) return value.map((item) => deepClone(item));
1510
- if (Object.getPrototypeOf(value) !== Object.prototype) return value;
1511
- const result = {};
1512
- for (const key of Object.keys(value)) result[key] = deepClone(value[key]);
1513
- return result;
1514
- }
1515
- function isObject$1(item) {
1516
- return !!item && typeof item === "object" && !Array.isArray(item);
1517
- }
1518
- function isPlainObject$1(obj) {
1519
- if (typeof obj !== "object" || obj === null || Array.isArray(obj)) return false;
1520
- return Object.getPrototypeOf(obj) === Object.prototype;
1521
- }
1522
- function mergeDeep(target, source, ignoreUndefined = false) {
1523
- if (!isObject$1(target)) return target;
1524
- const output = { ...target };
1525
- if (!isObject$1(source)) return output;
1526
- for (const key in source) {
1527
- if (key === "__proto__" || key === "constructor" || key === "prototype") continue;
1528
- if (Object.prototype.hasOwnProperty.call(source, key)) {
1529
- const sourceValue = source[key];
1530
- const outputValue = output[key];
1531
- if (ignoreUndefined && sourceValue === void 0) continue;
1532
- if (sourceValue instanceof Date) output[key] = new Date(sourceValue.getTime());
1533
- else if (Array.isArray(sourceValue)) if (Array.isArray(outputValue)) if (!(sourceValue.some(isPlainObject$1) || outputValue.some(isPlainObject$1))) output[key] = [...sourceValue];
1534
- else {
1535
- const newArray = [];
1536
- const maxLength = Math.max(outputValue.length, sourceValue.length);
1537
- for (let i = 0; i < maxLength; i++) {
1538
- const sourceItem = sourceValue[i];
1539
- const targetItem = outputValue[i];
1540
- if (i >= sourceValue.length) newArray[i] = targetItem;
1541
- else if (i >= outputValue.length) newArray[i] = sourceItem;
1542
- else if (sourceItem === null) newArray[i] = targetItem;
1543
- else if (isPlainObject$1(sourceItem) && isPlainObject$1(targetItem)) newArray[i] = mergeDeep(targetItem, sourceItem, ignoreUndefined);
1544
- else newArray[i] = sourceItem;
1545
- }
1546
- output[key] = newArray;
1547
- }
1548
- else output[key] = [...sourceValue];
1549
- else if (isPlainObject$1(sourceValue)) if (isPlainObject$1(outputValue)) output[key] = mergeDeep(outputValue, sourceValue, ignoreUndefined);
1550
- else output[key] = sourceValue;
1551
- else if (isObject$1(sourceValue)) output[key] = sourceValue;
1552
- else output[key] = sourceValue;
1553
- }
1554
- }
1555
- return output;
1556
- }
1557
- function removeFunctions(o) {
1558
- if (o === void 0) return void 0;
1559
- if (o === null) return null;
1560
- if (typeof o === "object") {
1561
- if (Array.isArray(o)) return o.map((v) => removeFunctions(v));
1562
- if (!isPlainObject$1(o)) return o;
1563
- return Object.entries(o).filter(([_, value]) => typeof value !== "function").map(([key, value]) => {
1564
- if (Array.isArray(value)) return { [key]: value.map((v) => removeFunctions(v)) };
1565
- else if (typeof value === "object") return { [key]: removeFunctions(value) };
1566
- else return { [key]: value };
1567
- }).reduce((a, b) => ({
1568
- ...a,
1569
- ...b
1570
- }), {});
1571
- }
1572
- return o;
1573
- }
1574
- //#endregion
1575
- //#region ../utils/src/sha1.ts
1576
- /**
1577
- * Minimal SHA-1 implementation that runs in both Node and the browser.
1578
- *
1579
- * This exists because generated Postgres policy names embed a SHA-1 digest of
1580
- * the security rule. The DDL generator runs on the server (where `node:crypto`
1581
- * is available) but the Studio has to derive the same names in the browser to
1582
- * tell a policy it generated apart from one it did not. `node:crypto` cannot be
1583
- * bundled for the browser, so the shared derivation needs a portable digest.
1584
- *
1585
- * SHA-1 is used purely to name things deterministically — never for security.
1586
- * The output is byte-identical to `createHash("sha1").update(str).digest("hex")`,
1587
- * which `sha1.test.ts` pins against `node:crypto` directly.
1588
- */
1589
- /** Rotate a 32-bit word left by `n` bits. */
1590
- function rotl(value, n) {
1591
- return value << n | value >>> 32 - n;
1592
- }
1593
- /**
1594
- * SHA-1 digest of a string, hex-encoded.
1595
- *
1596
- * The input is encoded as UTF-8, matching Node's default handling of strings
1597
- * passed to `hash.update(str)`.
1598
- */
1599
- function sha1Hex(input) {
1600
- const bytes = Array.from(new TextEncoder().encode(input));
1601
- const bitLength = bytes.length * 8;
1602
- bytes.push(128);
1603
- while (bytes.length % 64 !== 56) bytes.push(0);
1604
- const hi = Math.floor(bitLength / 4294967296);
1605
- const lo = bitLength >>> 0;
1606
- bytes.push(hi >>> 24 & 255, hi >>> 16 & 255, hi >>> 8 & 255, hi & 255);
1607
- bytes.push(lo >>> 24 & 255, lo >>> 16 & 255, lo >>> 8 & 255, lo & 255);
1608
- let h0 = 1732584193;
1609
- let h1 = 4023233417;
1610
- let h2 = 2562383102;
1611
- let h3 = 271733878;
1612
- let h4 = 3285377520;
1613
- const w = new Array(80);
1614
- for (let offset = 0; offset < bytes.length; offset += 64) {
1615
- for (let i = 0; i < 16; i++) {
1616
- const j = offset + i * 4;
1617
- w[i] = bytes[j] << 24 | bytes[j + 1] << 16 | bytes[j + 2] << 8 | bytes[j + 3] | 0;
1618
- }
1619
- for (let i = 16; i < 80; i++) w[i] = rotl(w[i - 3] ^ w[i - 8] ^ w[i - 14] ^ w[i - 16], 1);
1620
- let a = h0;
1621
- let b = h1;
1622
- let c = h2;
1623
- let d = h3;
1624
- let e = h4;
1625
- for (let i = 0; i < 80; i++) {
1626
- let f;
1627
- let k;
1628
- if (i < 20) {
1629
- f = b & c | ~b & d;
1630
- k = 1518500249;
1631
- } else if (i < 40) {
1632
- f = b ^ c ^ d;
1633
- k = 1859775393;
1634
- } else if (i < 60) {
1635
- f = b & c | b & d | c & d;
1636
- k = 2400959708;
1637
- } else {
1638
- f = b ^ c ^ d;
1639
- k = 3395469782;
1640
- }
1641
- const temp = rotl(a, 5) + f + e + k + w[i] | 0;
1642
- e = d;
1643
- d = c;
1644
- c = rotl(b, 30);
1645
- b = a;
1646
- a = temp;
1647
- }
1648
- h0 = h0 + a | 0;
1649
- h1 = h1 + b | 0;
1650
- h2 = h2 + c | 0;
1651
- h3 = h3 + d | 0;
1652
- h4 = h4 + e | 0;
1653
- }
1654
- return [
1655
- h0,
1656
- h1,
1657
- h2,
1658
- h3,
1659
- h4
1660
- ].map((word) => (word >>> 0).toString(16).padStart(8, "0")).join("");
1661
- }
1662
- //#endregion
1663
- //#region ../utils/src/policy-names.ts
1664
- /**
1665
- * Naming of the Postgres policies generated from a collection's security rules.
1666
- *
1667
- * A rule without an explicit `name` is compiled to `<table>_<op>_<hash>`, where
1668
- * the hash covers the rule's semantics. The Studio needs the same names to tell
1669
- * "this policy came from your code" apart from "someone wrote this in SQL" —
1670
- * without them it treats generated policies as foreign and offers to import
1671
- * them back into the codebase they came from.
1672
- *
1673
- * This is the single definition of that naming. The DDL and Drizzle generators
1674
- * both derive names from here, so a change cannot silently rename every policy
1675
- * in every deployed database while the UI keeps matching the old ones.
1676
- */
1677
- /** Stable digest of the parts of a rule that determine what the policy does. */
1678
- function getPolicyNameHash(rule) {
1679
- return sha1Hex(JSON.stringify({
1680
- a: rule.access,
1681
- m: rule.mode,
1682
- op: rule.operation,
1683
- ops: rule.operations?.slice().sort(),
1684
- own: rule.ownerField,
1685
- rol: rule.roles?.slice().sort(),
1686
- pg: rule.pgRoles?.slice().sort(),
1687
- u: rule.using,
1688
- w: rule.withCheck,
1689
- c: rule.condition,
1690
- ch: rule.check
1691
- })).substring(0, 7);
1692
- }
1693
- /** The operations a rule expands to — `operations` wins over `operation`. */
1694
- function getPolicyOperations(rule) {
1695
- return rule.operations && rule.operations.length > 0 ? rule.operations : [rule.operation ?? "all"];
1696
- }
1697
- /**
1698
- * Every Postgres policy name a single rule compiles to — one per operation.
1699
- *
1700
- * @param rule The security rule as written in the collection config.
1701
- * @param tableName The rule's table (see `getTableName` in `@rebasepro/common`).
1702
- */
1703
- function getPolicyNamesForRule(rule, tableName) {
1704
- const ops = getPolicyOperations(rule);
1705
- const ruleHash = getPolicyNameHash(rule);
1706
- return ops.map((op, opIdx) => rule.name ? ops.length > 1 ? `${rule.name}_${op}` : rule.name : `${tableName}_${op}_${ruleHash}${ops.length > 1 ? `_${opIdx}` : ""}`);
1707
- }
1708
- //#endregion
1709
- //#region ../utils/src/names.ts
1710
- /**
1711
- * Generates a foreign key column name from a given string, typically a collection slug or name.
1712
- * It converts the name to snake_case, attempts to singularize it by removing a trailing 's'
1713
- * (a common convention for collection names), and appends '_id'.
1714
- *
1715
- * @param name The base name to convert to a foreign key.
1716
- * @returns A foreign key name in the format 'singular_name_id'.
1717
- *
1718
- * @example
1719
- * // returns "user_id"
1720
- * generateForeignKeyName("users")
1721
- *
1722
- * @example
1723
- * // returns "post_id"
1724
- * generateForeignKeyName("posts")
1725
- *
1726
- * @example
1727
- * // returns "product_id"
1728
- * generateForeignKeyName("Product")
1729
- *
1730
- */
1731
- function generateForeignKeyName(name) {
1732
- const snakeCaseName = toSnakeCase(name);
1733
- return `${snakeCaseName.endsWith("s") ? snakeCaseName.slice(0, -1) : snakeCaseName}_id`;
1734
- }
1735
- //#endregion
1736
- //#region ../common/src/util/entities.ts
1737
- /**
1738
- * Update the automatic values in a entity before save
1739
- * @group Driver
1740
- */
1741
- function updateDateAutoValues({ inputValues, properties, status, timestampNowValue }) {
1742
- return traverseValuesProperties(inputValues, properties, (inputValue, property) => {
1743
- if (property.type === "date") if (status === "existing" && property.autoValue === "on_update") return timestampNowValue;
1744
- else if ((status === "new" || status === "copy") && (property.autoValue === "on_update" || property.autoValue === "on_create")) return timestampNowValue;
1745
- else return inputValue;
1746
- else return inputValue;
1747
- }) ?? {};
1748
- }
1749
- /**
1750
- * Normalize a value into a proper EntityRelation instance.
1751
- * Handles EntityRelation class instances, and plain objects
1752
- * with `__type === "relation"` or an `isEntityRelation()` method.
1753
- *
1754
- * When `propertyType` is `"relation"`, also accepts plain objects that
1755
- * have `id` and `path` fields — these are relation-shaped objects from
1756
- * edge cases in the data pipeline (REST fallback, stale cache, custom data source).
1757
- *
1758
- * Returns null if the value cannot be coerced.
1759
- */
1760
- function normalizeToEntityRelation(value, propertyType) {
1761
- if (value instanceof EntityRelation) return value;
1762
- if (!value || typeof value !== "object" || Array.isArray(value)) return null;
1763
- const obj = value;
1764
- 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;
1765
- return new EntityRelation(obj.id, obj.path, obj.data);
1766
- }
1767
- function traverseValuesProperties(inputValues, properties, operation) {
1768
- const safeInputValues = inputValues ?? {};
1769
- const result = mergeDeep(safeInputValues, Object.entries(properties).map(([key, property]) => {
1770
- const updatedValue = traverseValueProperty(safeInputValues && safeInputValues[key], property, operation);
1771
- if (updatedValue === null) return null;
1772
- if (updatedValue === void 0) return void 0;
1773
- return { [key]: updatedValue };
1774
- }).reduce((a, b) => ({
1775
- ...a,
1776
- ...b
1777
- }), {}));
1778
- if (!result || Object.keys(result).length === 0) return void 0;
1779
- return result;
1780
- }
1781
- function traverseValueProperty(inputValue, property, operation) {
1782
- let value;
1783
- if (property.type === "map" && property.properties) value = traverseValuesProperties(inputValue, property.properties, operation);
1784
- else if (property.type === "array") {
1785
- const of = property.of;
1786
- if (of && Array.isArray(inputValue) && !Array.isArray(of)) value = inputValue.map((e) => traverseValueProperty(e, of, operation));
1787
- else if (of && Array.isArray(inputValue) && Array.isArray(of)) value = inputValue.map((e, i) => {
1788
- if (i < of.length) return traverseValueProperty(e, of[i], operation);
1789
- return null;
1790
- }).filter(Boolean);
1791
- else if (property.oneOf && Array.isArray(inputValue)) {
1792
- const typeField = property.oneOf?.typeField ?? "type";
1793
- const valueField = property.oneOf?.valueField ?? "value";
1794
- value = inputValue.map((e) => {
1795
- if (e === null) return null;
1796
- if (typeof e !== "object") return e;
1797
- const rec = e;
1798
- const type = rec[typeField];
1799
- const childProperty = property.oneOf?.properties[type];
1800
- if (!type || !childProperty) return e;
1801
- return {
1802
- [typeField]: type,
1803
- [valueField]: traverseValueProperty(rec[valueField], childProperty, operation)
1804
- };
1805
- });
1806
- } else value = inputValue;
1807
- } else value = operation(inputValue, property);
1808
- return value;
1809
- }
1810
- /**
1811
- * Create a lightweight relation stub for CMS views.
1812
- * Replaces inline `{ id, path, __type: "relation" }` object literals.
1813
- */
1814
- function createRelationRef(id, path) {
1815
- return {
1816
- id,
1817
- path,
1818
- __type: "relation"
1819
- };
1820
- }
1821
- /**
1822
- * Create a hydrated relation reference that includes the full entity data.
1823
- * Used when entity data has been pre-fetched (e.g., via batch loading or JOINs).
1824
- */
1825
- function createRelationRefWithData(id, path, data) {
1826
- return {
1827
- id,
1828
- path,
1829
- __type: "relation",
1830
- data
1831
- };
1832
- }
1833
- /**
1834
- * Derive a row's address from its key columns.
1835
- *
1836
- * Single key → the value as a string. Composite → each part joined by
1837
- * {@link COMPOSITE_ID_SEPARATOR}, in primary-key order, which is what
1838
- * {@link parseIdValues} expects to invert.
1839
- */
1840
- function buildCompositeId(values, primaryKeys) {
1841
- if (primaryKeys.length === 0) return "";
1842
- if (primaryKeys.length === 1) return String(values[primaryKeys[0].fieldName] ?? "");
1843
- return primaryKeys.map((pk) => String(values[pk.fieldName] ?? "")).join(":::");
1844
- }
1845
- /**
1846
- * Invert {@link buildCompositeId}: turn an address back into key columns, each
1847
- * coerced to the type its column actually round-trips as.
1848
- *
1849
- * This is the boundary where a URL segment becomes a query parameter, so a
1850
- * malformed address must throw rather than silently produce a query that
1851
- * matches the wrong row (or none).
1852
- */
1853
- function parseIdValues(idValue, primaryKeys) {
1854
- const result = {};
1855
- if (primaryKeys.length === 0) return result;
1856
- if (primaryKeys.length === 1) {
1857
- const pk = primaryKeys[0];
1858
- if (pk.type === "number" && !pk.isUUID) {
1859
- const parsed = typeof idValue === "number" ? idValue : parseInt(String(idValue), 10);
1860
- if (isNaN(parsed)) throw new Error(`Invalid numeric ID: ${idValue}`);
1861
- result[pk.fieldName] = parsed;
1862
- } else result[pk.fieldName] = String(idValue);
1863
- return result;
1864
- }
1865
- const parts = String(idValue).split(":::");
1866
- if (parts.length !== primaryKeys.length) throw new Error(`Composite ID parts mismatch. Expected ${primaryKeys.length}, got ${parts.length} for ID: ${idValue}`);
1867
- for (let i = 0; i < primaryKeys.length; i++) {
1868
- const pk = primaryKeys[i];
1869
- const val = parts[i];
1870
- if (pk.type === "number" && !pk.isUUID) {
1871
- const parsed = parseInt(val, 10);
1872
- if (isNaN(parsed)) throw new Error(`Invalid numeric ID component: ${val}`);
1873
- result[pk.fieldName] = parsed;
1874
- } else result[pk.fieldName] = val;
1875
- }
1876
- return result;
1877
- }
1878
- /**
1879
- * The primary keys of a collection, as declared by its properties.
1880
- *
1881
- * This is the only tier both sides can read, because it is the only one written
1882
- * in the config: the postgres driver can also infer keys from the Drizzle
1883
- * schema, which the browser never sees and is never sent — the admin compiles
1884
- * the collection files into its own bundle rather than being served them. A key
1885
- * that lives only in the Drizzle schema is therefore invisible here, and the
1886
- * server says so at boot (`warnOnKeysTheAdminCannotResolve`) naming the `isId`
1887
- * to add.
1888
- *
1889
- * Returns an empty array when a collection declares none, which callers must
1890
- * treat as "not addressable" rather than defaulting to `id`: guessing a key
1891
- * that is not the real one produces confidently wrong addresses.
1892
- */
1893
- function getDeclaredPrimaryKeys(collection) {
1894
- const properties = collection.properties;
1895
- if (!properties) return [];
1896
- const keys = [];
1897
- for (const [fieldName, propRaw] of Object.entries(properties)) {
1898
- const prop = propRaw;
1899
- if (!prop || typeof prop !== "object") continue;
1900
- if (!("isId" in prop) || !prop.isId) continue;
1901
- keys.push({
1902
- fieldName,
1903
- type: prop.type === "number" ? "number" : "string",
1904
- isUUID: prop.isId === "uuid"
1905
- });
1906
- }
1907
- return keys;
1908
- }
1909
- /**
1910
- * The keys to address a collection's rows with, resolved the way the driver
1911
- * resolves them — minus the tier the browser cannot reach.
1912
- *
1913
- * The postgres driver tries, in order: properties marked `isId`; the primary
1914
- * keys of the Drizzle schema; and finally a column literally named `id`. Only
1915
- * the first and last are visible in a `CollectionConfig`, which is what both
1916
- * sides share.
1917
- *
1918
- * So the two agree except on a collection that declares no `isId` and whose key
1919
- * is known only to Drizzle. There, the driver reads the real key, and this
1920
- * either resolves nothing (reported to the console by the caller) or — if the
1921
- * table happens to have an unrelated `id` property — resolves `id`, which is
1922
- * the wrong key and cannot be detected from here: the addresses look right and
1923
- * route wrong. Only the config can settle it, so the server names both cases
1924
- * at boot (`warnOnKeysTheAdminCannotResolve`) with the `isId` to add.
1925
- */
1926
- function resolvePrimaryKeys(collection) {
1927
- const declared = getDeclaredPrimaryKeys(collection);
1928
- if (declared.length > 0) return declared;
1929
- const idProp = collection.properties?.id;
1930
- if (idProp && typeof idProp === "object") return [{
1931
- fieldName: "id",
1932
- type: idProp.type === "number" ? "number" : "string"
1933
- }];
1934
- return [];
1935
- }
1936
- //#endregion
1937
- //#region ../common/src/util/enums.ts
1938
- function enumToObjectEntries(enumValues) {
1939
- if (Array.isArray(enumValues)) return enumValues;
1940
- else return Object.entries(enumValues).map(([id, value]) => {
1941
- if (typeof value === "string") return {
1942
- id,
1943
- label: value
1944
- };
1945
- else return {
1946
- ...value,
1947
- id
1948
- };
1949
- });
1950
- }
1951
- //#endregion
1952
- //#region ../common/src/util/relations.ts
1953
- function sanitizeRelation(relation, sourceCollection, resolveCollection) {
1954
- if (!relation.target) throw new Error("Relation is missing a `target` collection.");
1955
- const rawTarget = relation.target;
1956
- let targetCollection;
1957
- if (typeof rawTarget === "string") {
1958
- if (resolveCollection) targetCollection = resolveCollection(rawTarget);
1959
- if (!targetCollection) targetCollection = {
1960
- slug: rawTarget,
1961
- name: rawTarget
1962
- };
1963
- } else if (typeof rawTarget === "function") {
1964
- const evaluated = rawTarget();
1965
- if (typeof evaluated === "string") {
1966
- if (resolveCollection) targetCollection = resolveCollection(evaluated);
1967
- if (!targetCollection) targetCollection = {
1968
- slug: evaluated,
1969
- name: evaluated
1970
- };
1971
- } else targetCollection = evaluated;
1972
- } else if (rawTarget && typeof rawTarget === "object") targetCollection = rawTarget;
1973
- if (!targetCollection) throw new Error("Relation is missing a valid `target` collection.");
1974
- const newRelation = { ...relation };
1975
- newRelation.target = () => {
1976
- if (typeof rawTarget === "string") return resolveCollection && resolveCollection(rawTarget) || targetCollection;
1977
- else if (typeof rawTarget === "function") {
1978
- const evaluated = rawTarget();
1979
- if (typeof evaluated === "string") return resolveCollection && resolveCollection(evaluated) || targetCollection;
1980
- return evaluated;
1981
- }
1982
- return targetCollection;
1983
- };
1984
- if (!newRelation.relationName) newRelation.relationName = toSnakeCase(targetCollection.slug);
1985
- if (!newRelation.direction) if (newRelation.foreignKeyOnTarget) newRelation.direction = "inverse";
1986
- else if (newRelation.through) newRelation.direction = "owning";
1987
- else if (newRelation.cardinality === "many") newRelation.direction = "inverse";
1988
- else newRelation.direction = "owning";
1989
- if (!newRelation.joinPath) {
1990
- const sourceName = toSnakeCase(sourceCollection.slug ?? sourceCollection.name);
1991
- if (newRelation.cardinality === "one" && newRelation.direction === "owning") {
1992
- if (!newRelation.localKey) newRelation.localKey = generateForeignKeyName(newRelation.relationName);
1993
- } else if (newRelation.cardinality === "one" && newRelation.direction === "inverse") {
1994
- if (!newRelation.foreignKeyOnTarget) {
1995
- let foundForeignKey = false;
1996
- try {
1997
- const targetRelations = getDataSourceCapabilities(targetCollection.engine).supportsRelations ? targetCollection.relations || [] : [];
1998
- for (const targetRel of targetRelations) if (targetRel.direction === "owning" && targetRel.cardinality === "one" && targetRel.localKey) try {
1999
- if (targetRel.target().slug === sourceCollection.slug) {
2000
- newRelation.foreignKeyOnTarget = targetRel.localKey;
2001
- foundForeignKey = true;
2002
- break;
2003
- }
2004
- } catch (e) {
2005
- continue;
2006
- }
2007
- } catch (e) {}
2008
- if (!foundForeignKey) newRelation.foreignKeyOnTarget = generateForeignKeyName(newRelation.inverseRelationName ? toSnakeCase(newRelation.inverseRelationName) : sourceName);
2009
- }
2010
- } else if (newRelation.cardinality === "many" && newRelation.direction === "inverse") {
2011
- let isManyToManyInverse = false;
2012
- if (newRelation.inverseRelationName && !newRelation.foreignKeyOnTarget) try {
2013
- const targetRelations = getDataSourceCapabilities(targetCollection.engine).supportsRelations ? targetCollection.relations || [] : [];
2014
- for (const targetRel of targetRelations) if (targetRel.cardinality === "many" && (targetRel.direction === "owning" || !targetRel.direction) && targetRel.relationName === newRelation.inverseRelationName) {
2015
- isManyToManyInverse = true;
2016
- break;
2017
- }
2018
- if (!isManyToManyInverse && targetCollection.properties) for (const [propKey, prop] of Object.entries(targetCollection.properties)) {
2019
- if (prop.type !== "relation") continue;
2020
- const relProp = prop;
2021
- if ((relProp.relationName || propKey) === newRelation.inverseRelationName && relProp.cardinality === "many" && (relProp.direction === "owning" || !relProp.direction)) {
2022
- isManyToManyInverse = true;
2023
- break;
2024
- }
2025
- }
2026
- } catch (e) {}
2027
- if (!isManyToManyInverse && !newRelation.foreignKeyOnTarget) newRelation.foreignKeyOnTarget = generateForeignKeyName(sourceName);
2028
- } else if (newRelation.cardinality === "many" && newRelation.direction === "owning") {
2029
- const sourceTableName = getTableName$1(sourceCollection);
2030
- const targetTableName = getTableName$1(targetCollection);
2031
- newRelation.through = {
2032
- table: newRelation.through?.table ?? [sourceTableName, targetTableName].sort().join("_"),
2033
- sourceColumn: newRelation.through?.sourceColumn ?? generateForeignKeyName(sourceName),
2034
- targetColumn: newRelation.through?.targetColumn ?? generateForeignKeyName(newRelation.relationName)
2035
- };
2036
- }
2037
- }
2038
- if (newRelation.cardinality === "one" && newRelation.direction === "owning" && !newRelation.localKey && !newRelation.joinPath) throw new Error(`Configuration Error in relation from '${sourceCollection.name}': An 'owning' one-to-one relation requires a 'localKey'. Check the relation config for '${newRelation.relationName}'`);
2039
- if (newRelation.cardinality === "one" && newRelation.direction === "inverse" && !newRelation.foreignKeyOnTarget && !newRelation.joinPath) throw new Error(`Configuration Error in relation from '${sourceCollection.name}': An 'inverse' one-to-one relation requires a 'foreignKeyOnTarget'. Check the relation config for '${newRelation.relationName}'`);
2040
- if (newRelation.cardinality === "many" && newRelation.direction === "inverse" && !newRelation.foreignKeyOnTarget && !newRelation.joinPath && !newRelation.inverseRelationName) throw new Error(`Configuration Error in relation from '${sourceCollection.name}': An 'inverse' one-to-many relation requires a 'foreignKeyOnTarget'. Check the relation config for '${newRelation.relationName}'`);
2041
- return newRelation;
2042
- }
2043
- /** WeakMap cache — same collection instance always yields the same relation map. */
2044
- var _resolvedRelationsCache = /* @__PURE__ */ new WeakMap();
2045
- function resolveCollectionRelations(collection) {
2046
- const cached = _resolvedRelationsCache.get(collection);
2047
- if (cached) return cached;
2048
- if (!getDataSourceCapabilities(collection.engine).supportsRelations) return {};
2049
- const relations = {};
2050
- const registeredRelationNames = /* @__PURE__ */ new Set();
2051
- if (collection.relations) collection.relations.forEach((relation) => {
2052
- try {
2053
- const normalizedRelation = sanitizeRelation(relation, collection);
2054
- const relationKey = normalizedRelation.relationName;
2055
- if (relationKey) {
2056
- relations[relationKey] = normalizedRelation;
2057
- registeredRelationNames.add(relationKey);
2058
- }
2059
- } catch (e) {}
2060
- });
2061
- if (collection.properties) Object.entries(collection.properties).forEach(([propKey, prop]) => {
2062
- const relation = resolvePropertyRelation({
2063
- propertyKey: propKey,
2064
- property: prop,
2065
- sourceCollection: collection
2066
- });
2067
- if (relation) {
2068
- if (relations[propKey]) return;
2069
- if (!relation.relationName) relation.relationName = propKey;
2070
- const normalizedRelation = sanitizeRelation(relation, collection);
2071
- relations[propKey] = normalizedRelation;
2072
- registeredRelationNames.add(normalizedRelation.relationName ?? propKey);
2073
- }
2074
- });
2075
- _resolvedRelationsCache.set(collection, relations);
2076
- return relations;
2077
- }
2078
- function resolvePropertyRelation({ propertyKey, property, sourceCollection }) {
2079
- if (property.type !== "relation") return void 0;
2080
- const relProp = property;
2081
- if (relProp.target) return {
2082
- relationName: relProp.relationName || propertyKey,
2083
- target: relProp.target,
2084
- cardinality: relProp.cardinality || "one",
2085
- direction: relProp.direction || "owning",
2086
- inverseRelationName: relProp.inverseRelationName,
2087
- localKey: relProp.localKey,
2088
- foreignKeyOnTarget: relProp.foreignKeyOnTarget,
2089
- through: relProp.through,
2090
- joinPath: relProp.joinPath,
2091
- onUpdate: relProp.onUpdate,
2092
- onDelete: relProp.onDelete,
2093
- overrides: relProp.overrides
2094
- };
2095
- console.warn(`Unrecognized or missing relation target for property '${propertyKey}' in collection '${sourceCollection.slug}'`);
2096
- }
2097
- function getTableName$1(collection) {
2098
- if (getDataSourceCapabilities(collection.engine).supportsRelations) return collection.table ?? toSnakeCase(collection.slug) ?? toSnakeCase(collection.name);
2099
- return toSnakeCase(collection.slug) ?? toSnakeCase(collection.name);
2100
- }
2101
- function getTableVarName(tableName) {
2102
- return tableName.replace(/_([a-z])/g, (_, char) => char.toUpperCase());
2103
- }
2104
- function getEnumVarName(tableName, propName) {
2105
- return `${getTableVarName(tableName)}${propName.charAt(0).toUpperCase() + propName.slice(1)}`;
2106
- }
2107
- function getColumnName(fullColumn) {
2108
- return fullColumn.includes(".") ? fullColumn.split(".").pop() : fullColumn;
2109
- }
2110
- /**
2111
- * Look up a relation by key with forgiving normalization.
2112
- *
2113
- * `resolveCollectionRelations` stores each relation under a single canonical
2114
- * key (no aliases). This helper tries the given key as-is, then falls back to
2115
- * slug form (underscores → hyphens) and snake_case form (hyphens → underscores)
2116
- * so that callers that receive a key from external input (URL path segments,
2117
- * user-provided config, etc.) can still find the right entry.
2118
- */
2119
- function findRelation(resolvedRelations, key) {
2120
- if (resolvedRelations[key]) return resolvedRelations[key];
2121
- const slugKey = key.replace(/_/g, "-");
2122
- if (slugKey !== key && resolvedRelations[slugKey]) return resolvedRelations[slugKey];
2123
- const snakeKey = key.replace(/-/g, "_");
2124
- if (snakeKey !== key && resolvedRelations[snakeKey]) return resolvedRelations[snakeKey];
2125
- }
2126
- //#endregion
2127
- //#region ../common/src/util/resolutions.ts
2128
- function getSubcollections(collection) {
2129
- if (collection.childCollections) return collection.childCollections() ?? [];
2130
- const declaredSubcollections = getDeclaredSubcollections(collection);
2131
- if (getDataSourceCapabilities(collection.engine).supportsSubcollections && declaredSubcollections) return declaredSubcollections() ?? [];
2132
- if (getDataSourceCapabilities(collection.engine).supportsRelations) {
2133
- const resolvedRelations = resolveCollectionRelations(collection);
2134
- return Object.values(resolvedRelations).filter((r) => r.cardinality === "many").map((r) => {
2135
- const target = r.target();
2136
- if (!target) return void 0;
2137
- const relationKey = r.relationName || target.slug;
2138
- let customName;
2139
- if (collection.properties) {
2140
- const prop = Object.entries(collection.properties).find(([_, p]) => p.type === "relation" && p.relationName === relationKey);
2141
- if (prop && prop[1].name) customName = prop[1].name;
2142
- }
2143
- const baseOverrides = { slug: relationKey };
2144
- if (customName) {
2145
- baseOverrides.name = customName;
2146
- baseOverrides.singularName = customName;
2147
- }
2148
- const targetWithOverrides = {
2149
- ...target,
2150
- ...baseOverrides
2151
- };
2152
- return r.overrides ? mergeDeep(targetWithOverrides, r.overrides) : targetWithOverrides;
2153
- }).filter((c) => Boolean(c));
2154
- }
2155
- return [];
2156
- }
2157
- //#endregion
2158
- //#region ../common/src/util/policy/sqlToPolicy.ts
2159
- /**
2160
- * A tiny, regex-based SQL "parser" for security rules.
2161
- *
2162
- * This is NOT a full SQL parser. It is designed to handle the subset of SQL
2163
- * commonly used in `USING` and `WITH CHECK` clauses, enough to drive the
2164
- * optimistic client-side UI decision.
2165
- *
2166
- * It handles:
2167
- * - `field = 'literal'`
2168
- * - `field != 'literal'`
2169
- * - `field = current_setting('app.uid')` (or the legacy `app.user_id`)
2170
- * - `A AND B`, `A OR B` — only where the keyword is at the top level
2171
- * - `true`
2172
- * - `IN (...)` (as optimistic true)
2173
- *
2174
- * For anything it doesn't understand, it returns a `raw` expression, which
2175
- * the evaluator treats as "unknown" (and usually optimistic true).
2176
- *
2177
- * **This output also round-trips back into DDL** via `policyToPostgres` (the
2178
- * schema/policy generators), so decomposing a clause the parser only partly
2179
- * understands is not a cosmetic mistake — it emits invalid SQL. When in doubt,
2180
- * prefer `raw`: it is reproduced verbatim.
2181
- */
2182
- /** True when `keyword` starts at `i` as a standalone word. */
2183
- function isKeywordAt(upper, i, keyword) {
2184
- if (!upper.startsWith(keyword, i)) return false;
2185
- const before = i === 0 ? " " : upper[i - 1];
2186
- const after = upper[i + keyword.length] ?? " ";
2187
- return /[\s()]/.test(before) && /[\s()]/.test(after);
2188
- }
2189
- /**
2190
- * Split `sql` on a boolean keyword, but only where it sits at paren depth 0 and
2191
- * outside a string literal. Returns null when it never does, so the caller
2192
- * leaves the clause alone.
2193
- *
2194
- * This used to be `sql.split(/ AND /i)`, which tore subqueries in half: the
2195
- * `AND` inside
2196
- * `EXISTS (SELECT 1 FROM organization_members m WHERE m.org = t.org AND m.user_id = auth.uid())`
2197
- * split the expression, and re-emitting the halves produced
2198
- * `(EXISTS (...) AND m.user_id = auth.uid())`
2199
- * where `m` is no longer in scope — SQL that Postgres rejects outright with
2200
- * "missing FROM-clause entry for table". Returning null instead keeps such a
2201
- * clause as a `raw` expression, which round-trips verbatim.
2202
- */
2203
- function splitTopLevel(sql, keyword) {
2204
- const upper = sql.toUpperCase();
2205
- const parts = [];
2206
- let depth = 0;
2207
- let inString = false;
2208
- let start = 0;
2209
- for (let i = 0; i < sql.length; i++) {
2210
- const ch = sql[i];
2211
- if (inString) {
2212
- if (ch === "'") if (sql[i + 1] === "'") i++;
2213
- else inString = false;
2214
- continue;
2215
- }
2216
- if (ch === "'") {
2217
- inString = true;
2218
- continue;
2219
- }
2220
- if (ch === "(") {
2221
- depth++;
2222
- continue;
2223
- }
2224
- if (ch === ")") {
2225
- depth--;
2226
- continue;
2227
- }
2228
- if (depth === 0 && isKeywordAt(upper, i, keyword)) {
2229
- parts.push(sql.slice(start, i));
2230
- i += keyword.length - 1;
2231
- start = i + 1;
2232
- }
2233
- }
2234
- if (parts.length === 0) return null;
2235
- parts.push(sql.slice(start));
2236
- const trimmedParts = parts.map((p) => p.trim()).filter((p) => p.length > 0);
2237
- return trimmedParts.length > 1 ? trimmedParts : null;
2238
- }
2239
- /** Drop redundant wrapping parens (`(a AND b)` → `a AND b`), never `(a) AND (b)`. */
2240
- function stripOuterParens(sql) {
2241
- let s = sql.trim();
2242
- for (;;) {
2243
- if (!s.startsWith("(") || !s.endsWith(")")) return s;
2244
- let depth = 0;
2245
- let inString = false;
2246
- let wraps = true;
2247
- for (let i = 0; i < s.length; i++) {
2248
- const ch = s[i];
2249
- if (inString) {
2250
- if (ch === "'") if (s[i + 1] === "'") i++;
2251
- else inString = false;
2252
- continue;
2253
- }
2254
- if (ch === "'") {
2255
- inString = true;
2256
- continue;
2257
- }
2258
- if (ch === "(") depth++;
2259
- else if (ch === ")") {
2260
- depth--;
2261
- if (depth === 0 && i < s.length - 1) {
2262
- wraps = false;
2263
- break;
2264
- }
2265
- }
2266
- }
2267
- if (!wraps) return s;
2268
- s = s.slice(1, -1).trim();
2269
- }
2270
- }
2271
- function sqlToPolicy(sql) {
2272
- const trimmed = stripOuterParens(sql.trim());
2273
- if (trimmed.toLowerCase() === "true") return policy.true();
2274
- if (trimmed.toLowerCase() === "false") return policy.false();
2275
- const overlapMatch = trimmed.match(/^string_to_array\s*\(\s*auth\.roles\(\)\s*,\s*','\s*\)\s*&&\s*ARRAY\s*\[(.+)\]$/i);
2276
- if (overlapMatch) {
2277
- const roles = overlapMatch[1].split(",").map((s) => s.trim().replace(/^'|'$/g, ""));
2278
- return policy.rolesOverlap(roles);
2279
- }
2280
- const containMatch = trimmed.match(/^string_to_array\s*\(\s*auth\.roles\(\)\s*,\s*','\s*\)\s*@>\s*ARRAY\s*\[(.+)\]$/i);
2281
- if (containMatch) {
2282
- const roles = containMatch[1].split(",").map((s) => s.trim().replace(/^'|'$/g, ""));
2283
- return policy.rolesContain(roles);
2284
- }
2285
- const orParts = splitTopLevel(trimmed, "OR");
2286
- if (orParts) return policy.or(...orParts.map(sqlToPolicy));
2287
- const andParts = splitTopLevel(trimmed, "AND");
2288
- if (andParts) return policy.and(...andParts.map(sqlToPolicy));
2289
- const match = trimmed.match(/^(.+?)\s*(!?=)\s*(.+)$/);
2290
- if (match) {
2291
- const [, leftStr, op, rightStr] = match;
2292
- const left = parseOperand(leftStr.trim());
2293
- const right = parseOperand(rightStr.trim());
2294
- if (left && right) return policy.compare(left, op === "=" ? "eq" : "neq", right);
2295
- }
2296
- return policy.raw(sql);
2297
- }
2298
- /**
2299
- * Literals from other BaaS platforms that people compare `auth.uid()` against
2300
- * out of habit. Mirrors the driver's `FOREIGN_CONVENTION_ROLES` guard on
2301
- * `pgRoles`, one surface over: the same muscle memory inside a `using:` string
2302
- * is the more dangerous spelling, because it inverts a rule instead of
2303
- * emptying a table.
2304
- */
2305
- var FOREIGN_CONVENTION_UIDS = {
2306
- anon: "Supabase",
2307
- authenticated: "Supabase",
2308
- service_role: "Supabase"
2309
- };
2310
- /** `auth.uid() IS NOT NULL` in raw SQL, the clause that is always true. */
2311
- var UID_NOT_NULL = /auth\.uid\(\)\s+IS\s+NOT\s+NULL/i;
2312
- /**
2313
- * Find clauses that read as "signed-in users only" but admit anonymous callers.
2314
- *
2315
- * Both spellings come from the same place — Supabase, where `auth.uid()` really
2316
- * is NULL for an anonymous request. Rebase substitutes
2317
- * {@link ANONYMOUS_USER_ID} instead (a blank id would read back as NULL, which
2318
- * is how the trusted *server* context is recognised), so:
2319
- *
2320
- * - `auth.uid() IS NOT NULL` is a tautology on the user path, and
2321
- * - `auth.uid() != 'anon'` compares against a string no caller ever has.
2322
- *
2323
- * Either one turns a lockdown into a full grant, and neither looks wrong. No
2324
- * real user id is ever one of these literals, and a user-context request is
2325
- * never NULL, so a match is always a mistake rather than a deliberate check.
2326
- *
2327
- * Structured expressions are checked too, not just parsed SQL: `policy.compare`
2328
- * can spell the same mistake.
2329
- */
2330
- function findAnonymousGrants(expr) {
2331
- const found = [];
2332
- const visit = (e) => {
2333
- switch (e.kind) {
2334
- case "and":
2335
- case "or":
2336
- e.operands.forEach(visit);
2337
- return;
2338
- case "not":
2339
- visit(e.operand);
2340
- return;
2341
- case "existsIn":
2342
- visit(e.where);
2343
- return;
2344
- case "raw":
2345
- if (UID_NOT_NULL.test(e.sql)) found.push({
2346
- pattern: "uid-not-null",
2347
- detail: e.sql,
2348
- explanation: `\`auth.uid() IS NOT NULL\` is true for every request that came from a client, including anonymous ones — they carry '${ANONYMOUS_USER_ID}', not NULL. Use \`condition: policy.authenticated()\` to mean "signed in".`
2349
- });
2350
- return;
2351
- case "compare": {
2352
- const literal = [e.left, e.right].find((o) => o.kind === "literal");
2353
- if (!(e.left.kind === "authUid" || e.right.kind === "authUid") || typeof literal?.value !== "string") return;
2354
- const platform = FOREIGN_CONVENTION_UIDS[literal.value];
2355
- if (!platform) return;
2356
- found.push({
2357
- pattern: "foreign-uid-literal",
2358
- detail: literal.value,
2359
- explanation: `'${literal.value}' is a ${platform} convention. Rebase reports an anonymous request as '${ANONYMOUS_USER_ID}', so comparing against '${literal.value}' passes for every caller. Use \`condition: policy.authenticated()\` to mean "signed in".`
2360
- });
2361
- return;
2362
- }
2363
- default: return;
2364
- }
2365
- };
2366
- visit(expr);
2367
- return found;
2368
- }
2369
- function parseOperand(str) {
2370
- if (/current_setting\s*\(\s*'app\.(uid|user_id)'\s*\)/i.test(str) || /auth\.uid\(\)/i.test(str)) return policy.authUid();
2371
- const stringMatch = str.match(/^'(.+)'$/);
2372
- if (stringMatch) return policy.literal(stringMatch[1]);
2373
- if (/^\w+$/.test(str)) return policy.field(str);
2374
- return null;
2375
- }
2376
- //#endregion
2377
- //#region ../common/src/util/policy/securityRuleToConditions.ts
2378
- /**
2379
- * Desugars a {@link SecurityRule} — its `access`/`ownerField`/`roles` shortcuts,
2380
- * structured `condition`/`check`, and raw `using`/`withCheck` — into a single
2381
- * normalized {@link PolicyExpression} pair.
2382
- *
2383
- * **This is the linchpin against drift:** both the Postgres DDL generators and
2384
- * the client-side evaluator consume this one function, so there is exactly one
2385
- * definition of what a rule means. In particular, application `roles` are folded
2386
- * into the expression here (AND'd with the base condition, matching how Postgres
2387
- * generates the clause) rather than being handled separately by each consumer.
2388
- */
2389
- function securityRuleToConditions(rule) {
2390
- return {
2391
- usingExpr: withRoles(baseUsing(rule), rule),
2392
- withCheckExpr: withRoles(baseWithCheck(rule), rule)
2393
- };
2394
- }
2395
- function baseUsing(rule) {
2396
- if (rule.condition) return rule.condition;
2397
- if (rule.using != null) return sqlToPolicy(rule.using);
2398
- if (rule.access === "public") return policy.true();
2399
- if (rule.ownerField) return policy.compare(policy.field(rule.ownerField), "eq", policy.authUid());
2400
- return null;
2401
- }
2402
- function baseWithCheck(rule) {
2403
- if (rule.check) return rule.check;
2404
- if (rule.withCheck != null) return sqlToPolicy(rule.withCheck);
2405
- return baseUsing(rule);
2406
- }
2407
- /**
2408
- * AND the base condition with an application-role check, or produce a roles-only
2409
- * condition when there is no base. Mirrors the Postgres generator so that a
2410
- * role-scoped restrictive rule denies exactly the same set of users on both
2411
- * sides.
2412
- */
2413
- function withRoles(base, rule) {
2414
- if (!rule.roles || rule.roles.length === 0) return base;
2415
- const rolesExpr = policy.rolesOverlap(rule.roles);
2416
- if (rule.mode === "restrictive") return base ? policy.or(policy.not(rolesExpr), base) : policy.not(rolesExpr);
2417
- return base ? policy.and(base, rolesExpr) : rolesExpr;
2418
- }
2419
- //#endregion
2420
- //#region ../common/src/util/policy/policyToPostgres.ts
2421
- /**
2422
- * Compiles a {@link PolicyExpression} to a PostgreSQL boolean SQL string,
2423
- * suitable for a `USING (...)` / `WITH CHECK (...)` clause.
2424
- *
2425
- * This is one of the two consumers of the shared policy model (the other being
2426
- * {@link evaluatePolicy}); the Postgres schema generators call it so that DDL
2427
- * and the admin UI derive from the exact same expression.
2428
- */
2429
- function policyToPostgres(expr, collection, options) {
2430
- return compile(expr, {
2431
- fieldCollection: collection,
2432
- fieldPrefix: "",
2433
- outerCollection: collection,
2434
- outerPrefix: "",
2435
- resolveCollection: options?.resolveCollection,
2436
- alias: { n: 0 }
2437
- });
2438
- }
2439
- function compile(expr, scope) {
2440
- switch (expr.kind) {
2441
- case "true": return "true";
2442
- case "false": return "false";
2443
- case "and": return expr.operands.length === 0 ? "true" : expr.operands.map((o) => `(${compile(o, scope)})`).join(" AND ");
2444
- case "or": return expr.operands.length === 0 ? "false" : expr.operands.map((o) => `(${compile(o, scope)})`).join(" OR ");
2445
- case "not": return `NOT (${compile(expr.operand, scope)})`;
2446
- case "compare": {
2447
- const castForAuthUid = (operand, sqlText, other) => other.kind === "authUid" && (operand.kind === "field" || operand.kind === "outerField") ? `(${sqlText})::text` : sqlText;
2448
- const leftSql = castForAuthUid(expr.left, operandToSql(expr.left, scope), expr.right);
2449
- const rightSql = castForAuthUid(expr.right, operandToSql(expr.right, scope), expr.left);
2450
- return `${leftSql} ${COMPARE_SQL[expr.op]} ${rightSql}`;
2451
- }
2452
- case "rolesOverlap": return `string_to_array(auth.roles(), ',') && ${rolesArraySql(expr.roles)}`;
2453
- case "rolesContain": return `string_to_array(auth.roles(), ',') @> ${rolesArraySql(expr.roles)}`;
2454
- case "authenticated": return `auth.uid() IS NOT NULL AND auth.uid() <> ${quoteLiteral$1(ANONYMOUS_USER_ID)}`;
2455
- case "serverContext": return "auth.uid() IS NULL";
2456
- case "existsIn": return compileExistsIn(expr, scope);
2457
- case "raw": return expr.sql.replace(/\{(\w+)\}/g, (_, col) => `${outerQualifier(scope)}${resolveColumnName$1(col, scope.outerCollection)}`);
2458
- }
2459
- }
2460
- /**
2461
- * Compiles `existsIn` to a correlated `EXISTS (SELECT 1 FROM <join> WHERE ...)`.
2462
- * Inside the subquery, `field` operands bind to the aliased join table and
2463
- * `outerField` operands bind to the (table-qualified) outer RLS row.
2464
- */
2465
- function compileExistsIn(expr, scope) {
2466
- const join = scope.resolveCollection?.(expr.collection);
2467
- const joinTable = join ? getTableName$1(join) : toSnakeCase(expr.collection);
2468
- const joinSchema = schemaOf(join) ?? schemaOf(scope.outerCollection) ?? "public";
2469
- const alias = `_ex${scope.alias.n++}`;
2470
- const outerPrefix = outerQualifier(scope);
2471
- const innerScope = {
2472
- fieldCollection: join,
2473
- fieldPrefix: `"${alias}".`,
2474
- outerCollection: scope.outerCollection,
2475
- outerPrefix,
2476
- resolveCollection: scope.resolveCollection,
2477
- alias: scope.alias
2478
- };
2479
- return `EXISTS (SELECT 1 FROM "${joinSchema}"."${joinTable}" "${alias}" WHERE ${compile(expr.where, innerScope)})`;
2480
- }
2481
- var COMPARE_SQL = {
2482
- eq: "=",
2483
- neq: "!=",
2484
- lt: "<",
2485
- lte: "<=",
2486
- gt: ">",
2487
- gte: ">="
2488
- };
2489
- function operandToSql(operand, scope) {
2490
- switch (operand.kind) {
2491
- case "field": return `${scope.fieldPrefix}${resolveColumnName$1(operand.name, scope.fieldCollection)}`;
2492
- case "outerField": return `${scope.outerPrefix}${resolveColumnName$1(operand.name, scope.outerCollection)}`;
2493
- case "literal": return quoteLiteral$1(operand.value);
2494
- case "authUid": return "auth.uid()";
2495
- case "authRoles": return "string_to_array(auth.roles(), ',')";
2496
- }
2497
- }
2498
- /**
2499
- * SQL prefix that qualifies a column of the outer RLS row (`"schema"."table".`),
2500
- * or `""` when the collection is unknown.
2501
- */
2502
- function outerQualifier(scope) {
2503
- const table = scope.outerCollection ? getTableName$1(scope.outerCollection) : void 0;
2504
- if (!table) return "";
2505
- return `"${schemaOf(scope.outerCollection) ?? "public"}"."${table}".`;
2506
- }
2507
- function schemaOf(collection) {
2508
- return collection?.schema || void 0;
2509
- }
2510
- function resolveColumnName$1(propName, collection) {
2511
- const prop = collection?.properties?.[propName];
2512
- if (prop && "columnName" in prop && typeof prop.columnName === "string") return prop.columnName;
2513
- return toSnakeCase(propName);
2514
- }
2515
- function quoteLiteral$1(value) {
2516
- if (value === null) return "NULL";
2517
- if (typeof value === "boolean") return value ? "true" : "false";
2518
- if (typeof value === "number") return String(value);
2519
- return `'${value.replace(/'/g, "''")}'`;
2520
- }
2521
- /** Sorted, single-quoted `ARRAY['a','b']` — matches the generators' output. */
2522
- function rolesArraySql(roles) {
2523
- return `ARRAY[${[...roles].sort().map((r) => `'${r}'`).join(",")}]`;
2524
- }
2525
- //#endregion
2526
- //#region ../common/src/util/callbacks.ts
2527
- /**
2528
- * Helper function to recursively check if there are any callbacks in the properties.
2529
- */
2530
- function hasPropertyCallbacks(properties, callbackName) {
2531
- if (!properties) return false;
2532
- for (const property of Object.values(properties)) {
2533
- if (property.callbacks?.[callbackName]) return true;
2534
- if (property.type === "map" && property.properties) {
2535
- if (hasPropertyCallbacks(property.properties, callbackName)) return true;
2536
- } else if (property.type === "array" && property.of) {
2537
- const ofs = Array.isArray(property.of) ? property.of : [property.of];
2538
- for (const of of ofs) {
2539
- if (of.callbacks?.[callbackName]) return true;
2540
- if (of.type === "map" && of.properties && hasPropertyCallbacks(of.properties, callbackName)) return true;
2541
- }
2542
- }
2543
- }
2544
- return false;
2545
- }
2546
- /**
2547
- * Recursively process properties to apply field-level hooks.
2548
- */
2549
- async function processProperties(properties, values, previousValues, propsContext, callbackName) {
2550
- if (!values || typeof values !== "object") return values;
2551
- const result = { ...values };
2552
- for (const [key, property] of Object.entries(properties)) {
2553
- if (result[key] === void 0) continue;
2554
- let currentValue = result[key];
2555
- const previousValue = previousValues?.[key];
2556
- if (property.type === "array" && Array.isArray(currentValue)) {
2557
- if (property.of && !Array.isArray(property.of)) currentValue = await Promise.all(currentValue.map(async (item, index) => {
2558
- const prevItem = Array.isArray(previousValue) ? previousValue[index] : void 0;
2559
- return (await processProperties({ "_tmp": property.of }, { "_tmp": item }, { "_tmp": prevItem }, propsContext, callbackName))["_tmp"];
2560
- }));
2561
- } else if (property.type === "map" && property.properties && typeof currentValue === "object") currentValue = await processProperties(property.properties, currentValue, previousValue ?? {}, propsContext, callbackName);
2562
- if (property.callbacks?.[callbackName]) {
2563
- const cbRes = await Promise.resolve(property.callbacks[callbackName]({
2564
- ...propsContext,
2565
- value: currentValue,
2566
- previousValue
2567
- }));
2568
- if (cbRes !== void 0) currentValue = cbRes;
2569
- }
2570
- result[key] = currentValue;
2571
- }
2572
- return result;
2573
- }
2574
- /**
2575
- * Helper function to extract field-level PropertyCallbacks from a properties schema
2576
- * and wrap them into an CollectionCallbacks object recursively.
2577
- */
2578
- var buildPropertyCallbacks = (properties) => {
2579
- if (!properties) return void 0;
2580
- const propertyCallbacks = {};
2581
- if (hasPropertyCallbacks(properties, "afterRead")) propertyCallbacks.afterRead = async (props) => {
2582
- const row = props.row;
2583
- const processedValues = await processProperties(properties, row, row, props, "afterRead");
2584
- return {
2585
- ...props.row,
2586
- ...processedValues
2587
- };
2588
- };
2589
- if (hasPropertyCallbacks(properties, "beforeSave")) propertyCallbacks.beforeSave = async (props) => {
2590
- return await processProperties(properties, props.values, props.previousValues ?? {}, props, "beforeSave");
2591
- };
2592
- return Object.keys(propertyCallbacks).length > 0 ? propertyCallbacks : void 0;
2593
- };
2594
- //#endregion
2595
- //#region ../common/src/util/auth-default-policies.ts
2596
- /**
2597
- * Default RLS policies injected by the schema generator.
2598
- *
2599
- * Rebase's enforcement model is unified: authenticated (user-context) requests
2600
- * run under the restricted `rebase_user` role, so Postgres RLS binds *every*
2601
- * statement — reads and writes. A collection's `securityRules` are the whole
2602
- * authorization model. The server context (auth flows, migrations,
2603
- * `dataAsAdmin`) runs as the owner and bypasses RLS.
2604
- *
2605
- * Because RLS default-denies, every collection is **locked by default**: with
2606
- * no rules, only the server context and admins can touch it. The generator
2607
- * injects that safe baseline:
2608
- *
2609
- * **For every collection**
2610
- * 1. A permissive **server-or-admin SELECT** grant.
2611
- * 2. A permissive **server-or-admin write** grant (insert/update/delete).
2612
- *
2613
- * Author `securityRules` are permissive and OR together, so explicit rules only
2614
- * *broaden* access from this locked baseline (e.g. "users read/write their own
2615
- * rows").
2616
- *
2617
- * **For auth collections additionally**
2618
- * 3. A permissive **self SELECT** grant (`id = auth.uid()`), so users can read
2619
- * their own row (profile, session bootstrap) without every app re-declaring
2620
- * it.
2621
- * 4. A **restrictive** admin write gate. Restrictive policies are AND'd with
2622
- * every other policy, so a write is rejected unless the caller is an admin
2623
- * (or the server context) — even if the author also wrote a permissive rule
2624
- * such as "a user may edit their own row". Without this, a permissive owner
2625
- * rule would let a user change their own `roles`.
2626
- *
2627
- * The server context is recognised as `auth.uid() IS NULL` (`policy.serverContext()`)
2628
- * — the built-in flows that run without a user (signup, migrations) set no user
2629
- * GUC — which also lets the owner connection satisfy these policies even under
2630
- * FORCE RLS. A *user* request never reaches that state: an anonymous one carries
2631
- * `ANONYMOUS_USER_ID`, precisely so it cannot pass for the server here.
2632
- *
2633
- * Opt out with `disableDefaultPolicies: true` to take full responsibility for
2634
- * the collection's RLS.
2635
- */
2636
- var SERVER_OR_ADMIN_EXPR$1 = policy.or(policy.serverContext(), policy.rolesOverlap(["admin"]));
2637
- /** Write operations that must be admin-gated by default on auth collections. */
2638
- var DEFAULT_GUARDED_OPS = [
2639
- "insert",
2640
- "update",
2641
- "delete"
2642
- ];
2643
- /** Whether a collection is flagged as an authentication collection. */
2644
- function isAuthCollection(collection) {
2645
- const auth = collection.auth;
2646
- return auth === true || typeof auth === "object" && auth?.enabled === true;
2647
- }
2648
- /** The property marked as the row id (falls back to `id`). */
2649
- function getIdPropertyName$1(collection) {
2650
- for (const [name, prop] of Object.entries(collection.properties ?? {})) if (prop && typeof prop === "object" && "isId" in prop && prop.isId) return name;
2651
- return "id";
2652
- }
2653
- /**
2654
- * Returns the security rules that should be applied to a collection: the
2655
- * author's explicit `securityRules` plus the framework defaults described in
2656
- * the module doc (baseline server/admin read for all collections; self-read
2657
- * and the admin write gate for auth collections).
2658
- *
2659
- * Collections that opt out via `disableDefaultPolicies` are returned unchanged.
2660
- */
2661
- function getEffectiveSecurityRules(collection) {
2662
- const explicit = [...(isPostgresCollectionConfig(collection) ? collection.securityRules : void 0) ?? []];
2663
- if (collection.disableDefaultPolicies) return explicit;
2664
- const tableName = getTableName$1(collection);
2665
- const injected = [];
2666
- injected.push({
2667
- name: `${tableName}_default_admin_read`,
2668
- operations: ["select"],
2669
- condition: SERVER_OR_ADMIN_EXPR$1
2670
- });
2671
- injected.push({
2672
- name: `${tableName}_default_admin_write`,
2673
- operations: [...DEFAULT_GUARDED_OPS],
2674
- condition: SERVER_OR_ADMIN_EXPR$1,
2675
- check: SERVER_OR_ADMIN_EXPR$1
2676
- });
2677
- if (isAuthCollection(collection)) {
2678
- injected.push({
2679
- name: `${tableName}_default_self_read`,
2680
- operations: ["select"],
2681
- condition: policy.compare(policy.field(getIdPropertyName$1(collection)), "eq", policy.authUid())
2682
- });
2683
- injected.push({
2684
- name: `${tableName}_require_admin_write`,
2685
- mode: "restrictive",
2686
- operations: [...DEFAULT_GUARDED_OPS],
2687
- condition: SERVER_OR_ADMIN_EXPR$1,
2688
- check: SERVER_OR_ADMIN_EXPR$1
2689
- });
2690
- }
2691
- return [...explicit, ...injected];
2692
- }
2693
- //#endregion
2694
- //#region ../common/src/util/junction-policies.ts
2695
- var SERVER_OR_ADMIN_EXPR = policy.or(policy.serverContext(), policy.rolesOverlap(["admin"]));
2696
- /**
2697
- * Walk every collection's resolved relations and aggregate the junction tables
2698
- * they declare. Two collections may declare the same junction from opposite
2699
- * sides (posts→tags and tags→posts through `posts_tags`); both become
2700
- * `declaringSides` of one spec, so derived write grants consider both.
2701
- */
2702
- function resolveJunctionSpecs(collections) {
2703
- const specs = /* @__PURE__ */ new Map();
2704
- for (const collection of collections) {
2705
- const resolved = resolveCollectionRelations(collection);
2706
- for (const relation of Object.values(resolved)) {
2707
- if (!relation.through) continue;
2708
- const targetCollection = typeof relation.target === "function" ? relation.target() : void 0;
2709
- if (!targetCollection) continue;
2710
- const rawName = relation.through.table;
2711
- const table = rawName.includes(".") ? rawName.split(".").pop() : rawName;
2712
- const schema = "public";
2713
- const source = {
2714
- collection,
2715
- junctionColumn: relation.through.sourceColumn,
2716
- relation
2717
- };
2718
- const target = {
2719
- collection: targetCollection,
2720
- junctionColumn: relation.through.targetColumn
2721
- };
2722
- const existing = specs.get(table);
2723
- if (!existing) specs.set(table, {
2724
- table,
2725
- schema,
2726
- endpoints: [source, target],
2727
- declaringSides: [source]
2728
- });
2729
- else if (!existing.declaringSides.some((s) => s.collection === collection)) existing.declaringSides.push(source);
2730
- }
2731
- }
2732
- return specs;
2733
- }
2734
- /**
2735
- * A synthetic CollectionConfig standing in for the junction during policy
2736
- * compilation and naming. Its two FK columns carry explicit `columnName`s so
2737
- * `outerField` operands resolve to the exact columns the CREATE TABLE emitted,
2738
- * whatever their casing.
2739
- */
2740
- function getJunctionCollectionConfig(spec) {
2741
- const properties = {};
2742
- for (const endpoint of spec.endpoints) properties[endpoint.junctionColumn] = {
2743
- type: "string",
2744
- columnName: endpoint.junctionColumn
2745
- };
2746
- return {
2747
- slug: spec.table,
2748
- name: spec.table,
2749
- table: spec.table,
2750
- schema: spec.schema,
2751
- properties
2752
- };
2753
- }
2754
- /** The property marked as the row id (falls back to `id`). */
2755
- function getIdPropertyName(collection) {
2756
- for (const [name, prop] of Object.entries(collection.properties ?? {})) if (prop && typeof prop === "object" && "isId" in prop && prop.isId) return name;
2757
- return "id";
2758
- }
2759
- /** `EXISTS (SELECT 1 FROM endpoint WHERE endpoint.pk = junction.fk [AND extra])`. */
2760
- function existsEndpoint(endpoint, extra) {
2761
- const correlation = policy.compare(policy.field(getIdPropertyName(endpoint.collection)), "eq", policy.outerField(endpoint.junctionColumn));
2762
- return policy.existsIn({
2763
- collection: endpoint.collection.slug,
2764
- where: extra ? policy.and(correlation, extra) : correlation
2765
- });
2766
- }
2767
- /**
2768
- * Whether a parent-rule expression keeps its meaning when moved inside the
2769
- * junction's `EXISTS` subquery — and the re-scoped copy if it does.
2770
- *
2771
- * Returns `null` when the rule cannot be embedded faithfully: `raw` SQL
2772
- * anywhere (its `{column}` placeholders would bind to the junction), or an
2773
- * `outerField` inside a nested `existsIn` (it would bind to the junction while
2774
- * the author meant the parent, and no operand can express "the middle scope").
2775
- * Top-level `outerField`s are rewritten to `field`, which is what they meant.
2776
- */
2777
- function embedParentExpression(expr, depth = 0) {
2778
- switch (expr.kind) {
2779
- case "raw": return null;
2780
- case "and":
2781
- case "or": {
2782
- const parts = [];
2783
- for (const child of expr.operands) {
2784
- const embedded = embedParentExpression(child, depth);
2785
- if (!embedded) return null;
2786
- parts.push(embedded);
2787
- }
2788
- return expr.kind === "and" ? policy.and(...parts) : policy.or(...parts);
2789
- }
2790
- case "not": {
2791
- const embedded = embedParentExpression(expr.operand, depth);
2792
- return embedded ? policy.not(embedded) : null;
2793
- }
2794
- case "existsIn": {
2795
- const where = embedParentExpression(expr.where, depth + 1);
2796
- return where ? policy.existsIn({
2797
- collection: expr.collection,
2798
- where
2799
- }) : null;
2800
- }
2801
- case "compare": {
2802
- const left = embedOperand(expr.left, depth);
2803
- const right = embedOperand(expr.right, depth);
2804
- if (!left || !right) return null;
2805
- return {
2806
- ...expr,
2807
- left,
2808
- right
2809
- };
2810
- }
2811
- default: return expr;
2812
- }
2813
- }
2814
- /** Re-scope an operand, or return `null` if its binding cannot be preserved. */
2815
- function embedOperand(operand, depth) {
2816
- if (operand.kind === "outerField") {
2817
- if (depth === 0) return policy.field(operand.name);
2818
- return null;
2819
- }
2820
- return operand;
2821
- }
2822
- /** Does the rule cover the `update` operation? */
2823
- function coversUpdate(rule) {
2824
- return getPolicyOperations(rule).some((op) => op === "update" || op === "all");
2825
- }
2826
- /**
2827
- * The full derived policy set for a junction table: the locked server/admin
2828
- * baseline, the endpoint-visibility read grant, inherited write grants, and
2829
- * inherited restrictive gates. Returns `[]` when every declaring collection set
2830
- * `disableDefaultPolicies` — the junction is then the author's to police, and
2831
- * stays locked (RLS is still enabled) until they write policies for it.
2832
- */
2833
- function getJunctionSecurityRules(spec) {
2834
- if (spec.declaringSides.every((side) => side.collection.disableDefaultPolicies)) return [];
2835
- const rules = [];
2836
- rules.push({
2837
- name: `${spec.table}_default_admin_read`,
2838
- operations: ["select"],
2839
- condition: SERVER_OR_ADMIN_EXPR
2840
- });
2841
- rules.push({
2842
- name: `${spec.table}_default_admin_write`,
2843
- operations: [
2844
- "insert",
2845
- "update",
2846
- "delete"
2847
- ],
2848
- condition: SERVER_OR_ADMIN_EXPR,
2849
- check: SERVER_OR_ADMIN_EXPR
2850
- });
2851
- rules.push({
2852
- name: `${spec.table}_default_edge_read`,
2853
- operations: ["select"],
2854
- condition: policy.and(existsEndpoint(spec.endpoints[0]), existsEndpoint(spec.endpoints[1]))
2855
- });
2856
- const writeGrants = [];
2857
- for (const side of spec.declaringSides) {
2858
- const updateRules = ((isPostgresCollectionConfig(side.collection) ? side.collection.securityRules : void 0) ?? []).filter(coversUpdate);
2859
- const permissive = updateRules.filter((r) => r.mode !== "restrictive");
2860
- const restrictive = updateRules.filter((r) => r.mode === "restrictive");
2861
- const embeddedGates = [];
2862
- let gatesEmbeddable = true;
2863
- for (const gate of restrictive) {
2864
- const using = securityRuleToConditions(gate).usingExpr;
2865
- const embedded = using ? embedParentExpression(using) : null;
2866
- if (!embedded) {
2867
- gatesEmbeddable = false;
2868
- break;
2869
- }
2870
- embeddedGates.push(embedded);
2871
- }
2872
- if (!gatesEmbeddable) continue;
2873
- const grants = [];
2874
- for (const rule of permissive) {
2875
- const using = securityRuleToConditions(rule).usingExpr;
2876
- const embedded = using ? embedParentExpression(using) : null;
2877
- if (embedded) grants.push(embedded);
2878
- }
2879
- if (grants.length === 0) continue;
2880
- const condition = embeddedGates.length > 0 ? policy.and(policy.or(...grants), ...embeddedGates) : policy.or(...grants);
2881
- writeGrants.push(existsEndpoint(side, condition));
2882
- }
2883
- if (writeGrants.length > 0) rules.push({
2884
- name: `${spec.table}_default_edge_write`,
2885
- operations: [
2886
- "insert",
2887
- "update",
2888
- "delete"
2889
- ],
2890
- condition: writeGrants.length === 1 ? writeGrants[0] : policy.or(...writeGrants),
2891
- check: writeGrants.length === 1 ? writeGrants[0] : policy.or(...writeGrants)
2892
- });
2893
- return rules;
2894
- }
2895
- (/* @__PURE__ */ __commonJSMin(((exports, module) => {
2896
- (function(root, factory) {
2897
- if (typeof define === "function" && define.amd) define(factory);
2898
- else if (typeof exports === "object") module.exports = factory();
2899
- else root.jsonLogic = factory();
2900
- })(exports, function() {
2901
- "use strict";
2902
- if (!Array.isArray) Array.isArray = function(arg) {
2903
- return Object.prototype.toString.call(arg) === "[object Array]";
2904
- };
2905
- /**
2906
- * Return an array that contains no duplicates (original not modified)
2907
- * @param {array} array Original reference array
2908
- * @return {array} New array with no duplicates
2909
- */
2910
- function arrayUnique(array) {
2911
- var a = [];
2912
- for (var i = 0, l = array.length; i < l; i++) if (a.indexOf(array[i]) === -1) a.push(array[i]);
2913
- return a;
2914
- }
2915
- var jsonLogic = {};
2916
- var operations = {
2917
- "==": function(a, b) {
2918
- return a == b;
2919
- },
2920
- "===": function(a, b) {
2921
- return a === b;
2922
- },
2923
- "!=": function(a, b) {
2924
- return a != b;
2925
- },
2926
- "!==": function(a, b) {
2927
- return a !== b;
2928
- },
2929
- ">": function(a, b) {
2930
- return a > b;
2931
- },
2932
- ">=": function(a, b) {
2933
- return a >= b;
2934
- },
2935
- "<": function(a, b, c) {
2936
- return c === void 0 ? a < b : a < b && b < c;
2937
- },
2938
- "<=": function(a, b, c) {
2939
- return c === void 0 ? a <= b : a <= b && b <= c;
2940
- },
2941
- "!!": function(a) {
2942
- return jsonLogic.truthy(a);
2943
- },
2944
- "!": function(a) {
2945
- return !jsonLogic.truthy(a);
2946
- },
2947
- "%": function(a, b) {
2948
- return a % b;
2949
- },
2950
- "log": function(a) {
2951
- console.log(a);
2952
- return a;
2953
- },
2954
- "in": function(a, b) {
2955
- if (!b || typeof b.indexOf === "undefined") return false;
2956
- return b.indexOf(a) !== -1;
2957
- },
2958
- "cat": function() {
2959
- return Array.prototype.join.call(arguments, "");
2960
- },
2961
- "substr": function(source, start, end) {
2962
- if (end < 0) {
2963
- var temp = String(source).substr(start);
2964
- return temp.substr(0, temp.length + end);
2965
- }
2966
- return String(source).substr(start, end);
2967
- },
2968
- "+": function() {
2969
- return Array.prototype.reduce.call(arguments, function(a, b) {
2970
- return parseFloat(a, 10) + parseFloat(b, 10);
2971
- }, 0);
2972
- },
2973
- "*": function() {
2974
- return Array.prototype.reduce.call(arguments, function(a, b) {
2975
- return parseFloat(a, 10) * parseFloat(b, 10);
2976
- });
2977
- },
2978
- "-": function(a, b) {
2979
- if (b === void 0) return -a;
2980
- else return a - b;
2981
- },
2982
- "/": function(a, b) {
2983
- return a / b;
2984
- },
2985
- "min": function() {
2986
- return Math.min.apply(this, arguments);
2987
- },
2988
- "max": function() {
2989
- return Math.max.apply(this, arguments);
2990
- },
2991
- "merge": function() {
2992
- return Array.prototype.reduce.call(arguments, function(a, b) {
2993
- return a.concat(b);
2994
- }, []);
2995
- },
2996
- "var": function(a, b) {
2997
- var not_found = b === void 0 ? null : b;
2998
- var data = this;
2999
- if (typeof a === "undefined" || a === "" || a === null) return data;
3000
- var sub_props = String(a).split(".");
3001
- for (var i = 0; i < sub_props.length; i++) {
3002
- if (data === null || data === void 0) return not_found;
3003
- data = data[sub_props[i]];
3004
- if (data === void 0) return not_found;
3005
- }
3006
- return data;
3007
- },
3008
- "missing": function() {
3009
- var missing = [];
3010
- var keys = Array.isArray(arguments[0]) ? arguments[0] : arguments;
3011
- for (var i = 0; i < keys.length; i++) {
3012
- var key = keys[i];
3013
- var value = jsonLogic.apply({ "var": key }, this);
3014
- if (value === null || value === "") missing.push(key);
3015
- }
3016
- return missing;
3017
- },
3018
- "missing_some": function(need_count, options) {
3019
- var are_missing = jsonLogic.apply({ "missing": options }, this);
3020
- if (options.length - are_missing.length >= need_count) return [];
3021
- else return are_missing;
3022
- }
3023
- };
3024
- jsonLogic.is_logic = function(logic) {
3025
- return typeof logic === "object" && logic !== null && !Array.isArray(logic) && Object.keys(logic).length === 1;
3026
- };
3027
- jsonLogic.truthy = function(value) {
3028
- if (Array.isArray(value) && value.length === 0) return false;
3029
- return !!value;
3030
- };
3031
- jsonLogic.get_operator = function(logic) {
3032
- return Object.keys(logic)[0];
3033
- };
3034
- jsonLogic.get_values = function(logic) {
3035
- return logic[jsonLogic.get_operator(logic)];
3036
- };
3037
- jsonLogic.apply = function(logic, data) {
3038
- if (Array.isArray(logic)) return logic.map(function(l) {
3039
- return jsonLogic.apply(l, data);
3040
- });
3041
- if (!jsonLogic.is_logic(logic)) return logic;
3042
- var op = jsonLogic.get_operator(logic);
3043
- var values = logic[op];
3044
- var i;
3045
- var current;
3046
- var scopedLogic;
3047
- var scopedData;
3048
- var initial;
3049
- if (!Array.isArray(values)) values = [values];
3050
- if (op === "if" || op == "?:") {
3051
- for (i = 0; i < values.length - 1; i += 2) if (jsonLogic.truthy(jsonLogic.apply(values[i], data))) return jsonLogic.apply(values[i + 1], data);
3052
- if (values.length === i + 1) return jsonLogic.apply(values[i], data);
3053
- return null;
3054
- } else if (op === "and") {
3055
- for (i = 0; i < values.length; i += 1) {
3056
- current = jsonLogic.apply(values[i], data);
3057
- if (!jsonLogic.truthy(current)) return current;
3058
- }
3059
- return current;
3060
- } else if (op === "or") {
3061
- for (i = 0; i < values.length; i += 1) {
3062
- current = jsonLogic.apply(values[i], data);
3063
- if (jsonLogic.truthy(current)) return current;
3064
- }
3065
- return current;
3066
- } else if (op === "filter") {
3067
- scopedData = jsonLogic.apply(values[0], data);
3068
- scopedLogic = values[1];
3069
- if (!Array.isArray(scopedData)) return [];
3070
- return scopedData.filter(function(datum) {
3071
- return jsonLogic.truthy(jsonLogic.apply(scopedLogic, datum));
3072
- });
3073
- } else if (op === "map") {
3074
- scopedData = jsonLogic.apply(values[0], data);
3075
- scopedLogic = values[1];
3076
- if (!Array.isArray(scopedData)) return [];
3077
- return scopedData.map(function(datum) {
3078
- return jsonLogic.apply(scopedLogic, datum);
3079
- });
3080
- } else if (op === "reduce") {
3081
- scopedData = jsonLogic.apply(values[0], data);
3082
- scopedLogic = values[1];
3083
- initial = typeof values[2] !== "undefined" ? jsonLogic.apply(values[2], data) : null;
3084
- if (!Array.isArray(scopedData)) return initial;
3085
- return scopedData.reduce(function(accumulator, current) {
3086
- return jsonLogic.apply(scopedLogic, {
3087
- current,
3088
- accumulator
3089
- });
3090
- }, initial);
3091
- } else if (op === "all") {
3092
- scopedData = jsonLogic.apply(values[0], data);
3093
- scopedLogic = values[1];
3094
- if (!Array.isArray(scopedData) || !scopedData.length) return false;
3095
- for (i = 0; i < scopedData.length; i += 1) if (!jsonLogic.truthy(jsonLogic.apply(scopedLogic, scopedData[i]))) return false;
3096
- return true;
3097
- } else if (op === "none") {
3098
- scopedData = jsonLogic.apply(values[0], data);
3099
- scopedLogic = values[1];
3100
- if (!Array.isArray(scopedData) || !scopedData.length) return true;
3101
- for (i = 0; i < scopedData.length; i += 1) if (jsonLogic.truthy(jsonLogic.apply(scopedLogic, scopedData[i]))) return false;
3102
- return true;
3103
- } else if (op === "some") {
3104
- scopedData = jsonLogic.apply(values[0], data);
3105
- scopedLogic = values[1];
3106
- if (!Array.isArray(scopedData) || !scopedData.length) return false;
3107
- for (i = 0; i < scopedData.length; i += 1) if (jsonLogic.truthy(jsonLogic.apply(scopedLogic, scopedData[i]))) return true;
3108
- return false;
3109
- }
3110
- values = values.map(function(val) {
3111
- return jsonLogic.apply(val, data);
3112
- });
3113
- if (operations.hasOwnProperty(op) && typeof operations[op] === "function") return operations[op].apply(data, values);
3114
- else if (op.indexOf(".") > 0) {
3115
- var sub_ops = String(op).split(".");
3116
- var operation = operations;
3117
- for (i = 0; i < sub_ops.length; i++) {
3118
- if (!operation.hasOwnProperty(sub_ops[i])) throw new Error("Unrecognized operation " + op + " (failed at " + sub_ops.slice(0, i + 1).join(".") + ")");
3119
- operation = operation[sub_ops[i]];
3120
- }
3121
- return operation.apply(data, values);
3122
- }
3123
- throw new Error("Unrecognized operation " + op);
3124
- };
3125
- jsonLogic.uses_data = function(logic) {
3126
- var collection = [];
3127
- if (jsonLogic.is_logic(logic)) {
3128
- var op = jsonLogic.get_operator(logic);
3129
- var values = logic[op];
3130
- if (!Array.isArray(values)) values = [values];
3131
- if (op === "var") collection.push(values[0]);
3132
- else values.forEach(function(val) {
3133
- collection.push.apply(collection, jsonLogic.uses_data(val));
3134
- });
3135
- }
3136
- return arrayUnique(collection);
3137
- };
3138
- jsonLogic.add_operation = function(name, code) {
3139
- operations[name] = code;
3140
- };
3141
- jsonLogic.rm_operation = function(name) {
3142
- delete operations[name];
3143
- };
3144
- jsonLogic.rule_like = function(rule, pattern) {
3145
- if (pattern === rule) return true;
3146
- if (pattern === "@") return true;
3147
- if (pattern === "number") return typeof rule === "number";
3148
- if (pattern === "string") return typeof rule === "string";
3149
- if (pattern === "array") return Array.isArray(rule) && !jsonLogic.is_logic(rule);
3150
- if (jsonLogic.is_logic(pattern)) {
3151
- if (jsonLogic.is_logic(rule)) {
3152
- var pattern_op = jsonLogic.get_operator(pattern);
3153
- var rule_op = jsonLogic.get_operator(rule);
3154
- if (pattern_op === "@" || pattern_op === rule_op) return jsonLogic.rule_like(jsonLogic.get_values(rule, false), jsonLogic.get_values(pattern, false));
3155
- }
3156
- return false;
3157
- }
3158
- if (Array.isArray(pattern)) if (Array.isArray(rule)) {
3159
- if (pattern.length !== rule.length) return false;
3160
- for (var i = 0; i < pattern.length; i += 1) if (!jsonLogic.rule_like(rule[i], pattern[i])) return false;
3161
- return true;
3162
- } else return false;
3163
- return false;
3164
- };
3165
- return jsonLogic;
3166
- });
3167
- })))();
3168
- //#endregion
3169
- //#region ../common/src/util/filter-operator-resolution.ts
3170
- /**
3171
- * Default operators offered per property type, before engine capabilities and
3172
- * per-property narrowing are applied. These mirror what the built-in filter
3173
- * fields can render.
3174
- */
3175
- var COMPARISON_OPS = [
3176
- "==",
3177
- "!=",
3178
- ">",
3179
- ">=",
3180
- "<",
3181
- "<="
3182
- ];
3183
- var NULL_CHECK_OPS = ["is-null", "is-not-null"];
3184
- var MEMBERSHIP_OPS = ["in", "not-in"];
3185
- var PATTERN_OPS = [
3186
- "like",
3187
- "ilike",
3188
- "not-like",
3189
- "not-ilike"
3190
- ];
3191
- [
3192
- ...COMPARISON_OPS,
3193
- ...MEMBERSHIP_OPS,
3194
- ...PATTERN_OPS,
3195
- ...NULL_CHECK_OPS
3196
- ], [
3197
- ...COMPARISON_OPS,
3198
- ...MEMBERSHIP_OPS,
3199
- ...NULL_CHECK_OPS
3200
- ], [...COMPARISON_OPS, ...NULL_CHECK_OPS], [...NULL_CHECK_OPS], [...MEMBERSHIP_OPS, ...NULL_CHECK_OPS], [...MEMBERSHIP_OPS, ...NULL_CHECK_OPS];
3201
- //#endregion
3202
- //#region ../../node_modules/.pnpm/fast-equals@6.0.0/node_modules/fast-equals/dist/es/index.mjs
3203
- var { getOwnPropertyNames, getOwnPropertySymbols } = Object;
3204
- var { hasOwnProperty } = Object.prototype;
3205
- /**
3206
- * Combine two comparators into a single comparators.
3207
- */
3208
- function combineComparators(comparatorA, comparatorB) {
3209
- return function isEqual(a, b, state) {
3210
- return comparatorA(a, b, state) && comparatorB(a, b, state);
3211
- };
3212
- }
3213
- /**
3214
- * Wrap the provided `areItemsEqual` method to manage the circular state, allowing
3215
- * for circular references to be safely included in the comparison without creating
3216
- * stack overflows.
3217
- */
3218
- function createIsCircular(areItemsEqual) {
3219
- return function isCircular(a, b, state) {
3220
- if (!a || !b || typeof a !== "object" || typeof b !== "object") return areItemsEqual(a, b, state);
3221
- const { cache } = state;
3222
- const cachedA = cache.get(a);
3223
- const cachedB = cache.get(b);
3224
- if (cachedA && cachedB) return cachedA === b && cachedB === a;
3225
- cache.set(a, b);
3226
- cache.set(b, a);
3227
- const result = areItemsEqual(a, b, state);
3228
- cache.delete(a);
3229
- cache.delete(b);
3230
- return result;
3231
- };
3232
- }
3233
- /**
3234
- * Get the properties to strictly examine, which include both own properties that are
3235
- * not enumerable and symbol properties.
3236
- */
3237
- function getStrictProperties(object) {
3238
- return getOwnPropertyNames(object).concat(getOwnPropertySymbols(object));
3239
- }
3240
- /**
3241
- * Whether the object contains the property passed as an own property.
3242
- */
3243
- var hasOwn = Object.hasOwn || ((object, property) => hasOwnProperty.call(object, property));
3244
- var PREACT_VNODE = "__v";
3245
- var PREACT_OWNER = "__o";
3246
- var REACT_OWNER = "_owner";
3247
- var { getOwnPropertyDescriptor, keys } = Object;
3248
- /**
3249
- * Whether the values passed are equal based on a [SameValue](https://262.ecma-international.org/7.0/#sec-samevalue) basis.
3250
- * Simplified, this maps to if the two values are referentially equal to one another (`a === b`) or both are `NaN`.
3251
- *
3252
- * @note
3253
- * When available in the environment, this is just a re-export of the global
3254
- * [`Object.is`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is) method.
3255
- */
3256
- var sameValueEqual = Object.is || function sameValueEqual(a, b) {
3257
- return a === b ? a !== 0 || 1 / a === 1 / b : a !== a && b !== b;
3258
- };
3259
- /**
3260
- * Whether the values passed are equal based on a
3261
- * [Strict Equality Comparison](https://262.ecma-international.org/7.0/#sec-strict-equality-comparison) basis.
3262
- * Simplified, this maps to if the two values are referentially equal to one another (`a === b`).
3263
- *
3264
- * @note
3265
- * This is mainly available as a convenience function, such as being a default when a function to determine equality between
3266
- * two objects is used.
3267
- */
3268
- function strictEqual(a, b) {
3269
- return a === b;
3270
- }
3271
- /**
3272
- * Whether the array buffers are equal in value.
3273
- */
3274
- function areArrayBuffersEqual(a, b) {
3275
- return a.byteLength === b.byteLength && areTypedArraysEqual(new Uint8Array(a), new Uint8Array(b));
3276
- }
3277
- /**
3278
- * Whether the arrays are equal in value.
3279
- */
3280
- function areArraysEqual(a, b, state) {
3281
- let index = a.length;
3282
- if (b.length !== index) return false;
3283
- while (index-- > 0) if (!state.equals(a[index], b[index], index, index, a, b, state)) return false;
3284
- return true;
3285
- }
3286
- /**
3287
- * Whether the dataviews are equal in value.
3288
- */
3289
- function areDataViewsEqual(a, b) {
3290
- return a.byteLength === b.byteLength && areTypedArraysEqual(new Uint8Array(a.buffer, a.byteOffset, a.byteLength), new Uint8Array(b.buffer, b.byteOffset, b.byteLength));
3291
- }
3292
- /**
3293
- * Whether the dates passed are equal in value.
3294
- */
3295
- function areDatesEqual(a, b) {
3296
- return sameValueEqual(a.getTime(), b.getTime());
3297
- }
3298
- /**
3299
- * Whether the errors passed are equal in value.
3300
- */
3301
- function areErrorsEqual(a, b) {
3302
- return a.name === b.name && a.message === b.message && a.cause === b.cause && a.stack === b.stack;
3303
- }
3304
- /**
3305
- * Whether the `Map`s are equal in value.
3306
- */
3307
- function areMapsEqual(a, b, state) {
3308
- const size = a.size;
3309
- if (size !== b.size) return false;
3310
- if (!size) return true;
3311
- const matchedIndices = new Array(size);
3312
- const aIterable = a.entries();
3313
- let aResult;
3314
- let bResult;
3315
- let index = 0;
3316
- while (aResult = aIterable.next()) {
3317
- if (aResult.done) break;
3318
- const bIterable = b.entries();
3319
- let hasMatch = false;
3320
- let matchIndex = 0;
3321
- while (bResult = bIterable.next()) {
3322
- if (bResult.done) break;
3323
- if (matchedIndices[matchIndex]) {
3324
- matchIndex++;
3325
- continue;
3326
- }
3327
- const aEntry = aResult.value;
3328
- const bEntry = bResult.value;
3329
- if (state.equals(aEntry[0], bEntry[0], index, matchIndex, a, b, state) && state.equals(aEntry[1], bEntry[1], aEntry[0], bEntry[0], a, b, state)) {
3330
- hasMatch = matchedIndices[matchIndex] = true;
3331
- break;
3332
- }
3333
- matchIndex++;
3334
- }
3335
- if (!hasMatch) return false;
3336
- index++;
3337
- }
3338
- return true;
3339
- }
3340
- /**
3341
- * Whether the objects are equal in value.
3342
- */
3343
- function areObjectsEqual(a, b, state) {
3344
- const properties = keys(a);
3345
- let index = properties.length;
3346
- if (keys(b).length !== index) return false;
3347
- while (index-- > 0) if (!isPropertyEqual(a, b, state, properties[index])) return false;
3348
- return true;
3349
- }
3350
- /**
3351
- * Whether the objects are equal in value with strict property checking.
3352
- */
3353
- function areObjectsEqualStrict(a, b, state) {
3354
- const properties = getStrictProperties(a);
3355
- let index = properties.length;
3356
- if (getStrictProperties(b).length !== index) return false;
3357
- let property;
3358
- let descriptorA;
3359
- let descriptorB;
3360
- while (index-- > 0) {
3361
- property = properties[index];
3362
- if (!isPropertyEqual(a, b, state, property)) return false;
3363
- descriptorA = getOwnPropertyDescriptor(a, property);
3364
- descriptorB = getOwnPropertyDescriptor(b, property);
3365
- if ((descriptorA || descriptorB) && (!descriptorA || !descriptorB || descriptorA.configurable !== descriptorB.configurable || descriptorA.enumerable !== descriptorB.enumerable || descriptorA.writable !== descriptorB.writable)) return false;
3366
- }
3367
- return true;
3368
- }
3369
- /**
3370
- * Whether the primitive wrappers passed are equal in value.
3371
- */
3372
- function arePrimitiveWrappersEqual(a, b) {
3373
- return sameValueEqual(a.valueOf(), b.valueOf());
3374
- }
3375
- /**
3376
- * Whether the regexps passed are equal in value.
3377
- */
3378
- function areRegExpsEqual(a, b) {
3379
- return a.source === b.source && a.flags === b.flags;
3380
- }
3381
- /**
3382
- * Whether the `Set`s are equal in value.
3383
- */
3384
- function areSetsEqual(a, b, state) {
3385
- const size = a.size;
3386
- if (size !== b.size) return false;
3387
- if (!size) return true;
3388
- const matchedIndices = new Array(size);
3389
- const aIterable = a.values();
3390
- let aResult;
3391
- let bResult;
3392
- while (aResult = aIterable.next()) {
3393
- if (aResult.done) break;
3394
- const bIterable = b.values();
3395
- let hasMatch = false;
3396
- let matchIndex = 0;
3397
- while (bResult = bIterable.next()) {
3398
- if (bResult.done) break;
3399
- if (!matchedIndices[matchIndex] && state.equals(aResult.value, bResult.value, aResult.value, bResult.value, a, b, state)) {
3400
- hasMatch = matchedIndices[matchIndex] = true;
3401
- break;
3402
- }
3403
- matchIndex++;
3404
- }
3405
- if (!hasMatch) return false;
3406
- }
3407
- return true;
3408
- }
3409
- /**
3410
- * Whether the TypedArray instances are equal in value.
3411
- */
3412
- function areTypedArraysEqual(a, b) {
3413
- let index = a.byteLength;
3414
- if (b.byteLength !== index || a.byteOffset !== b.byteOffset) return false;
3415
- while (index-- > 0) if (a[index] !== b[index]) return false;
3416
- return true;
3417
- }
3418
- /**
3419
- * Whether the URL instances are equal in value.
3420
- */
3421
- function areUrlsEqual(a, b) {
3422
- return a.hostname === b.hostname && a.pathname === b.pathname && a.protocol === b.protocol && a.port === b.port && a.hash === b.hash && a.username === b.username && a.password === b.password;
3423
- }
3424
- function isPropertyEqual(a, b, state, property) {
3425
- if ((property === REACT_OWNER || property === PREACT_OWNER || property === PREACT_VNODE) && (a.$$typeof || b.$$typeof)) return true;
3426
- return hasOwn(b, property) && state.equals(a[property], b[property], property, property, a, b, state);
3427
- }
3428
- var toString$1 = Object.prototype.toString;
3429
- /**
3430
- * Create a comparator method based on the type-specific equality comparators passed.
3431
- */
3432
- function createEqualityComparator(config) {
3433
- const supportedComparatorMap = createSupportedComparatorMap(config);
3434
- const { areArraysEqual, areDatesEqual, areFunctionsEqual, areMapsEqual, areNumbersEqual, areObjectsEqual, areRegExpsEqual, areSetsEqual, getUnsupportedCustomComparator } = config;
3435
- /**
3436
- * compare the value of the two objects and return true if they are equivalent in values
3437
- */
3438
- return function comparator(a, b, state) {
3439
- if (a === b) return true;
3440
- if (a == null || b == null) return false;
3441
- const type = typeof a;
3442
- if (type !== typeof b) return false;
3443
- if (type !== "object") {
3444
- if (type === "number" || type === "bigint") return areNumbersEqual(a, b, state);
3445
- if (type === "function") return areFunctionsEqual(a, b, state);
3446
- return false;
3447
- }
3448
- const constructor = a.constructor;
3449
- if (constructor !== b.constructor) return false;
3450
- if (constructor === Object) return areObjectsEqual(a, b, state);
3451
- if (constructor === Array) return areArraysEqual(a, b, state);
3452
- if (constructor === Date) return areDatesEqual(a, b, state);
3453
- if (constructor === RegExp) return areRegExpsEqual(a, b, state);
3454
- if (constructor === Map) return areMapsEqual(a, b, state);
3455
- if (constructor === Set) return areSetsEqual(a, b, state);
3456
- if (constructor === Promise) return false;
3457
- if (Array.isArray(a)) return areArraysEqual(a, b, state);
3458
- const tag = toString$1.call(a);
3459
- const supportedComparator = supportedComparatorMap[tag];
3460
- if (supportedComparator) return supportedComparator(a, b, state);
3461
- const unsupportedCustomComparator = getUnsupportedCustomComparator && getUnsupportedCustomComparator(a, b, state, tag);
3462
- if (unsupportedCustomComparator) return unsupportedCustomComparator(a, b, state);
3463
- return false;
3464
- };
3465
- }
3466
- /**
3467
- * Create the configuration object used for building comparators.
3468
- */
3469
- function createEqualityComparatorConfig({ circular, createCustomConfig, strict }) {
3470
- let config = {
3471
- areArrayBuffersEqual,
3472
- areArraysEqual: strict ? areObjectsEqualStrict : areArraysEqual,
3473
- areDataViewsEqual,
3474
- areDatesEqual,
3475
- areErrorsEqual,
3476
- areFunctionsEqual: strictEqual,
3477
- areMapsEqual: strict ? combineComparators(areMapsEqual, areObjectsEqualStrict) : areMapsEqual,
3478
- areNumbersEqual: sameValueEqual,
3479
- areObjectsEqual: strict ? areObjectsEqualStrict : areObjectsEqual,
3480
- arePrimitiveWrappersEqual,
3481
- areRegExpsEqual,
3482
- areSetsEqual: strict ? combineComparators(areSetsEqual, areObjectsEqualStrict) : areSetsEqual,
3483
- areTypedArraysEqual: strict ? combineComparators(areTypedArraysEqual, areObjectsEqualStrict) : areTypedArraysEqual,
3484
- areUrlsEqual,
3485
- getUnsupportedCustomComparator: void 0
3486
- };
3487
- if (createCustomConfig) config = Object.assign({}, config, createCustomConfig(config));
3488
- if (circular) {
3489
- const areArraysEqual = createIsCircular(config.areArraysEqual);
3490
- const areMapsEqual = createIsCircular(config.areMapsEqual);
3491
- const areObjectsEqual = createIsCircular(config.areObjectsEqual);
3492
- const areSetsEqual = createIsCircular(config.areSetsEqual);
3493
- config = Object.assign({}, config, {
3494
- areArraysEqual,
3495
- areMapsEqual,
3496
- areObjectsEqual,
3497
- areSetsEqual
3498
- });
3499
- }
3500
- return config;
3501
- }
3502
- /**
3503
- * Default equality comparator pass-through, used as the standard `isEqual` creator for
3504
- * use inside the built comparator.
3505
- */
3506
- function createInternalEqualityComparator(compare) {
3507
- return function(a, b, _indexOrKeyA, _indexOrKeyB, _parentA, _parentB, state) {
3508
- return compare(a, b, state);
3509
- };
3510
- }
3511
- /**
3512
- * Create the `isEqual` function used by the consuming application.
3513
- */
3514
- function createIsEqual({ circular, comparator, createState, equals, strict }) {
3515
- if (createState) return function isEqual(a, b) {
3516
- const { cache = circular ? /* @__PURE__ */ new WeakMap() : void 0, meta } = createState();
3517
- return comparator(a, b, {
3518
- cache,
3519
- equals,
3520
- meta,
3521
- strict
3522
- });
3523
- };
3524
- if (circular) return function isEqual(a, b) {
3525
- return comparator(a, b, {
3526
- cache: /* @__PURE__ */ new WeakMap(),
3527
- equals,
3528
- meta: void 0,
3529
- strict
3530
- });
3531
- };
3532
- const state = {
3533
- cache: void 0,
3534
- equals,
3535
- meta: void 0,
3536
- strict
3537
- };
3538
- return function isEqual(a, b) {
3539
- return comparator(a, b, state);
3540
- };
3541
- }
3542
- /**
3543
- * Create a map of `toString()` values to their respective handlers for `tag`-based lookups.
3544
- */
3545
- function createSupportedComparatorMap({ areArrayBuffersEqual, areArraysEqual, areDataViewsEqual, areDatesEqual, areErrorsEqual, areFunctionsEqual, areMapsEqual, areNumbersEqual, areObjectsEqual, arePrimitiveWrappersEqual, areRegExpsEqual, areSetsEqual, areTypedArraysEqual, areUrlsEqual }) {
3546
- return {
3547
- "[object Arguments]": areObjectsEqual,
3548
- "[object Array]": areArraysEqual,
3549
- "[object ArrayBuffer]": areArrayBuffersEqual,
3550
- "[object AsyncGeneratorFunction]": areFunctionsEqual,
3551
- "[object BigInt]": areNumbersEqual,
3552
- "[object BigInt64Array]": areTypedArraysEqual,
3553
- "[object BigUint64Array]": areTypedArraysEqual,
3554
- "[object Boolean]": arePrimitiveWrappersEqual,
3555
- "[object DataView]": areDataViewsEqual,
3556
- "[object Date]": areDatesEqual,
3557
- "[object Error]": areErrorsEqual,
3558
- "[object Float16Array]": areTypedArraysEqual,
3559
- "[object Float32Array]": areTypedArraysEqual,
3560
- "[object Float64Array]": areTypedArraysEqual,
3561
- "[object Function]": areFunctionsEqual,
3562
- "[object GeneratorFunction]": areFunctionsEqual,
3563
- "[object Int8Array]": areTypedArraysEqual,
3564
- "[object Int16Array]": areTypedArraysEqual,
3565
- "[object Int32Array]": areTypedArraysEqual,
3566
- "[object Map]": areMapsEqual,
3567
- "[object Number]": arePrimitiveWrappersEqual,
3568
- "[object Object]": (a, b, state) => typeof a.then !== "function" && typeof b.then !== "function" && areObjectsEqual(a, b, state),
3569
- "[object RegExp]": areRegExpsEqual,
3570
- "[object Set]": areSetsEqual,
3571
- "[object String]": arePrimitiveWrappersEqual,
3572
- "[object URL]": areUrlsEqual,
3573
- "[object Uint8Array]": areTypedArraysEqual,
3574
- "[object Uint8ClampedArray]": areTypedArraysEqual,
3575
- "[object Uint16Array]": areTypedArraysEqual,
3576
- "[object Uint32Array]": areTypedArraysEqual
3577
- };
3578
- }
3579
- /**
3580
- * Whether the items passed are deeply-equal in value.
3581
- */
3582
- var deepEqual$1 = createCustomEqual();
3583
- createCustomEqual({ strict: true });
3584
- createCustomEqual({ circular: true });
3585
- createCustomEqual({
3586
- circular: true,
3587
- strict: true
3588
- });
3589
- createCustomEqual({ createInternalComparator: () => sameValueEqual });
3590
- createCustomEqual({
3591
- strict: true,
3592
- createInternalComparator: () => sameValueEqual
3593
- });
3594
- createCustomEqual({
3595
- circular: true,
3596
- createInternalComparator: () => sameValueEqual
3597
- });
3598
- createCustomEqual({
3599
- circular: true,
3600
- createInternalComparator: () => sameValueEqual,
3601
- strict: true
3602
- });
3603
- /**
3604
- * Create a custom equality comparison method.
3605
- *
3606
- * This can be done to create very targeted comparisons in extreme hot-path scenarios
3607
- * where the standard methods are not performant enough, but can also be used to provide
3608
- * support for legacy environments that do not support expected features like
3609
- * `RegExp.prototype.flags` out of the box.
3610
- */
3611
- function createCustomEqual(options = {}) {
3612
- const { circular = false, createInternalComparator: createCustomInternalComparator, createState, strict = false } = options;
3613
- const comparator = createEqualityComparator(createEqualityComparatorConfig(options));
3614
- return createIsEqual({
3615
- circular,
3616
- comparator,
3617
- createState,
3618
- equals: createCustomInternalComparator ? createCustomInternalComparator(comparator) : createInternalEqualityComparator(comparator),
3619
- strict
3620
- });
3621
- }
3622
- //#endregion
3623
- //#region ../common/src/data/resolveDataSource.ts
3624
- /**
3625
- * Resolve the effective data source for a collection — the single source of
3626
- * truth shared by the frontend router, the backend driver registry, and the
3627
- * editor's capability lookups.
3628
- *
3629
- * Resolution order:
3630
- * 1. The routing **key** is `collection.dataSource`, else
3631
- * {@link DEFAULT_DATA_SOURCE_KEY}.
3632
- * 2. If a definition is registered for that key, it provides `engine`,
3633
- * `transport`, and `databaseId`.
3634
- * 3. Otherwise values are synthesized: `engine` from `collection.engine`
3635
- * (or the key, or `"postgres"`), `transport` defaults to `"server"`,
3636
- * and `databaseId` from the collection.
3637
- *
3638
- * `capabilities` are always derived from the resolved `engine`, so two
3639
- * data sources sharing an engine share capabilities.
3640
- *
3641
- * @param collection the collection (or any object carrying the routing fields)
3642
- * @param registry optional registry of declared data sources
3643
- */
3644
- function resolveDataSource(collection, registry) {
3645
- const key = collection?.dataSource ?? "(default)";
3646
- const def = registry?.[key];
3647
- const engine = def?.engine ?? collection?.engine ?? (key !== "(default)" ? key : "postgres");
3648
- return {
3649
- key,
3650
- engine,
3651
- transport: def?.transport ?? "server",
3652
- databaseId: collection?.databaseId ?? def?.databaseId,
3653
- capabilities: getDataSourceCapabilities(engine)
3654
- };
3655
- }
3656
- //#endregion
3657
- //#region ../common/src/collections/CollectionRegistry.ts
3658
- var CollectionRegistry = class {
3659
- /**
3660
- * Declared data sources, used during normalization to resolve each
3661
- * collection's engine (so `dataSource`-only collections get the right
3662
- * capabilities). Empty by default.
3663
- */
3664
- dataSources = {};
3665
- /**
3666
- * Global lifecycle callbacks applied to every collection.
3667
- * Runs on all data paths (REST, WebSocket, `rebase.data`).
3668
- * Execution order: global → collection → property callbacks.
3669
- */
3670
- _globalCallbacks;
3671
- /**
3672
- * Set global lifecycle callbacks that apply to every collection.
3673
- * Typically called once during backend initialization.
3674
- */
3675
- setGlobalCallbacks(callbacks) {
3676
- this._globalCallbacks = callbacks;
3677
- }
3678
- /**
3679
- * Get the currently registered global callbacks, if any.
3680
- */
3681
- getGlobalCallbacks() {
3682
- return this._globalCallbacks;
3683
- }
3684
- collectionsByTableName = /* @__PURE__ */ new Map();
3685
- collectionsBySlug = /* @__PURE__ */ new Map();
3686
- rootCollections = [];
3687
- cachedCollectionsList = null;
3688
- rawCollectionsByTableName = /* @__PURE__ */ new Map();
3689
- rawCollectionsBySlug = /* @__PURE__ */ new Map();
3690
- rawRootCollections = [];
3691
- cachedRawCollectionsList = null;
3692
- lastRawInputEntity = null;
3693
- constructor(collections, dataSources) {
3694
- if (dataSources) this.dataSources = dataSources;
3695
- if (collections) this.registerMultiple(collections);
3696
- }
3697
- /**
3698
- * Provide the declared data sources used to resolve each collection's
3699
- * engine during normalization. Set this before registering collections.
3700
- * Returns true if the registry changed (callers may re-register).
3701
- */
3702
- setDataSources(dataSources) {
3703
- if (deepEqual$1(this.dataSources, dataSources)) return false;
3704
- this.dataSources = dataSources ?? {};
3705
- return true;
3706
- }
3707
- reset() {
3708
- this.collectionsByTableName.clear();
3709
- this.collectionsBySlug.clear();
3710
- this.rootCollections = [];
3711
- this.cachedCollectionsList = null;
3712
- this.rawCollectionsByTableName.clear();
3713
- this.rawCollectionsBySlug.clear();
3714
- this.rawRootCollections = [];
3715
- this.cachedRawCollectionsList = null;
3716
- }
3717
- /**
3718
- * Registers a collection and its subcollections recursively.
3719
- * Returns true if the collections have changed, false otherwise.
3720
- *
3721
- * Idempotent: compares the raw input (before normalization) against a stored
3722
- * entity. Only re-normalizes and re-registers when the raw input actually changed.
3723
- * @param collections
3724
- */
3725
- registerMultiple(collections) {
3726
- const rawEntity = collections.map((c) => removeFunctions(c));
3727
- if (this.lastRawInputEntity && deepEqual$1(this.lastRawInputEntity, rawEntity)) return false;
3728
- this.reset();
3729
- collections.forEach((c) => {
3730
- if (c.slug) this.collectionsBySlug.set(c.slug, c);
3731
- this.collectionsByTableName.set(getTableName$1(c), c);
3732
- });
3733
- const normalizedCollections = collections.map((c) => this.normalizeCollection({ ...c }));
3734
- normalizedCollections.forEach((c, index) => {
3735
- const raw = deepClone(collections[index]);
3736
- this.rootCollections.push(c);
3737
- this.rawRootCollections.push(raw);
3738
- const normalized = this.normalizeCollection(c);
3739
- this.collectionsByTableName.set(getTableName$1(normalized), normalized);
3740
- this.rawCollectionsByTableName.set(getTableName$1(raw), raw);
3741
- if (normalized.slug) this.collectionsBySlug.set(normalized.slug, normalized);
3742
- if (raw.slug) this.rawCollectionsBySlug.set(raw.slug, raw);
3743
- });
3744
- normalizedCollections.forEach((c) => {
3745
- const subcollections = getSubcollections(c);
3746
- if (subcollections && subcollections.length > 0) subcollections.forEach((subCollection) => {
3747
- if (!subCollection) return;
3748
- this._registerRecursively(this.normalizeCollection({ ...subCollection }), deepClone(subCollection));
3749
- });
3750
- });
3751
- this.lastRawInputEntity = rawEntity;
3752
- return true;
3753
- }
3754
- register(collection, rawCollection) {
3755
- const raw = rawCollection ? deepClone(rawCollection) : deepClone(collection);
3756
- this.rootCollections.push(collection);
3757
- this.rawRootCollections.push(raw);
3758
- this._registerRecursively(collection, raw);
3759
- }
3760
- _registerRecursively(collection, rawCollection) {
3761
- if (this.collectionsByTableName.has(getTableName$1(collection))) return;
3762
- const normalizedCollection = this.normalizeCollection(collection);
3763
- this.collectionsByTableName.set(getTableName$1(normalizedCollection), normalizedCollection);
3764
- this.rawCollectionsByTableName.set(getTableName$1(rawCollection), rawCollection);
3765
- if (normalizedCollection.slug) this.collectionsBySlug.set(normalizedCollection.slug, normalizedCollection);
3766
- if (rawCollection.slug) this.rawCollectionsBySlug.set(rawCollection.slug, rawCollection);
3767
- const subcollections = getSubcollections(normalizedCollection);
3768
- if (subcollections && subcollections.length > 0) subcollections.forEach((subCollection) => {
3769
- if (!subCollection) return;
3770
- this._registerRecursively(this.normalizeCollection({ ...subCollection }), deepClone(subCollection));
3771
- });
3772
- }
3773
- normalizeCollection(collection) {
3774
- const result = { ...collection };
3775
- {
3776
- const resolved = resolveDataSource(result, this.dataSources);
3777
- if (!result.dataSource) result.dataSource = resolved.key;
3778
- if (!result.engine) result.engine = resolved.engine;
3779
- }
3780
- const extractedRelations = this.extractRelationsFromProperties(result.properties);
3781
- const relResult = result;
3782
- const manualRelations = getDataSourceCapabilities(result.engine).supportsRelations ? relResult.relations ?? [] : [];
3783
- const mergedRelationsRaw = [...extractedRelations];
3784
- for (const manual of manualRelations) {
3785
- const name = manual.relationName;
3786
- if (!name) mergedRelationsRaw.push(manual);
3787
- else {
3788
- const existingIndex = mergedRelationsRaw.findIndex((r) => r.relationName === name);
3789
- if (existingIndex === -1) mergedRelationsRaw.push(manual);
3790
- else mergedRelationsRaw[existingIndex] = {
3791
- ...manual,
3792
- ...mergedRelationsRaw[existingIndex]
3793
- };
3794
- }
3795
- }
3796
- let mergedRelations = mergedRelationsRaw;
3797
- if (getDataSourceCapabilities(result.engine).supportsRelations) {
3798
- mergedRelations = mergedRelationsRaw.map((r) => {
3799
- try {
3800
- return sanitizeRelation(r, result, (slug) => this.get(slug));
3801
- } catch {
3802
- return r;
3803
- }
3804
- });
3805
- relResult.relations = mergedRelations;
3806
- }
3807
- result.properties = this.normalizeProperties(result.properties, mergedRelations);
3808
- if (!result.childCollections) {
3809
- const capabilities = getDataSourceCapabilities(result.engine);
3810
- const declaredSubcollections = getDeclaredSubcollections(result);
3811
- if (capabilities.supportsSubcollections && declaredSubcollections) result.childCollections = declaredSubcollections;
3812
- else if (capabilities.supportsRelations && relResult.relations) {
3813
- const manyRelations = relResult.relations.filter((r) => r.cardinality === "many");
3814
- if (manyRelations.length > 0) result.childCollections = () => manyRelations.map((r) => {
3815
- const target = r.target();
3816
- return r.overrides ? mergeDeep(target, r.overrides) : target;
3817
- });
3818
- }
3819
- }
3820
- return result;
3821
- }
3822
- /**
3823
- * Extract Relation[] from properties that have inline relation config (i.e. `target` is set).
3824
- * This allows developers to define relations directly on properties without a separate
3825
- * `relations[]` entry on the collection.
3826
- */
3827
- extractRelationsFromProperties(properties) {
3828
- const relations = [];
3829
- for (const [key, property] of Object.entries(properties)) if (property.type === "relation") {
3830
- const relProp = property;
3831
- const target = relProp.target ?? relProp.relation?.target;
3832
- if (target) {
3833
- const relationName = relProp.relationName ?? relProp.relation?.relationName ?? key;
3834
- relations.push({
3835
- relationName,
3836
- target,
3837
- cardinality: relProp.cardinality ?? relProp.relation?.cardinality ?? "one",
3838
- direction: relProp.direction ?? relProp.relation?.direction ?? "owning",
3839
- inverseRelationName: relProp.inverseRelationName ?? relProp.relation?.inverseRelationName,
3840
- localKey: relProp.localKey ?? relProp.relation?.localKey,
3841
- foreignKeyOnTarget: relProp.foreignKeyOnTarget ?? relProp.relation?.foreignKeyOnTarget,
3842
- through: relProp.through ?? relProp.relation?.through,
3843
- joinPath: relProp.joinPath ?? relProp.relation?.joinPath,
3844
- onUpdate: relProp.onUpdate ?? relProp.relation?.onUpdate,
3845
- onDelete: relProp.onDelete ?? relProp.relation?.onDelete,
3846
- overrides: relProp.overrides ?? relProp.relation?.overrides
3847
- });
3848
- }
3849
- } else if (property.type === "map" && property.properties) relations.push(...this.extractRelationsFromProperties(property.properties));
3850
- return relations;
3851
- }
3852
- normalizeProperties(properties, relations) {
3853
- const newProperties = {};
3854
- for (const key in properties) newProperties[key] = this.normalizeProperty(key, properties[key], relations);
3855
- return newProperties;
3856
- }
3857
- normalizeProperty(key, property, relations) {
3858
- const newProperty = { ...property };
3859
- if (newProperty.type === "map" && newProperty.properties) newProperty.properties = this.normalizeProperties(newProperty.properties, relations);
3860
- else if (newProperty.type === "array") {
3861
- const arrayProp = newProperty;
3862
- if (arrayProp.of) if (Array.isArray(arrayProp.of)) arrayProp.of = arrayProp.of.map((p, i) => this.normalizeProperty(`${key}[${i}]`, p, relations));
3863
- else arrayProp.of = this.normalizeProperty(`${key}.of`, arrayProp.of, relations);
3864
- else if (arrayProp.oneOf && arrayProp.oneOf.properties) arrayProp.oneOf.properties = this.normalizeProperties(arrayProp.oneOf.properties, relations);
3865
- } else if ((newProperty.type === "string" || newProperty.type === "number") && newProperty.enum) {
3866
- const stringOrNumberProperty = newProperty;
3867
- if (typeof stringOrNumberProperty.enum === "object" && !Array.isArray(stringOrNumberProperty.enum)) stringOrNumberProperty.enum = enumToObjectEntries(stringOrNumberProperty.enum)?.filter((value) => value && (value.id || value.id === 0) && value.label) ?? [];
3868
- } else if (newProperty.type === "relation") {
3869
- const relationProperty = newProperty;
3870
- const name = relationProperty.relationName || key;
3871
- const relation = relations.find((r) => r.relationName === name);
3872
- if (relation) relationProperty.relation = relation;
3873
- else console.warn(`Could not find relation for property '${key}' with relationName: ${name}`);
3874
- }
3875
- return newProperty;
3876
- }
3877
- get(path) {
3878
- const bySlug = this.collectionsBySlug.get(path);
3879
- if (bySlug) return bySlug;
3880
- if (path.includes("-")) {
3881
- const normalized = path.replace(/-/g, "_");
3882
- const byNormalized = this.collectionsBySlug.get(normalized);
3883
- if (byNormalized) return byNormalized;
3884
- }
3885
- return this.collectionsByTableName.get(path);
3886
- }
3887
- /**
3888
- * Gets the pristine, un-normalized collection exactly as it was provided.
3889
- * Useful for the AST editor so it doesn't accidentally serialize injected metadata back to disk.
3890
- */
3891
- getRaw(path) {
3892
- const bySlug = this.rawCollectionsBySlug.get(path);
3893
- if (bySlug) return bySlug;
3894
- if (path.includes("-")) {
3895
- const normalized = path.replace(/-/g, "_");
3896
- const byNormalized = this.rawCollectionsBySlug.get(normalized);
3897
- if (byNormalized) return byNormalized;
3898
- }
3899
- return this.rawCollectionsByTableName.get(path);
3900
- }
3901
- /**
3902
- * Get collection by resolving multi-segment paths through relations
3903
- * e.g., "authors/70/posts" resolves to the posts collection
3904
- */
3905
- getCollectionByPath(collectionPath) {
3906
- if (!collectionPath.includes("/")) return this.get(collectionPath);
3907
- const pathSegments = collectionPath.split("/").filter((p) => p);
3908
- if (pathSegments.length < 3 || pathSegments.length % 2 === 0) throw new Error(`Invalid relation path: ${collectionPath}. Expected format: collection/id/relation or collection/id/relation/id/relation`);
3909
- const rootCollectionPath = pathSegments[0];
3910
- let currentCollection = this.get(rootCollectionPath);
3911
- if (!currentCollection) throw new Error(`Root collection not found: ${rootCollectionPath}`);
3912
- for (let i = 2; i < pathSegments.length; i += 2) {
3913
- const relationKey = pathSegments[i];
3914
- if (!getDataSourceCapabilities(currentCollection.engine).supportsRelations) throw new Error(`Relation path navigation requires a collection that supports relations, but '${currentCollection.slug}' uses engine '${currentCollection.engine}'`);
3915
- const relation = findRelation(resolveCollectionRelations(currentCollection), relationKey);
3916
- if (!relation) throw new Error(`Relation '${relationKey}' not found in collection '${currentCollection.slug}'`);
3917
- const target = relation.target();
3918
- const targetRelationKey = relation.relationName || target.slug;
3919
- const targetSlug = relation.overrides?.slug ?? targetRelationKey;
3920
- currentCollection = this.get(targetSlug) || this.normalizeCollection(target);
3921
- if (i + 1 < pathSegments.length) {}
3922
- }
3923
- return currentCollection;
3924
- }
3925
- getCollections() {
3926
- if (!this.cachedCollectionsList) this.cachedCollectionsList = Array.from(this.collectionsByTableName.values());
3927
- return this.cachedCollectionsList;
3928
- }
3929
- getRawCollections() {
3930
- if (!this.cachedRawCollectionsList) this.cachedRawCollectionsList = Array.from(this.rawCollectionsByTableName.values());
3931
- return this.cachedRawCollectionsList;
3932
- }
3933
- /**
3934
- * Resolves a multi-segment path like "products/123/locales" and returns
3935
- * information about the collections and entity IDs along the path
3936
- */
3937
- resolvePathToCollections(path) {
3938
- const pathSegments = path.split("/").filter((p) => p);
3939
- if (pathSegments.length === 0) throw new Error(`Invalid path: ${path}`);
3940
- if (pathSegments.length % 2 !== 1) throw new Error(`Invalid collection path: ${path}. It must have an odd number of segments.`);
3941
- const collections = [];
3942
- const entityIds = [];
3943
- let currentCollection = this.get(pathSegments[0]);
3944
- if (!currentCollection) throw new Error(`Unknown collection path or slug: ${pathSegments[0]}`);
3945
- collections.push(currentCollection);
3946
- for (let i = 1; i < pathSegments.length; i += 2) {
3947
- const entityId = pathSegments[i];
3948
- entityIds.push(entityId);
3949
- if (i + 1 < pathSegments.length) {
3950
- const subcollectionSlug = pathSegments[i + 1];
3951
- const subcollections = getSubcollections(currentCollection);
3952
- if (!subcollections || subcollections.length === 0) throw new Error(`No subcollections found for ${currentCollection.slug} in path: ${path}`);
3953
- const subcollection = subcollections.find((c) => c.slug === subcollectionSlug);
3954
- if (!subcollection) throw new Error(`Subcollection '${subcollectionSlug}' not found in ${currentCollection.slug}`);
3955
- currentCollection = this.get(subcollection.slug) || this.normalizeCollection(subcollection);
3956
- collections.push(currentCollection);
3957
- }
3958
- }
3959
- return {
3960
- collections,
3961
- entityIds,
3962
- finalCollection: currentCollection
3963
- };
3964
- }
3965
- };
3966
- //#endregion
3967
- //#region ../common/src/data/query_builder.ts
3968
- var QueryBuilder = class {
3969
- collection;
3970
- params = { where: {} };
3971
- constructor(collection) {
3972
- this.collection = collection;
3973
- }
3974
- where(columnOrCondition, operator, value) {
3975
- if (typeof columnOrCondition === "object" && columnOrCondition !== null && "type" in columnOrCondition) {
3976
- this.params.logical = columnOrCondition;
3977
- return this;
3978
- }
3979
- if (!this.params.where) this.params.where = {};
3980
- const column = columnOrCondition;
3981
- const condition = [operator, value];
3982
- const existing = this.params.where[column];
3983
- if (existing === void 0) this.params.where[column] = condition;
3984
- else if (Array.isArray(existing) && existing.length > 0 && Array.isArray(existing[0])) this.params.where[column].push(condition);
3985
- else {
3986
- let firstCondition;
3987
- if (Array.isArray(existing) && existing.length === 2 && typeof existing[0] === "string") firstCondition = existing;
3988
- else firstCondition = ["==", existing];
3989
- this.params.where[column] = [firstCondition, condition];
3990
- }
3991
- return this;
3992
- }
3993
- /**
3994
- * Order the results by a specific column.
3995
- * @example
3996
- * client.collection('users').orderBy('createdAt', 'desc').find()
3997
- */
3998
- orderBy(column, direction = "asc") {
3999
- this.params.orderBy = [column, direction];
4000
- return this;
4001
- }
4002
- /**
4003
- * Limit the number of results returned.
4004
- */
4005
- limit(count) {
4006
- this.params.limit = count;
4007
- return this;
4008
- }
4009
- /**
4010
- * Skip the first N results.
4011
- */
4012
- offset(count) {
4013
- this.params.offset = count;
4014
- return this;
4015
- }
4016
- /**
4017
- * Set a free-text search string if supported by the backend.
4018
- */
4019
- search(searchString) {
4020
- this.params.searchString = searchString;
4021
- return this;
4022
- }
4023
- /**
4024
- * Include related entities in the response.
4025
- * Relations will be populated with full entity data instead of just IDs.
4026
- *
4027
- * @param relations - Relation names to include, or "*" for all.
4028
- * @example
4029
- * // Include specific relations
4030
- * client.data.posts.include("tags", "author").find()
4031
- *
4032
- * // Include all relations
4033
- * client.data.posts.include("*").find()
4034
- */
4035
- include(...relations) {
4036
- this.params.include = relations;
4037
- return this;
4038
- }
4039
- /**
4040
- * Execute the find query and return the results.
4041
- */
4042
- async find() {
4043
- return this.collection.find(this.params);
4044
- }
4045
- /**
4046
- * Listen to realtime updates matching this query.
4047
- */
4048
- listen(onUpdate, onError) {
4049
- if (!this.collection.listen) throw new Error("Listen is only available when RebaseClient is configured with a websocketUrl.");
4050
- return this.collection.listen(this.params, onUpdate, onError);
4051
- }
38
+ var connection_exports = /* @__PURE__ */ __exportAll({
39
+ createDirectDatabaseConnection: () => createDirectDatabaseConnection,
40
+ createPostgresDatabaseConnection: () => createPostgresDatabaseConnection,
41
+ createReadReplicaConnection: () => createReadReplicaConnection,
42
+ guardPoolAgainstDirtyRelease: () => guardPoolAgainstDirtyRelease
43
+ });
44
+ var DEFAULT_POOL = {
45
+ max: 20,
46
+ idleTimeoutMillis: 3e4,
47
+ connectionTimeoutMillis: 1e4,
48
+ queryTimeout: 6e4,
49
+ statementTimeout: 3e4,
50
+ keepAlive: true
4052
51
  };
4053
- //#endregion
4054
- //#region ../common/src/data/filter-dialect.ts
4055
- /**
4056
- * REST wire-format adapter for the unified filter system.
4057
- *
4058
- * This module is the ONLY code in the entire codebase that knows about
4059
- * PostgREST-style dot-syntax strings (`eq.active`, `gt.18`, `in.(a,b)`).
4060
- * Everything else speaks `FilterValues` exclusively.
4061
- *
4062
- * Wire-format values are always strings — the wire format carries no type
4063
- * metadata, so type coercion is the responsibility of the server-side data
4064
- * driver which has access to the collection schema.
4065
- *
4066
- * Commas inside list values are backslash-escaped (`\,`), and literal
4067
- * backslashes are escaped as `\\`.
4068
- *
4069
- * @module
4070
- */
4071
- /**
4072
- * Unescape a single list item from the wire format.
4073
- * `\\` → `\`, `\,` → `,`
4074
- */
4075
- function unescapeListItem(value) {
4076
- let result = "";
4077
- for (let i = 0; i < value.length; i++) if (value[i] === "\\" && i + 1 < value.length) {
4078
- result += value[i + 1];
4079
- i++;
4080
- } else result += value[i];
4081
- return result;
4082
- }
4083
- /**
4084
- * Split a parenthesized list string on unescaped commas.
4085
- * Input is the content between `(` and `)`.
4086
- *
4087
- * @example
4088
- * splitListItems("admin,editor") // ["admin", "editor"]
4089
- * splitListItems("hello\\, world,foo") // ["hello, world", "foo"]
4090
- */
4091
- function splitListItems(inner) {
4092
- const items = [];
4093
- let current = "";
4094
- for (let i = 0; i < inner.length; i++) if (inner[i] === "\\" && i + 1 < inner.length) {
4095
- current += inner[i] + inner[i + 1];
4096
- i++;
4097
- } else if (inner[i] === ",") {
4098
- items.push(unescapeListItem(current));
4099
- current = "";
4100
- } else current += inner[i];
4101
- items.push(unescapeListItem(current));
4102
- return items;
4103
- }
4104
- var REST_OP_LOOKUP = REST_TO_CANONICAL;
52
+ /** ReadyForQuery status byte: `I` idle, `T` in transaction, `E` failed transaction. */
53
+ var TX_IDLE = "I";
4105
54
  /**
4106
- * Parse a single PostgREST dot-string into a `[WhereFilterOp, unknown]` tuple.
55
+ * Destroy pool clients that are released while still inside a transaction.
4107
56
  *
4108
- * All values are returned as strings — the wire format carries no type
4109
- * metadata, so coercion is the data driver's responsibility.
57
+ * pg-pool returns a client to the idle list whenever `release()` is called
58
+ * without an error — even if the connection is still mid-transaction (status
59
+ * `T`/`E`). That happens in practice: drizzle's pool transaction releases in
60
+ * a `finally` after attempting ROLLBACK, and if the ROLLBACK itself fails
61
+ * (e.g. it was queued behind a statement that hit the client-side
62
+ * query_timeout), the client goes back dirty. The next checkout then runs
63
+ * its statements inside the zombie transaction — with the previous request's
64
+ * `app.*` RLS GUCs still applied, which turns unrelated queries into
65
+ * RLS-scoped ones (observed in production as registration failing with
66
+ * SQLSTATE 42501 under a leaked anonymous context).
4110
67
  *
4111
- * If the string doesn't match a known operator prefix, it falls back to
4112
- * `["==", originalString]` (treating the whole string as an equality value).
4113
- * This intentional defense handles values like `"user@host.com"` or
4114
- * `"1.2.3"` that happen to contain dots.
68
+ * pg-pool emits `release` before it consults its private `_expired` set, so
69
+ * marking the client expired here makes `_release()` destroy it instead of
70
+ * pooling it. Both `client._txStatus` (pg ≥ 8.16) and `pool._expired` are
71
+ * private APIs — feature-detect and fall back to loud logging so an upstream
72
+ * change degrades to observability, never to silent corruption.
4115
73
  */
4116
- function deserializeSingle(raw) {
4117
- const dotIndex = raw.indexOf(".");
4118
- if (dotIndex === -1) return ["==", raw];
4119
- const prefix = raw.substring(0, dotIndex);
4120
- const rest = raw.substring(dotIndex + 1);
4121
- const canonicalOp = REST_OP_LOOKUP[prefix];
4122
- if (!canonicalOp) return ["==", raw];
4123
- if (NULL_OPS.has(canonicalOp)) return [canonicalOp, null];
4124
- if (rest.startsWith("(") && rest.endsWith(")")) return [canonicalOp, splitListItems(rest.slice(1, -1))];
4125
- return [canonicalOp, rest];
74
+ function guardPoolAgainstDirtyRelease(pool, label) {
75
+ pool.on("release", (err, client) => {
76
+ if (err) return;
77
+ const txStatus = client?._txStatus;
78
+ if (typeof txStatus !== "string" || txStatus === TX_IDLE) return;
79
+ const expired = pool._expired;
80
+ if (expired && typeof expired.add === "function" && typeof expired.has === "function" && client && typeof client === "object") {
81
+ expired.add(client);
82
+ logger.error(`[${label}] Client released back to the pool while still in a transaction (status '${txStatus}') — destroying it so the open transaction and its session state (RLS GUCs) cannot leak into the next request.`);
83
+ } else logger.error(`[${label}] Client released mid-transaction (status '${txStatus}') but the pool's internal expiry set is unavailable (pg-pool internals changed?). The connection may leak its open transaction into subsequent requests.`);
84
+ });
4126
85
  }
4127
86
  /**
4128
- * Convert a PostgREST-style querystring record to `FilterValues`.
4129
- *
4130
- * - String values are parsed as single conditions.
4131
- * - String arrays (repeated query params) become multiple conditions on the same field.
87
+ * Create a Drizzle-backed Postgres connection with a production-grade
88
+ * connection pool.
4132
89
  *
4133
- * @example
4134
- * deserializeFilter({ status: "eq.active" })
4135
- * // → { status: ["==", "active"] }
90
+ * @param connectionString Postgres connection URL
91
+ * @param schema Optional Drizzle schema for the relational API
92
+ * @param poolConfig Optional pool tuning (merged over defaults)
4136
93
  *
4137
- * deserializeFilter({ age: ["gte.18", "lt.65"] })
4138
- * // → { age: [[">=", "18"], ["<", "65"]] }
94
+ * @returns `{ db, pool, connectionString }` — the `pool` is exposed so
95
+ * callers can register shutdown hooks (`pool.end()`) or monitor
96
+ * pool metrics.
4139
97
  */
4140
- function deserializeFilter(query) {
4141
- const result = {};
4142
- for (const [field, raw] of Object.entries(query)) {
4143
- if (raw === void 0) continue;
4144
- if (Array.isArray(raw) && raw.length === 2 && typeof raw[0] === "string" && toCanonicalOp(raw[0]) === raw[0]) {
4145
- result[field] = raw;
4146
- continue;
4147
- }
4148
- if (Array.isArray(raw)) {
4149
- if (raw.length === 0) continue;
4150
- if (Array.isArray(raw[0]) && raw[0].length === 2 && typeof raw[0][0] === "string" && toCanonicalOp(raw[0][0]) === raw[0][0]) {
4151
- result[field] = raw;
4152
- continue;
4153
- }
4154
- if (raw.length === 1) result[field] = typeof raw[0] === "string" ? deserializeSingle(raw[0]) : ["==", raw[0]];
4155
- else if (typeof raw[0] === "string" && raw[0].includes(".")) result[field] = raw.map((r) => typeof r === "string" ? deserializeSingle(r) : ["==", r]);
4156
- else result[field] = ["in", raw];
4157
- } else if (typeof raw === "string") result[field] = deserializeSingle(raw);
4158
- else result[field] = ["==", raw];
4159
- }
4160
- return result;
4161
- }
4162
- //#endregion
4163
- //#region ../common/src/data/buildRebaseData.ts
4164
- function createPrimaryKeyResolver(options) {
4165
- const cache = /* @__PURE__ */ new Map();
4166
- const warned = /* @__PURE__ */ new Set();
4167
- return function primaryKeysFor(slug) {
4168
- const cached = cache.get(slug);
4169
- if (cached) return cached;
4170
- const collection = options?.resolveCollection?.(slug);
4171
- if (!collection) return [];
4172
- const keys = resolvePrimaryKeys(collection);
4173
- if (keys.length > 0) {
4174
- cache.set(slug, keys);
4175
- return keys;
4176
- }
4177
- if (!warned.has(slug)) {
4178
- warned.add(slug);
4179
- console.warn(`[rebase] Collection '${slug}' declares no primary key, so its rows have no address: detail links, caching and relations will not work for it. Mark the key property with \`isId\` in its collection config — the server logs which column to mark at boot, if its schema knows the key.`);
4180
- }
4181
- return keys;
98
+ function createPostgresDatabaseConnection(connectionString, schema, poolConfig) {
99
+ const opts = {
100
+ ...DEFAULT_POOL,
101
+ ...poolConfig
4182
102
  };
4183
- }
4184
- /**
4185
- * Give a flat row the Entity view-model the admin renders.
4186
- *
4187
- * The address is *derived here* — it is not a column, and the row it came from
4188
- * does not contain one. Rows carry exactly what the table has, with the types
4189
- * Postgres returned; the id is this layer's invention, and this is the only
4190
- * place it is minted.
4191
- *
4192
- * `primaryKeys` empty falls back to a literal `id` on the row: drivers other
4193
- * than postgres still serve rows with one, and this keeps them working.
4194
- */
4195
- function rowToEntity(row, slug, primaryKeys = []) {
103
+ const pool = new Pool({
104
+ connectionString,
105
+ max: opts.max,
106
+ idleTimeoutMillis: opts.idleTimeoutMillis,
107
+ connectionTimeoutMillis: opts.connectionTimeoutMillis,
108
+ query_timeout: opts.queryTimeout,
109
+ statement_timeout: opts.statementTimeout,
110
+ keepAlive: opts.keepAlive,
111
+ keepAliveInitialDelayMillis: 0
112
+ });
113
+ pool.on("error", (err) => {
114
+ logger.error("[pg-pool] Unexpected pool error", { detail: err.message });
115
+ if (err.message.includes("ETIMEDOUT")) logger.warn("[pg-pool] Connection timeout detected — pool will auto-retry");
116
+ });
117
+ guardPoolAgainstDirtyRelease(pool, "pg-pool");
4196
118
  return {
4197
- id: primaryKeys.length > 0 ? buildCompositeId(row, primaryKeys) : row.id,
4198
- path: slug,
4199
- values: row
4200
- };
4201
- }
4202
- function createDriverAccessor(driver, slug, getPks = () => []) {
4203
- const accessor = {
4204
- async find(params) {
4205
- const filter = params?.where ? deserializeFilter(params.where) : void 0;
4206
- const limit = params?.limit ?? 20;
4207
- const offset = params?.offset ?? 0;
4208
- const fetchService = driver.restFetchService;
4209
- const rows = fetchService && params?.include && params.include.length > 0 ? await fetchService.fetchCollectionForRest(slug, {
4210
- filter,
4211
- limit: params?.limit,
4212
- offset: params?.offset,
4213
- orderBy: params?.orderBy?.[0],
4214
- order: params?.orderBy?.[1],
4215
- searchString: params?.searchString
4216
- }, params.include) : await driver.fetchCollection({
4217
- path: slug,
4218
- limit: params?.limit,
4219
- offset: params?.offset,
4220
- filter,
4221
- orderBy: params?.orderBy?.[0],
4222
- order: params?.orderBy?.[1],
4223
- searchString: params?.searchString
4224
- });
4225
- let total = rows.length + offset;
4226
- let hasMore = rows.length >= limit;
4227
- if (driver.count) {
4228
- total = await driver.count({
4229
- path: slug,
4230
- filter
4231
- });
4232
- hasMore = offset + rows.length < total;
4233
- }
4234
- return {
4235
- data: rows.map((row) => rowToEntity(row, slug, getPks())),
4236
- meta: {
4237
- total,
4238
- limit,
4239
- offset,
4240
- hasMore
4241
- }
4242
- };
4243
- },
4244
- async findById(id) {
4245
- const row = await driver.fetchOne({
4246
- path: slug,
4247
- id
4248
- });
4249
- return row ? rowToEntity(row, slug, getPks()) : void 0;
4250
- },
4251
- async create(data, id) {
4252
- return rowToEntity(await driver.save({
4253
- path: slug,
4254
- values: data,
4255
- id,
4256
- status: "new"
4257
- }), slug, getPks());
4258
- },
4259
- createMany: driver.saveMany ? async (data, options) => {
4260
- return (await driver.saveMany({
4261
- path: slug,
4262
- rows: data,
4263
- upsert: options?.upsert
4264
- })).map((row) => rowToEntity(row, slug, getPks()));
4265
- } : void 0,
4266
- async update(id, data) {
4267
- return rowToEntity(await driver.save({
4268
- path: slug,
4269
- values: data,
4270
- id,
4271
- status: "existing"
4272
- }), slug, getPks());
4273
- },
4274
- async delete(id) {
4275
- return driver.delete({ row: {
4276
- id,
4277
- path: slug,
4278
- values: {}
4279
- } });
4280
- },
4281
- count: driver.count ? async (params) => {
4282
- const filter = params?.where ? deserializeFilter(params.where) : void 0;
4283
- return driver.count({
4284
- path: slug,
4285
- filter
4286
- });
4287
- } : void 0,
4288
- listen: driver.listenCollection ? (params, onUpdate, onError) => {
4289
- const limit = params?.limit ?? 20;
4290
- const offset = params?.offset ?? 0;
4291
- return driver.listenCollection({
4292
- path: slug,
4293
- limit: params?.limit,
4294
- offset: params?.offset,
4295
- filter: params?.where,
4296
- orderBy: params?.orderBy?.[0],
4297
- order: params?.orderBy?.[1],
4298
- searchString: params?.searchString,
4299
- onUpdate: (entities) => {
4300
- onUpdate({
4301
- data: entities.map((row) => rowToEntity(row, slug, getPks())),
4302
- meta: {
4303
- total: entities.length,
4304
- limit,
4305
- offset,
4306
- hasMore: entities.length >= limit
4307
- }
4308
- });
4309
- },
4310
- onError
4311
- });
4312
- } : void 0,
4313
- listenById: driver.listenOne ? (id, onUpdate, onError) => {
4314
- return driver.listenOne({
4315
- path: slug,
4316
- id,
4317
- onUpdate: (entity) => onUpdate(entity ? rowToEntity(entity, slug, getPks()) : void 0),
4318
- onError
4319
- });
4320
- } : void 0,
4321
- where(columnOrCondition, operator, value) {
4322
- const builder = new QueryBuilder(accessor);
4323
- if (typeof columnOrCondition === "object") return builder.where(columnOrCondition);
4324
- return builder.where(columnOrCondition, operator, value);
4325
- },
4326
- orderBy(column, ascending) {
4327
- return new QueryBuilder(accessor).orderBy(column, ascending);
4328
- },
4329
- limit(count) {
4330
- return new QueryBuilder(accessor).limit(count);
4331
- },
4332
- offset(count) {
4333
- return new QueryBuilder(accessor).offset(count);
4334
- },
4335
- search(searchString) {
4336
- return new QueryBuilder(accessor).search(searchString);
4337
- },
4338
- include(...relations) {
4339
- return new QueryBuilder(accessor).include(...relations);
4340
- }
119
+ db: schema ? drizzle(pool, { schema }) : drizzle(pool),
120
+ pool,
121
+ connectionString
4341
122
  };
4342
- return accessor;
4343
123
  }
4344
124
  /**
4345
- * Build a `RebaseData` object from a `DataDriver` using JavaScript Proxy.
4346
- *
4347
- * This is the key bridge: any property access like `data.products` returns
4348
- * a `CollectionAccessor` backed by the underlying DataDriver, without
4349
- * needing per-collection code generation.
125
+ * Create a direct (non-pooled) connection for operations that require
126
+ * session-level features incompatible with PgBouncer transaction mode,
127
+ * such as LISTEN/NOTIFY, prepared statements, or advisory locks.
4350
128
  *
4351
- * @example
4352
- * const data = buildRebaseData(driver);
4353
- * await data.products.create({ name: "Camera", price: 299 });
4354
- * const { data: items } = await data.products.find({ where: { status: ["==", "published"] } });
4355
- */
4356
- function buildRebaseData(driver, options) {
4357
- const cache = /* @__PURE__ */ new Map();
4358
- const primaryKeysFor = createPrimaryKeyResolver(options);
4359
- function getAccessor(slug) {
4360
- let accessor = cache.get(slug);
4361
- if (!accessor) {
4362
- accessor = createDriverAccessor(driver, slug, () => primaryKeysFor(slug));
4363
- cache.set(slug, accessor);
4364
- }
4365
- return accessor;
4366
- }
4367
- return new Proxy({ collection: getAccessor }, { get(_target, prop) {
4368
- if (prop === "collection") return getAccessor;
4369
- if (typeof prop === "symbol") return void 0;
4370
- if (prop === "then" || prop === "toJSON" || prop === "$$typeof") return void 0;
4371
- return getAccessor(toSnakeCase(prop));
4372
- } });
4373
- }
4374
- /**
4375
- * Unwrap a Entity back into the flat row it was built from. `rowToEntity` keeps
4376
- * the row untouched under `.values` and derives `.id` alongside it, so dropping
4377
- * the wrapper is the whole operation — the address was never part of the row.
4378
- */
4379
- function entityToRow(entity) {
4380
- return entity.values;
4381
- }
4382
- /**
4383
- * Fluent query builder for the flat SDK data layer. Mirrors {@link QueryBuilder}
4384
- * but resolves to `FindResult<M>` (flat rows) instead of Entity-wrapped
4385
- * `FindResponse<M>`.
4386
- */
4387
- var SdkQueryBuilder = class {
4388
- client;
4389
- params = { where: {} };
4390
- constructor(client) {
4391
- this.client = client;
4392
- }
4393
- where(columnOrCondition, operator, value) {
4394
- if (typeof columnOrCondition === "object" && columnOrCondition !== null && "type" in columnOrCondition) {
4395
- this.params.logical = columnOrCondition;
4396
- return this;
4397
- }
4398
- if (!this.params.where) this.params.where = {};
4399
- const column = columnOrCondition;
4400
- const condition = [operator, value];
4401
- const existing = this.params.where[column];
4402
- if (existing === void 0) this.params.where[column] = condition;
4403
- else if (Array.isArray(existing) && existing.length > 0 && Array.isArray(existing[0])) this.params.where[column].push(condition);
4404
- else {
4405
- let firstCondition;
4406
- if (Array.isArray(existing) && existing.length === 2 && typeof existing[0] === "string") firstCondition = existing;
4407
- else firstCondition = ["==", existing];
4408
- this.params.where[column] = [firstCondition, condition];
4409
- }
4410
- return this;
4411
- }
4412
- orderBy(column, direction = "asc") {
4413
- this.params.orderBy = [column, direction];
4414
- return this;
4415
- }
4416
- limit(count) {
4417
- this.params.limit = count;
4418
- return this;
4419
- }
4420
- offset(count) {
4421
- this.params.offset = count;
4422
- return this;
4423
- }
4424
- search(searchString) {
4425
- this.params.searchString = searchString;
4426
- return this;
4427
- }
4428
- include(...relations) {
4429
- this.params.include = relations;
4430
- return this;
4431
- }
4432
- async find() {
4433
- return this.client.find(this.params);
4434
- }
4435
- async count() {
4436
- return this.client.count ? this.client.count(this.params) : 0;
4437
- }
4438
- listen(onUpdate, onError) {
4439
- if (!this.client.listen) throw new Error("Listen is only available when the driver supports realtime.");
4440
- return this.client.listen(this.params, onUpdate, onError);
4441
- }
4442
- };
4443
- /**
4444
- * Wrap a Entity-shaped {@link CollectionAccessor} into a flat
4445
- * {@link SDKCollectionClient}. Every returned record is unwrapped to a flat row
4446
- * so the backend SDK is byte-for-byte the same shape as the frontend client.
129
+ * Uses a smaller pool since this is only for specific use cases.
4447
130
  */
4448
- function toSdkCollectionClient(snap) {
4449
- const client = {
4450
- async find(params) {
4451
- const res = await snap.find(params);
4452
- return {
4453
- data: res.data.map(entityToRow),
4454
- meta: res.meta
4455
- };
4456
- },
4457
- async findById(id) {
4458
- const s = await snap.findById(id);
4459
- return s ? entityToRow(s) : void 0;
4460
- },
4461
- async create(data, id) {
4462
- return entityToRow(await snap.create(data, id));
4463
- },
4464
- async createMany(data, options) {
4465
- if (!Array.isArray(data)) throw new TypeError("createMany expects an array of records.");
4466
- if (data.length === 0) return [];
4467
- if (!snap.createMany) throw new Error("Bulk writes are not supported by this collection's data source. Fall back to create() per record.");
4468
- return (await snap.createMany(data, options)).map(entityToRow);
4469
- },
4470
- async update(id, data) {
4471
- return entityToRow(await snap.update(id, data));
4472
- },
4473
- delete(id) {
4474
- return snap.delete(id);
4475
- },
4476
- count: snap.count ? (params) => snap.count(params) : void 0,
4477
- listen: snap.listen ? (params, onUpdate, onError) => snap.listen(params, (res) => onUpdate({
4478
- data: res.data.map(entityToRow),
4479
- meta: res.meta
4480
- }), onError) : void 0,
4481
- listenById: snap.listenById ? (id, onUpdate, onError) => snap.listenById(id, (s) => onUpdate(s ? entityToRow(s) : void 0), onError) : void 0,
4482
- where(columnOrCondition, operator, value) {
4483
- const builder = new SdkQueryBuilder(client);
4484
- if (typeof columnOrCondition === "object") return builder.where(columnOrCondition);
4485
- return builder.where(columnOrCondition, operator, value);
4486
- },
4487
- orderBy: (column, direction) => new SdkQueryBuilder(client).orderBy(column, direction),
4488
- limit: (count) => new SdkQueryBuilder(client).limit(count),
4489
- offset: (count) => new SdkQueryBuilder(client).offset(count),
4490
- search: (searchString) => new SdkQueryBuilder(client).search(searchString),
4491
- include: (...relations) => new SdkQueryBuilder(client).include(...relations)
131
+ function createDirectDatabaseConnection(connectionString, schema, poolConfig) {
132
+ const opts = {
133
+ ...DEFAULT_POOL,
134
+ max: 5,
135
+ ...poolConfig
136
+ };
137
+ const pool = new Pool({
138
+ connectionString,
139
+ max: opts.max,
140
+ idleTimeoutMillis: opts.idleTimeoutMillis,
141
+ connectionTimeoutMillis: opts.connectionTimeoutMillis,
142
+ query_timeout: opts.queryTimeout,
143
+ statement_timeout: opts.statementTimeout,
144
+ keepAlive: opts.keepAlive,
145
+ keepAliveInitialDelayMillis: 0
146
+ });
147
+ pool.on("error", (err) => {
148
+ logger.error("[pg-direct-pool] Unexpected pool error", { detail: err.message });
149
+ });
150
+ guardPoolAgainstDirtyRelease(pool, "pg-direct-pool");
151
+ return {
152
+ db: schema ? drizzle(pool, { schema }) : drizzle(pool),
153
+ pool,
154
+ connectionString
4492
155
  };
4493
- return client;
4494
- }
4495
- /**
4496
- * Wrap a Entity-shaped {@link RebaseData} into a flat {@link RebaseSdkData}.
4497
- *
4498
- * Every collection accessor is adapted to return flat rows. Use this to derive
4499
- * the flat SDK data layer (`context.data`) from an existing Entity data layer
4500
- * — e.g. the admin routes its Entity data via `useData()` and exposes the
4501
- * same routing as flat `context.data` for callbacks by wrapping it here.
4502
- */
4503
- function wrapAsSdkData(entityData) {
4504
- const cache = /* @__PURE__ */ new Map();
4505
- function getAccessor(slug) {
4506
- let accessor = cache.get(slug);
4507
- if (!accessor) {
4508
- accessor = toSdkCollectionClient(entityData.collection(slug));
4509
- cache.set(slug, accessor);
4510
- }
4511
- return accessor;
4512
- }
4513
- return new Proxy({ collection: getAccessor }, { get(_target, prop) {
4514
- if (prop === "collection") return getAccessor;
4515
- if (typeof prop === "symbol") return void 0;
4516
- if (prop === "then" || prop === "toJSON" || prop === "$$typeof") return void 0;
4517
- return getAccessor(toSnakeCase(prop));
4518
- } });
4519
- }
4520
- /**
4521
- * Build a flat {@link RebaseSdkData} from a `DataDriver`.
4522
- *
4523
- * This is the developer-facing SDK data layer used by backend framework
4524
- * callbacks & scripts (`context.data` / `rebase.data`). It returns flat rows —
4525
- * identical in shape to the frontend SDK client — so the API is symmetric
4526
- * across front and back. The admin CMS uses {@link buildRebaseData} (Entity).
4527
- */
4528
- function buildSdkData(driver) {
4529
- return wrapAsSdkData(buildRebaseData(driver));
4530
156
  }
4531
- //#endregion
4532
- //#region ../common/src/table-classification.ts
4533
- /** Schemas that are always considered Rebase-internal. */
4534
- var REBASE_INTERNAL_SCHEMAS = ["rebase", "auth"];
4535
- /** Table-name prefixes that mark a table as Rebase-internal regardless of schema. */
4536
- var REBASE_INTERNAL_PREFIXES = [
4537
- "_rebase_",
4538
- "_auth_",
4539
- "drizzle_"
4540
- ];
4541
157
  /**
4542
- * Synchronously classify a table based on naming conventions.
4543
- *
4544
- * @param tableName - The unqualified name of the table.
4545
- * @param schemaName - The schema the table belongs to (e.g. `"public"`, `"rebase"`).
4546
- * @returns `"rebase-internal"` when the table belongs to a reserved schema or
4547
- * carries a reserved prefix; `"user"` otherwise.
4548
- *
4549
- * @remarks
4550
- * Junction-table detection requires an async database query and is therefore
4551
- * **not** handled by this function. Use {@link detectJunctionTables} to obtain
4552
- * the set of junction tables, then reclassify as needed.
158
+ * Create a read-only connection for routing read queries to replicas.
159
+ * Uses a moderate pool size since reads are distributed across replicas.
4553
160
  */
4554
- function classifyTable(tableName, schemaName) {
4555
- if (REBASE_INTERNAL_SCHEMAS.includes(schemaName) || REBASE_INTERNAL_PREFIXES.some((prefix) => tableName.startsWith(prefix))) return "rebase-internal";
4556
- return "user";
161
+ function createReadReplicaConnection(connectionString, schema, poolConfig) {
162
+ const opts = {
163
+ ...DEFAULT_POOL,
164
+ max: 10,
165
+ ...poolConfig
166
+ };
167
+ const pool = new Pool({
168
+ connectionString,
169
+ max: opts.max,
170
+ idleTimeoutMillis: opts.idleTimeoutMillis,
171
+ connectionTimeoutMillis: opts.connectionTimeoutMillis,
172
+ query_timeout: opts.queryTimeout,
173
+ statement_timeout: opts.statementTimeout,
174
+ keepAlive: opts.keepAlive,
175
+ keepAliveInitialDelayMillis: 0
176
+ });
177
+ pool.on("error", (err) => {
178
+ logger.error("[pg-replica-pool] Unexpected pool error", { detail: err.message });
179
+ });
180
+ guardPoolAgainstDirtyRelease(pool, "pg-replica-pool");
181
+ return {
182
+ db: schema ? drizzle(pool, { schema }) : drizzle(pool),
183
+ pool,
184
+ connectionString
185
+ };
4557
186
  }
4558
- /** SQL query that detects junction tables in the `public` schema. */
4559
- var JUNCTION_TABLES_SQL = `
4560
- SELECT t.table_name
4561
- FROM information_schema.tables t
4562
- WHERE t.table_schema = 'public'
4563
- AND t.table_type = 'BASE TABLE'
4564
- AND NOT EXISTS (
4565
- SELECT 1
4566
- FROM information_schema.columns c
4567
- WHERE c.table_schema = t.table_schema
4568
- AND c.table_name = t.table_name
4569
- AND c.column_name NOT IN (
4570
- SELECT kcu.column_name
4571
- FROM information_schema.key_column_usage kcu
4572
- JOIN information_schema.table_constraints tc
4573
- ON tc.constraint_name = kcu.constraint_name
4574
- AND tc.table_schema = kcu.table_schema
4575
- WHERE tc.constraint_type = 'FOREIGN KEY'
4576
- AND kcu.table_schema = t.table_schema
4577
- AND kcu.table_name = t.table_name
4578
- )
4579
- )
4580
- `;
4581
187
  /**
4582
- * Asynchronously detect junction (link) tables in the `public` schema.
188
+ * Resolve a client-supplied list `limit` into a safe, always-defined value.
4583
189
  *
4584
- * A junction table is defined as a table where **every** column participates in
4585
- * at least one foreign-key constraint.
190
+ * - A provided limit is coerced to an integer and clamped to `[1, maxLimit]`,
191
+ * so `0`, negatives, and absurd values can never bypass the cap.
192
+ * - An absent / blank / non-numeric limit falls back to the mode default:
193
+ * `vectorDefaultLimit` for a vector search, otherwise `defaultLimit`.
4586
194
  *
4587
- * @param executeSql - A callback that executes a raw SQL string and returns the
4588
- * resulting rows.
4589
- * @returns A `Set` containing the names of all detected junction tables.
195
+ * The return is never `undefined` — no ingress that routes its client limit
196
+ * through this can produce an unbounded read.
4590
197
  */
4591
- async function detectJunctionTables(executeSql) {
4592
- const rows = await executeSql(JUNCTION_TABLES_SQL);
4593
- const junctionTables = /* @__PURE__ */ new Set();
4594
- for (const row of rows) if (typeof row.table_name === "string") junctionTables.add(row.table_name);
4595
- return junctionTables;
198
+ function resolveClientListLimit(rawLimit, opts = {}) {
199
+ const maxLimit = opts.maxLimit ?? 1e3;
200
+ if (rawLimit != null && String(rawLimit).trim() !== "") {
201
+ const parsed = typeof rawLimit === "number" ? rawLimit : parseInt(String(rawLimit), 10);
202
+ if (Number.isFinite(parsed)) return Math.min(Math.max(1, Math.floor(parsed)), maxLimit);
203
+ }
204
+ return opts.vectorSearch ? opts.vectorDefaultLimit ?? 10 : opts.defaultLimit ?? 50;
4596
205
  }
4597
206
  //#endregion
4598
207
  //#region src/services/collection-helpers.ts
@@ -9637,9 +5246,9 @@ var getDrizzleColumn = (propName, prop, collection, collections) => {
9637
5246
  if (stringProp.enum) columnDefinition = `${getEnumVarName(getTableName$1(collection), propName)}("${colName}")`;
9638
5247
  else if ("isId" in stringProp && stringProp.isId === "uuid") columnDefinition = `uuid("${colName}")`;
9639
5248
  else if (stringProp.columnType === "uuid") columnDefinition = `uuid("${colName}")`;
9640
- else if (stringProp.columnType === "text" || stringProp.ui?.markdown || stringProp.ui?.multiline) columnDefinition = `text("${colName}")`;
9641
5249
  else if (stringProp.columnType === "char") columnDefinition = `char("${colName}")`;
9642
- else columnDefinition = `varchar("${colName}")`;
5250
+ else if (stringProp.columnType === "varchar") columnDefinition = `varchar("${colName}")`;
5251
+ else columnDefinition = `text("${colName}")`;
9643
5252
  if (isIdProperty(propName, prop, collection)) columnDefinition += ".primaryKey()";
9644
5253
  if ("isId" in stringProp && stringProp.isId !== "manual" && stringProp.isId !== true) {
9645
5254
  if (stringProp.isId === "uuid") columnDefinition += ".defaultRandom()";
@@ -9725,7 +5334,7 @@ var getDrizzleColumn = (propName, prop, collection, collections) => {
9725
5334
  const targetTableVar = getTableVarName(getTableName$1(targetCollection));
9726
5335
  const pkProp = getPrimaryKeyProp(targetCollection);
9727
5336
  const targetIdField = pkProp.name;
9728
- const baseColumn = pkProp.type === "number" ? `integer("${fkColumnName}")` : pkProp.isUuid ? `uuid("${fkColumnName}")` : `varchar("${fkColumnName}")`;
5337
+ const baseColumn = pkProp.type === "number" ? `integer("${fkColumnName}")` : pkProp.isUuid ? `uuid("${fkColumnName}")` : `text("${fkColumnName}")`;
9729
5338
  const onUpdate = relation.onUpdate ? `onUpdate: "${relation.onUpdate}"` : "";
9730
5339
  const required = prop.validation?.required;
9731
5340
  const refOptionsParts = [onUpdate, `onDelete: \"${relation.onDelete ?? (required ? "cascade" : "set null")}\"`].filter(Boolean);
@@ -9738,13 +5347,13 @@ var getDrizzleColumn = (propName, prop, collection, collections) => {
9738
5347
  const refProp = prop;
9739
5348
  const targetCollection = collections.find((c) => c.slug === refProp.path || getTableName$1(c) === refProp.path);
9740
5349
  if (!targetCollection) {
9741
- columnDefinition = `varchar("${colName}")`;
5350
+ columnDefinition = `text("${colName}")`;
9742
5351
  break;
9743
5352
  }
9744
5353
  const pkProp = getPrimaryKeyProp(targetCollection);
9745
5354
  const targetTableVar = getTableVarName(getTableName$1(targetCollection));
9746
5355
  const targetIdField = pkProp.name;
9747
- const baseColumn = pkProp.type === "number" ? `integer("${colName}")` : pkProp.isUuid ? `uuid("${colName}")` : `varchar("${colName}")`;
5356
+ const baseColumn = pkProp.type === "number" ? `integer("${colName}")` : pkProp.isUuid ? `uuid("${colName}")` : `text("${colName}")`;
9748
5357
  const required = prop.validation?.required;
9749
5358
  columnDefinition = `${baseColumn}.references(() => ${targetTableVar}.${targetIdField}, ${`{ onDelete: "${required ? "cascade" : "set null"}" }`})`;
9750
5359
  if (required) columnDefinition += ".notNull()";
@@ -9920,8 +5529,8 @@ var generateSchema = async (collections, stripPolicies = false) => {
9920
5529
  const baseTableName = tableName.includes(".") ? tableName.split(".").pop() : tableName;
9921
5530
  const { sourceColumn, targetColumn } = relation.through;
9922
5531
  const refOptions = `{ onDelete: \"${relation.onDelete ?? "cascade"}\" }`;
9923
- const sourceColType = isNumericId(sourceCollection) ? "integer" : getPrimaryKeyProp(sourceCollection).isUuid ? "uuid" : "varchar";
9924
- const targetColType = isNumericId(targetCollection) ? "integer" : getPrimaryKeyProp(targetCollection).isUuid ? "uuid" : "varchar";
5532
+ const sourceColType = isNumericId(sourceCollection) ? "integer" : getPrimaryKeyProp(sourceCollection).isUuid ? "uuid" : "text";
5533
+ const targetColType = isNumericId(targetCollection) ? "integer" : getPrimaryKeyProp(targetCollection).isUuid ? "uuid" : "text";
9925
5534
  const sourceId = getPrimaryKeyName(sourceCollection);
9926
5535
  const targetId = getPrimaryKeyName(targetCollection);
9927
5536
  schemaContent += `export const ${tableVarName} = ${tableCreator}(\"${baseTableName}\", {\n`;
@@ -9948,7 +5557,7 @@ var generateSchema = async (collections, stripPolicies = false) => {
9948
5557
  const columnString = getDrizzleColumn(propName, prop, collection, collections);
9949
5558
  if (columnString) columns.add(columnString);
9950
5559
  });
9951
- if (!Array.from(columns).some((col) => col.includes(".primaryKey()"))) columns.add(" id: varchar(\"id\").primaryKey()");
5560
+ if (!Array.from(columns).some((col) => col.includes(".primaryKey()"))) columns.add(" id: text(\"id\").primaryKey()");
9952
5561
  schemaContent += `${Array.from(columns).join(",\n")}`;
9953
5562
  const securityRules = getEffectiveSecurityRules(collection);
9954
5563
  if (!stripPolicies && securityRules.length > 0) {
@@ -24628,6 +20237,27 @@ function createPostgresBootstrapper(pgConfig) {
24628
20237
  async initializeRealtime(_config, driverResult) {
24629
20238
  return driverResult.internals.realtimeService;
24630
20239
  },
20240
+ /**
20241
+ * Create any collection tables, columns and enum types the database is
20242
+ * missing — additively, never destructively.
20243
+ *
20244
+ * This is what lets the managed runtime boot a project against a fresh
20245
+ * database and actually serve it. Before this, only auth tables were
20246
+ * ensured, so a managed tenant came up with working sign-in and a 500 on
20247
+ * every data route.
20248
+ *
20249
+ * Runs through the drizzle handle's underlying session so it uses the
20250
+ * same connection (and therefore the same privileges) the driver already
20251
+ * proved it can bootstrap with.
20252
+ */
20253
+ async ensureCollectionSchema(collections, driverResult, log) {
20254
+ const internals = driverResult.internals;
20255
+ const { ensureCollectionTables } = await import("./ensure-collection-tables-C9gy4STB.js");
20256
+ return { applied: (await ensureCollectionTables({ async query(text) {
20257
+ const result = await internals.db.execute(sql.raw(text));
20258
+ return { rows: result.rows ?? (Array.isArray(result) ? result : []) };
20259
+ } }, collections, log)).actions.length };
20260
+ },
24631
20261
  getAdmin(driverResult) {
24632
20262
  return driverResult.internals.driver.admin;
24633
20263
  },