{"_id":"@bounkhong/idempotency-core","name":"@bounkhong/idempotency-core","dist-tags":{"latest":"0.1.0"},"versions":{"0.1.0":{"name":"@bounkhong/idempotency-core","version":"0.1.0","description":"Core idempotency orchestration for Node.js backends","license":"MIT","author":{"name":"Bounkhong","url":"AIF"},"repository":{"type":"git","url":"git+https://github.com/aif/idempotency-package.git"},"bugs":{"url":"https://github.com/aif/idempotency-package/issues"},"homepage":"https://github.com/aif/idempotency-package#readme","keywords":["idempotency","nodejs","backend","deduplication","payments"],"type":"module","main":"dist/index.js","types":"dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"}},"publishConfig":{"access":"public"},"scripts":{"build":"tsc -p tsconfig.json","test":"vitest run","lint":"tsc -p tsconfig.json --noEmit","typecheck":"tsc -p tsconfig.json --noEmit"},"_id":"@bounkhong/idempotency-core@0.1.0","_integrity":"sha512-KgiJI8+H9WonNoDY0frGLlMElYvM1C2vL69wFg9ebVAGE8Jjq2RTJiSN4o/iJR0dQiKEDde73U99eSnhuEicGw==","_resolved":"/tmp/d4c9608d852e4c11fe2562eb1335017d/bounkhong-idempotency-core-0.1.0.tgz","_from":"file:bounkhong-idempotency-core-0.1.0.tgz","_nodeVersion":"22.22.3","_npmVersion":"10.9.8","dist":{"integrity":"sha512-KgiJI8+H9WonNoDY0frGLlMElYvM1C2vL69wFg9ebVAGE8Jjq2RTJiSN4o/iJR0dQiKEDde73U99eSnhuEicGw==","shasum":"50560cf8720f6ec4fbc9a090085c95b123430ff1","tarball":"https://registry.npmjs.org/@bounkhong/idempotency-core/-/idempotency-core-0.1.0.tgz","fileCount":6,"unpackedSize":16475,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQDDGkmjv+t61s2+aUdH/REDfXZ3vcOKFbyNthANCqINzAIgOejGYPUU/j3jlRY3R6ZTySJQas/7gSte4GGxrsVQZK0="}]},"_npmUser":{"name":"bounkhong","email":"bounkhong6655@gmail.com"},"directories":{},"maintainers":[{"name":"bounkhong","email":"bounkhong6655@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/idempotency-core_0.1.0_1779338602637_0.24394885763479435"},"_hasShrinkwrap":false}},"time":{"created":"2026-05-21T04:43:22.475Z","0.1.0":"2026-05-21T04:43:22.784Z","modified":"2026-05-21T04:43:23.004Z"},"maintainers":[{"name":"bounkhong","email":"bounkhong6655@gmail.com"}],"description":"Core idempotency orchestration for Node.js backends","homepage":"https://github.com/aif/idempotency-package#readme","keywords":["idempotency","nodejs","backend","deduplication","payments"],"repository":{"type":"git","url":"git+https://github.com/aif/idempotency-package.git"},"author":{"name":"Bounkhong","url":"AIF"},"bugs":{"url":"https://github.com/aif/idempotency-package/issues"},"license":"MIT","readme":"# @bounkhong/idempotency-core\n\nCore idempotency primitives and orchestration, independent of framework and storage.\n\n## Install\n\n```bash\npnpm add @bounkhong/idempotency-core\n```\n\n## What it provides\n\n- `IdempotencyStore` interface\n- `IdempotencyService` orchestration\n- state machine: `IN_PROGRESS | COMPLETED | FAILED | EXPIRED`\n- policy contract (`requireKey`, `ttlSeconds`, `scopeBuilder`, `fingerprintBuilder`, `inProgressStrategy`)\n- helper `defaultFingerprintBuilder`\n\n## Core flow\n\n1. `service.handle(input, policy)`\n2. If `action === \"execute\"`, run business logic once and call `service.complete(...)`\n3. On errors, call `service.fail(...)`\n4. If duplicate and completed, returns `action === \"replay\"`\n\n## Minimal usage\n\n```ts\nimport {\n  IdempotencyService,\n  defaultFingerprintBuilder,\n  type IdempotencyPolicy\n} from \"@bounkhong/idempotency-core\";\nimport { MemoryIdempotencyStore } from \"@bounkhong/idempotency-adapter-memory\";\n\nconst service = new IdempotencyService(new MemoryIdempotencyStore());\n\nconst policy: IdempotencyPolicy = {\n  requireKey: true,\n  ttlSeconds: 300,\n  inProgressStrategy: \"wait\",\n  scopeBuilder: (i) => `${i.method}:${i.route}:${i.idempotencyKey}`,\n  fingerprintBuilder: (i) => defaultFingerprintBuilder(i.payload)\n};\n\nconst result = await service.handle(\n  {\n    method: \"POST\",\n    route: \"/payments\",\n    idempotencyKey: \"pay-001\",\n    payload: { orderId: \"o-1\", amount: 100 }\n  },\n  policy\n);\n\nif (result.action === \"execute\") {\n  const responseBody = { id: \"pay_123\", status: \"captured\" };\n  await service.complete(result.scopeKey, {\n    statusCode: 201,\n    headers: {},\n    body: responseBody,\n    completedAt: new Date().toISOString()\n  });\n}\n```\n\n## Error behavior\n\n- same key + different payload => throws `IdempotencyConflictError`\n- missing key when `requireKey=true` => throws `IdempotencyKeyRequiredError`\n","readmeFilename":"README.md","_rev":"1-881d83171254442b890c179cb4e317fd"}