@burojs/hasura 0.2.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.
- package/LICENSE +21 -0
- package/README.md +122 -0
- package/dist/index.cjs +854 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +466 -0
- package/dist/index.d.ts +466 -0
- package/dist/index.js +839 -0
- package/dist/index.js.map +1 -0
- package/package.json +48 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/endpoint.ts","../src/live-provider.ts","../src/data-provider.ts"],"names":["token","query","data"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Same-origin GraphQL path Hasura serves by default. The single source for\n * both halves of this package: `createHasuraDataProvider`'s POST target and\n * `createHasuraLiveProvider`'s WebSocket derivation.\n *\n * It lives in its own module rather than in `data-provider.ts` because\n * `live-provider.ts` needs it too, and `data-provider.ts` already imports\n * `createHasuraLiveProvider` from `live-provider.ts`. `live-provider.ts`'s\n * existing back-reference is `import type { ResourceMapping }` — TYPE-only, so\n * it is erased and no runtime cycle exists. Importing a VALUE back across that\n * edge would create a real one. This third module keeps the constant defined\n * exactly once without introducing it.\n *\n * DISTILLATION NOTE (divergence 5 of 7 — deployment fact, neither side wins).\n * The two source apps read this from their OWN `env.ts`: playground as\n * `API_BASE_URL` (`import.meta.env.VITE_API_BASE_URL ?? ''`, an origin-root\n * deployment), l2-web-ui as `API_PREFIX` (`?? '/tandt'`, a non-empty default\n * that exists because every GraphQL call 404'd behind an nginx rule stripping\n * that prefix while the dev proxy passed paths through unprefixed). Both\n * defaults are correct FOR THEIR OWN DEPLOYMENT and neither belongs in a\n * published package, so this package takes no opinion: it exposes the\n * `endpoint` config field (the mechanism l2-web-ui had already added) and\n * defaults to the bare same-origin path. An app behind a path prefix passes\n * `endpoint: `${prefix}/gql/v1/graphql``.\n */\nexport const DEFAULT_HASURA_ENDPOINT = '/gql/v1/graphql';\n","import {\n type DataLiveProvider,\n type LiveConnectionStatus,\n type LiveObserver,\n normalizeDataError,\n} from '@burojs/core';\nimport { createClient } from 'graphql-ws';\n\nimport type { ResourceMapping } from './data-provider.js';\nimport { DEFAULT_HASURA_ENDPOINT } from './endpoint.js';\n\ninterface SubscriptionPayload {\n readonly query: string;\n readonly variables?: Record<string, unknown>;\n}\n\ninterface SubscriptionSink {\n next(value: unknown): void;\n error(error: unknown): void;\n complete(): void;\n}\n\ninterface GraphqlWsClient {\n subscribe(payload: SubscriptionPayload, sink: SubscriptionSink): () => void;\n}\n\ninterface GraphqlWsClientOptions {\n readonly url: string;\n readonly lazy: boolean;\n readonly keepAlive: number;\n readonly retryAttempts: number;\n readonly shouldRetry: () => boolean;\n readonly connectionParams: () => Promise<Record<string, unknown>>;\n readonly on: {\n connecting(): void;\n connected(): void;\n closed(): void;\n };\n}\n\nexport interface HasuraLiveProviderConfig {\n readonly resources: Record<string, ResourceMapping>;\n readonly getToken: () => Promise<string | null>;\n /**\n * The SAME GraphQL endpoint the data provider POSTs to — Hasura serves\n * subscriptions on that exact path. Converted to `ws(s)://` by\n * {@link hasuraWsUrl}. Defaults to {@link DEFAULT_HASURA_ENDPOINT}.\n *\n * `createHasuraDataProvider` forwards its own resolved endpoint here, so the\n * socket and the POST target can never drift apart.\n */\n readonly endpoint?: string;\n /** `X-Hasura-Role` sent in the socket's connection params. `null`/omitted sends none. */\n readonly role?: string | null;\n /** Test seam; production uses graphql-ws directly. */\n readonly clientFactory?: (options: GraphqlWsClientOptions) => GraphqlWsClient;\n}\n\n/**\n * `https://host/path` → `wss://host/path` (Hasura serves subscriptions on the\n * same path it serves queries on). `endpoint` may be `''`, a same-origin path\n * (`/gql/v1/graphql`, `/tandt/gql/v1/graphql`) or an absolute http(s) URL.\n *\n * DISTILLATION NOTE (divergence 6 of 7 — NEITHER a bug fix, verified\n * equivalent; playground's FORM taken, l2-web-ui's TESTS taken). The two apps\n * implement this differently: playground resolves through\n * `new URL(path, window.location.origin)` and flips the protocol; l2-web-ui\n * string-concatenates `origin.replace(/^http/, 'ws') + prefix + path` under a\n * comment warning about a \"prior version\" bug. That warning describes a\n * since-superseded implementation in l2-web-ui's OWN history, NOT playground's\n * current code — the research pass computed both functions for `('', https)`,\n * `('/tandt', https)`, `('/tandt', http)` and `('', http)` and got\n * byte-identical output every time. playground's `new URL()` form is taken\n * because its input domain is strictly wider (it is also correct when handed\n * an absolute `http(s)://` endpoint, which l2-web-ui's concat form explicitly\n * is not designed for), and l2-web-ui's CONTRACT-level tests (scheme + host +\n * prefix placement, never a literal echo of the implementation) are carried\n * into this package's suite because that is the testing style which caught the\n * original production regression.\n */\nexport function hasuraWsUrl(endpoint: string): string {\n // No window (SSR/unit import without a DOM): fall back to the bare path.\n if (typeof window === 'undefined') return endpoint;\n const url = new URL(endpoint, window.location.origin);\n url.protocol = url.protocol === 'https:' ? 'wss:' : 'ws:';\n return url.toString();\n}\n\nfunction listSubscription(mapping: ResourceMapping): SubscriptionPayload {\n const where = mapping.fixedFilter;\n return {\n query: where\n ? `subscription Live_${mapping.table}_list($where: ${mapping.table}_bool_exp) {\n ${mapping.table}_aggregate(where: $where) { aggregate { count max { updated_at } } }\n }`\n : `subscription Live_${mapping.table}_list {\n ${mapping.table}_aggregate { aggregate { count max { updated_at } } }\n }`,\n ...(where === undefined ? {} : { variables: { where } }),\n };\n}\n\nfunction oneSubscription(\n mapping: ResourceMapping,\n id: string | number,\n): SubscriptionPayload | null {\n const pkField = mapping.pkField ?? 'id';\n const pkType = mapping.pkType ?? 'bigint';\n const root = mapping.byPkRoot === false ? null : (mapping.byPkRoot ?? `${mapping.table}_by_pk`);\n if (root === null) return null;\n return {\n query: `subscription Live_${mapping.table}_one($id: ${pkType}!) {\n ${root}(${pkField}: $id) { ${pkField} updated_at }\n }`,\n variables: { id },\n };\n}\n\n/**\n * Native Hasura live provider. The socket transmits only a change signal; rows\n * always come from the regular descriptor query, so mapping/pagination remain\n * single-sourced in the data provider.\n */\nexport function createHasuraLiveProvider(config: HasuraLiveProviderConfig): DataLiveProvider {\n const listeners = new Set<(status: LiveConnectionStatus) => void>();\n const endpoint = config.endpoint ?? DEFAULT_HASURA_ENDPOINT;\n const role = config.role ?? null;\n let client: GraphqlWsClient | undefined;\n\n const status = (value: LiveConnectionStatus) => {\n for (const listener of listeners) listener(value);\n };\n\n function getClient(): GraphqlWsClient {\n if (client !== undefined) return client;\n const options: GraphqlWsClientOptions = {\n url: hasuraWsUrl(endpoint),\n lazy: true,\n keepAlive: 10_000,\n retryAttempts: Number.POSITIVE_INFINITY,\n shouldRetry: () => true,\n connectionParams: async () => {\n const token = await config.getToken();\n return {\n headers: {\n ...(token ? { Authorization: `Bearer ${token}` } : {}),\n ...(role ? { 'X-Hasura-Role': role } : {}),\n },\n };\n },\n on: {\n connecting: () => status('connecting'),\n connected: () => status('connected'),\n closed: () => status('degraded'),\n },\n };\n client =\n config.clientFactory?.(options) ??\n (createClient(options as never) as unknown as GraphqlWsClient);\n return client;\n }\n\n return {\n async open(descriptor, openContext) {\n if (openContext.signal.aborted) return null;\n const mapping = config.resources[descriptor.resource];\n if (mapping?.live !== true) return null;\n const payload =\n descriptor.kind === 'list'\n ? listSubscription(mapping)\n : descriptor.kind === 'one'\n ? oneSubscription(mapping, descriptor.id)\n : null;\n if (payload === null) return null;\n\n return {\n kind: 'invalidate' as const,\n initial: 'query' as const,\n subscribe(observer: LiveObserver, subscribeContext) {\n if (openContext.signal.aborted || subscribeContext.signal.aborted) return () => undefined;\n let primed = false;\n let closed = false;\n let upstream: (() => void) | undefined = undefined;\n\n const close = () => {\n if (closed) return;\n closed = true;\n listeners.delete(onStatus);\n openContext.signal.removeEventListener('abort', close);\n subscribeContext.signal.removeEventListener('abort', close);\n upstream?.();\n };\n const onStatus = (value: LiveConnectionStatus) => {\n if (!closed) observer.status(value);\n };\n const sink: SubscriptionSink = {\n next: () => {\n if (closed) return;\n // Hasura immediately emits the subscription's current snapshot.\n // The normal query is the baseline for this plan, so only later\n // payloads signal a refetch.\n if (!primed) {\n primed = true;\n return;\n }\n observer.next(undefined);\n },\n error: (error) => {\n if (closed) return;\n observer.error(normalizeDataError(error));\n // An operation-level GraphQL error is terminal for this\n // subscription. Close it eagerly; socket-level reconnect events\n // arrive through the client hooks instead.\n close();\n },\n complete: () => {\n // Socket reconnect is transport-owned. Do not complete the plan:\n // graphql-ws can resubscribe this operation after reconnect.\n if (!closed) observer.status('degraded');\n },\n };\n\n listeners.add(onStatus);\n openContext.signal.addEventListener('abort', close, { once: true });\n subscribeContext.signal.addEventListener('abort', close, { once: true });\n upstream = getClient().subscribe(payload, sink);\n // DISTILLATION NOTE (divergence 7 of 7 — bug fix, playground only,\n // the ONE that went the opposite way from every other divergence).\n // If `sink.error(...)`\n // fires SYNCHRONOUSLY inside `subscribe(...)` — before the\n // assignment above completes — `close()` runs with `upstream` still\n // `undefined`, so its `upstream?.()` is a silent no-op and the real\n // unsubscribe handle, assigned moments later, is never called: an\n // open graphql-ws subscription registration leaks. playground\n // shipped this one-line guard (git-confirmed as a dedicated fix —\n // commit c89ca660 — with its regression test carried into this\n // package's suite verbatim); l2-web-ui never received it, and leaked\n // until this branch backported the guard to it (99e670aa). Stated in\n // the past tense on purpose: the earlier wording said \"leaks to this\n // day\", which the backport made false four commits later.\n if (closed) upstream();\n if (openContext.signal.aborted || subscribeContext.signal.aborted) close();\n // Promise form intentionally makes coordinator-owned late-handle\n // disposal observable; close itself is idempotent across both paths.\n return Promise.resolve(close);\n },\n };\n },\n };\n}\n","import {\n defineDataProvider,\n isDataError,\n type CountResult,\n type DataError,\n type DataOperationContext,\n type DataProvider,\n type ErasedResourceHandle,\n type FilterExpression,\n} from '@burojs/core';\nimport { DEFAULT_HASURA_ENDPOINT } from './endpoint.js';\nimport { createHasuraLiveProvider } from './live-provider.js';\n\nexport interface HasuraDataProviderConfig {\n /** Returns a fresh JWT or null if user is not authed. */\n getToken: () => Promise<string | null>;\n /**\n * GraphQL endpoint every query/mutation is POSTed to, and the endpoint the\n * live provider derives its WebSocket URL from. May be a same-origin path\n * (`/gql/v1/graphql`, `/tandt/gql/v1/graphql`) or an absolute http(s) URL.\n * Defaults to {@link DEFAULT_HASURA_ENDPOINT}.\n */\n endpoint?: string;\n /**\n * Hasura role sent as `X-Hasura-Role` for resources whose mapping does not\n * declare a `role` of its own. `null` (the default) sends no role header at\n * all, leaving the JWT's own default role in force.\n *\n * A resource mapping's `role` always wins when it is defined — including\n * `role: null`, which suppresses the header for that one resource.\n *\n * `''` is treated as `null`, in both halves of the package: it is the shape\n * of a missing env var, not a role. See {@link normalizeRole}.\n */\n defaultRole?: string | null;\n /**\n * Revalidates authentication after a request comes back with HTTP **401**.\n * The callback owns any terminal sign-out; returning true permits one retry\n * with a newly obtained token, while false preserves the original 401\n * response.\n *\n * ⚠️ KNOWN GAP, stated here because this is where a consumer reads: HTTP 401\n * is NOT how the Hasura deployment this provider was distilled from rejects\n * a credential. The one capture in this repository of a real rejection\n * (`packages/mock-kit/fixtures/hasura/error-unauthorized.json`, taken from\n * the live backend with a deliberately malformed bearer token) came back\n * **HTTP 200** with an `invalid-jwt` errors envelope. Replayed through this\n * provider it surfaces as `{ kind: 'protocol', code: 'graphql-error' }` and\n * `recoverAuth` is never consulted — no refresh, no retry, and app logic\n * keyed on `kind: 'auth'` never fires either. Pinned by\n * `tests/fixture-fidelity.test.ts`'s `error-unauthorized` case.\n *\n * So this callback fires only for a deployment that really answers 401 (a\n * proxy or gateway in front of Hasura, typically). Keying recovery on the\n * error envelope instead is a product decision, deliberately not taken here;\n * the existing 401 tests use a FABRICATED 401 and must not be read as proof\n * that recovery works against Hasura itself.\n */\n recoverAuth?: () => Promise<boolean>;\n /** Map our resource name → table + field selection. */\n resources: Record<string, ResourceMapping>;\n /**\n * Optional global scope read on every getList. Returns key → value pairs\n * that get merged into the where clause as `{ <key>: { _eq: <value> } }`,\n * but only for resources that whitelist the key in `scopeFields`.\n *\n * Example: `() => ({ pg: 'radio', location_id: 5 })` — applied to documents\n * (which have both fields) but not products (which only have pg).\n */\n getScope?: (context: DataOperationContext) => Record<string, unknown>;\n /**\n * Closed, application-owned custom operation registry. A descriptor selects\n * an entry by its already-declared `{ resource, operation }` binding; it can\n * never supply a GraphQL document, URL, or result mapper itself.\n */\n operations?: HasuraOperationRegistry;\n fetchImpl?: typeof fetch;\n}\n\nexport interface HasuraCustomOperation {\n /** Which native provider slot may execute this declaration. */\n readonly kind: 'query' | 'mutation';\n /** Static GraphQL document owned by the application/provider integration. */\n readonly document: string;\n /** Maps the declared operation input to the document's variables. */\n readonly variables: (input: unknown) => Record<string, unknown> | undefined;\n /** Maps the full GraphQL response to the declared operation output. */\n readonly mapResult?: (data: unknown) => unknown;\n /** Overrides the mapped resource role; undefined keeps that mapped role. */\n readonly role?: string | null;\n}\n\n/**\n * Registry entries are keyed by the resource binding first, then the declared\n * custom operation name. This makes cross-resource operation reuse explicit\n * rather than allowing a descriptor to name an arbitrary backend operation.\n */\nexport type HasuraOperationRegistry = Readonly<\n Record<string, Readonly<Record<string, HasuraCustomOperation>>>\n>;\n\nexport interface ResourceMapping {\n table: string;\n selectFields: string[]; // fields to select in queries\n /**\n * GraphQL scalar name for this table's primary key, interpolated into the\n * `$id` variable declaration of every by-pk query/mutation. Default\n * `'bigint'`.\n *\n * DISTILLATION NOTE (divergence 3 of 7 — feature, additive, l2-web-ui only).\n * l2-web-ui added `'String'` for tables whose pk is a genuine string\n * business key (a GS1 marking code), not a uuid/Int/bigint\n * wire type: Hasura's by-pk root for such a table is literally\n * `<table>_by_pk(<pk>: $id)` with `$id: String!`, which none of the other\n * three names can express (playground's union stopped at\n * `'bigint' | 'uuid' | 'Int'`). Purely a type-union widening — no runtime\n * branch reads `pkType` beyond interpolating it — so l2-web-ui's wider union\n * is taken wholesale rather than forked.\n */\n pkType?: 'bigint' | 'uuid' | 'Int' | 'String'; // default 'bigint'\n /**\n * Skip the aggregate on every `getList`. This is a COST decision, not a\n * schema fact: the table has an `_aggregate` root but counting it on each\n * page is too slow to pay for unprompted. (Measured in one of the apps this\n * provider was distilled from: ~9.8M-row and ~28.9M-row tables, the latter\n * taking ~55 s per count.) `total` is then omitted and the list renders the\n * unknown-total shape.\n *\n * ⚠️ NOT the same thing as {@link ResourceMapping.aggregate} `: false`, and\n * NOT a proxy for it — most `noAggregate` tables CAN be counted on demand,\n * which is exactly what `getCount` is for. Deriving one from the other gets\n * the flagship resources backwards.\n */\n noAggregate?: boolean;\n /**\n * Which aggregate root field backs this table, for the on-demand `getCount`\n * (and for `getList`'s own count when it runs):\n * - absent — derive `${table}_aggregate` (the Hasura default; today's behaviour);\n * - `false` — no aggregate root exists at all, under any name. `getCount`\n * answers `{ total: null }` without a round trip and the UI drops the\n * affordance for the session;\n * - a string — an explicitly-named root, for tables whose custom root fields\n * break the derivation.\n *\n * ⚠️ Establish this by introspecting the live schema under the role the app\n * actually runs as, not by reading `noAggregate` or a code comment. Both\n * have been wrong here.\n */\n aggregate?: false | string;\n /**\n * Root field for a single-row fetch by primary key. Defaults to the derived\n * `${table}_by_pk`. Set `false` when the active role exposes only the\n * collection root; `getOne` then queries it with pk `where` + `limit: 1`.\n *\n * ⚠️ Same class of fact as `aggregate`, and established the same way — by\n * introspecting the live schema, not by reading a comment. In one of the\n * source apps exactly one table of forty had a non-derivable by-pk root (a\n * plural table whose root was singular), so the derived name 400'd and its\n * Show page was a dead-end error reachable in two clicks from the sidebar.\n */\n byPkRoot?: string | false;\n /** Field to order by in getList. Defaults to 'id'. */\n orderByField?: string;\n /** Name of the primary-key field in the row (for synthetic id in list rows). Defaults to 'id'. */\n pkField?: string;\n /**\n * Hasura role for this resource. `null` (or `''`) means no role header (use\n * the JWT's default role). Undefined falls back to\n * {@link HasuraDataProviderConfig.defaultRole}.\n */\n role?: string | null;\n /**\n * Columns typed `int64` in a Hasura ClickHouse source. Hasura serialises\n * int64 as a JSON STRING and REJECTS a numeric filter value with\n * «expected a string for type 'int64'» — so a `document_id` filter sent as a\n * number matched nothing and the affected list tabs came back empty.\n * Filter values for these fields are coerced to strings before the where\n * clause is built. (Verified live: numeric/int literal → error, string → rows.)\n */\n int64Fields?: string[];\n /**\n * Whitelist of scope keys this table actually has columns for. Only these\n * keys from `getScope()` get injected into where clauses. Defaults to `[]`\n * (no scope injection — useful for tables that lack the scope columns).\n */\n scopeFields?: string[];\n /**\n * JSONB-spill routing for tables whose forms submit a flat values record but\n * whose real columns nest most of those keys inside JSONB blobs (e.g. a\n * `documents` table where template head fields live inside `head`, a couple\n * live inside `meta`, and only a handful — type/status/… — are real columns).\n *\n * When set, create/update partition the incoming flat `variables`:\n * - keys that ARE real columns (present in `selectFields`) stay top-level;\n * - keys listed in `metaKeys` nest under `metaColumn`;\n * - every OTHER key nests under `column` (the head spill).\n * getOne does the inverse — it spreads the fetched `column`/`metaColumn`\n * objects back onto the flat record so edit forms / show pages read those\n * keys as flat fields (the raw blobs are kept too).\n *\n * SCOPE: scalar / relation / enum head+meta fields only. Data-body arrays\n * (children) live in a sibling table — see `dataBody`.\n */\n jsonbSpill?: JsonbSpillConfig;\n /**\n * Data-body routing for resources whose heavy array payload lives in a\n * SEPARATE 1:1 sibling table rather than a JSONB column on the row itself\n * (e.g. a `documents.items[]` / `products[]` payload living in\n * `documents_data.data`, keyed by `document_id`).\n *\n * When set, create/update peel the `keys` off the flat `variables` FIRST\n * (before `jsonbSpill` runs, so they never leak into `head`), write the parent\n * row, then upsert the sibling row (`insert_<table>_one … on_conflict`). getOne\n * nested-selects the sibling via `relationship` and spreads its `column` blob\n * back onto the flat record (so edit forms read `items` as a top-level field),\n * dropping the raw relationship object so it can't round-trip into `head`.\n * getList is left untouched — list columns are head/meta scalars, never the\n * heavy data body.\n */\n dataBody?: DataBodyConfig;\n /**\n * Fixed, always-on Hasura `where` fragment ANDed into every getList /\n * getOne query for this resource. Powers \"per-type\" / projection resources:\n * several resource names can map to the SAME table, each scoped to a\n * different slice — e.g. `fixedFilter: { type: { _eq: 'work_order' } }` turns\n * a `work_orders` resource into a work-orders-only view of a shared\n * `documents` table. The fragment is a raw Hasura `<table>_bool_exp` object\n * (same shape `filtersToWhere` emits), so nested / `_and` / `_or` clauses are\n * all valid. Merged with `mergeWhere` (AND) after user filters + scope, so\n * the user can still filter/search WITHIN the fixed slice.\n *\n * getOne: because `<table>_by_pk` takes no `where`, a resource with a\n * `fixedFilter` fetches its single row via a `where`-based `limit: 1` query\n * (pk `_eq` id AND fixedFilter) instead — so the row is only returned when it\n * actually belongs to the slice (a work-order id won't resolve under\n * `movements`). Resources without a `fixedFilter` keep the `_by_pk` path.\n */\n fixedFilter?: Record<string, unknown>;\n /**\n * Opt this resource into real-time updates. The live provider then opens a\n * cheap change-signal subscription for its list / single-record views and\n * invalidates matching native runtime queries when the table changes.\n *\n * Off by default on purpose: every live resource holds an open server-side\n * subscription, so it is a cost you opt into for data that actually moves\n * (documents change constantly during processing; a country lookup does not).\n */\n live?: boolean;\n}\n\n/** @see ResourceMapping.jsonbSpill */\nexport interface JsonbSpillConfig {\n /** JSONB column that catches every non-base, non-meta key (e.g. `head`). */\n column: string;\n /** JSONB column that catches the `metaKeys` (e.g. `meta`). */\n metaColumn: string;\n /** Flat keys routed to `metaColumn` instead of the `column` spill. */\n metaKeys: string[];\n /**\n * Flat form key → dotted NESTED path inside the head `column`. Lets a flat\n * field (e.g. `vsd_number`) persist to a nested head location (e.g.\n * `regulator_data.crpt.vsd_number`) without dotted field keys. getOne reads\n * the nested value back out to the flat key.\n */\n nestedKeys?: Record<string, string>;\n}\n\n/** Set `obj.a.b.c = value`, creating intermediate objects. */\nfunction setNestedPath(obj: Record<string, unknown>, path: string, value: unknown): void {\n const parts = path.split('.');\n const leaf = parts.pop();\n // `String.split` always yields at least one element, so this never fires at\n // runtime; it is how the leaf is narrowed without a non-null assertion.\n if (leaf === undefined) return;\n let cur = obj;\n for (const p of parts) {\n const next = cur[p];\n if (typeof next !== 'object' || next === null) cur[p] = {};\n cur = cur[p] as Record<string, unknown>;\n }\n cur[leaf] = value;\n}\n\n/** Read `obj.a.b.c` (undefined if any segment is missing). */\nfunction getNestedPath(obj: Record<string, unknown>, path: string): unknown {\n let cur: unknown = obj;\n for (const p of path.split('.')) {\n if (cur == null || typeof cur !== 'object') return undefined;\n cur = (cur as Record<string, unknown>)[p];\n }\n return cur;\n}\n\n/** @see ResourceMapping.dataBody */\nexport interface DataBodyConfig {\n /** Sibling table holding the heavy data body, 1:1 with the parent (e.g. `documents_data`). */\n table: string;\n /** FK column on the sibling pointing back at the parent pk (e.g. `document_id`). */\n fk: string;\n /** JSONB column on the sibling that holds the whole data body (e.g. `data`). */\n column: string;\n /** Reverse object-relationship name on the PARENT row → sibling, for the getOne nested select (e.g. `document_data`). */\n relationship: string;\n /** `on_conflict` constraint enum for the upsert (e.g. `document_data_pkey`). */\n constraint: string;\n /** Flat value keys that belong to the data body — routed to the sibling `column` (e.g. `['items', 'products']`). */\n keys: string[];\n}\n\n/**\n * Split a flat `values` record for a data-body resource into the sibling-table\n * payload and the remainder. Keys listed in `cfg.keys` whose value is defined\n * are collected into `dataBody` (they become the sibling `column` blob); every\n * other key passes through in `rest` (to be further partitioned by jsonbSpill).\n * The raw `cfg.relationship` key (the nested object getOne leaves behind on a\n * re-submitted record) is dropped from both so it can never leak into `head`.\n *\n * `hasDataBody` is true iff at least one data-body key was present — callers\n * skip the sibling write entirely when false, so a document type WITHOUT a data\n * body (e.g. a work order) never gets an empty sibling row.\n *\n * Exported for unit testing; the provider calls it with `m.dataBody`.\n */\nexport function partitionDataBody(\n values: Record<string, unknown>,\n cfg: DataBodyConfig,\n): { dataBody: Record<string, unknown>; rest: Record<string, unknown>; hasDataBody: boolean } {\n const keySet = new Set(cfg.keys);\n const dataBody: Record<string, unknown> = {};\n const rest: Record<string, unknown> = {};\n let hasDataBody = false;\n for (const [key, value] of Object.entries(values)) {\n if (key === cfg.relationship) continue; // never round-trip the raw nested rel object\n if (keySet.has(key)) {\n if (value !== undefined) {\n dataBody[key] = value;\n hasDataBody = true;\n }\n } else {\n rest[key] = value;\n }\n }\n return { dataBody, rest, hasDataBody };\n}\n\n/**\n * Partition a flat `values` record for a jsonb-spill resource.\n *\n * Routing rule (first match wins per key):\n * 1. `key === spill.column` / `key === spill.metaColumn` — an explicitly passed\n * JSONB object (e.g. an edit form re-submitting the raw `head` blob). Its\n * entries are merged UNDER any individually-spilled keys so freshly edited\n * flat values win over the stale blob, and un-modelled legacy keys survive.\n * 2. `key ∈ metaKeys` — nests under `metaColumn`.\n * 3. `key ∈ baseColumns` — stays a top-level column.\n * 4. otherwise — nests under the `column` spill (head).\n *\n * `undefined` values are dropped (a never-set optional field must not clobber\n * an existing column / blob key). Empty JSONB objects are omitted entirely.\n *\n * Exported for unit testing; the provider calls it with `baseColumns =\n * m.selectFields` (the table's real columns, which include `column`/`metaColumn`\n * themselves — handled by rule 1 before the base check).\n */\nexport function partitionJsonbSpill(\n values: Record<string, unknown>,\n spill: JsonbSpillConfig,\n baseColumns: string[],\n): Record<string, unknown> {\n const baseSet = new Set(baseColumns);\n const metaSet = new Set(spill.metaKeys);\n const nestedKeys = spill.nestedKeys ?? {};\n const base: Record<string, unknown> = {};\n const headExplicit: Record<string, unknown> = {};\n const metaExplicit: Record<string, unknown> = {};\n const headSpill: Record<string, unknown> = {};\n const metaSpill: Record<string, unknown> = {};\n const nestedSpill: Array<[string, unknown]> = []; // [nested head path, value]\n\n for (const [key, value] of Object.entries(values)) {\n if (value === undefined) continue;\n const nestedPath = nestedKeys[key];\n if (key === spill.column) {\n if (value && typeof value === 'object')\n Object.assign(headExplicit, value as Record<string, unknown>);\n } else if (key === spill.metaColumn) {\n if (value && typeof value === 'object')\n Object.assign(metaExplicit, value as Record<string, unknown>);\n } else if (metaSet.has(key)) {\n metaSpill[key] = value;\n } else if (nestedPath) {\n nestedSpill.push([nestedPath, value]);\n } else if (baseSet.has(key)) {\n base[key] = value;\n } else {\n headSpill[key] = value;\n }\n }\n\n // Individually-spilled keys win over the merged raw blob (edited value beats\n // the stale object; keys only present in the blob are preserved).\n const head = { ...headExplicit, ...headSpill };\n // Nested head keys (e.g. regulator_data.crpt.vsd_number) applied last.\n for (const [path, value] of nestedSpill) setNestedPath(head, path, value);\n const meta = { ...metaExplicit, ...metaSpill };\n const out: Record<string, unknown> = { ...base };\n if (Object.keys(head).length > 0) out[spill.column] = head;\n if (Object.keys(meta).length > 0) out[spill.metaColumn] = meta;\n return out;\n}\n\n/**\n * Inverse of {@link partitionJsonbSpill}: spread a fetched row's `head` / `meta`\n * JSONB blobs back onto the flat record so head/meta keys (e.g. `batch_number`,\n * `regulatory_system`) read as top-level fields on show pages, edit forms, AND\n * per-type list columns. Base columns win on collision (`...rec` last), and the\n * raw `head` / `meta` objects are preserved so tabs / re-submission still have\n * them. A non-object / null blob is ignored.\n *\n * Shared by getOne (single record) and getList (each row) so the two stay in\n * lockstep. Returns the input unchanged when it isn't an object.\n */\nexport function flattenJsonbSpill(item: unknown, spill: JsonbSpillConfig): unknown {\n if (!item || typeof item !== 'object') return item;\n const rec = item as Record<string, unknown>;\n const headObj = rec[spill.column];\n const metaObj = rec[spill.metaColumn];\n const out: Record<string, unknown> = {\n ...(headObj && typeof headObj === 'object' ? (headObj as Record<string, unknown>) : {}),\n ...(metaObj && typeof metaObj === 'object' ? (metaObj as Record<string, unknown>) : {}),\n ...rec,\n };\n // Read nested head paths back out to their flat form keys.\n if (spill.nestedKeys && headObj && typeof headObj === 'object') {\n for (const [flatKey, path] of Object.entries(spill.nestedKeys)) {\n const v = getNestedPath(headObj as Record<string, unknown>, path);\n if (v !== undefined) out[flatKey] = v;\n }\n }\n return out;\n}\n\n/**\n * This provider's own code for \"no token to send\" — `getToken()` resolved `null`, so no\n * request was ever attempted. Exported so downstream error-classification code can tell\n * this apart from a genuine rejected-credentials answer (a real 401 the retry/`recoverAuth`\n * path still couldn't clear) without inventing a parallel distinction of its own: a request\n * that never left the client is the \"we never asked\" case, not a session failure.\n *\n * DISTILLATION NOTE (divergence 4 of 7 — hygiene, l2-web-ui only, zero\n * behaviour change). playground inlined the literal `'not-authenticated'` at\n * both throw sites; l2-web-ui extracted and exported this constant so its own\n * `classify-data-error.ts` could match a symbol instead of a string. The STRING\n * VALUE is identical either way — nothing observable differs — so l2-web-ui's\n * exported form is taken purely because a published package owes consumers a\n * stable symbol.\n */\nexport const NOT_AUTHENTICATED_CODE = 'not-authenticated';\n\ninterface GqlResponse<T> {\n data?: T;\n errors?: Array<{ message: string }>;\n}\n\ninterface HasuraScopedQuery {\n readonly filter?: FilterExpression<ErasedResourceHandle>;\n readonly providerOptions?: { readonly ignoreScope?: boolean };\n}\n\nconst OP_MAP: Record<string, string> = {\n eq: '_eq',\n neq: '_neq',\n ne: '_neq',\n lt: '_lt',\n lte: '_lte',\n gt: '_gt',\n gte: '_gte',\n in: '_in',\n notIn: '_nin',\n nin: '_nin',\n contains: '_ilike',\n containss: '_like',\n startsWith: '_ilike',\n endsWith: '_ilike',\n startswith: '_ilike',\n endswith: '_ilike',\n null: '_is_null',\n};\n\n/**\n * The shared refusal code for \"this provider cannot express that filter\n * operator\". `@burojs/pocketbase` throws the SAME `kind` and the SAME code, so\n * an application handling one handles the other — see\n * {@link filtersToWhere} for why that agreement is load-bearing.\n */\nexport const FILTER_OPERATOR_UNSUPPORTED_CODE = 'filter-operator-unsupported';\n\n/**\n * Operators this provider knowingly cannot express, kept separate from \"we\n * have never heard of this\" so the error can say WHY rather than just \"no\".\n *\n * `has` / `hasAny` / `hasAll` are first-class `@burojs/core` operators over a\n * COLLECTION field (`CollectionPredicate`, `packages/core/src/data/filters.ts`).\n * Hasura can express collection membership — but WHICH operator is correct\n * depends on the column's Postgres type, and nothing this provider is given\n * declares it:\n *\n * - a `jsonb` column takes `_has_key` / `_has_keys_any` / `_has_keys_all`\n * (Postgres `?`, `?|`, `?&` — \"does this string exist as a top-level key or\n * array element\"), or `_contains` (`@>`);\n * - a Postgres ARRAY column (`text[]`) has no `_has_key*` at all; containment\n * is `_contains` / `_contained_in`.\n *\n * `ResourceMapping` declares `table`, `selectFields`, `pkType`, `int64Fields`\n * and the JSONB SPILL columns — nothing that distinguishes \"this column is\n * jsonb\" from \"this column is a Postgres array\" for an arbitrary filterable\n * field. Emitting one family for a column of the other type is either a\n * Hasura validation error or, worse, a valid query with different meaning.\n *\n * PROVENANCE, kept separate as the PocketBase truth table does:\n * - DOCUMENTED HASURA SEMANTICS settle which operator families exist and\n * which column types accept them (above).\n * - NOTHING IN THIS REPOSITORY settles which family any given resource needs.\n * All 37 captured live fixtures filter on scalar columns only — the\n * operators appearing across the whole corpus are `_eq` (16), `_and` (4),\n * `_or` (3), `_is_null` (2), `_in` (1), `_not` (1), and no capture touches a\n * collection column. `hasuraAdapter` implements three where-operators\n * (`_eq`, `_in`, `_is_null`), so it cannot settle it either.\n *\n * So this refuses, LOUDLY, rather than guessing. The way to implement it later\n * is to declare the column's shape on the mapping (e.g. a\n * `collectionFields: Record<string, 'jsonb' | 'array'>`) and translate per\n * declaration — the same registry-driven pattern `int64Fields` already uses —\n * ideally after capturing one real response per family.\n */\nconst UNEXPRESSIBLE_OPS: Readonly<Record<string, string>> = {\n has: 'a collection-membership test',\n hasAny: 'a collection-membership test',\n hasAll: 'a collection-membership test',\n};\n\nfunction unsupportedOperator(field: string, op: string): DataError {\n const why = UNEXPRESSIBLE_OPS[op];\n return {\n kind: 'capability',\n code: FILTER_OPERATOR_UNSUPPORTED_CODE,\n message: why\n ? `@burojs/hasura cannot express the '${op}' filter operator on '${field}': ${why}, whose Hasura encoding depends on whether the column is jsonb or a Postgres array — something no ResourceMapping field declares. Declare it and translate explicitly, or filter on a scalar column.`\n : `@burojs/hasura does not support the filter operator '${op}' (on '${field}').`,\n };\n}\n\n/**\n * Filter `scope` to keys whitelisted by `scopeFields`, drop nullish/empty\n * values, and translate to a Hasura where object using `_eq`.\n * Returns `undefined` when nothing applies.\n */\nexport function scopeToWhere(\n scope: Record<string, unknown>,\n scopeFields: string[],\n): Record<string, unknown> | undefined {\n const clauses: Array<Record<string, unknown>> = [];\n for (const key of scopeFields) {\n const v = scope[key];\n if (v == null || v === '') continue;\n clauses.push({ [key]: { _eq: v } });\n }\n if (clauses.length === 0) return undefined;\n if (clauses.length === 1) return clauses[0];\n return { _and: clauses };\n}\n\n/**\n * Combine two where objects with `_and`. Either or both may be undefined.\n */\nexport function mergeWhere(\n a: Record<string, unknown> | undefined,\n b: Record<string, unknown> | undefined,\n): Record<string, unknown> | undefined {\n if (!a) return b;\n if (!b) return a;\n return { _and: [a, b] };\n}\n\n/** Translate the native filter AST into a Hasura bool expression. */\nexport function filtersToWhere(\n filter?: FilterExpression<ErasedResourceHandle>,\n): Record<string, unknown> | undefined {\n if (!filter || typeof filter !== 'object') return undefined;\n // ── The empty-combinator rule (both branches below) ────────────────────────\n //\n // THE CLASS, stated once: this function uses `undefined` as a sentinel\n // meaning \"no constraint was expressed here — drop me\". A branchless\n // combinator is NOT that. `_and: []` is vacuously TRUE and `_or: []` is\n // vacuously FALSE, and dropping a node with a truth value is only sound in\n // an AND position, where a TRUE conjunct is genuinely absorbed. Under `not`,\n // or beside a disjunct in an `or`, dropping it changes what the query means.\n //\n // Both forms are therefore emitted EXPLICITLY, so they survive negation and\n // disjunction with their truth value intact. Checked on the SOURCE array\n // before mapping, because a combinator whose branches all mapped away\n // because NO VALUE was supplied for them really is the drop-me case. That\n // drop condition is a missing or `undefined` value — never `''`, which both\n // this package and `@burojs/pocketbase` translate.\n //\n // Provenance, kept separate on purpose:\n // - The two truth values are settled by CAPTURE, not by reasoning.\n // `packages/mock-kit/fixtures/hasura/where-or-empty.json` sends\n // `where: {_or: []}` to the live backend and comes back with `items: []`;\n // `where-and-empty.json` sends `{_and: []}` and comes back with the same\n // five rows `where-and-empty-baseline-no-filter.json` gets for no `where`\n // at all.\n // - How those two values COMPOSE under `_not`/`_or` is Hasura's documented\n // boolean semantics; no capture exercises a composed empty combinator.\n // The composed forms are verified end to end against `hasuraAdapter`\n // instead (`examples/marketplace-ops/tests/hasura-provider-contract.test.ts`),\n // whose own implementation was written from the GraphQL spec.\n //\n // The `or` half was fixed first (it was the one a capture caught directly);\n // the `and` half followed from sweeping the class rather than the instance —\n // before it, `{not: {and: []}}` matched every row where it must match none.\n if ('and' in filter) {\n if (filter.and.length === 0) return { _and: [] };\n const clauses = filter.and\n .map(filtersToWhere)\n .filter((item): item is Record<string, unknown> => item !== undefined);\n if (clauses.length === 0) return undefined;\n return clauses.length === 1 ? clauses[0] : { _and: clauses };\n }\n if ('or' in filter) {\n if (filter.or.length === 0) return { _or: [] };\n const clauses = filter.or\n .map(filtersToWhere)\n .filter((item): item is Record<string, unknown> => item !== undefined);\n if (clauses.length === 0) return undefined;\n return clauses.length === 1 ? clauses[0] : { _or: clauses };\n }\n if ('not' in filter) {\n const clause = filtersToWhere(filter.not);\n return clause === undefined ? undefined : { _not: clause };\n }\n if (!('field' in filter) || typeof filter.field !== 'string' || !('op' in filter))\n return undefined;\n\n const { field, op } = filter;\n if (op === 'isNull') return { [field]: { _is_null: true } };\n if (op === 'isNotNull') return { [field]: { _is_null: false } };\n // Missing / `undefined` value: no constraint was expressed, so drop.\n //\n // `''` is deliberately NOT in that set any more, and the two providers now\n // agree on it. It used to be dropped here, which meant `{name: {op: 'eq',\n // value: ''}}` — \"name IS the empty string\", an ordinary query — silently\n // matched every row, while `@burojs/pocketbase` emitted it. That is the\n // BLOCKER's own shape (one filter AST, two providers, different answers)\n // outside the branchless subclass.\n //\n // The drop existed for the empty-SEARCH-BOX idiom the two source apps had.\n // That idiom is already handled one layer up, in the only place every search\n // box in this framework goes through: `searchToFilter`\n // (`packages/core/src/data/search.ts`) returns `undefined` for an empty or\n // whitespace-only query and never builds a predicate at all. So suppressing\n // it a second time here bought nothing and cost the `eq: ''` case.\n if (!('value' in filter) || filter.value === undefined) return undefined;\n\n // NO `?? '_eq'` FALLBACK. An operator this provider cannot express must fail\n // loudly, not silently become equality against a value of the wrong shape.\n // The fallback is what turned `hasAny: []` — \"match nothing\" — into\n // `{tags: {_eq: []}}`, and it guaranteed that EVERY operator added to\n // `@burojs/core` in future would arrive here as a silent `_eq` rather than as\n // something someone noticed.\n //\n // WHERE IT FAILS: at request time, in the translator, not at construction.\n // That is forced rather than chosen — the operator is a property of the\n // FILTER, which arrives on the descriptor per request, and `ResourceMapping`\n // (the only thing available at construction) declares tables and columns, not\n // which operators a caller will use. There is nothing to validate at\n // construction time. It throws from `filtersToWhere` rather than returning a\n // sentinel so that every caller — `list`, `count`, `many`, the `fixedFilter`\n // merge — inherits the refusal without each having to check.\n const operator = OP_MAP[op];\n if (operator === undefined) throw unsupportedOperator(field, op);\n let value: unknown = filter.value;\n if (operator === '_ilike' || operator === '_like') {\n const text = String(value);\n value = op === 'startsWith' ? `${text}%` : op === 'endsWith' ? `%${text}` : `%${text}%`;\n }\n return { [field]: { [operator]: value } };\n}\n\nfunction coerceInt64Filter(\n filter: FilterExpression<ErasedResourceHandle> | undefined,\n fields: readonly string[] | undefined,\n): FilterExpression<ErasedResourceHandle> | undefined {\n if (!filter || !fields?.length) return filter;\n if ('and' in filter)\n return {\n and: filter.and.map(\n (entry) => coerceInt64Filter(entry, fields) as FilterExpression<ErasedResourceHandle>,\n ),\n };\n if ('or' in filter)\n return {\n or: filter.or.map(\n (entry) => coerceInt64Filter(entry, fields) as FilterExpression<ErasedResourceHandle>,\n ),\n };\n if ('not' in filter)\n return { not: coerceInt64Filter(filter.not, fields) as FilterExpression<ErasedResourceHandle> };\n if (\n 'field' in filter &&\n fields.includes(filter.field) &&\n 'value' in filter &&\n filter.value != null\n ) {\n const value = Array.isArray(filter.value) ? filter.value.map(String) : String(filter.value);\n return { ...filter, value } as FilterExpression<ErasedResourceHandle>;\n }\n return filter;\n}\n\nfunction hasuraError(error: unknown, signal: AbortSignal, fallback: string): DataError {\n if (isDataError(error)) return error;\n if (signal.aborted)\n return {\n kind: 'cancelled',\n code: 'request-aborted',\n message: 'Hasura request was aborted.',\n cause: error,\n };\n return {\n kind: 'transport',\n code: 'hasura-request-failed',\n message: error instanceof Error && error.message ? error.message : fallback,\n cause: error,\n };\n}\n\n/**\n * Resolve the Hasura aggregate root field for a mapping, or `null` when the\n * registry declares that none exists. Registry-driven on purpose: which tables\n * can be counted is a per-resource FACT, so it is declared once on the mapping\n * (`aggregate`) and read here — never a `if (resource === 'users')` chain in the\n * provider, which is the shape this codebase has been deleting.\n */\nexport function aggregateRoot(m: ResourceMapping): string | null {\n if (m.aggregate === false) return null;\n return typeof m.aggregate === 'string' ? m.aggregate : `${m.table}_aggregate`;\n}\n\n/**\n * Root field for a by-pk read. Declarative per resource for the same reason\n * {@link aggregateRoot} is: the name is a fact about the backend schema, not\n * something to branch on by resource name inside the provider.\n */\nexport function byPkRoot(m: ResourceMapping): string | null {\n if (m.byPkRoot === false) return null;\n return m.byPkRoot ?? `${m.table}_by_pk`;\n}\n\nfunction snapshotOperationRegistry(\n source: HasuraOperationRegistry | undefined,\n): Readonly<Record<string, Readonly<Record<string, HasuraCustomOperation>>>> {\n if (source === undefined) return Object.freeze({});\n const resources: Record<string, Readonly<Record<string, HasuraCustomOperation>>> = {};\n for (const [resource, operations] of Object.entries(source)) {\n const entries: Record<string, HasuraCustomOperation> = {};\n for (const [name, operation] of Object.entries(operations)) {\n entries[name] = Object.freeze({ ...operation });\n }\n resources[resource] = Object.freeze(entries);\n }\n return Object.freeze(resources);\n}\n\nfunction hasRegisteredOperationKind(\n operations: Readonly<Record<string, Readonly<Record<string, HasuraCustomOperation>>>>,\n kind: HasuraCustomOperation['kind'],\n): boolean {\n return Object.values(operations).some((byName) =>\n Object.values(byName).some((operation) => operation.kind === kind),\n );\n}\n\n/**\n * `''` is not a role — it is the ordinary shape of a missing env var, and it is\n * exactly how both source apps built their endpoint constants\n * (`import.meta.env.VITE_X ?? ''`). It is normalised to `null` — \"send no role\n * header\" — once, at the two places a role enters the provider.\n *\n * Why once and not at each use: the HTTP half gated on `!== null` and the\n * socket half on truthiness, so `defaultRole: ''` used to send an empty\n * `X-Hasura-Role` on every POST and NO header on the subscription — one config\n * value, two answers, in a package whose `endpoint` comment promises the two\n * halves \"can never drift apart\". Normalising at the boundary is what makes\n * that promise structural instead of a convention two call sites have to keep.\n *\n * `undefined` is handled by the CALLER, not here, because it means different\n * things in the two positions: on a mapping it means \"inherit the default\", on\n * the config it means \"no default\".\n */\nfunction normalizeRole(role: string | null | undefined): string | null {\n return role === undefined || role === null || role === '' ? null : role;\n}\n\nexport function createHasuraDataProvider(config: HasuraDataProviderConfig): DataProvider {\n const endpoint = config.endpoint ?? DEFAULT_HASURA_ENDPOINT;\n const defaultRole = normalizeRole(config.defaultRole);\n const operations = snapshotOperationRegistry(config.operations);\n const hasCustomQueries = hasRegisteredOperationKind(operations, 'query');\n const hasCustomMutations = hasRegisteredOperationKind(operations, 'mutation');\n\n async function gql<T>(\n query: string,\n variables: Record<string, unknown> | undefined,\n role: string | null | undefined,\n signal: AbortSignal,\n ): Promise<T> {\n try {\n const request = async (token: string) => {\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${token}`,\n };\n // Divergence 5 of 7, role half (see `endpoint.ts` for the endpoint\n // half). `defaultRole` is what both apps imported from their own\n // `env.ts` as `HASURA_ROLE` — playground's `'company-admin'`,\n // l2-web-ui's `'operator'`, each an app deployment fact. It is\n // configuration here, defaulting to `null` (no role header at all).\n // A mapping `role` of `undefined` inherits it; an explicit `null`\n // suppresses the header for that one resource.\n const effectiveRole = role === undefined ? defaultRole : normalizeRole(role);\n if (effectiveRole !== null) headers['X-Hasura-Role'] = effectiveRole;\n // Divergence 5 of 7, endpoint half: both apps interpolated their own\n // app-owned env constant into a URL here. The package posts to the\n // configured `endpoint` and imports no app module.\n // Resolved HERE, per call — not once at construction. Captured at\n // construction, a `fetch` installed AFTERWARDS is unreachable for the\n // life of the provider: a provider built at module scope, before an MSW\n // server or worker has started, silently escapes the mock and goes to\n // the real network instead — and nothing throws. `@burojs/pocketbase`'s\n // `auth-provider.ts` carries the same note; it had shipped this exact\n // bug once and it stayed invisible until something needed real fixture\n // data from it. The three provider packages agree on this.\n const fetchImpl = config.fetchImpl ?? fetch;\n return fetchImpl(endpoint, {\n method: 'POST',\n headers,\n body: JSON.stringify({ query, variables }),\n signal,\n });\n };\n\n let token = await config.getToken();\n if (!token)\n throw {\n kind: 'auth',\n code: NOT_AUTHENTICATED_CODE,\n message: 'Not authenticated.',\n } satisfies DataError;\n let res = await request(token);\n if (res.status === 401 && config.recoverAuth && (await config.recoverAuth())) {\n token = await config.getToken();\n if (!token)\n throw {\n kind: 'auth',\n code: NOT_AUTHENTICATED_CODE,\n message: 'Not authenticated.',\n } satisfies DataError;\n res = await request(token);\n }\n if (!res.ok)\n throw {\n kind: 'transport',\n code: 'graphql-http-error',\n message: `GraphQL HTTP ${res.status}`,\n status: res.status,\n } satisfies DataError;\n const body = (await res.json()) as GqlResponse<T>;\n if (body.errors?.length)\n throw {\n kind: 'protocol',\n code: 'graphql-error',\n message: body.errors.map((e) => e.message).join('; '),\n details: body.errors,\n } satisfies DataError;\n if (body.data === undefined)\n throw {\n kind: 'protocol',\n code: 'empty-graphql-response',\n message: 'Empty GraphQL response.',\n } satisfies DataError;\n return body.data;\n } catch (error) {\n throw hasuraError(error, signal, 'Hasura request failed.');\n }\n }\n\n function mapping(resource: string): ResourceMapping {\n const m = config.resources[resource];\n if (!m)\n throw {\n kind: 'configuration',\n code: 'unknown-resource',\n message: `Unknown resource: ${resource}`,\n } satisfies DataError;\n return m;\n }\n\n function registeredOperation(\n resource: string,\n operation: string,\n kind: HasuraCustomOperation['kind'],\n ): HasuraCustomOperation {\n const registered = operations[resource]?.[operation];\n if (registered === undefined || registered.kind !== kind) {\n throw {\n kind: 'capability',\n code: 'hasura-custom-operation-unsupported',\n message: `Hasura ${kind} operation '${operation}' is not declared for '${resource}'.`,\n } satisfies DataError;\n }\n return registered;\n }\n\n async function executeCustomOperation(\n resource: string,\n operationName: string,\n input: unknown,\n kind: HasuraCustomOperation['kind'],\n signal: AbortSignal,\n ): Promise<unknown> {\n const operation = registeredOperation(resource, operationName, kind);\n // Do not inspect descriptor providerOptions here. The operation's static\n // registry entry is the only source of GraphQL text and variable mapping.\n const result = await gql(\n operation.document,\n operation.variables(input),\n operation.role ?? config.resources[resource]?.role,\n signal,\n );\n return operation.mapResult?.(result) ?? result;\n }\n\n /**\n * The ONE composition of a list-shaped `where`, shared by `getList` and\n * `getCount`. Four things go in, in this order:\n * 1. int64 coercion — ClickHouse-sourced columns typed `int64` are rejected\n * as numbers, so those filter values become strings (see `int64Fields`);\n * 2. the user's filters (`filtersToWhere`);\n * 3. the active sidebar scope, whitelisted by `scopeFields`, unless the\n * caller opted out with `meta.ignoreScope`;\n * 4. the mapping's `fixedFilter` (per-type / projection resources), ANDed in\n * LAST so the user still filters WITHIN the slice.\n *\n * ⚠️ `getCount` MUST NOT re-derive this from `filtersToWhere` alone. Scope and\n * `fixedFilter` are invisible to the caller — a resource declaring\n * `scopeFields: ['pg', 'location_id']` would have a filters-only count report\n * the total across every product group and location. A confidently wrong\n * number is strictly worse than no number, which is what the list already\n * degrades to.\n */\n function composeListWhere(\n m: ResourceMapping,\n descriptor: HasuraScopedQuery,\n context: DataOperationContext,\n ): Record<string, unknown> | undefined {\n const userWhere = filtersToWhere(coerceInt64Filter(descriptor.filter, m.int64Fields));\n\n // A query may opt OUT of scope via `meta.ignoreScope` when it must search\n // the whole table regardless of the active sidebar scope — e.g. resolving a\n // product by its globally-unique GTIN, which shouldn't 404 just because the\n // sidebar is filtered to a different product group.\n const ignoreScope = descriptor.providerOptions?.ignoreScope === true;\n const sessionScope =\n context.session.scopeKey !== null &&\n typeof context.session.scopeKey === 'object' &&\n !Array.isArray(context.session.scopeKey)\n ? (context.session.scopeKey as Record<string, unknown>)\n : {};\n const scope = ignoreScope ? {} : { ...sessionScope, ...(config.getScope?.(context) ?? {}) };\n const scopeWhere = scopeToWhere(scope, m.scopeFields ?? []);\n\n return mergeWhere(mergeWhere(userWhere, scopeWhere), m.fixedFilter);\n }\n\n /**\n * Issue the aggregate COUNT for a mapping against an already-composed `where`.\n * Shared by `getList`'s inline count and the on-demand `getCount` so the two\n * emit byte-identical queries. `root` comes from {@link aggregateRoot}; the\n * caller has already established that one exists.\n */\n async function runAggregateCount(\n m: ResourceMapping,\n root: string,\n where: Record<string, unknown> | undefined,\n signal: AbortSignal,\n ): Promise<number> {\n const aggWhereArg = where ? '($where: ' + m.table + '_bool_exp)' : '';\n const aggWhereParam = where ? '(where: $where)' : '';\n const metaQuery = `query Count_${m.table} ${aggWhereArg} {\n meta: ${root} ${aggWhereParam} { aggregate { count } }\n }`;\n const aggVars: Record<string, unknown> = {};\n if (where) aggVars['where'] = where;\n const metaData = await gql<{ meta: { aggregate: { count: number } } }>(\n metaQuery,\n where ? aggVars : undefined,\n m.role,\n signal,\n );\n return metaData.meta.aggregate.count;\n }\n\n /**\n * Upsert the data-body sibling row for a parent record. Uses Hasura's\n * `insert_<table>_one … on_conflict` so the same call inserts (create) or\n * replaces (edit) the single FK-keyed row. `constraint` / `column`\n * are unquoted GraphQL enum literals — they come from static mapping config,\n * never user input, so string-interpolating them is safe.\n */\n async function upsertDataBody(\n db: DataBodyConfig,\n parentId: string | number,\n body: Record<string, unknown>,\n role: string | null | undefined,\n signal: AbortSignal,\n ): Promise<void> {\n const mutation = `mutation UpsertDataBody($object: ${db.table}_insert_input!) {\n result: insert_${db.table}_one(\n object: $object,\n on_conflict: { constraint: ${db.constraint}, update_columns: [${db.column}] }\n ) { ${db.fk} }\n }`;\n await gql(mutation, { object: { [db.fk]: parentId, [db.column]: body } }, role, signal);\n }\n\n function mutationRecord(\n m: ResourceMapping,\n idField: string,\n item: unknown,\n resource: string,\n expectedId?: string | number,\n ) {\n if (item === null || typeof item !== 'object' || Array.isArray(item)) {\n throw {\n kind: 'protocol',\n code: 'record-not-found',\n message: `Not found: ${resource}`,\n } satisfies DataError;\n }\n const record = item as Record<string, unknown>;\n const id = record[m.pkField ?? idField];\n if (typeof id !== 'string' && (typeof id !== 'number' || !Number.isFinite(id))) {\n throw {\n kind: 'protocol',\n code: 'mutation-record-id-missing',\n message: `Mutation for '${resource}' returned no valid '${m.pkField ?? idField}'.`,\n } satisfies DataError;\n }\n if (expectedId !== undefined && id !== expectedId) {\n throw {\n kind: 'protocol',\n code: 'unexpected-record-id',\n message: `Mutation for '${resource}' returned '${String(id)}' instead of '${String(expectedId)}'.`,\n } satisfies DataError;\n }\n // Mutations select the declared table fields but do not re-read relation\n // data bodies or server-computed presentation values. Marking them partial\n // makes React invalidate dependent reads rather than write an incomplete\n // record into a one-record cache.\n return { kind: 'record' as const, id, record: item, completeness: 'partial' as const };\n }\n\n async function readMutationRecord(\n m: ResourceMapping,\n id: string | number,\n signal: AbortSignal,\n ): Promise<unknown> {\n const fields = m.selectFields.join(' ');\n const pkType = m.pkType ?? 'bigint';\n const pkField = m.pkField ?? 'id';\n const root = byPkRoot(m);\n if (m.fixedFilter || root === null) {\n const where = mergeWhere({ [pkField]: { _eq: id } }, m.fixedFilter);\n const query = `query One_${m.table}($where: ${m.table}_bool_exp) {\n items: ${m.table}(where: $where, limit: 1) { ${fields} }\n }`;\n const data = await gql<{ items: unknown[] }>(query, { where }, m.role, signal);\n return data.items?.[0] ?? null;\n }\n // DISTILLATION FIX — not a port. Neither source app had fixed this branch\n // when the package was distilled (both were backported from here later in\n // the same branch, 99e670aa; the earlier \"NEITHER source app fixed this\"\n // wording went stale four commits after it was written).\n // l2-web-ui fixed the identical hardcoded-`id` bug in `one()` (see\n // divergence 1 of 7 there) and left this direct-root branch — reached by\n // `updateOne` when the `_set` is empty, i.e. a data-body-only edit that\n // just re-reads the row — still emitting `${root}(id: $id)`. For any\n // mapping whose `pkField` is not literally `id` that argument name does\n // not exist on the by-pk root, so Hasura 400s. Same bug class, same fix,\n // now applied in both places.\n const query = `query One_${m.table}($id: ${pkType}!) {\n item: ${root}(${pkField}: $id) { ${fields} }\n }`;\n const data = await gql<{ item: unknown }>(query, { id }, m.role, signal);\n return data.item;\n }\n\n return defineDataProvider({\n queries: {\n async list(descriptor, context) {\n const m = mapping(descriptor.resource);\n if (descriptor.pagination?.kind === 'cursor') {\n throw {\n kind: 'capability',\n code: 'cursor-pagination-unsupported',\n message: 'Hasura provider supports offset pagination only.',\n } satisfies DataError;\n }\n const limit =\n descriptor.pagination?.kind === 'offset' ? descriptor.pagination.pageSize : 25;\n const page = descriptor.pagination?.kind === 'offset' ? descriptor.pagination.page : 1;\n const offset = (page - 1) * limit;\n\n // int64 coercion + user filters + scope + fixedFilter, composed exactly\n // once — `getCount` calls the SAME helper so an on-demand count can never\n // describe a different set of rows than the page it sits under.\n const where = composeListWhere(m, descriptor, context);\n\n // Sort: take native sort expressions if present, fall back to mapping default.\n // Guard against entries with falsy `field` — Hasura would reject the\n // resulting `[{undefined: asc}]` and bring down the whole query.\n const sorters = descriptor.sort?.filter((s) => s.field);\n let orderByExpr: string;\n if (sorters && sorters.length > 0) {\n // Hasura order_by accepts an array of single-field bool exps.\n // We emit `[{field1: asc}, {field2: desc}]` — exact spec for multi-sort.\n orderByExpr = `[${sorters.map((s) => `{${s.field}: ${s.direction}}`).join(', ')}]`;\n } else {\n const defaultField = m.orderByField ?? 'id';\n orderByExpr = `{${defaultField}: desc}`;\n }\n\n const fields = m.selectFields.join(' ');\n const whereArg = where ? ', $where: ' + m.table + '_bool_exp' : '';\n const whereParam = where ? ', where: $where' : '';\n const itemsQuery = `query List_${m.table}($limit: Int, $offset: Int${whereArg}) {\n items: ${m.table}(limit: $limit, offset: $offset, order_by: ${orderByExpr}${whereParam}) { ${fields} }\n }`;\n const itemsVars: Record<string, unknown> = { limit, offset };\n if (where) itemsVars['where'] = where;\n const itemsData = await gql<{ items: unknown[] }>(\n itemsQuery,\n itemsVars,\n m.role,\n context.signal,\n );\n // `total` is OMITTED (undefined) when we cannot honestly produce a count:\n // `noAggregate` tables skip the count deliberately (a COUNT over ~29M rows\n // took ~55 s and hung the page in one of the source apps). The list's\n // unknown-total contract then takes over — range without a grand total,\n // Next while the page is full, no jump-to-end. NEVER substitute\n // `items.length`: that is the CURRENT PAGE's length, and reporting it as\n // the total collapses the list to one page.\n let total: number | undefined;\n const listAggRoot = aggregateRoot(m);\n if (!m.noAggregate && listAggRoot) {\n try {\n total = await runAggregateCount(m, listAggRoot, where, context.signal);\n } catch (err) {\n // A TRANSIENT failure on a countable table. Keeping the page length\n // here would be the same lie, so `total` stays undefined and the list\n // degrades to unknown-total — but log it, because (unlike\n // `noAggregate`) this is an error, not a design decision.\n console.warn(`[hasura] count failed for ${m.table}; rendering unknown-total`, err);\n }\n }\n // jsonb-spill inverse per row: flatten head/meta so per-type list columns\n // (batch_number, releaseMethodType, …) read as flat fields. Base columns\n // win; a list whose columns are all base is unaffected (the extra\n // flattened keys are simply never rendered).\n const spill = m.jsonbSpill;\n const items = spill\n ? itemsData.items.map((it) => flattenJsonbSpill(it, spill))\n : itemsData.items;\n return { data: items, total };\n },\n\n /**\n * On-demand row count — the answer to \"how many are there?\" on the lists\n * that page without a grand total (`noAggregate`). Never fired implicitly:\n * one source app measured ~55 s for a single COUNT, which is exactly why\n * the list stopped issuing one on every page.\n *\n * `{ total: null }` means \"not countable here at all\" — the registry says\n * this table has no aggregate root, or the resource isn't mapped by this\n * provider. It is a DECISION, and the UI latches the affordance off for the\n * session. A transient backend failure REJECTS instead (it propagates out of\n * `gql`), so a retry stays possible; never conflate the two.\n *\n * The `where` comes from the same {@link composeListWhere} `getList` uses —\n * same filters, same scope, same `fixedFilter` — so the number always\n * describes the rows the list is paging through.\n */\n async count(descriptor, context): Promise<CountResult> {\n // Deny by default: `mapping()` THROWS on an unmapped resource, and a\n // count is an optional nicety — it must degrade to \"unavailable\", never\n // take the page down.\n const m = config.resources[descriptor.resource];\n if (!m) return { total: null };\n const root = aggregateRoot(m);\n if (!root) return { total: null };\n return {\n total: await runAggregateCount(\n m,\n root,\n composeListWhere(m, descriptor, context),\n context.signal,\n ),\n };\n },\n\n async many(descriptor, context) {\n const m = mapping(descriptor.resource);\n if (descriptor.ids.length === 0) return { data: [] };\n\n const pkField = m.pkField ?? 'id';\n const idsWhere = { [pkField]: { _in: descriptor.ids } };\n const where = mergeWhere(\n idsWhere,\n composeListWhere(m, descriptor as unknown as HasuraScopedQuery, context),\n );\n const fields = m.selectFields.join(' ');\n const query = `query Many_${m.table}($where: ${m.table}_bool_exp) {\n items: ${m.table}(where: $where) { ${fields} }\n }`;\n const data = await gql<{ items: unknown[] }>(query, { where }, m.role, context.signal);\n const spill = m.jsonbSpill;\n const items = spill ? data.items.map((item) => flattenJsonbSpill(item, spill)) : data.items;\n return { data: items };\n },\n\n async one(descriptor, context) {\n const m = mapping(descriptor.resource);\n // When a data body lives in a sibling table, nested-select it alongside the\n // row (`document_data { data }`) so the whole record loads in one round trip.\n const dbSelect = m.dataBody ? ` ${m.dataBody.relationship} { ${m.dataBody.column} }` : '';\n const fields = m.selectFields.join(' ') + dbSelect;\n const pkType = m.pkType ?? 'bigint';\n const pkField = m.pkField ?? 'id';\n let item: unknown;\n const root = byPkRoot(m);\n if (m.fixedFilter || root === null) {\n // `<table>_by_pk` accepts no `where`, so a fixed-filter resource fetches\n // its single row via a `where`-scoped `limit: 1` query: the id must ALSO\n // satisfy the fixed slice, so a row of the wrong slice (e.g. a movement\n // id under a work-orders resource) resolves to null → Not found.\n const where = mergeWhere({ [pkField]: { _eq: descriptor.id } }, m.fixedFilter);\n const query = `query One_${m.table}($where: ${m.table}_bool_exp) {\n items: ${m.table}(where: $where, limit: 1) { ${fields} }\n }`;\n const data = await gql<{ items: unknown[] }>(query, { where }, m.role, context.signal);\n item = data.items?.[0] ?? null;\n } else {\n // DISTILLATION NOTE (divergence 1 of 7 — bug fix, l2-web-ui only).\n // The by-pk root's argument is named after the RESOURCE'S pk field\n // (`pkField`, default `'id'`) — not always literally `id`:\n // `marking_codes_by_pk(code: $id)`, not `marking_codes_by_pk(id: $id)`.\n // l2-web-ui shipped this fix (with three regression tests, ported into\n // this package's suite); playground still hardcoded `id` here and\n // would 400 for any mapping with a non-`id` `pkField`. `many()` /\n // `updateOne` / `deleteOne` already parametrized it — the two direct\n // by-pk READ branches (here and `readMutationRecord`) were the\n // stragglers.\n const query = `query One_${m.table}($id: ${pkType}!) {\n item: ${root}(${pkField}: $id) { ${fields} }\n }`;\n const data = await gql<{ item: unknown }>(\n query,\n { id: descriptor.id },\n m.role,\n context.signal,\n );\n item = data.item;\n }\n if (item == null)\n throw {\n kind: 'protocol',\n code: 'record-not-found',\n message: `Not found: ${descriptor.resource}/${descriptor.id}`,\n } satisfies DataError;\n // jsonb-spill inverse: spread the fetched head/meta blobs back onto the\n // flat record so edit forms + the show page read `regulatory_system` etc.\n // as flat fields. Base columns win on collision; the raw head/meta objects\n // are kept (so update can merge them, and tabs that want the blob still\n // have it). Same helper flattens getList rows.\n let result: unknown = m.jsonbSpill ? flattenJsonbSpill(item, m.jsonbSpill) : item;\n // data-body inverse: spread the sibling `data` blob onto the flat record\n // (so the form reads `items` / `products` top-level) and DROP the raw\n // relationship object so it can't round-trip back into `head` on save.\n if (m.dataBody && result && typeof result === 'object') {\n const rec = { ...(result as Record<string, unknown>) };\n const sibling = rec[m.dataBody.relationship];\n const body =\n sibling && typeof sibling === 'object'\n ? (sibling as Record<string, unknown>)[m.dataBody.column]\n : null;\n delete rec[m.dataBody.relationship];\n result =\n body && typeof body === 'object'\n ? { ...rec, ...(body as Record<string, unknown>) }\n : rec;\n }\n return { data: result };\n },\n\n ...(hasCustomQueries\n ? {\n async custom(descriptor, context) {\n return executeCustomOperation(\n descriptor.resource,\n descriptor.operation,\n descriptor.input,\n 'query',\n context.signal,\n );\n },\n }\n : {}),\n },\n mutations: {\n async createOne(descriptor, context) {\n const m = mapping(descriptor.resource);\n const fields = m.selectFields.join(' ');\n const rawInput = descriptor.input as Record<string, unknown>;\n let mainInput = rawInput;\n let dataBody: Record<string, unknown> | undefined;\n if (m.dataBody) {\n const split = partitionDataBody(rawInput, m.dataBody);\n mainInput = split.rest;\n dataBody = split.hasDataBody ? split.dataBody : undefined;\n }\n const object = m.jsonbSpill\n ? partitionJsonbSpill(mainInput, m.jsonbSpill, m.selectFields)\n : mainInput;\n const query = `mutation Create_${m.table}($object: ${m.table}_insert_input!) {\n item: insert_${m.table}_one(object: $object) { ${fields} }\n }`;\n const data = await gql<{ item: unknown }>(query, { object }, m.role, context.signal);\n const result = mutationRecord(m, descriptor.idField, data.item, descriptor.resource);\n if (m.dataBody && dataBody)\n await upsertDataBody(m.dataBody, result.id, dataBody, m.role, context.signal);\n return result;\n },\n\n async updateOne(descriptor, context) {\n const m = mapping(descriptor.resource);\n const fields = m.selectFields.join(' ');\n const rawInput = descriptor.input as Record<string, unknown>;\n let mainInput = rawInput;\n let dataBody: Record<string, unknown> | undefined;\n if (m.dataBody) {\n const split = partitionDataBody(rawInput, m.dataBody);\n mainInput = split.rest;\n dataBody = split.hasDataBody ? split.dataBody : undefined;\n }\n const set = m.jsonbSpill\n ? partitionJsonbSpill(mainInput, m.jsonbSpill, m.selectFields)\n : mainInput;\n const pkField = m.pkField ?? descriptor.idField;\n // DISTILLATION NOTE (divergence 2 of 7 — feature, l2-web-ui only, inert\n // unless asked for). Optimistic-concurrency precondition, added by\n // l2-web-ui (a shop-floor MES) which needs last-write-wins conflict\n // detection on its config/line records; playground never needed it and\n // has no equivalent.\n // Carried here as an OPT-IN: with no `providerOptions.ifUpdatedAt` the\n // two `!= null` checks below are the only added work and every emitted\n // query is byte-identical to the version without this feature.\n //\n // `!= null` (not `!== undefined`) is load-bearing and is itself a\n // shipped bug fix: a caller seeded from a row whose `updated_at` really\n // was `null` (a `string | null` column) passed the `!== undefined`\n // guard, built `{ updated_at: { _eq: null } }`, which Hasura's `_eq`\n // matches NEVER, so every save threw the same `stale-record` conflict a\n // real staleness would and locked that operator out permanently. Both\n // `undefined` and `null` must mean \"no precondition\".\n const ifUpdatedAt = (\n descriptor.providerOptions as { ifUpdatedAt?: string | null } | undefined\n )?.ifUpdatedAt;\n let item: unknown;\n if (Object.keys(set).length === 0) {\n item = await readMutationRecord(m, descriptor.id, context.signal);\n } else if (m.fixedFilter || ifUpdatedAt != null) {\n let where = mergeWhere({ [pkField]: { _eq: descriptor.id } }, m.fixedFilter);\n if (ifUpdatedAt != null) where = mergeWhere(where, { updated_at: { _eq: ifUpdatedAt } });\n const query = `mutation Update_${m.table}($where: ${m.table}_bool_exp!, $set: ${m.table}_set_input!) {\n result: update_${m.table}(where: $where, _set: $set) { affected_rows returning { ${fields} } }\n }`;\n const data = await gql<{ result: { affected_rows: number; returning: unknown[] } }>(\n query,\n { where, set },\n m.role,\n context.signal,\n );\n // A precondition that matches no row must never look like a silent\n // no-op success — whether the server signals it via `affected_rows`\n // or via an empty `returning`, either shape is the same \"someone else\n // changed this record\" fact and must reach React as a `DataError`.\n if (\n ifUpdatedAt != null &&\n ((data.result.affected_rows ?? 0) === 0 || (data.result.returning?.length ?? 0) === 0)\n ) {\n throw {\n kind: 'conflict',\n code: 'stale-record',\n message: `Update for '${descriptor.resource}/${descriptor.id}' matched no row: the record was changed since it was loaded.`,\n } satisfies DataError;\n }\n item = data.result.returning?.[0] ?? null;\n } else {\n const pkType = m.pkType ?? 'bigint';\n const query = `mutation Update_${m.table}($id: ${pkType}!, $set: ${m.table}_set_input!) {\n item: update_${m.table}_by_pk(pk_columns: {${pkField}: $id}, _set: $set) { ${fields} }\n }`;\n const data = await gql<{ item: unknown }>(\n query,\n { id: descriptor.id, set },\n m.role,\n context.signal,\n );\n item = data.item;\n }\n const result = mutationRecord(\n m,\n descriptor.idField,\n item,\n descriptor.resource,\n descriptor.id,\n );\n if (m.dataBody && dataBody)\n await upsertDataBody(m.dataBody, result.id, dataBody, m.role, context.signal);\n return result;\n },\n\n async deleteOne(descriptor, context) {\n const m = mapping(descriptor.resource);\n const fields = m.selectFields.join(' ');\n const pkField = m.pkField ?? descriptor.idField;\n let item: unknown;\n if (m.fixedFilter) {\n const where = mergeWhere({ [pkField]: { _eq: descriptor.id } }, m.fixedFilter);\n const query = `mutation Delete_${m.table}($where: ${m.table}_bool_exp!) {\n result: delete_${m.table}(where: $where) { affected_rows returning { ${fields} } }\n }`;\n const data = await gql<{ result: { returning: unknown[] } }>(\n query,\n { where },\n m.role,\n context.signal,\n );\n item = data.result.returning?.[0] ?? null;\n } else {\n const pkType = m.pkType ?? 'bigint';\n const query = `mutation Delete_${m.table}($id: ${pkType}!) {\n item: delete_${m.table}_by_pk(${pkField}: $id) { ${fields} }\n }`;\n const data = await gql<{ item: unknown }>(\n query,\n { id: descriptor.id },\n m.role,\n context.signal,\n );\n item = data.item;\n }\n mutationRecord(m, descriptor.idField, item, descriptor.resource, descriptor.id);\n return { kind: 'identity' as const, id: descriptor.id };\n },\n\n ...(hasCustomMutations\n ? {\n async custom(descriptor, context) {\n return executeCustomOperation(\n descriptor.resource,\n descriptor.operation,\n descriptor.input,\n 'mutation',\n context.signal,\n );\n },\n }\n : {}),\n },\n live: createHasuraLiveProvider({\n resources: config.resources,\n getToken: config.getToken,\n endpoint,\n role: defaultRole,\n }),\n });\n}\n"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@burojs/hasura",
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"license": "MIT",
|
|
5
|
+
"description": "Buro: Hasura GraphQL data provider and live (subscription) provider",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"main": "./dist/index.cjs",
|
|
8
|
+
"module": "./dist/index.js",
|
|
9
|
+
"types": "./dist/index.d.ts",
|
|
10
|
+
"exports": {
|
|
11
|
+
".": {
|
|
12
|
+
"import": {
|
|
13
|
+
"types": "./dist/index.d.ts",
|
|
14
|
+
"default": "./dist/index.js"
|
|
15
|
+
},
|
|
16
|
+
"require": {
|
|
17
|
+
"types": "./dist/index.d.cts",
|
|
18
|
+
"default": "./dist/index.cjs"
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
"./package.json": "./package.json"
|
|
22
|
+
},
|
|
23
|
+
"files": [
|
|
24
|
+
"dist",
|
|
25
|
+
"README.md"
|
|
26
|
+
],
|
|
27
|
+
"dependencies": {
|
|
28
|
+
"graphql-ws": "^6.1.0",
|
|
29
|
+
"@burojs/core": "0.2.0"
|
|
30
|
+
},
|
|
31
|
+
"devDependencies": {
|
|
32
|
+
"tsup": "^8.3.0",
|
|
33
|
+
"typescript": "^5.5.0",
|
|
34
|
+
"vitest": "^2.1.0",
|
|
35
|
+
"@burojs/mock-kit": "0.2.0",
|
|
36
|
+
"@burojs/tooling-eslint": "0.0.0",
|
|
37
|
+
"@burojs/tooling-tsconfig": "0.0.0"
|
|
38
|
+
},
|
|
39
|
+
"publishConfig": {
|
|
40
|
+
"access": "public"
|
|
41
|
+
},
|
|
42
|
+
"scripts": {
|
|
43
|
+
"build": "tsup",
|
|
44
|
+
"dev": "tsup --watch",
|
|
45
|
+
"typecheck": "tsc --noEmit",
|
|
46
|
+
"typecheck:tests": "tsc -p tsconfig.test.json"
|
|
47
|
+
}
|
|
48
|
+
}
|