Skip to content

Usage and constraints

The root exports SDK-independent types, resource services, search helpers, decimal wrapping and cache identity. Import database adapters from explicit subpaths. Optional peers are not needed to import the root. Install a provider’s SDK when using that provider; the Supabase declarations require its SDK’s real types. No connection is opened by importing an adapter. The application supplies clients, driver bindings, credentials, server endpoints and authorization.

DataAccessAdapter works with named collections and records. StorageAdapter works with object keys and binary data; it lives in universal-storage. Neither package directly depends on the other. Attachment callbacks in resource services are extension points, not a database/storage transaction implementation.

Filters, query options and backend differences

Section titled “Filters, query options and backend differences”

Filter is a TypeScript Record<string, unknown>, not a runtime validator. The caller must validate and allowlist fields/operators, bound payload size, query cost, result limits and resource names before accepting untrusted API requests. SQL identifiers must come from trusted application configuration; value binding does not make arbitrary identifiers safe. Do not expose raw adapters to a model or public HTTP client without an application validation/authorization layer.

  • SQLite/D1 accept simple identifiers and scalar bindings (JSON objects/arrays require caller conversion). Their implemented filter operators are $eq, $neq, $gt, $gte, $lt, $lte, $in and $nin. Null equality becomes SQL IS NULL/IS NOT NULL. Regex, logical $or/$and and other unsupported operators throw. There is no generic join/populate support.
  • Mongo HTTP operations require a matching application server implementation. This is a request protocol, not automatic deployment or a direct MongoDB client.
  • Supabase REST uses PostgREST and configured database relations. GraphQL requires pg_graphql and matching GraphQL field/collection names; select fields explicitly.
  • Neon supports comparisons, $in/$nin, $regex/$ilike and nonempty $and/$or. Supabase REST supports comparisons, lists, $regex (substring ILIKE), $ilike and nonempty $and; $or is rejected. GraphQL supports comparisons, $in and POSIX $regex; $nin and logical groups are rejected. Null equality/inequality uses the pg_graphql is enum. Unknown operators, invalid operands, undefined/nonfinite values and empty groups throw before executing the query; they are never discarded.
  • Neon quotes qualified segments separately. Limit/skip for Neon must be nonnegative safe integers. An empty $in matches nothing; an empty $nin excludes nothing. SQL null equality/inequality uses IS NULL/IS NOT NULL. Backend null-in-list behavior remains provider-specific.
  • createTableSearchHandler emits $or and $ilike; use it only with a backend that supports both. It does not expand an adapter’s supported operators.

QueryOptions is extensible, so its TypeScript shape is not a portability guarantee. signal, projection, populate, pagination, count and bulk operations differ by adapter. Check optional method availability. createResourceService.bulkCreate and .bulkUpdate throw when their underlying optional operations are absent. Bulk fallbacks may make multiple independent requests; no cross-backend atomicity, rollback, transaction or uniform concurrency guarantee is provided.

defaultQueryOptions applies to the service’s find method; per-call options win. Other service methods forward their per-call options. Resource services do not apply schema validation, permission checks, or a database migration automatically.

Keep DB passwords, privileged Supabase keys and direct DB connection strings on the server. A browser-facing API must enforce its own permissions, tenant boundary and database access rules. An injected token callback/fetch is a transport hook, not an authorization implementation. Tests use mocks and in-memory SQLite; they cannot verify a consumer’s real DB permissions or cloud deployment.

Cache identities are runtime-local. An adapter instance gets a distinct identity. An explicit cacheScope deliberately shares cached data with other adapters using that scope. Include the tenant/access boundary and rotate it when the authorized user or role changes. Never use raw credentials as a cache key. No cache client, React provider or global cache is supplied here.

The package does not depend on AJV/Zod or data-engine. Validate JSON Schema in application code, or use engine’s /integrations/supabase Supabase integration. That integration depends on data-access, never the reverse.

BigNumberDataAccessAdapter receives a compatible decimal constructor and explicit field rules; it does not install a decimal SDK. Validate decimal scale/rounding requirements for the application. HTTP JSON cannot transport JavaScript bigint without an explicit conversion.

Attachment metadata is application-neutral. The optional second metadata type parameter of ResourceService/createResourceService lets applications specialize it. Project detail IDs/codes are defined by private app-core, not this package. File upload and record updates can fail independently; the application decides cleanup and retry behavior.

Run bun run verify: source+test typecheck, package boundaries, unit/mock tests, real in-memory SQLite, ESM/CJS build and an isolated packed consumer on Node/Bun. Consumer tests check SDK-free import/type use, provider SDK declarations, browser bundling of SDK-independent entry points, and all export targets. No production DB credentials or real external service are used.

The unified site reads local package Markdown from the same public monorepo checkout. One root lockfile and Changesets workflow manage development and releases.

SDK-independent packed entry points are checked with TypeScript 6.0.3, without Node ambient types. All provider entries with the real Supabase 2.118 SDK are checked with TypeScript 5.7.3 and strict declaration checking (skipLibCheck: false). Supabase auth-js 2.118’s WebAuthn declarations conflict with TypeScript 6.0.3 DOM PublicKeyCredential.toJSON types. This is a known SDK/browser type compatibility limit, not a failure of record CRUD. Do not claim strict TS 6 + that SDK is supported; verify newer SDK/compiler combinations before updating this compatibility matrix.

Oracle Duality View follows the same fail-before-execution filter policy as Direct SQL. It supports the listed comparison/list/regex operators, rejects logical groups, uses IS NULL/IS NOT NULL for equality, and validates collection names, sort paths and limit/skip. Collections may be schema-qualified; column/JSON paths consist only of named [A-Za-z_][A-Za-z0-9_]* segments. Array indexes and raw SQL/JSON-path expressions are unsupported. Do not pass user-controlled resource names without a host allowlist. Direct create/update/replace use generated bind names, so ordinary columns named target_id, ret_id or value_0 retain their values. Empty create/update data is rejected. Both Oracle count implementations return numeric 0 for empty results. Real target-version and permission checks remain the host’s responsibility.

Oracle SQL/Duality View/ORDS/function adapters are private premium integrations. Use bun run test:containers for real PostgreSQL CRUD through NeonAdapter queryFn.