{"_id":"sync-promise-expanded","_rev":"2-ce80ac0a6e8e759d97cba07b2583b8eb","name":"sync-promise-expanded","dist-tags":{"latest":"2.0.0"},"versions":{"1.0.0":{"name":"sync-promise-expanded","version":"1.0.0","keywords":["indexeddb","promises"],"author":{"name":"Simon Friis Vindum"},"license":"ISC","_id":"sync-promise-expanded@1.0.0","maintainers":[{"name":"brettz9","email":"brettz9@yahoo.com"}],"contributors":[{"name":"Brett Zamir"}],"homepage":"https://github.com/brettz9/sync-promise","bugs":{"url":"https://github.com/brettz9/sync-promise/issues"},"dist":{"shasum":"cbf23f2929124a6cf174979601ef8bf97ed87587","tarball":"https://registry.npmjs.org/sync-promise-expanded/-/sync-promise-expanded-1.0.0.tgz","fileCount":15,"integrity":"sha512-pdxxEOaeKO6LghTz0Fe7yw82fx95gtS0SxVgRvIwvN4h9qTie8oOF/pWuH8PGp+PVduS84RXXxO/xrW93Nno9w==","signatures":[{"sig":"MEUCIQDZ5CN6u84C9Hbpt9wYLaSeGL4c3K5CdoU89eIEoQfwLQIgUcTmgESuQWmNOIEdze9Je53WDDRh9p0pMRYm5ULhggc=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":44942},"main":"dist/sync-promise-commonjs.cjs","type":"module","_from":"file:sync-promise-expanded-1.0.0.tgz","types":"./dist/index.d.ts","engines":{"node":">=16.0.0"},"exports":{".":{"types":"./dist/index.d.ts","import":"./index.js","require":"./dist/sync-promise-commonjs.cjs"}},"scripts":{"tsc":"tsc","lint":"npm run eslint","test":"c8 npm run mocha","build":"npm run rollup && tsc -p tsconfig-prod.json","mocha":"mocha","eslint":"eslint --ext=js,md,html .","rollup":"rollup -c"},"_npmUser":{"name":"brettz9","email":"brettz9@yahoo.com"},"_resolved":"/private/var/folders/2n/_szg3q3d15n9mn2jd_q91cym0000gn/T/0ea41109b07c616eac38c4a13e2818c6/sync-promise-expanded-1.0.0.tgz","_integrity":"sha512-pdxxEOaeKO6LghTz0Fe7yw82fx95gtS0SxVgRvIwvN4h9qTie8oOF/pWuH8PGp+PVduS84RXXxO/xrW93Nno9w==","repository":{"url":"git+https://github.com/brettz9/sync-promise.git","type":"git"},"_npmVersion":"9.6.4","description":"Ultra compact synchronized promise implementation.","directories":{"test":"test"},"_nodeVersion":"20.0.0","_hasShrinkwrap":false,"devDependencies":{"c8":"^7.13.0","mocha":"^10.2.0","eslint":"^8.40.0","rollup":"^3.22.0","@types/node":"^20.1.7","@types/mocha":"^10.0.1","@rollup/plugin-terser":"^0.4.2","eslint-config-ash-nazg":"^34.12.0"},"_npmOperationalInternal":{"tmp":"tmp/sync-promise-expanded_1.0.0_1684336961093_0.064635839954031","host":"s3://npm-registry-packages"}},"2.0.0":{"name":"sync-promise-expanded","version":"2.0.0","description":"Ultra compact synchronized promise implementation.","type":"module","types":"./dist/index.d.ts","exports":{".":{"import":{"types":"./dist/index.d.ts","default":"./index.js"},"require":{"types":"./dist/index.d.cts","default":"./dist/sync-promise-commonjs.cjs"}}},"directories":{"test":"test"},"engines":{"node":">=16.0.0"},"repository":{"type":"git","url":"git+https://github.com/brettz9/sync-promise.git"},"devDependencies":{"@arethetypeswrong/cli":"^0.18.5","@rollup/plugin-terser":"^1.0.0","@types/mocha":"^10.0.10","@types/node":"^26.1.2","c8":"^12.0.0","eslint":"^10.8.0","eslint-config-ash-nazg":"^42.1.1","mocha":"^11.8.0","rollup":"^4.62.4"},"keywords":["indexeddb","promises"],"author":{"name":"Simon Friis Vindum"},"contributors":[{"name":"Brett Zamir"}],"license":"ISC","bugs":{"url":"https://github.com/brettz9/sync-promise/issues"},"homepage":"https://github.com/brettz9/sync-promise","scripts":{"attw":"attw --pack .","tsc":"tsc","rollup":"rollup -c","build":"npm run rollup && tsc -p tsconfig-prod.json","lint":"npm run eslint","eslint":"eslint --ext=js,md,html .","mocha":"mocha","test":"c8 npm run mocha"},"_id":"sync-promise-expanded@2.0.0","_integrity":"sha512-4RtYBt1GfCSmPyPH8wmFYYpLgJCw1bl82OzPXxSIylWVBhJeZcXh9i6jMRhImsEcmdYGRqnesEqyBbkKojgjvw==","_resolved":"/private/var/folders/2n/_szg3q3d15n9mn2jd_q91cym0000gn/T/88e5fcb997f2c6916eb4e9de3877434b/sync-promise-expanded-2.0.0.tgz","_from":"file:sync-promise-expanded-2.0.0.tgz","_nodeVersion":"22.23.1","_npmVersion":"12.0.2","dist":{"integrity":"sha512-4RtYBt1GfCSmPyPH8wmFYYpLgJCw1bl82OzPXxSIylWVBhJeZcXh9i6jMRhImsEcmdYGRqnesEqyBbkKojgjvw==","shasum":"d435153dca3357aa647888bb8c0808a9af130a52","tarball":"https://registry.npmjs.org/sync-promise-expanded/-/sync-promise-expanded-2.0.0.tgz","fileCount":19,"unpackedSize":47814,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQD12+ZXRWf1La6IuP7YqnJmXy6u5B3w4ePJObttvl4T7gIhAJktVoIIPam97slJxlfymUUTMPB8NuBCDg5NU2UJ5EvF"}]},"_npmUser":{"name":"brettz9","email":"brettz9@yahoo.com"},"maintainers":[{"name":"brettz9","email":"brettz9@yahoo.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/sync-promise-expanded_2.0.0_1786038341155_0.8012576708173718"},"_hasShrinkwrap":false}},"time":{"created":"2023-05-17T15:22:41.026Z","modified":"2026-08-06T17:45:41.432Z","1.0.0":"2023-05-17T15:22:41.310Z","2.0.0":"2026-08-06T17:45:41.294Z"},"bugs":{"url":"https://github.com/brettz9/sync-promise/issues"},"author":{"name":"Simon Friis Vindum"},"license":"ISC","homepage":"https://github.com/brettz9/sync-promise","keywords":["indexeddb","promises"],"repository":{"type":"git","url":"git+https://github.com/brettz9/sync-promise.git"},"description":"Ultra compact synchronized promise implementation.","contributors":[{"name":"Brett Zamir"}],"maintainers":[{"name":"brettz9","email":"brettz9@yahoo.com"}],"readme":"# SyncPromise\n\nA fast, small, _safe_ promise implementation with synchronous promise\nresolution and an API which resembles ECMAScript promises.\n\nSyncPromise is incompliant with the Promises/A+ spec, specifically part\n[2.2.4](https://promisesaplus.com/#point-34).\n\n## Why\n\nPromises make handling asynchronous operations easier. IndexedDB exposes a\nlot of asynchronous operations. That sounds like a great match? Well, [unfortunately things\nare not so simple](http://stackoverflow.com/questions/28388129/inconsistent-interplay-between-indexeddb-transactions-and-promises/)\nIt is not possible to use Promises/A+ promises inside IndexedDB transactions\nin a cross browser way.\n\nSyncPromise was created because it's author wanted to use promises in\nIndexedDB transaction for the library [SyncedDB](https://github.com/paldepind/synceddb)\n– both internally and in the user facing API. It was released in the hope that\nit would be of use to others who work directly with IndexedDB.\n\n## Features\n\n* Weighs less than 1KB when minified (not gzipped).\n* Familiar API that is very similar to the native ECMAScript promises API.\n* Provides a safety mechanism to prevent [releasing Zalgo](http://blog.izs.me/post/59142742143/designing-apis-for-asynchrony)\n* Distributed both as a CommonJS package, AMD module, global export and as a\n  version suitable for including directly in other source code.\n\n## Safety\n\nIt is for good reason that the Promises/A+ specification requires\nasynchronous resolution! Without care taken one can end up creating promises\nthat are sometimes synchronous and sometimes asynchronous. That is a _very_\nbad idea that leads to unpredictable non-deterministic behaviour ([see this post for a\ndetailed explanation](http://blog.ometer.com/2011/07/24/callbacks-synchronous-and-asynchronous/)).\n\n### Restrictions\n\nFortunately SyncPromise imposes two restrictions on usage. The first ensures\nthat promises are never resolved immediately. The second makes sure\nthat no errors get swallowed. Together these restrictions ensure that a\npromise chain will _always_ be run asynchronously.\n\n### Promises that are synchronously resolved can't be chained\n\nThrowing an exception directly in the promise body counts as a synchronous\nresolution and will therefore be resolved instead with `setTimeout(..., 0)`.\n\n```javascript\nnew SyncPromise((resolve, reject) => {\n  resolve('foo'); // <- Will be treated as async resolve\n}).then((result) => {\n  // result === 'foo'; // true\n});\n\nnew SyncPromise((resolve, reject) => {\n  setTimeout(resolve, 10); // <- Asynchronous resolve\n}).then(() => {\n  return 1; // Fine!\n}).then((n) => {\n  // n === 1; // true\n});\n```\n\nUncaught errors will be thrown if the rejection occurs within the `SyncPromise`\nfunction body and there is no `catch`, however:\n\n```javascript\nconst syncProm = new SyncPromise((res, rej) => {\n  setTimeout(() => {\n    throw new Error('err');\n  }, 0);\n});\n```\n\n### If a promise rejects, at least one `onRejected` callback must have been attached\n\nThis ensures that all rejected promises are handled. Other promise libraries\n(Bluebird for instance) use async mechanisms to ensure this.\n\n```javascript\nconst p = new SyncPromise((resolve, reject) => {\n  // Error is thrown – no rejection handlers attached yet\n  setTimeout(reject, 10);\n});\nsetTimeout(() => {\n  p.catch(() => {\n    //\n  });\n}, 20);\n```\n\n## Installation\n\n### Node.js/Browserify\n\n```shell\nnpm install sync-promise-expanded\n```\n\nThen:\n\n```js\nimport SyncPromise from 'sync-promise-expanded';\n\nSyncPromise.all([\n  // ...\n]);\n```\n\n### Browser\n\n```shell\nnpm install sync-promise-expanded\n```\n\nThen include the global export or the AMD module.\n\n## Example\n\n```javascript\n// This is a wrapper around IDBStore#get.\n// Had it been written using native promises it would have closed the\n// transaction when calling `resolve` or `reject`\nfunction getRecord (IDBStore, key) {\n  return new SyncPromise((resolve, reject) => {\n    const req = IDBStore.get(key);\n    req.onsuccess = function () {\n      if (req.result !== undefined) {\n        resolve(req.result);\n      } else {\n        reject('KeyNotFoundError');\n      }\n    };\n    req.addEventListener('error', reject);\n  });\n}\n\n// Usage\nconst tx = db.transaction('books', 'readonly');\nconst bookStore = tx.objectStore('books');\n\ngetRecord(bookStore, 'Bedrock Nights').then((book) => {\n  // We got the book, and the transaction is still open so we\n  // can make another request. Had `getRecord` used native promises\n  // the transaction whould have been closed by now.\n});\n```\n\n## Differences from ECMAScript promises\n\n* Synchronized resolution and rejection, of course.\n* `Promise.resolve` and `Promise.reject` are implemented with\n  `setTimeout(..., 0)` as are `resolve()` and `reject()` when run\n  synchronously.\n\n## API\n\n### new SyncPromise(function)\n\nCreates a new promise. The passed function is passed callbacks to both\nresolve and reject the promise.\n\n__Example:__\n\n```javascript\nconst p = new SyncPromise((resolve, reject) => {\n  const req = anIDBStore.get(key);\n  req.onsuccess = function () {\n    if (req.result !== undefined) {\n      resolve(req.result);\n    } else {\n      reject('KeyNotFoundError');\n    }\n  };\n  req.addEventListener('error', reject);\n});\n```\n\n### SyncPromise#then(function)\n\nThe passed function will be called if the promise is fulfilled. A new promise\nchained from the original promise is returned. The new promise is resolved with\nthe value that the function return. The new promise is rejected if the function\nthrows an error.\n\n__Example:__\n\n```javascript\ngetSomething.then((v) => {\n  return doSomething(v);\n}).then((v) => {\n  doSomethingElse(v);\n});\n```\n\n### SyncPromise#catch(function)\n\nThe passed function will be called if the promise is rejected. A new promise\nchained from the original promise is returned. The new promise is resolved with\nthe value that the function return. The new promise is rejected if the function\nthrows an error.\n\n__Example:__\n\n```javascript\ngetSomething.then((v) => {\n  return doSomething(v);\n}).then((v) => {\n  doSomethingElse(v);\n});\n```\n\n### SyncPromise.all(array)\n\nReturn a promise that is resolved when all promises in the array has fulfilled.\nIf one rejects, the promise is rejected for the same reason.\n\n__Example:__\n\n```javascript\nconst ps = [\n  new SyncPromise((resolve) => {\n    setTimeout(() => {\n      resolve(1);\n    }, 100);\n  }),\n  2,\n  new SyncPromise((resolve) => {\n    setTimeout(() => {\n      resolve(3);\n    }, 9);\n  })\n];\nSyncPromise.all(ps).then((ns) => {\n  assert.deepEqual(ns, [1, 2, 3]);\n});\n```\n\n### SyncPromise.race(array)\n\nReturn a promise that is resolved when one of the promises in the array has\nfulfilled. If one rejects, the promise is rejected for the same reason.\n\n__Example:__\n\n```javascript\nconst ps = [\n  new SyncPromise((resolve) => {\n    resolve(1);\n  }),\n  2,\n  new SyncPromise((resolve) => {\n    setTimeout(() => {\n      resolve(3);\n    }, 9);\n  })\n];\nSyncPromise.race(ps).then((ns) => {\n  assert.deepEqual(ns, 2);\n});\n```\n\n### SyncPromise.resolve(val)\n\nEquivalent to:\n\n<!-- eslint-skip -->\n```javascript\nreturn new SyncPromise((resolve, reject) => {\n  setTimeout(() => {\n    resolve(val);\n  }, 0);\n});\n```\n\n### SyncPromise.reject(val)\n\nEquivalent to:\n\n<!-- eslint-skip -->\n```javascript\nreturn new SyncPromise((resolve, reject) => {\n  setTimeout(() => {\n    reject(val);\n  }, 0);\n});\n```\n","readmeFilename":"README.md"}