@absolutejs/sync 1.10.0 → 1.12.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/dist/testing.js CHANGED
@@ -318,7 +318,7 @@ var wrap = (source) => `
318
318
  const userFn = (${source});
319
319
  if (typeof userFn !== 'function') {
320
320
  throw new Error(
321
- 'sandboxedHandler must evaluate to (args, ctx, actions) => result; got ' +
321
+ 'sandboxedHandler must evaluate to (args, ctx, actions, unsafeHost) => result; got ' +
322
322
  typeof userFn
323
323
  );
324
324
  }
@@ -330,12 +330,24 @@ var wrap = (source) => `
330
330
  now: () => __dispatch(__callId, 'now'),
331
331
  fetch: (url, init) => __dispatch(__callId, 'fetch', url, init)
332
332
  };
333
- return userFn(args, ctx, actions);
333
+ // Escape hatch \u2014 host fns the mutation explicitly opted in to.
334
+ // The Proxy means every property access is a host call; the
335
+ // engine throws if the property name isn't declared in the
336
+ // mutation's sandbox.unsafeHost map.
337
+ const unsafeHost = new Proxy({}, {
338
+ get: (_target, fnName) => {
339
+ if (typeof fnName !== 'string') return undefined;
340
+ return (...callArgs) =>
341
+ __dispatch(__callId, 'unsafeHost', fnName, callArgs);
342
+ }
343
+ });
344
+ return userFn(args, ctx, actions, unsafeHost);
334
345
  }
335
346
  `;
336
347
  var compile = async (source, config, bridgeFetch) => {
337
348
  const { Reference, createIsolatedRunner, resolveIsolatePolicy } = await loadIsolatedJsc();
338
349
  const callMap = new Map;
350
+ const unsafeHost = config.unsafeHost;
339
351
  const dispatch = new Reference((callId, op, ...rest) => {
340
352
  const a = callMap.get(callId);
341
353
  if (a === undefined) {
@@ -354,6 +366,14 @@ var compile = async (source, config, bridgeFetch) => {
354
366
  return a.now();
355
367
  case "fetch":
356
368
  return runBridgeFetch(bridgeFetch, rest[0], rest[1]);
369
+ case "unsafeHost": {
370
+ const fnName = rest[0];
371
+ const callArgs = rest[1] ?? [];
372
+ if (unsafeHost === undefined || typeof unsafeHost[fnName] !== "function") {
373
+ throw new Error(`sandboxedHandler called unsafeHost.${fnName}() but it was not declared in the mutation's sandbox.unsafeHost config. Declare it (and only the host fns you intend to expose) to opt in to the escape hatch.`);
374
+ }
375
+ return unsafeHost[fnName](...callArgs);
376
+ }
357
377
  default:
358
378
  throw new Error(`unknown sandbox action op: ${String(op)}`);
359
379
  }
@@ -1643,6 +1663,55 @@ var createSyncEngine = (options = {}) => {
1643
1663
  }
1644
1664
  throw lastError;
1645
1665
  },
1666
+ runMutations: async (specs, ctx) => {
1667
+ if (specs.length === 0)
1668
+ return [];
1669
+ const resolved = specs.map((spec) => {
1670
+ const mutation = mutations.get(spec.name);
1671
+ if (mutation === undefined) {
1672
+ throw new Error(`Unknown mutation "${spec.name}"`);
1673
+ }
1674
+ return { args: spec.args, mutation, name: spec.name };
1675
+ });
1676
+ const runBatch = async (tx) => {
1677
+ const results = [];
1678
+ const accumulated = [];
1679
+ for (const { args, mutation, name } of resolved) {
1680
+ if (mutation.authorize !== undefined) {
1681
+ const allowed = await mutation.authorize(args, ctx);
1682
+ if (!allowed) {
1683
+ throw new UnauthorizedError(`run mutation "${name}"`);
1684
+ }
1685
+ }
1686
+ const sandboxRunner = sandboxRunners.get(name);
1687
+ const invokeHandler = sandboxRunner !== undefined ? sandboxRunner : (a, c, actions2) => Promise.resolve(mutation.handler(a, c, actions2));
1688
+ const { actions, buffered } = makeActions(tx, ctx, true);
1689
+ const result = await invokeHandler(args, ctx, actions);
1690
+ results.push(result);
1691
+ accumulated.push(...buffered);
1692
+ }
1693
+ return { accumulated, results };
1694
+ };
1695
+ try {
1696
+ const { accumulated, results } = runInTransaction !== undefined ? await runInTransaction((tx) => runBatch(tx)) : await runBatch(undefined);
1697
+ await applyChangeBatch(accumulated);
1698
+ emitActivity({
1699
+ type: "mutationBatch",
1700
+ at: Date.now(),
1701
+ names: resolved.map((entry) => entry.name),
1702
+ status: "ok"
1703
+ });
1704
+ return results;
1705
+ } catch (error) {
1706
+ emitActivity({
1707
+ type: "mutationBatch",
1708
+ at: Date.now(),
1709
+ names: resolved.map((entry) => entry.name),
1710
+ status: "error"
1711
+ });
1712
+ throw error;
1713
+ }
1714
+ },
1646
1715
  registerSchedule: (schedule) => {
1647
1716
  schedules.set(schedule.name, schedule);
1648
1717
  },
@@ -1934,5 +2003,5 @@ export {
1934
2003
  createTestEngine
1935
2004
  };
1936
2005
 
1937
- //# debugId=CDFC0D23D33F4AF664756E2164756E21
2006
+ //# debugId=E33DC349D71B8BBE64756E2164756E21
1938
2007
  //# sourceMappingURL=testing.js.map