@rebasepro/types 0.13.0 → 0.13.1-canary.g249daa1

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.
@@ -82,6 +82,8 @@ export interface FetchCollectionProps<M extends Record<string, unknown> = Record
82
82
  startAfter?: unknown;
83
83
  orderBy?: string;
84
84
  searchString?: string;
85
+ /** Ask each row which declared search field matched — populates `_matches`. */
86
+ searchExplain?: boolean;
85
87
  order?: "desc" | "asc";
86
88
  /** Vector similarity search configuration */
87
89
  vectorSearch?: VectorSearchParams;
@@ -128,6 +130,25 @@ export interface SaveManyProps<M extends Record<string, unknown> = Record<string
128
130
  /** Apply every row as INSERT ... ON CONFLICT DO UPDATE. See {@link SaveProps.upsert}. */
129
131
  upsert?: boolean;
130
132
  }
133
+ /**
134
+ * @internal
135
+ */
136
+ export interface UpdateManyProps<M extends Record<string, unknown> = Record<string, unknown>> {
137
+ path: string;
138
+ /**
139
+ * The rows to update, each named by its address.
140
+ *
141
+ * Distinct from {@link SaveManyProps.rows}, which carries keys *inside* the
142
+ * values and is insert-shaped — `saveMany` passes `status: "new"` and no
143
+ * `id`, so it cannot express "update exactly this row". This can, and it is
144
+ * why bulk update is a separate driver method rather than a flag on that one.
145
+ */
146
+ updates: {
147
+ id: string | number;
148
+ values: Partial<EntityValues<M>>;
149
+ }[];
150
+ collection?: CollectionConfig<M>;
151
+ }
131
152
  /**
132
153
  * @internal
133
154
  */
@@ -139,6 +160,14 @@ export interface DeleteProps<M extends Record<string, unknown> = Record<string,
139
160
  };
140
161
  collection?: CollectionConfig<M>;
141
162
  }
163
+ /**
164
+ * @internal
165
+ */
166
+ export interface DeleteManyProps<M extends Record<string, unknown> = Record<string, unknown>> {
167
+ path: string;
168
+ ids: (string | number)[];
169
+ collection?: CollectionConfig<M>;
170
+ }
142
171
  export type FilterCombinationValidProps = {
143
172
  path: string;
144
173
  databaseId?: string;
@@ -210,6 +239,16 @@ export interface DataDriver {
210
239
  * back to `save` per row.
211
240
  */
212
241
  saveMany?<M extends Record<string, unknown> = Record<string, unknown>>(props: SaveManyProps<M>): Promise<Record<string, unknown>[]>;
242
+ /**
243
+ * Update many rows in one transaction, each addressed by id.
244
+ *
245
+ * Optional for the same reason `saveMany` is: a driver that cannot make the
246
+ * batch atomic should not pretend to. The REST layer reports
247
+ * `BULK_UNSUPPORTED` rather than silently falling back to a loop of single
248
+ * writes, which would be neither atomic nor one round trip — the two things
249
+ * a caller reaches for a batch to get.
250
+ */
251
+ updateMany?<M extends Record<string, unknown> = Record<string, unknown>>(props: UpdateManyProps<M>): Promise<Record<string, unknown>[]>;
213
252
  /**
214
253
  * Delete a entity
215
254
  * @param props
@@ -221,6 +260,13 @@ export interface DataDriver {
221
260
  * @param path Collection path
222
261
  */
223
262
  deleteAll?(path: string): Promise<void>;
263
+ /**
264
+ * Delete many rows in one transaction, addressed by id.
265
+ *
266
+ * Ids rather than a filter, deliberately — see
267
+ * {@link SDKCollectionClient.deleteMany}. Optional, as `saveMany` is.
268
+ */
269
+ deleteMany?<M extends Record<string, unknown> = Record<string, unknown>>(props: DeleteManyProps<M>): Promise<void>;
224
270
  /**
225
271
  * Check if the given property is unique in the given collection
226
272
  * @param path Collection path
@@ -303,6 +349,8 @@ export interface RestFetchService {
303
349
  offset?: number;
304
350
  startAfter?: Record<string, unknown>;
305
351
  searchString?: string;
352
+ /** Ask each row which declared search fields matched — populates `_matches`. */
353
+ searchExplain?: boolean;
306
354
  databaseId?: string;
307
355
  vectorSearch?: VectorSearchParams;
308
356
  }, include?: string[]): Promise<Record<string, unknown>[]>;
package/dist/errors.d.ts CHANGED
@@ -1,3 +1,29 @@
1
+ /**
2
+ * The error codes every route can produce, as `RebaseApiError.code`.
3
+ *
4
+ * These are the defaults on `ApiError`'s static constructors server-side, so
5
+ * any endpoint can answer with one. They are **not** the complete set: routes
6
+ * pass their own more specific codes too (`EMAIL_EXISTS`, `TOKEN_EXPIRED`,
7
+ * `INVALID_BULK_BODY`, …), and auth alone defines a couple of dozen.
8
+ *
9
+ * Hence the union is deliberately open rather than closed. It exists to give
10
+ * autocomplete and to catch a typo in the common cases — `code` was a bare
11
+ * `string`, so `e.code === "NOT_FOUND"` and `e.code === "NOTFOUND"` were
12
+ * equally valid and only one of them worked. Closing it would be a lie that
13
+ * broke the moment a route added a code.
14
+ *
15
+ * @example
16
+ * if (e instanceof RebaseApiError) {
17
+ * switch (e.code) {
18
+ * case "NOT_FOUND": return null; // completed
19
+ * case "FORBIDDEN": return redirect();
20
+ * default: throw e; // routes' own codes land here
21
+ * }
22
+ * }
23
+ *
24
+ * @group Errors
25
+ */
26
+ export type RebaseErrorCode = "BAD_REQUEST" | "UNAUTHORIZED" | "FORBIDDEN" | "NOT_FOUND" | "CONFLICT" | "INTERNAL_ERROR" | "SERVICE_UNAVAILABLE" | "DB_PERMISSION_DENIED" | "SCHEMA_DRIFT" | (string & {});
1
27
  /**
2
28
  * Structured initializer for {@link RebaseApiError}.
3
29
  *
@@ -10,8 +36,8 @@ export interface RebaseErrorInit {
10
36
  * logic errors that have no HTTP status.
11
37
  */
12
38
  status?: number;
13
- /** Stable, machine-readable error code (e.g. `"NOT_FOUND"`, `"BAD_REQUEST"`). */
14
- code?: string;
39
+ /** Stable, machine-readable error code. See {@link RebaseErrorCode}. */
40
+ code?: RebaseErrorCode;
15
41
  /** Structured error payload returned by the server, when present. */
16
42
  details?: unknown;
17
43
  /** The underlying error this one wraps, if any. */
@@ -44,8 +70,8 @@ export interface RebaseErrorInit {
44
70
  export declare class RebaseApiError extends Error {
45
71
  /** HTTP status code, or `undefined` for non-HTTP errors. */
46
72
  readonly status?: number;
47
- /** Stable machine-readable error code, when the server supplied one. */
48
- readonly code?: string;
73
+ /** Stable machine-readable error code, when the server supplied one. See {@link RebaseErrorCode}. */
74
+ readonly code?: RebaseErrorCode;
49
75
  /** Structured error payload from the server, when present. */
50
76
  readonly details?: unknown;
51
77
  constructor(message: string, init?: RebaseErrorInit);
package/dist/index.es.js CHANGED
@@ -26,7 +26,7 @@
26
26
  var RebaseApiError = class extends Error {
27
27
  /** HTTP status code, or `undefined` for non-HTTP errors. */
28
28
  status;
29
- /** Stable machine-readable error code, when the server supplied one. */
29
+ /** Stable machine-readable error code, when the server supplied one. See {@link RebaseErrorCode}. */
30
30
  code;
31
31
  /** Structured error payload from the server, when present. */
32
32
  details;
@@ -307,6 +307,7 @@ var ADMIN_COLLECTION_KEYS = [
307
307
  "defaultSize",
308
308
  "defaultViewMode",
309
309
  "disableDefaultActions",
310
+ "display",
310
311
  "enabledViews",
311
312
  "entityActions",
312
313
  "entityViews",
@@ -317,6 +318,7 @@ var ADMIN_COLLECTION_KEYS = [
317
318
  "formAutoSave",
318
319
  "formView",
319
320
  "group",
321
+ "hideFromEntityViews",
320
322
  "hideFromNavigation",
321
323
  "hideIdFromCollection",
322
324
  "hideIdFromForm",
@@ -577,6 +579,22 @@ function getDeclaredSubcollections(collection) {
577
579
  return collection.subcollections;
578
580
  }
579
581
  //#endregion
582
+ //#region src/types/search.ts
583
+ /** The column name used when {@link SearchConfig.column} is not given. */
584
+ var DEFAULT_SEARCH_COLUMN = "search_vector";
585
+ /** The text search configuration used when {@link SearchConfig.language} is not given. */
586
+ var DEFAULT_SEARCH_LANGUAGE = "simple";
587
+ /** The weight a field carries when it does not name one. */
588
+ var DEFAULT_SEARCH_WEIGHT = "B";
589
+ /** The similarity floor used when {@link SearchConfig.fuzzyThreshold} is not given. */
590
+ var DEFAULT_FUZZY_THRESHOLD = .3;
591
+ /**
592
+ * The relevance sort key. Valid only on a collection that declares a
593
+ * {@link SearchConfig} *and* on a query that carries a search string; anywhere
594
+ * else it is an unknown field and the request is refused.
595
+ */
596
+ var RELEVANCE_SORT_FIELD = "_score";
597
+ //#endregion
580
598
  //#region src/types/relations.ts
581
599
  /** @group Models */
582
600
  function hasForeignKeyOnTarget(relation) {
@@ -593,7 +611,7 @@ function isToMany(relation) {
593
611
  //#endregion
594
612
  //#region src/types/policy.ts
595
613
  /**
596
- * The id a request without a logged-in user reports as `auth.uid()`.
614
+ * The id a request without a logged-in user reports as `rebase.uid()`.
597
615
  *
598
616
  * A user-context request always sets `app.uid`: blank would read back as
599
617
  * `NULL`, and `NULL` is how the trusted server context is recognised, so an
@@ -601,7 +619,7 @@ function isToMany(relation) {
601
619
  * therefore substitutes this sentinel at the single chokepoint where the GUC
602
620
  * is set.
603
621
  *
604
- * The consequence for policy authors is that **`auth.uid() IS NOT NULL` is a
622
+ * The consequence for policy authors is that **`rebase.uid() IS NOT NULL` is a
605
623
  * tautology on the user path** — it is true for anonymous visitors too. Use
606
624
  * {@link policy.authenticated} to mean "signed in", and
607
625
  * {@link policy.serverContext} to mean "the trusted server context". Do not
@@ -618,7 +636,7 @@ var ANONYMOUS_USER_ID = "anonymous";
618
636
  * JavaScript evaluator and the linter were all built on
619
637
  * {@link ANONYMOUS_USER_ID}, while the request path scoped unauthenticated
620
638
  * callers as `'anon'` — so `policy.authenticated()`, which compiled to
621
- * `auth.uid() <> 'anonymous'`, was *true* for an anonymous visitor. The
639
+ * `rebase.uid() <> 'anonymous'`, was *true* for an anonymous visitor. The
622
640
  * sanctioned way to write "signed in" granted to everyone, and the linter
623
641
  * flagged the spelling that actually worked as a foreign convention.
624
642
  *
@@ -700,6 +718,96 @@ var policy = {
700
718
  authRoles: () => ({ kind: "authRoles" })
701
719
  };
702
720
  //#endregion
721
+ //#region src/types/rls-functions.ts
722
+ /**
723
+ * The SQL helper functions RLS policies call, and the schema they live in.
724
+ *
725
+ * ## One schema, and it is ours
726
+ *
727
+ * Rebase creates exactly one schema in a project's database: `rebase`. These
728
+ * three functions live in it alongside the framework's own tables, and that is
729
+ * the whole contract — a reader can look at a database and know precisely which
730
+ * namespace belongs to the framework and that nothing else was touched.
731
+ *
732
+ * It used to be two. `uid()`, `jwt()` and `roles()` sat in a schema called
733
+ * `auth`, which is Supabase's name, chosen so that a developer who had written
734
+ * Supabase RLS would recognise `auth.uid()`. The familiarity was real but the
735
+ * name was not Rebase's to take, and taking it had a concrete cost: pointing
736
+ * Rebase at a database that already had a Supabase `auth` schema meant
737
+ * `CREATE OR REPLACE FUNCTION auth.uid() RETURNS text` against Supabase's
738
+ * `RETURNS uuid`, which Postgres rejects outright —
739
+ *
740
+ * ERROR: cannot change return type of existing function
741
+ * HINT: Use DROP FUNCTION auth.uid() first.
742
+ *
743
+ * — and the failure landed inside a catch-all that logged a warning and carried
744
+ * on, leaving a database with auth tables, no helper functions, and policies
745
+ * calling functions that did not exist. Under `rebase db migrate` the same
746
+ * statements aborted the migration instead.
747
+ *
748
+ * `rebase.uid()` collides with nobody. A Supabase database keeps its `auth`
749
+ * schema untouched and gains a `rebase` one, which is what a gradual migration
750
+ * needs.
751
+ *
752
+ * ## Why functions at all, rather than inlining `current_setting`
753
+ *
754
+ * Because the indirection has already been spent once. `uid()` resolves
755
+ * `app.uid` and falls back to the pre-rename `app.user_id`, so that during a
756
+ * rolling deploy — old and new pods serving one database — both eras resolve
757
+ * the principal. That was a single `CREATE OR REPLACE`. Inlined into policy
758
+ * bodies it would have been a rewrite of every policy on every table.
759
+ *
760
+ * ## Why the name is not configurable
761
+ *
762
+ * A policy body is stored SQL: Postgres parses `USING (…)` once and keeps it, so
763
+ * these strings are written into every policy in every database Rebase has
764
+ * provisioned. Everything that reads policies back — the SQL-to-policy parser
765
+ * behind the admin UI, the drift checker, `rls-check` — would have to know the
766
+ * configured value to recognise its own output. One frozen name is the feature.
767
+ */
768
+ /** The schema Rebase owns. The only schema Rebase creates. */
769
+ var REBASE_SCHEMA = "rebase";
770
+ /**
771
+ * The principal of the current request, as text, or NULL in the server context.
772
+ *
773
+ * Never NULL for a user request — an anonymous one carries
774
+ * {@link ANONYMOUS_USER_ID} — which is what makes `IS NULL` a reliable test for
775
+ * the trusted server plane and `IS NOT NULL` a tautology.
776
+ */
777
+ var RLS_UID_SQL = `${REBASE_SCHEMA}.uid()`;
778
+ /** The request's roles as a comma-separated string, for `string_to_array`. */
779
+ var RLS_ROLES_SQL = `${REBASE_SCHEMA}.roles()`;
780
+ /** The request's JWT claims as `jsonb`, or `{}`. */
781
+ var RLS_JWT_SQL = `${REBASE_SCHEMA}.jwt()`;
782
+ /**
783
+ * The pre-1.0 spellings, for recognising policies and hand-written SQL that
784
+ * predate the move.
785
+ *
786
+ * Kept because policies outlive the server that wrote them: a database migrated
787
+ * by an older release still holds `auth.uid()` in its policy bodies until the
788
+ * next push or boot recompiles them, and anything that reads policies back has
789
+ * to recognise both eras or report the framework's own output as foreign drift.
790
+ * Also used to give a project whose `securityRules` contain raw `auth.uid()` a
791
+ * message naming the replacement, instead of a parse failure.
792
+ */
793
+ var LEGACY_RLS_SCHEMA = "auth";
794
+ var LEGACY_RLS_UID_SQL = `${LEGACY_RLS_SCHEMA}.uid()`;
795
+ var LEGACY_RLS_ROLES_SQL = `${LEGACY_RLS_SCHEMA}.roles()`;
796
+ var LEGACY_RLS_JWT_SQL = `${LEGACY_RLS_SCHEMA}.jwt()`;
797
+ /**
798
+ * Rewrites the pre-1.0 function calls in a fragment of policy SQL.
799
+ *
800
+ * Deliberately anchored on a word boundary and the schema qualifier, so a column
801
+ * called `auth_uid` or a table named `auth` is left alone.
802
+ */
803
+ function rewriteLegacyRlsFunctions(sql) {
804
+ return sql.replace(/\bauth\.(uid|jwt|roles)\s*\(\s*\)/gi, (_match, fn) => `${REBASE_SCHEMA}.${fn.toLowerCase()}()`);
805
+ }
806
+ /** Whether a fragment of SQL still calls the pre-1.0 functions. */
807
+ function usesLegacyRlsFunctions(sql) {
808
+ return /\bauth\.(uid|jwt|roles)\s*\(\s*\)/i.test(sql);
809
+ }
810
+ //#endregion
703
811
  //#region src/types/backend.ts
704
812
  /**
705
813
  * Type guard: does this admin support SQL operations?
@@ -1180,6 +1288,6 @@ function isPublicStoragePath(path) {
1180
1288
  return p.startsWith("public/") || p.startsWith(`default/public/`);
1181
1289
  }
1182
1290
  //#endregion
1183
- export { ADMIN_COLLECTION_KEYS, ADMIN_PROPERTY_KEYS, ALL_WHERE_FILTER_OPS, ANONYMOUS_USER_ID, ANONYMOUS_USER_IDS, BUNDLE_FORMAT_VERSION, CANONICAL_TO_REST, DEFAULT_CAPABILITIES, DEFAULT_DATA_SOURCE_KEY, DEFAULT_FILTERABLE_RELATION_KINDS, DEFAULT_LIST_LIMIT, DEFAULT_STORAGE_SOURCE_KEY, DEFAULT_VECTOR_LIST_LIMIT, EntityReference, EntityRelation, FIREBASE_CAPABILITIES, GeoPoint, MAX_LIST_LIMIT, MONGODB_CAPABILITIES, NULL_OPS, POSTGRES_CAPABILITIES, PUBLIC_STORAGE_PREFIX, REST_TO_CANONICAL, RUNTIME_CONTRACT_VERSION, RebaseApiError, RebaseClientError, SCHEMA_VERSION_HEADER, Vector, canonicalSchemaPayload, computeSchemaVersion, deserializeCollections, findStorageSuffixCollision, getCollectionDataPath, getDataSourceCapabilities, getDeclaredSubcollections, hasForeignKeyOnTarget, isAnonymousUid, isBranchAdmin, isChannelBusInstance, isDocumentAdmin, isFirebaseCollectionConfig, isLazyComponentRef, isManyToMany, isMongoDBCollectionConfig, isPostgresCollectionConfig, isPublicStoragePath, isRelationalCollectionConfig, isSQLAdmin, isSchemaAdmin, isSerializedCollectionRef, isToMany, normalizeStorageSources, policy, registerDataSourceCapabilities, resolveClientListLimit, serializeCollections, storageEnvSuffix, toCanonicalOp };
1291
+ export { ADMIN_COLLECTION_KEYS, ADMIN_PROPERTY_KEYS, ALL_WHERE_FILTER_OPS, ANONYMOUS_USER_ID, ANONYMOUS_USER_IDS, BUNDLE_FORMAT_VERSION, CANONICAL_TO_REST, DEFAULT_CAPABILITIES, DEFAULT_DATA_SOURCE_KEY, DEFAULT_FILTERABLE_RELATION_KINDS, DEFAULT_FUZZY_THRESHOLD, DEFAULT_LIST_LIMIT, DEFAULT_SEARCH_COLUMN, DEFAULT_SEARCH_LANGUAGE, DEFAULT_SEARCH_WEIGHT, DEFAULT_STORAGE_SOURCE_KEY, DEFAULT_VECTOR_LIST_LIMIT, EntityReference, EntityRelation, FIREBASE_CAPABILITIES, GeoPoint, LEGACY_RLS_JWT_SQL, LEGACY_RLS_ROLES_SQL, LEGACY_RLS_SCHEMA, LEGACY_RLS_UID_SQL, MAX_LIST_LIMIT, MONGODB_CAPABILITIES, NULL_OPS, POSTGRES_CAPABILITIES, PUBLIC_STORAGE_PREFIX, REBASE_SCHEMA, RELEVANCE_SORT_FIELD, REST_TO_CANONICAL, RLS_JWT_SQL, RLS_ROLES_SQL, RLS_UID_SQL, RUNTIME_CONTRACT_VERSION, RebaseApiError, RebaseClientError, SCHEMA_VERSION_HEADER, Vector, canonicalSchemaPayload, computeSchemaVersion, deserializeCollections, findStorageSuffixCollision, getCollectionDataPath, getDataSourceCapabilities, getDeclaredSubcollections, hasForeignKeyOnTarget, isAnonymousUid, isBranchAdmin, isChannelBusInstance, isDocumentAdmin, isFirebaseCollectionConfig, isLazyComponentRef, isManyToMany, isMongoDBCollectionConfig, isPostgresCollectionConfig, isPublicStoragePath, isRelationalCollectionConfig, isSQLAdmin, isSchemaAdmin, isSerializedCollectionRef, isToMany, normalizeStorageSources, policy, registerDataSourceCapabilities, resolveClientListLimit, rewriteLegacyRlsFunctions, serializeCollections, storageEnvSuffix, toCanonicalOp, usesLegacyRlsFunctions };
1184
1292
 
1185
1293
  //# sourceMappingURL=index.es.js.map