{"_id":"@actualwave/deferred-data-access","_rev":"4-8010d0e5416c590e41ceb45fbfd4abb8","name":"@actualwave/deferred-data-access","dist-tags":{"latest":"2.1.2"},"versions":{"2.0.0":{"name":"@actualwave/deferred-data-access","version":"2.0.0","_id":"@actualwave/deferred-data-access@2.0.0","maintainers":[{"name":"actualwave","email":"burdiuz@gmail.com"}],"dist":{"shasum":"303abbf2ca7446477a1fb11ab5d421b3443b0086","tarball":"https://registry.npmjs.org/@actualwave/deferred-data-access/-/deferred-data-access-2.0.0.tgz","fileCount":106,"integrity":"sha512-OCEStZt3kHeDBQG95WPISXHbz4G7GFZJP5DzdGmCjZQd5SkOEy/AlSQgBU2dPBET9lJxlGS7UUYy8PySbW4pIw==","signatures":[{"sig":"MEQCIHZ5igGtzmlhu4WicC40aKfNsXnnJEXmcWWyvgB+RP9WAiAgI9ADBGi8xmpIM7JXzGBEbTAf/QmG66qaleJj/FdMuA==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":145726},"main":"dist/deferred-data-access.js","types":"index.d.ts","module":"index.js","gitHead":"79068d23cefe0122bcf2dea27abb4b5d0048284d","scripts":{"build":"tsc --project tsconfig.es.json && rollup -c rollup.config.js","postinstall":"npm run build"},"_npmUser":{"name":"actualwave","email":"burdiuz@gmail.com"},"_npmVersion":"9.5.0","description":"Deferred Data Access(DDA) is a framework for building async CRUD APIs. It transforms object calls into commands that can be interpreted by custom function.","directories":{},"_nodeVersion":"18.14.2","dependencies":{"@actualwave/has-own":"^0.0.3","@actualwave/weak-storage":"^0.1.0"},"publishConfig":{"directory":"../../dist/deferred-data-access"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/deferred-data-access_2.0.0_1724958546228_0.739334753079218","host":"s3://npm-registry-packages"}},"2.0.1":{"name":"@actualwave/deferred-data-access","version":"2.0.1","_id":"@actualwave/deferred-data-access@2.0.1","maintainers":[{"name":"actualwave","email":"burdiuz@gmail.com"}],"dist":{"shasum":"1f8bb6b9d9dabba8c564b904880976618e5384b3","tarball":"https://registry.npmjs.org/@actualwave/deferred-data-access/-/deferred-data-access-2.0.1.tgz","fileCount":106,"integrity":"sha512-kjie3w97uRNCQzmt6VdkycCscc1kfnfSYvtuxAUL0s+A5PEKcb7bOWVmQQ3jy7Z4slUnzGQEbKVLddfXfkSwXQ==","signatures":[{"sig":"MEUCIQCXy4ok+L3XBBDy3b3UZmYbHmFwkwAwrRKhHa7K3KLK7wIgdErUTganxsTIwzUR4OZd49QtOG4SaCJRbMerHex8maY=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":145690},"main":"dist/deferred-data-access.js","types":"index.d.ts","module":"index.js","gitHead":"79068d23cefe0122bcf2dea27abb4b5d0048284d","scripts":{"build":"tsc --project tsconfig.es.json && rollup -c rollup.config.js"},"_npmUser":{"name":"actualwave","email":"burdiuz@gmail.com"},"_npmVersion":"9.5.0","description":"Deferred Data Access(DDA) is a framework for building async CRUD APIs. It transforms object calls into commands that can be interpreted by custom function.","directories":{},"_nodeVersion":"18.14.2","dependencies":{"@actualwave/has-own":"^0.0.3","@actualwave/weak-storage":"^0.1.0"},"publishConfig":{"directory":"../../dist/deferred-data-access"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/deferred-data-access_2.0.1_1724959525300_0.9233554570158773","host":"s3://npm-registry-packages"}},"2.1.1":{"name":"@actualwave/deferred-data-access","version":"2.1.1","_id":"@actualwave/deferred-data-access@2.1.1","maintainers":[{"name":"actualwave","email":"burdiuz@gmail.com"}],"dist":{"shasum":"52dd34945d9d6115d13716509cf9ec00a730ffbe","tarball":"https://registry.npmjs.org/@actualwave/deferred-data-access/-/deferred-data-access-2.1.1.tgz","fileCount":154,"integrity":"sha512-/tnwWfkx++m9wsxoCfvv9m9Lzt0klxJ5iitBPpqZ2MW4oQvIdlZyyZhYAJNlOzK1kQrdTL59i5XEjwLIvaqsTw==","signatures":[{"sig":"MEQCIGJrfZLt8zZCinnznWvkpXSkxsDKWJvCkxCu3zXwr1yQAiAy5w8BfUERDszC7GnxanNZHcrHYqq8WjV3MG9G+Yo5Xw==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":355806},"main":"index.js","type":"module","types":"index.d.ts","module":"index.es.js","gitHead":"0e34b1d61b9c658865a777fbfaa0fe8845884d1a","scripts":{"test":"jest","build":"tsc --project tsconfig.es.json && rollup -c rollup.config.js","test:coverage":"jest --coverage"},"_npmUser":{"name":"actualwave","email":"burdiuz@gmail.com"},"_npmVersion":"11.5.1","description":"Deferred Data Access (DDA) is a TypeScript library that wraps any object or Promise in a `Proxy` and records every property access, assignment, deletion, and function call as a typed **command**. A developer-supplied handler function decides what each com","directories":{},"_nodeVersion":"24.6.0","dependencies":{"@actualwave/weak-storage":"0.2.0"},"publishConfig":{"directory":"../../dist/deferred-data-access"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/deferred-data-access_2.1.1_1778701863541_0.549143202431525","host":"s3://npm-registry-packages-npm-production"}},"2.1.2":{"name":"@actualwave/deferred-data-access","version":"2.1.2","main":"index.js","module":"index.es.js","types":"index.d.ts","scripts":{"build":"tsc --project tsconfig.es.json && rollup -c rollup.config.js","test":"jest","test:coverage":"jest --coverage"},"type":"module","homepage":"https://github.com/burdiuz/js-deferred-data-access/tree/master/packages/iframe-interface","bugs":{"url":"https://github.com/burdiuz/js-deferred-data-access/issues","email":"burdiuz@gmail.com"},"license":"MIT","author":{"name":"Oleg Galaburda","email":"burdiuz@gmail.com","url":"http://actualwave.com/"},"repository":{"type":"git","url":"git+https://github.com/burdiuz/js-deferred-data-access.git"},"publishConfig":{"directory":"../../dist/deferred-data-access"},"dependencies":{"@actualwave/weak-storage":"0.2.0"},"_id":"@actualwave/deferred-data-access@2.1.2","gitHead":"0e34b1d61b9c658865a777fbfaa0fe8845884d1a","description":"Deferred Data Access (DDA) is a TypeScript library that wraps any object or Promise in a `Proxy` and records every property access, assignment, deletion, and function call as a typed **command**. A developer-supplied handler function decides what each com","_nodeVersion":"24.6.0","_npmVersion":"11.5.1","dist":{"integrity":"sha512-V9TOciFlT86sL9ifwmlTnhMwLMlYDw+3Q6oW+TCqlJ3KfZC8a+Gz+LyIXuQilWGkgsZBeifsDEauxQHcqXBxJg==","shasum":"27ab68c6713bd3d4268b706a0c8f405118f133bc","tarball":"https://registry.npmjs.org/@actualwave/deferred-data-access/-/deferred-data-access-2.1.2.tgz","fileCount":122,"unpackedSize":345982,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQCzvkHSbpku9Jh+hdTwwsId0jT7nyYx0n+ou/widDIswQIgSHcw7KxD2kUtW19h6IDw84nROiwj4sRWv1+HnYozHzI="}]},"_npmUser":{"name":"actualwave","email":"burdiuz@gmail.com"},"directories":{},"maintainers":[{"name":"actualwave","email":"burdiuz@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/deferred-data-access_2.1.2_1778829461122_0.6459481847301811"},"_hasShrinkwrap":false}},"time":{"created":"2024-08-29T19:09:06.100Z","modified":"2026-05-15T07:17:41.434Z","2.0.0":"2024-08-29T19:09:06.458Z","2.0.1":"2024-08-29T19:25:25.552Z","2.1.1":"2026-05-13T19:51:03.698Z","2.1.2":"2026-05-15T07:17:41.315Z"},"description":"Deferred Data Access (DDA) is a TypeScript library that wraps any object or Promise in a `Proxy` and records every property access, assignment, deletion, and function call as a typed **command**. A developer-supplied handler function decides what each com","maintainers":[{"name":"actualwave","email":"burdiuz@gmail.com"}],"readme":"# Deferred Data Access\n\nDeferred Data Access (DDA) is a TypeScript library that wraps any object or Promise in a `Proxy` and records every property access, assignment, deletion, and function call as a typed **command**. A developer-supplied handler function decides what each command means — fetching from a REST API, forwarding to a Web Worker, replaying in a test, or anything else.\n\n## Table of contents\n\n- [Installation](#installation)\n- [Quick start](#quick-start)\n- [How it works](#how-it-works)\n- [Lazy vs reactive mode](#lazy-vs-reactive-mode)\n- [Command types](#command-types)\n- [Command handler](#command-handler)\n- [createCommandHandler](#createcommandhandler)\n- [CommandChain API](#commandchain-api)\n- [Resource system](#resource-system)\n- [Cross-context interface](#cross-context-interface)\n- [Sub-package reference](#sub-package-reference)\n- [Projects built on DDA](#projects-built-on-dda)\n\n---\n\n## Installation\n\n```bash\nnpm install @actualwave/deferred-data-access\n```\n\n---\n\n## Quick start\n\n```typescript\nimport { handle } from '@actualwave/deferred-data-access';\nimport { ProxyCommand } from '@actualwave/deferred-data-access/proxy';\n\n// 1. Define a handler that interprets commands\nconst handler = async (command, context, wrap) => {\n  if (command.type === ProxyCommand.GET) {\n    const target = await context;\n    return target[command.name];\n  }\n  // ...\n};\n\n// 2. Create a wrap factory for a given handler\nconst wrap = handle(handler);\n\n// 3. Wrap an object (or a Promise of one) — returns a Proxy\nconst proxy = wrap({ user: { name: 'Alice' } });\n\n// 4. Access properties — in lazy mode handler is called once on .then()\nconst name = await proxy.user.name; // → 'Alice'\n```\n\n---\n\n## How it works\n\n1. `handle(handler)` returns a `wrap` factory.\n2. `wrap(target)` wraps `target` in a `Proxy`. Every property access, assignment, deletion, or call is intercepted.\n3. Intercepted operations are chained into a `CommandChain` — a linked list of `ICommand` nodes, head to tail.\n4. When the result is awaited (`.then()` / `await`), the handler receives the full chain plus a context Promise and must return a Promise with the resolved value.\n5. The handler can call `wrap(result, command)` to return a new proxy that continues the same chain, enabling deeply nested lazy access.\n\n---\n\n## Lazy vs reactive mode\n\n`handle(handler, lazy?)` — second argument controls the mode (default: `true`).\n\n### Lazy mode (default)\n\nThe handler is called **once** per `.then()` / `.catch()` invocation. Intermediate GET/APPLY operations build up a `CommandChain` but do not invoke the handler until the result is awaited.\n\n```typescript\nconst wrap = handle(handler); // lazy = true\n\nconst proxy = wrap(rootObject);\nproxy.a.b.c; // no handler calls yet\nawait proxy.a.b.c; // handler called once with chain: GET(c) → GET(b) → GET(a)\n```\n\nThe command delivered to the handler is the **head** of the chain. Walk `command.prev` to reach earlier operations.\n\n### Reactive mode\n\nThe handler is called on **every** intercepted operation.\n\n```typescript\nconst wrap = handle(handler, false); // lazy = false\n\nconst proxy = wrap(rootObject);\nproxy.a; // handler called: GET('a')\nproxy.a.b; // handler called: GET('a'), then GET('b') on its result\n```\n\n---\n\n## Command types\n\nImported from `@actualwave/deferred-data-access/proxy`:\n\n| Constant | Value | Triggered by |\n|---|---|---|\n| `ProxyCommand.GET` | `'P:get'` | `proxy.prop` |\n| `ProxyCommand.SET` | `'P:set'` | `proxy.prop = value` |\n| `ProxyCommand.DELETE_PROPERTY` | `'P:del'` | `delete proxy.prop` |\n| `ProxyCommand.APPLY` | `'P:apply'` | `proxy(args)` |\n| `ProxyCommand.METHOD_CALL` | `'P:call'` | `proxy.method(args)` *(lazy mode only — collapses GET + APPLY)* |\n| `ProxyCommand.CONSTRUCT` | `'P:new'` | `new proxy(args)` |\n\n`METHOD_CALL` is only generated in lazy mode when a `GET` is immediately followed by an `APPLY`. It carries the method name in `command.name` and the arguments in `command.value`.\n\n`CONSTRUCT` fires when the proxy is used as a constructor (`new proxy(args)`). The arguments are passed in `command.value`. When used over the cross-context interface (`initialize()`), the newly created instance is automatically registered in the resource pool and returned as a resource descriptor, so the caller receives a proxy to the remote instance.\n\n> **Important — GC hazard with CONSTRUCT over `initialize()`:**  \n> The resource pool stores values through `WeakRef` (via `WeakValueMap`). If no strong reference to the constructed instance is held on the side that created it, the garbage collector may collect it at any time. Once collected, `pool.getById(id)` returns `undefined` and any subsequent method call on the remote proxy will throw `\"Resource does not exist\"`.  \n> **Always store the result of a `CONSTRUCT` call in a variable (or a collection) that outlives its use.** Do not rely on the pool itself to keep the instance alive.\n\n### Command shape\n\n```typescript\ninterface ICommand {\n  type: string;          // ProxyCommand value\n  name?: PropertyName;   // string | symbol — property name\n  value?: unknown;       // SET value, APPLY args, or METHOD_CALL args\n  context?: Promise<unknown>; // Promise resolving to the target object\n}\n```\n\n---\n\n## Command handler\n\n```typescript\ntype CommandHandler = (\n  command: ICommandList,\n  context: CommandContext | undefined,\n  wrap: (context: CommandContext, command?: ICommandChain) => unknown\n) => Promise<unknown>;\n```\n\n| Argument | Description |\n|---|---|\n| `command` | Head of the `CommandChain` — inspect `command.type`, `command.name`, `command.value`. Walk `command.prev` for earlier operations. |\n| `context` | A `Promise` resolving to the target object the command was issued against. `undefined` for the root call. |\n| `wrap` | Re-wraps a new Promise with the same handler, enabling chained lazy access on sub-objects. |\n\n### Example — object property access\n\n```typescript\nconst handler = async (command, context, wrap) => {\n  const target = await context;\n\n  switch (command.type) {\n    case ProxyCommand.GET:\n      return target[command.name];\n\n    case ProxyCommand.SET:\n      target[command.name] = command.value;\n      return;\n\n    case ProxyCommand.METHOD_CALL:\n      return target[command.name](...command.value);\n\n    case ProxyCommand.APPLY:\n      return (target as Function)(...command.value);\n\n    case ProxyCommand.DELETE_PROPERTY:\n      return delete target[command.name];\n\n    case ProxyCommand.CONSTRUCT:\n      return new (target as new (...args: unknown[]) => unknown)(...command.value as unknown[]);\n  }\n};\n```\n\n---\n\n## createCommandHandler\n\nA utility that dispatches to per-type handler functions:\n\n```typescript\nimport { createCommandHandler } from '@actualwave/deferred-data-access/command';\nimport { ProxyCommand } from '@actualwave/deferred-data-access/proxy';\n\nconst handler = createCommandHandler({\n  handlers: {\n    [ProxyCommand.GET]: async (command, context) => {\n      const target = await context;\n      return target[command.name];\n    },\n    [ProxyCommand.SET]: async (command, context) => {\n      const target = await context;\n      target[command.name] = command.value;\n    },\n  },\n  defaultHandler: async (command) => {\n    throw new Error(`Unhandled command: ${command.type}`);\n  },\n});\n\nconst wrap = handle(handler, false);\n```\n\nIf no matching handler and no `defaultHandler`, the call resolves to `undefined`.\n\n---\n\n## CommandChain API\n\n`CommandChain` extends `Command` and is iterable from head to tail:\n\n```typescript\nimport { CommandChain } from '@actualwave/deferred-data-access/command';\n\n// Iterate head → tail\nfor (const node of command) {\n  console.log(node.type, node.name);\n}\n\n// Functional traversal\nconst types = command.map(node => node.type);\nconst path  = command.reduce((acc, node) => [node.name, ...acc], []);\n\ncommand.forEach(node => { /* head → tail */ });\ncommand.isTail(); // true if this node has no prev\n```\n\n### withoutPrev()\n\nCreates an immutable copy of the node with the `prev` link removed. Use this instead of mutating `prev` directly to avoid corrupting shared chain references:\n\n```typescript\nconst severed = command.withoutPrev();\n// severed.prev === undefined\n// command.prev is unchanged\n```\n\n---\n\n## Resource system\n\nResources allow objects to be referenced by ID across serialisation boundaries (e.g. `postMessage`). Each `Resource` gets a stable string ID and lives in a `ResourcePool`.\n\n```typescript\nimport {\n  ResourcePool,\n  getDefaultResourcePool,\n  isResourceObject,\n} from '@actualwave/deferred-data-access/resource';\n\nconst pool = getDefaultResourcePool(); // lazily-created singleton\n\n// Register an object\nconst resource = pool.set(myObject);\nconsole.log(resource.id);     // stable string ID\nconsole.log(resource.poolId); // pool's own ID\n\n// Serialise for postMessage\nconst descriptor = resource.toObject();\n// { id: '...', poolId: '...', type: 'object' }\n\n// Reconstruct on the other side\nconst retrieved = pool.getById(descriptor.id);\n\n// Type guard\nif (isResourceObject(value)) {\n  const live = pool.getById(value.id);\n}\n```\n\nMultiple pools can be managed through `ResourcePoolRegistry`:\n\n```typescript\nimport { getRegistry } from '@actualwave/deferred-data-access/resource';\n\nconst registry = getRegistry(); // lazily-created singleton\nconst pool = registry.createPool();\nregistry.get(pool.id); // → pool\n```\n\n### Custom FinalizationRegistry\n\nIn environments where `globalThis.FinalizationRegistry` is absent or needs to be replaced (e.g. React Native / Hermes), set a custom implementation before any pools are created:\n\n```typescript\nimport { setCustomFinalizationRegistryClass } from '@actualwave/deferred-data-access/resource';\n\nsetCustomFinalizationRegistryClass(MyFinalizationRegistryPolyfill);\n// All ResourcePools created after this call will use MyFinalizationRegistryPolyfill.\n// Pass null to explicitly disable GC-based cleanup.\n```\n\nThe constructor of `ResourcePool` also accepts a `FinalizationRegistry` directly, which takes precedence over the module-level setting:\n\n```typescript\nconst pool = new ResourcePool(MyFinalizationRegistryPolyfill);\n```\n\n### Replacing singletons\n\n```typescript\nimport {\n  setDefaultResourcePool,\n  setRegistry,\n} from '@actualwave/deferred-data-access/resource';\n\nsetDefaultResourcePool(myPool);   // replace the default pool singleton\nsetRegistry(myRegistry);          // replace the default registry singleton\n```\n\n---\n\n## Cross-context interface\n\n`initialize()` sets up a **bidirectional proxy channel** between two contexts (main thread ↔ Worker, two iframes, WebSocket peers, etc.). Each side runs `initialize()` and they perform a handshake before exposing proxies to each other's `root` object.\n\n```typescript\nimport { initialize, InterfaceType } from '@actualwave/deferred-data-access/interface';\n\n// --- Main thread (HOST) ---\nconst worker = new Worker('./worker.js');\n\nconst { root, stop } = await initialize({\n  type: InterfaceType.HOST,\n  root: { greet: (name: string) => `Hello, ${name}!` }, // expose to worker\n  subscribe:   (fn) => worker.addEventListener('message', fn),\n  unsubscribe: (fn) => worker.removeEventListener('message', fn),\n  sendMessage: (data) => worker.postMessage(data),\n  handshakeTimeout: 5000,\n  responseTimeout: 10000,\n});\n\n// `root` is a proxy to the worker's exported API\nconst result = await root.remoteMethod('arg');\nstop(); // detach message listener\n```\n\n```typescript\n// --- Worker (GUEST) ---\nimport { initialize, InterfaceType } from '@actualwave/deferred-data-access/interface';\n\nawait initialize({\n  type: InterfaceType.GUEST,\n  root: { remoteMethod: (arg: string) => arg.toUpperCase() },\n  subscribe:   (fn) => self.addEventListener('message', fn),\n  unsubscribe: (fn) => self.removeEventListener('message', fn),\n  sendMessage: (data) => self.postMessage(data),\n  handshakeTimeout: 5000,\n  responseTimeout: 10000,\n});\n```\n\n### InitConfig options\n\n| Option | Type | Default | Description |\n|---|---|---|---|\n| `type` | `InterfaceType` | required | `HOST` waits for the guest; `GUEST` initiates |\n| `root` | `unknown` | — | Object to expose to the remote side |\n| `subscribe` | `(fn) => void` | required | Attach a message listener |\n| `unsubscribe` | `(fn) => void` | required | Detach a message listener |\n| `sendMessage` | `(data) => void` | required | Send a message to the remote side |\n| `id` | `string` | auto | Stable ID for this interface endpoint |\n| `remoteId` | `string` | — | Expected remote ID (skips handshake if both sides know each other's ID) |\n| `handshakeTimeout` | `number` | — | ms before handshake times out |\n| `handshakeInterval` | `number` | — | ms between handshake retry attempts (GUEST only) |\n| `responseTimeout` | `number` | `0` (none) | ms before a remote call times out |\n| `preprocessResponse` | `(data) => unknown` | identity | Transform raw message data before parsing |\n\n### initialize() return value\n\n```typescript\n{\n  stop: () => void;           // detach the message listener\n  pool: ResourcePool;         // local resource pool\n  root: unknown | null;       // proxy to the remote root (null if remote has no root)\n  wrap: Function;             // wrap factory with the same handler (for advanced use)\n  pendingRequests: Map<…>;    // in-flight request map (for advanced use)\n}\n```\n\n---\n\n## Sub-package reference\n\n| Import path | Key exports |\n|---|---|\n| `@actualwave/deferred-data-access` | `handle` |\n| `@actualwave/deferred-data-access/command` | `Command`, `CommandChain`, `createCommandHandler` |\n| `@actualwave/deferred-data-access/proxy` | `ProxyCommand`, `wrapWithProxy`, `isWrappedWithProxy`, `unwrapProxy`, `generateProxyCommand` |\n| `@actualwave/deferred-data-access/resource` | `Resource`, `ResourcePool`, `ResourcePoolRegistry`, `getDefaultResourcePool`, `setDefaultResourcePool`, `getRegistry`, `setRegistry`, `getCustomFinalizationRegistryClass`, `setCustomFinalizationRegistryClass`, `isResourceObject`, `createResource` |\n| `@actualwave/deferred-data-access/record` | `recordHandlerCalls`, `latestCall`, `latestCallFor`, `clearLatestCalls` |\n| `@actualwave/deferred-data-access/utils` | `IdOwner`, `generateId`, `createUIDGenerator`, `isReservedPropertyName`, `ReservedPropertyNames`, `reject` |\n| `@actualwave/deferred-data-access/interface` | `initialize`, `InterfaceType`, `MessageType`, `createSubscriberFns`, `findEventEmitter`, `findMessagePort` |\n\n### recordHandlerCalls\n\nWraps a `CommandHandler` to track the latest in-flight call Promise, useful for implementing loading indicators or sequential request logic:\n\n```typescript\nimport { recordHandlerCalls, latestCall, latestCallFor } from '@actualwave/deferred-data-access/record';\n\nconst trackedHandler = recordHandlerCalls(myHandler);\nconst wrap = handle(trackedHandler);\n\nconst proxy = wrap(rootObject);\nproxy.doWork();\n\n// latestCall() returns the Promise of the most recent handler invocation\nawait latestCall();\n\n// latestCallFor(context) returns the Promise for a specific context Promise\n```\n\n---\n\n## Projects built on DDA\n\n- [RESTObject](https://github.com/burdiuz/js-deferred-data-access/tree/master/packages/rest-object) — REST API access using dot notation\n- [WorkerInterface](https://github.com/burdiuz/js-deferred-data-access/tree/master/packages/worker-interface) — transparent proxy to a Web Worker's API\n","readmeFilename":"README.md","homepage":"https://github.com/burdiuz/js-deferred-data-access/tree/master/packages/iframe-interface","repository":{"type":"git","url":"git+https://github.com/burdiuz/js-deferred-data-access.git"},"author":{"name":"Oleg Galaburda","email":"burdiuz@gmail.com","url":"http://actualwave.com/"},"bugs":{"url":"https://github.com/burdiuz/js-deferred-data-access/issues","email":"burdiuz@gmail.com"},"license":"MIT"}