@gleanql/client 0.1.8 → 0.1.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.mts CHANGED
@@ -601,6 +601,22 @@ interface RunMutationOptions<TData = unknown> {
601
601
  * for logical failures — inspect `ok`/`userErrors`/`errors`.
602
602
  */
603
603
  declare function runMutation<TData = Record<string, unknown>>(options: RunMutationOptions<TData>): Promise<MutationResult<TData>>;
604
+ /**
605
+ * Server-side mutation execution: run a compiled mutation through the adapter and
606
+ * surface `userErrors`, WITHOUT a client cache/runtime. This is the core of the
607
+ * server `mutate()` primitive — server actions, webhooks, jobs, and proxy handlers
608
+ * mutate Shopify without a hydrated read graph. Never rejects for logical failures;
609
+ * inspect `ok`/`userErrors`/`errors`.
610
+ */
611
+ declare function runServerMutation<TData = Record<string, unknown>>(params: {
612
+ readonly operation: {
613
+ readonly name: string;
614
+ readonly document: string;
615
+ };
616
+ readonly variables: Record<string, unknown>;
617
+ readonly adapter: GraphClientAdapter;
618
+ readonly context: GraphRequestContext;
619
+ }): Promise<MutationResult<TData>>;
604
620
  /** Invalidate a record by graph value (proxy) or raw ref — next read re-fetches. */
605
621
  declare function invalidateValue(runtime: GraphRuntime, value: GraphRef | unknown): void;
606
622
  /** One rule for stringifying unknown errors, shared across hooks and transports. */
@@ -735,6 +751,13 @@ interface GraphIntegration<Ctx extends Record<string, unknown>> {
735
751
  getGraph(requestInfo: RequestInfo<Ctx>): BoundGraph;
736
752
  /** The `graph.mutate.*` namespace for this request (throws if not preloaded). */
737
753
  getMutator(requestInfo: RequestInfo<Ctx>): BoundMutations;
754
+ /**
755
+ * Run a compiled mutation by name, server-side, WITHOUT a preloaded read graph —
756
+ * the executor behind the server `mutate()` primitive (server actions, webhooks,
757
+ * jobs). Resolves the op, maps `vars` via its factory, runs it through the
758
+ * adapter, and surfaces `userErrors`. Never rejects; inspect `ok`/`userErrors`.
759
+ */
760
+ mutate<TData = unknown>(opName: string, vars: unknown, context?: GraphRequestContext): Promise<MutationResult<TData>>;
738
761
  /** Invalidate a graph value / ref in this request's cache (refetch on next read). */
739
762
  invalidate(requestInfo: RequestInfo<Ctx>, value: GraphRef | unknown): void;
740
763
  /** Read the full active request state (runtime, roots, variables, ...). */
@@ -951,4 +974,4 @@ interface PersistedResolverOptions {
951
974
  }
952
975
  declare function createPersistedResolver(operations: Readonly<Record<string, PersistedLookupOperation>>, options?: PersistedResolverOptions): (body: PersistedRequestBody) => PersistedResolution;
953
976
  //#endregion
954
- export { ActiveGraph, ActiveRequestGraph, BindGraphOptions, BoundGraph, BoundMutations, BuildRouteContextOptions, CacheResolution, CompiledOperation, CreateMutatorOptions, FetchAdapterOptions, FieldLookup, FieldValue, GRAPH_REF, GRAPH_TRAIL, GRAPH_TYPE, GraphBinding, GraphCache, GraphClientAdapter, GraphHydrationPayload, GraphIntegration, GraphIntegrationOptions, GraphOperation, GraphPagePointer, GraphQLError, GraphRef, GraphRequestContext, GraphResult, GraphRouteContext, GraphRuntime, GraphRuntimeOptions, GraphScope, GraphSelection, GraphWsAdapterOptions, GraphWsClient, GraphWsPayload, GraphWsSink, HydrateGraphOptions, HydratedGraph, KeyOf, MissingFieldMode, MissingFieldRead, MissingFieldResult, MutateFn, MutationOperationLike, MutationResult, MutationTransaction, PathStep, PersistedLookupOperation, PersistedRequestBody, PersistedResolution, PersistedResolverOptions, PushPullIterator, RequestInfo, RunMutationOptions, RunRouteOptions, RunRouteResult, SerializeGraphOptions, UserError, absorbHydrationPayload, bindGraph, bindScope, buildRouteContext, createFetchAdapter, createGraphIntegration, createGraphProxy, createGraphWsAdapter, createMutator, createPersistedResolver, errorMessage, graphHydrationScriptContent, hydrateGraph, invalidateValue, isGraphRef, normalizeValue, pagePointer, persistRootLinks, pushPullIterator, readGraphHydrationPayload, refetch, renderGraphHydrationScript, resolveFromCache, responseKeyCandidates, result, runMutation, runRoute, seedResult, selectionOf, serializeGraph, setReadTracker, toArgMap, trailOf };
977
+ export { ActiveGraph, ActiveRequestGraph, BindGraphOptions, BoundGraph, BoundMutations, BuildRouteContextOptions, CacheResolution, CompiledOperation, CreateMutatorOptions, FetchAdapterOptions, FieldLookup, FieldValue, GRAPH_REF, GRAPH_TRAIL, GRAPH_TYPE, GraphBinding, GraphCache, GraphClientAdapter, GraphHydrationPayload, GraphIntegration, GraphIntegrationOptions, GraphOperation, GraphPagePointer, GraphQLError, GraphRef, GraphRequestContext, GraphResult, GraphRouteContext, GraphRuntime, GraphRuntimeOptions, GraphScope, GraphSelection, GraphWsAdapterOptions, GraphWsClient, GraphWsPayload, GraphWsSink, HydrateGraphOptions, HydratedGraph, KeyOf, MissingFieldMode, MissingFieldRead, MissingFieldResult, MutateFn, MutationOperationLike, MutationResult, MutationTransaction, PathStep, PersistedLookupOperation, PersistedRequestBody, PersistedResolution, PersistedResolverOptions, PushPullIterator, RequestInfo, RunMutationOptions, RunRouteOptions, RunRouteResult, SerializeGraphOptions, UserError, absorbHydrationPayload, bindGraph, bindScope, buildRouteContext, createFetchAdapter, createGraphIntegration, createGraphProxy, createGraphWsAdapter, createMutator, createPersistedResolver, errorMessage, graphHydrationScriptContent, hydrateGraph, invalidateValue, isGraphRef, normalizeValue, pagePointer, persistRootLinks, pushPullIterator, readGraphHydrationPayload, refetch, renderGraphHydrationScript, resolveFromCache, responseKeyCandidates, result, runMutation, runRoute, runServerMutation, seedResult, selectionOf, serializeGraph, setReadTracker, toArgMap, trailOf };
package/dist/index.mjs CHANGED
@@ -1050,6 +1050,46 @@ async function runMutation(options) {
1050
1050
  ok: true
1051
1051
  };
1052
1052
  }
1053
+ /**
1054
+ * Server-side mutation execution: run a compiled mutation through the adapter and
1055
+ * surface `userErrors`, WITHOUT a client cache/runtime. This is the core of the
1056
+ * server `mutate()` primitive — server actions, webhooks, jobs, and proxy handlers
1057
+ * mutate Shopify without a hydrated read graph. Never rejects for logical failures;
1058
+ * inspect `ok`/`userErrors`/`errors`.
1059
+ */
1060
+ async function runServerMutation(params) {
1061
+ let result;
1062
+ try {
1063
+ result = await params.adapter.execute({
1064
+ name: params.operation.name,
1065
+ kind: "mutation",
1066
+ document: params.operation.document
1067
+ }, params.variables, params.context);
1068
+ } catch (error) {
1069
+ return {
1070
+ userErrors: [],
1071
+ errors: [{ message: errorMessage(error) }],
1072
+ ok: false
1073
+ };
1074
+ }
1075
+ if (result.errors && result.errors.length > 0) return {
1076
+ userErrors: [],
1077
+ errors: result.errors,
1078
+ ok: false
1079
+ };
1080
+ const data = result.data;
1081
+ const userErrors = data ? extractUserErrors(data) : [];
1082
+ if (userErrors.length > 0) return {
1083
+ data,
1084
+ userErrors,
1085
+ ok: false
1086
+ };
1087
+ return {
1088
+ data,
1089
+ userErrors: [],
1090
+ ok: true
1091
+ };
1092
+ }
1053
1093
  /** Invalidate a record by graph value (proxy) or raw ref — next read re-fetches. */
1054
1094
  function invalidateValue(runtime, value) {
1055
1095
  const ref = toRef(value);
@@ -1218,6 +1258,25 @@ function createGraphIntegration(options) {
1218
1258
  graph: active.graph
1219
1259
  }, fn);
1220
1260
  }
1261
+ async function mutate(opName, vars, context) {
1262
+ const op = options.operations[opName];
1263
+ if (!op || op.kind !== "mutation") return {
1264
+ ok: false,
1265
+ userErrors: [],
1266
+ errors: [{ message: `unknown mutation operation: ${opName}` }]
1267
+ };
1268
+ const toVariables = op.variables;
1269
+ const variables = toVariables(vars) ?? {};
1270
+ return runServerMutation({
1271
+ operation: {
1272
+ name: op.name,
1273
+ document: op.document
1274
+ },
1275
+ variables,
1276
+ adapter: options.adapter,
1277
+ context: context ?? {}
1278
+ });
1279
+ }
1221
1280
  return {
1222
1281
  preload,
1223
1282
  getGraph,
@@ -1225,7 +1284,8 @@ function createGraphIntegration(options) {
1225
1284
  invalidate,
1226
1285
  getActive,
1227
1286
  refetch,
1228
- runInScope
1287
+ runInScope,
1288
+ mutate
1229
1289
  };
1230
1290
  }
1231
1291
  /** Default missing-field resolution: leave each miss undefined (hybrid allow/warn). */
@@ -1409,4 +1469,4 @@ function createPersistedResolver(operations, options = {}) {
1409
1469
  };
1410
1470
  }
1411
1471
  //#endregion
1412
- export { GRAPH_REF, GRAPH_TRAIL, GRAPH_TYPE, GraphCache, GraphRuntime, GraphScope, MutationTransaction, absorbHydrationPayload, bindGraph, bindScope, buildRouteContext, createFetchAdapter, createGraphIntegration, createGraphProxy, createGraphWsAdapter, createMutator, createPersistedResolver, errorMessage, graphHydrationScriptContent, hydrateGraph, invalidateValue, isGraphRef, normalizeValue, pagePointer, persistRootLinks, pushPullIterator, readGraphHydrationPayload, refetch, renderGraphHydrationScript, resolveFromCache, responseKeyCandidates, result, runMutation, runRoute, seedResult, selectionOf, serializeGraph, setReadTracker, toArgMap, trailOf };
1472
+ export { GRAPH_REF, GRAPH_TRAIL, GRAPH_TYPE, GraphCache, GraphRuntime, GraphScope, MutationTransaction, absorbHydrationPayload, bindGraph, bindScope, buildRouteContext, createFetchAdapter, createGraphIntegration, createGraphProxy, createGraphWsAdapter, createMutator, createPersistedResolver, errorMessage, graphHydrationScriptContent, hydrateGraph, invalidateValue, isGraphRef, normalizeValue, pagePointer, persistRootLinks, pushPullIterator, readGraphHydrationPayload, refetch, renderGraphHydrationScript, resolveFromCache, responseKeyCandidates, result, runMutation, runRoute, runServerMutation, seedResult, selectionOf, serializeGraph, setReadTracker, toArgMap, trailOf };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gleanql/client",
3
- "version": "0.1.8",
3
+ "version": "0.1.9",
4
4
  "description": "Glean's runtime: normalized cache, fine-grained reactivity, mutations, subscriptions and React hooks",
5
5
  "license": "MIT",
6
6
  "author": "Alexander Liljengard",
@@ -26,7 +26,7 @@
26
26
  "access": "public"
27
27
  },
28
28
  "dependencies": {
29
- "@gleanql/core": "0.1.8"
29
+ "@gleanql/core": "0.1.9"
30
30
  },
31
31
  "peerDependencies": {
32
32
  "react": ">=18"
@@ -4,6 +4,8 @@ import {
4
4
  createMutator,
5
5
  invalidateValue,
6
6
  runRoute,
7
+ runServerMutation,
8
+ type MutationResult,
7
9
  type BoundGraph,
8
10
  type BoundMutations,
9
11
  type CompiledOperation,
@@ -83,6 +85,17 @@ export interface GraphIntegration<Ctx extends Record<string, unknown>> {
83
85
  getGraph(requestInfo: RequestInfo<Ctx>): BoundGraph;
84
86
  /** The `graph.mutate.*` namespace for this request (throws if not preloaded). */
85
87
  getMutator(requestInfo: RequestInfo<Ctx>): BoundMutations;
88
+ /**
89
+ * Run a compiled mutation by name, server-side, WITHOUT a preloaded read graph —
90
+ * the executor behind the server `mutate()` primitive (server actions, webhooks,
91
+ * jobs). Resolves the op, maps `vars` via its factory, runs it through the
92
+ * adapter, and surfaces `userErrors`. Never rejects; inspect `ok`/`userErrors`.
93
+ */
94
+ mutate<TData = unknown>(
95
+ opName: string,
96
+ vars: unknown,
97
+ context?: GraphRequestContext,
98
+ ): Promise<MutationResult<TData>>;
86
99
  /** Invalidate a graph value / ref in this request's cache (refetch on next read). */
87
100
  invalidate(requestInfo: RequestInfo<Ctx>, value: GraphRef | unknown): void;
88
101
  /** Read the full active request state (runtime, roots, variables, ...). */
@@ -192,7 +205,28 @@ export function createGraphIntegration<Ctx extends Record<string, unknown> = Rec
192
205
  return options.scope.run({ runtime: active.runtime, graph: active.graph }, fn);
193
206
  }
194
207
 
195
- return { preload, getGraph, getMutator, invalidate, getActive, refetch, runInScope };
208
+ async function mutate<TData = unknown>(
209
+ opName: string,
210
+ vars: unknown,
211
+ context?: GraphRequestContext,
212
+ ): Promise<MutationResult<TData>> {
213
+ const op = options.operations[opName];
214
+ if (!op || op.kind !== "mutation") {
215
+ return { ok: false, userErrors: [], errors: [{ message: `unknown mutation operation: ${opName}` }] };
216
+ }
217
+ // A mutation op's `variables` factory maps the selector `vars` (not the route
218
+ // context the read-typed signature expects) — same cast `resolveBoundOp` uses.
219
+ const toVariables = op.variables as (vars: unknown) => Record<string, unknown> | undefined;
220
+ const variables = (toVariables(vars) ?? {}) as Record<string, unknown>;
221
+ return runServerMutation<TData>({
222
+ operation: { name: op.name, document: op.document },
223
+ variables,
224
+ adapter: options.adapter,
225
+ context: context ?? ({} as GraphRequestContext),
226
+ });
227
+ }
228
+
229
+ return { preload, getGraph, getMutator, invalidate, getActive, refetch, runInScope, mutate };
196
230
  }
197
231
 
198
232
  /** Default missing-field resolution: leave each miss undefined (hybrid allow/warn). */
package/src/mutation.ts CHANGED
@@ -133,6 +133,40 @@ export async function runMutation<TData = Record<string, unknown>>(
133
133
  return { data, userErrors: [], ok: true };
134
134
  }
135
135
 
136
+ /**
137
+ * Server-side mutation execution: run a compiled mutation through the adapter and
138
+ * surface `userErrors`, WITHOUT a client cache/runtime. This is the core of the
139
+ * server `mutate()` primitive — server actions, webhooks, jobs, and proxy handlers
140
+ * mutate Shopify without a hydrated read graph. Never rejects for logical failures;
141
+ * inspect `ok`/`userErrors`/`errors`.
142
+ */
143
+ export async function runServerMutation<TData = Record<string, unknown>>(params: {
144
+ readonly operation: { readonly name: string; readonly document: string };
145
+ readonly variables: Record<string, unknown>;
146
+ readonly adapter: GraphClientAdapter;
147
+ readonly context: GraphRequestContext;
148
+ }): Promise<MutationResult<TData>> {
149
+ let result;
150
+ try {
151
+ result = await params.adapter.execute(
152
+ { name: params.operation.name, kind: "mutation", document: params.operation.document },
153
+ params.variables,
154
+ params.context,
155
+ );
156
+ } catch (error) {
157
+ return { userErrors: [], errors: [{ message: errorMessage(error) }], ok: false };
158
+ }
159
+
160
+ if (result.errors && result.errors.length > 0) {
161
+ return { userErrors: [], errors: result.errors, ok: false };
162
+ }
163
+
164
+ const data = result.data as TData | undefined;
165
+ const userErrors = data ? extractUserErrors(data as Record<string, unknown>) : [];
166
+ if (userErrors.length > 0) return { data, userErrors, ok: false };
167
+ return { data, userErrors: [], ok: true };
168
+ }
169
+
136
170
  /** Invalidate a record by graph value (proxy) or raw ref — next read re-fetches. */
137
171
  export function invalidateValue(runtime: GraphRuntime, value: GraphRef | unknown): void {
138
172
  const ref = toRef(value);