@absolutejs/sync 1.9.2 → 1.11.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.
@@ -178,6 +178,28 @@ export type SyncEngine = {
178
178
  * mutation / a handler throw. Drive this from the transport's mutate frame.
179
179
  */
180
180
  runMutation: (name: string, args: unknown, ctx: unknown) => Promise<unknown>;
181
+ /**
182
+ * Atomically run N mutations in a single transaction (sync 1.11+).
183
+ * Each `{ name, args }` spec is authorized, then handlers fire in
184
+ * order against shared buffered changes. If any handler throws, the
185
+ * entire transaction rolls back — no partial commits, no fanned-out
186
+ * diffs. On success the accumulated changes apply as ONE live batch
187
+ * and the per-mutation results return in order.
188
+ *
189
+ * No retry policy applies to batches in v0.2; configure per-mutation
190
+ * retries on individual `runMutation` calls when atomicity isn't
191
+ * needed. A failed batch passes the original error through with no
192
+ * wrapping.
193
+ *
194
+ * Requires `transaction` to be set in {@link SyncEngineOptions} for
195
+ * actual DB-level atomicity; without it the batch still buffers
196
+ * changes into one fan-out but the underlying adapter writes
197
+ * piecemeal.
198
+ */
199
+ runMutations: (specs: Array<{
200
+ name: string;
201
+ args: unknown;
202
+ }>, ctx: unknown) => Promise<unknown[]>;
181
203
  /**
182
204
  * A point-in-time snapshot of the engine for devtools: registered collections
183
205
  * (+ kind, tables, live subscription counts), mutations, schedules, readers,
package/dist/index.js CHANGED
@@ -2065,6 +2065,55 @@ var createSyncEngine = (options = {}) => {
2065
2065
  }
2066
2066
  throw lastError;
2067
2067
  },
2068
+ runMutations: async (specs, ctx) => {
2069
+ if (specs.length === 0)
2070
+ return [];
2071
+ const resolved = specs.map((spec) => {
2072
+ const mutation = mutations.get(spec.name);
2073
+ if (mutation === undefined) {
2074
+ throw new Error(`Unknown mutation "${spec.name}"`);
2075
+ }
2076
+ return { args: spec.args, mutation, name: spec.name };
2077
+ });
2078
+ const runBatch = async (tx) => {
2079
+ const results = [];
2080
+ const accumulated = [];
2081
+ for (const { args, mutation, name } of resolved) {
2082
+ if (mutation.authorize !== undefined) {
2083
+ const allowed = await mutation.authorize(args, ctx);
2084
+ if (!allowed) {
2085
+ throw new UnauthorizedError(`run mutation "${name}"`);
2086
+ }
2087
+ }
2088
+ const sandboxRunner = sandboxRunners.get(name);
2089
+ const invokeHandler = sandboxRunner !== undefined ? sandboxRunner : (a, c, actions2) => Promise.resolve(mutation.handler(a, c, actions2));
2090
+ const { actions, buffered } = makeActions(tx, ctx, true);
2091
+ const result = await invokeHandler(args, ctx, actions);
2092
+ results.push(result);
2093
+ accumulated.push(...buffered);
2094
+ }
2095
+ return { accumulated, results };
2096
+ };
2097
+ try {
2098
+ const { accumulated, results } = runInTransaction !== undefined ? await runInTransaction((tx) => runBatch(tx)) : await runBatch(undefined);
2099
+ await applyChangeBatch(accumulated);
2100
+ emitActivity({
2101
+ type: "mutationBatch",
2102
+ at: Date.now(),
2103
+ names: resolved.map((entry) => entry.name),
2104
+ status: "ok"
2105
+ });
2106
+ return results;
2107
+ } catch (error) {
2108
+ emitActivity({
2109
+ type: "mutationBatch",
2110
+ at: Date.now(),
2111
+ names: resolved.map((entry) => entry.name),
2112
+ status: "error"
2113
+ });
2114
+ throw error;
2115
+ }
2116
+ },
2068
2117
  registerSchedule: (schedule) => {
2069
2118
  schedules.set(schedule.name, schedule);
2070
2119
  },
@@ -2626,5 +2675,5 @@ export {
2626
2675
  createPresenceHub
2627
2676
  };
2628
2677
 
2629
- //# debugId=2C8AB0508E99C22364756E2164756E21
2678
+ //# debugId=FFB4969DBBAB620C64756E2164756E21
2630
2679
  //# sourceMappingURL=index.js.map