@selvajs/supabase-provider 0.14.3 → 0.14.4-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (86) hide show
  1. package/dist/auth/SupabaseAuthProvider.d.ts +57 -0
  2. package/dist/auth/SupabaseAuthProvider.d.ts.map +1 -1
  3. package/dist/auth/SupabaseAuthProvider.js +116 -4
  4. package/dist/auth/SupabaseAuthProvider.js.map +1 -1
  5. package/dist/auth/__tests__/token-verification.test.d.ts +13 -0
  6. package/dist/auth/__tests__/token-verification.test.d.ts.map +1 -0
  7. package/dist/auth/__tests__/token-verification.test.js +135 -0
  8. package/dist/auth/__tests__/token-verification.test.js.map +1 -0
  9. package/dist/data/SupabaseComputeServerStore.d.ts +34 -2
  10. package/dist/data/SupabaseComputeServerStore.d.ts.map +1 -1
  11. package/dist/data/SupabaseComputeServerStore.js +146 -39
  12. package/dist/data/SupabaseComputeServerStore.js.map +1 -1
  13. package/dist/data/SupabaseDataProvider.d.ts +5 -2
  14. package/dist/data/SupabaseDataProvider.d.ts.map +1 -1
  15. package/dist/data/SupabaseDataProvider.js +24 -18
  16. package/dist/data/SupabaseDataProvider.js.map +1 -1
  17. package/dist/data/SupabaseDefinitionStore.d.ts +2 -1
  18. package/dist/data/SupabaseDefinitionStore.d.ts.map +1 -1
  19. package/dist/data/SupabaseDefinitionStore.js +68 -67
  20. package/dist/data/SupabaseDefinitionStore.js.map +1 -1
  21. package/dist/data/SupabaseInviteStore.d.ts.map +1 -1
  22. package/dist/data/SupabaseInviteStore.js +11 -22
  23. package/dist/data/SupabaseInviteStore.js.map +1 -1
  24. package/dist/data/SupabaseOrgStore.d.ts.map +1 -1
  25. package/dist/data/SupabaseOrgStore.js +49 -86
  26. package/dist/data/SupabaseOrgStore.js.map +1 -1
  27. package/dist/data/SupabaseProjectStore.d.ts.map +1 -1
  28. package/dist/data/SupabaseProjectStore.js +51 -70
  29. package/dist/data/SupabaseProjectStore.js.map +1 -1
  30. package/dist/data/SupabaseShareLinkStore.d.ts.map +1 -1
  31. package/dist/data/SupabaseShareLinkStore.js +13 -27
  32. package/dist/data/SupabaseShareLinkStore.js.map +1 -1
  33. package/dist/data/__tests__/compute-server-conformance.test.js +6 -1
  34. package/dist/data/__tests__/compute-server-conformance.test.js.map +1 -1
  35. package/dist/data/__tests__/compute-server-encryption.test.d.ts +12 -0
  36. package/dist/data/__tests__/compute-server-encryption.test.d.ts.map +1 -0
  37. package/dist/data/__tests__/compute-server-encryption.test.js +143 -0
  38. package/dist/data/__tests__/compute-server-encryption.test.js.map +1 -0
  39. package/dist/data/__tests__/share-link-concurrency.test.d.ts +22 -0
  40. package/dist/data/__tests__/share-link-concurrency.test.d.ts.map +1 -0
  41. package/dist/data/__tests__/share-link-concurrency.test.js +115 -0
  42. package/dist/data/__tests__/share-link-concurrency.test.js.map +1 -0
  43. package/dist/data/client.d.ts +35 -3
  44. package/dist/data/client.d.ts.map +1 -1
  45. package/dist/data/client.js +67 -16
  46. package/dist/data/client.js.map +1 -1
  47. package/dist/data/errors.d.ts +2 -0
  48. package/dist/data/errors.d.ts.map +1 -0
  49. package/dist/data/errors.js +23 -0
  50. package/dist/data/errors.js.map +1 -0
  51. package/dist/data/index.d.ts +7 -2
  52. package/dist/data/index.d.ts.map +1 -1
  53. package/dist/data/index.js +5 -1
  54. package/dist/data/index.js.map +1 -1
  55. package/dist/data/query.d.ts +20 -0
  56. package/dist/data/query.d.ts.map +1 -0
  57. package/dist/data/query.js +13 -0
  58. package/dist/data/query.js.map +1 -0
  59. package/dist/data/rowStamp.d.ts +38 -0
  60. package/dist/data/rowStamp.d.ts.map +1 -0
  61. package/dist/data/rowStamp.js +43 -0
  62. package/dist/data/rowStamp.js.map +1 -0
  63. package/dist/index.d.ts +2 -2
  64. package/dist/index.d.ts.map +1 -1
  65. package/dist/index.js +1 -1
  66. package/dist/index.js.map +1 -1
  67. package/package.json +2 -2
  68. package/src/auth/SupabaseAuthProvider.ts +140 -4
  69. package/src/auth/__tests__/token-verification.test.ts +158 -0
  70. package/src/data/SupabaseComputeServerStore.ts +163 -43
  71. package/src/data/SupabaseDataProvider.ts +35 -15
  72. package/src/data/SupabaseDefinitionStore.ts +73 -66
  73. package/src/data/SupabaseInviteStore.ts +13 -25
  74. package/src/data/SupabaseOrgStore.ts +51 -95
  75. package/src/data/SupabaseProjectStore.ts +55 -78
  76. package/src/data/SupabaseShareLinkStore.ts +15 -30
  77. package/src/data/__tests__/compute-server-conformance.test.ts +7 -1
  78. package/src/data/__tests__/compute-server-encryption.test.ts +173 -0
  79. package/src/data/__tests__/share-link-concurrency.test.ts +124 -0
  80. package/src/data/client.ts +95 -20
  81. package/src/data/errors.ts +45 -0
  82. package/src/data/index.ts +19 -2
  83. package/src/data/query.ts +22 -0
  84. package/src/data/rowStamp.ts +48 -0
  85. package/src/index.ts +20 -2
  86. package/supabase/migrations/20260711120000_selva_definition_schema_version.sql +18 -0
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Small query-builder helpers shared across Supabase stores.
3
+ */
4
+
5
+ /**
6
+ * The slice of a PostgREST filter builder these helpers touch: an `.is()`
7
+ * method that returns the same builder for chaining. Generic over the builder
8
+ * type so the caller's concrete builder (and its row generic) flows through.
9
+ */
10
+ interface DeletableQuery {
11
+ is(column: string, value: null): this;
12
+ }
13
+
14
+ /**
15
+ * Apply the soft-delete filter `deleted_at IS NULL`. The `.is('deleted_at', null)`
16
+ * idiom is repeated across every store that soft-deletes; this names it.
17
+ *
18
+ * let q = notDeleted(client.from('projects').select(COLS));
19
+ */
20
+ export function notDeleted<Q extends DeletableQuery>(query: Q): Q {
21
+ return query.is('deleted_at', null);
22
+ }
@@ -0,0 +1,48 @@
1
+ import type { RequestContext } from '@selvajs/platform';
2
+ import { auditSoftDelete } from '@selvajs/platform';
3
+
4
+ /**
5
+ * Row-level (snake_case) audit-stamp helpers for Supabase stores.
6
+ *
7
+ * Platform's `auditUpdate` / `auditSoftDelete` emit camelCase *domain* fields
8
+ * (`updatedAt` / `updatedBy`), but Postgres rows are snake_case, so every store
9
+ * hand-translated them. These helpers own that translation once. Row-column
10
+ * naming is a provider concern, so they live here rather than in platform.
11
+ *
12
+ * Two deliberate rules, matched to how the engine's stores already write rows:
13
+ * - `updated_by` is written ONLY when `ctx.userId` is set. On system contexts
14
+ * it's the empty string, and the column FKs `auth.users(id)` with
15
+ * `ON DELETE SET NULL` — writing `''` would violate the FK, so it's omitted
16
+ * and the existing value is left untouched.
17
+ * - Plain updates DON'T stamp `updated_at`: a per-table `updated_at` trigger
18
+ * already sets it. Only the soft-delete stamp writes `updated_at` explicitly,
19
+ * so it matches `deleted_at` (a single timestamp for the deletion event).
20
+ */
21
+
22
+ /**
23
+ * Stamp for a plain UPDATE: `{ updated_by }` when the context carries a user,
24
+ * `{}` otherwise (the DB trigger handles `updated_at`). Spread into the row:
25
+ * `const row = { ...patch, ...stampUpdate(ctx) }`.
26
+ */
27
+ export function stampUpdate(ctx: RequestContext): { updated_by?: string } {
28
+ return ctx.userId ? { updated_by: ctx.userId } : {};
29
+ }
30
+
31
+ /**
32
+ * Stamp for a soft-delete: `{ deleted_at, updated_at, updated_by? }`. `updated_at`
33
+ * is set explicitly to equal `deleted_at`; `updated_by` follows the same
34
+ * omit-when-empty rule as {@link stampUpdate}. `fallbackActor` defaults to
35
+ * `ctx.userId` (matching the engine stores' `auditSoftDelete(ctx, ctx.userId)`).
36
+ */
37
+ export function stampSoftDelete(
38
+ ctx: RequestContext,
39
+ fallbackActor: string | null | undefined = ctx.userId
40
+ ): { deleted_at: string; updated_at: string; updated_by?: string } {
41
+ const stamp = auditSoftDelete(ctx, fallbackActor);
42
+ const row: { deleted_at: string; updated_at: string; updated_by?: string } = {
43
+ deleted_at: stamp.deletedAt,
44
+ updated_at: stamp.updatedAt
45
+ };
46
+ if (stamp.updatedBy) row.updated_by = stamp.updatedBy;
47
+ return row;
48
+ }
package/src/index.ts CHANGED
@@ -12,9 +12,27 @@ export {
12
12
  SupabaseEventSink,
13
13
  SupabaseSolveMetricSink,
14
14
  SupabaseAuditQuery,
15
- buildClientBundle
15
+ buildClientBundle,
16
+ clientBundleFromEnv,
17
+ DEFAULT_SCHEMA,
18
+ mapPostgrestError,
19
+ stampUpdate,
20
+ stampSoftDelete,
21
+ notDeleted,
22
+ toRange,
23
+ orderColumn,
24
+ nextCursorFromRange,
25
+ encodeCursor,
26
+ decodeCursor
27
+ } from './data/index.js';
28
+ export type {
29
+ ClientBundle,
30
+ BuildClientOptions,
31
+ ForRequestOptions,
32
+ SchemaClient,
33
+ SelvaSchemaClient,
34
+ RangeSpec
16
35
  } from './data/index.js';
17
- export type { ClientBundle, BuildClientOptions } from './data/index.js';
18
36
 
19
37
  export { SupabaseUserProfileProvider } from './userProfile/index.js';
20
38
 
@@ -0,0 +1,18 @@
1
+ -- ============================================================================
2
+ -- Expose the cached schema's format version as a queryable column (ADR 0005).
3
+ --
4
+ -- The stored `schema` blob is a disposable cache of the compute-extracted UI
5
+ -- schema; its embedded `schemaVersion` says which schema format it was written
6
+ -- in. A GENERATED column keeps that version queryable for ops ("how many
7
+ -- versions are stale?") with zero write-path involvement — it can never drift
8
+ -- from the blob, and rows whose schema is NULL (pre-caching uploads) yield
9
+ -- NULL. The web render path re-extracts from compute on version mismatch; it
10
+ -- reads the version from the blob itself, not from this column.
11
+ -- ============================================================================
12
+
13
+ alter table selva.definition_versions
14
+ add column if not exists schema_version text
15
+ generated always as (schema ->> 'schemaVersion') stored;
16
+
17
+ comment on column selva.definition_versions.schema_version is
18
+ 'Schema format version of the cached `schema` blob (generated from schema->>''schemaVersion''). NULL when no schema is cached. Ops/diagnostics only — the app reads the version from the blob.';