{"_id":"@blueprime/cross-store","_rev":"4-575bdcb3ce73cea21a2e54cb33e2876a","name":"@blueprime/cross-store","dist-tags":{"latest":"0.2.2"},"versions":{"0.1.0":{"name":"@blueprime/cross-store","version":"0.1.0","keywords":["timescaledb","postgres","cross-database","referential-integrity","foreign-key","typeorm","prisma"],"license":"Apache-2.0","_id":"@blueprime/cross-store@0.1.0","maintainers":[{"name":"blueprime-tech","email":"developers@blueprime.app"}],"homepage":"https://github.com/BluePrime-Technologies/typeorm-timescaledb/tree/main/packages/cross-store#readme","bugs":{"url":"https://github.com/BluePrime-Technologies/typeorm-timescaledb/issues"},"dist":{"shasum":"22717da322fb84fa1ebc22b5038c115282e69b3d","tarball":"https://registry.npmjs.org/@blueprime/cross-store/-/cross-store-0.1.0.tgz","fileCount":56,"integrity":"sha512-S0I4qQRPiYcc1BcMdEcEpBPtabxuupOJbciYIGsvxBl4LFEDlXFSFtXgFQmZwcYywCvQXF/029KNVCoK7LFcpQ==","signatures":[{"sig":"MEUCIQCmJZm9I5/vmCTJ3aJ/6Z9r7li3VTQxOUBAIelVikt50AIgBFJhJuEaRFLgIv+KQ/DnYhnq03EjrX3gNPvX+nFVtlM=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":166865},"type":"module","_from":"file:blueprime-cross-store-0.1.0.tgz","types":"./dist/index.d.ts","engines":{"node":"^20.19.0 || >=22.12.0"},"exports":{".":{"import":{"types":"./dist/index.d.ts","default":"./dist/index.js"}},"./prisma":{"import":{"types":"./dist/prisma.d.ts","default":"./dist/prisma.js"}},"./typeorm":{"import":{"types":"./dist/typeorm.d.ts","default":"./dist/typeorm.js"}}},"scripts":{"test":"vitest run --passWithNoTests","build":"tsc -b","test:unit":"vitest run --passWithNoTests --exclude '**/*.integration.test.ts'","typecheck":"tsc -b"},"_npmUser":{"name":"blueprime-tech","email":"developers@blueprime.app"},"_resolved":"/tmp/131b16961367b876b9b7481ad642f540/blueprime-cross-store-0.1.0.tgz","_integrity":"sha512-S0I4qQRPiYcc1BcMdEcEpBPtabxuupOJbciYIGsvxBl4LFEDlXFSFtXgFQmZwcYywCvQXF/029KNVCoK7LFcpQ==","repository":{"url":"git+https://github.com/BluePrime-Technologies/typeorm-timescaledb.git","type":"git","directory":"packages/cross-store"},"_npmVersion":"10.9.8","description":"Validated cross-store (@Resolve) references between TimescaleDB and another database.","directories":{},"sideEffects":false,"_nodeVersion":"22.23.1","dependencies":{"@blueprime/timescaledb-core":"0.5.0"},"publishConfig":{"access":"public"},"typesVersions":{"*":{"prisma":["./dist/prisma.d.ts"],"typeorm":["./dist/typeorm.d.ts"]}},"_hasShrinkwrap":false,"devDependencies":{"pg":"^8.21.0","prisma":"^6.0.0","typeorm":"^1.0.0","@prisma/client":"^6.0.0","testcontainers":"^12.0.1"},"peerDependencies":{"typeorm":"^0.3.20 || ^1.0.0","@prisma/client":"^5.0.0 || ^6.0.0"},"peerDependenciesMeta":{"typeorm":{"optional":true},"@prisma/client":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/cross-store_0.1.0_1784664108872_0.687120113034817","host":"s3://npm-registry-packages-npm-production"}},"0.2.0":{"name":"@blueprime/cross-store","version":"0.2.0","keywords":["timescaledb","postgres","cross-database","referential-integrity","foreign-key","typeorm","prisma"],"license":"Apache-2.0","_id":"@blueprime/cross-store@0.2.0","maintainers":[{"name":"blueprime-tech","email":"developers@blueprime.app"}],"homepage":"https://github.com/BluePrime-Technologies/typeorm-timescaledb/tree/main/packages/cross-store#readme","bugs":{"url":"https://github.com/BluePrime-Technologies/typeorm-timescaledb/issues"},"dist":{"shasum":"0800f6af09396cb13f2ac4a28d383909a97eed0b","tarball":"https://registry.npmjs.org/@blueprime/cross-store/-/cross-store-0.2.0.tgz","fileCount":60,"integrity":"sha512-BznkuneUIFZHkLGfMgiysEz4/aKM8Qj/JkzrT1fiunHmsecRdXRB9M1ZeyxiZSSjeRDB6g/Ogl4bVH1KIxvEOQ==","signatures":[{"sig":"MEUCIQD3Tm0UxwCdYkt50Y5z+6Mz0vUN3s4UKLgeyl1RYW0sRQIgLz2i5f58WrhEhxvpDmJVg8doVG0qfEdXsl0/eizewPA=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":186628},"type":"module","_from":"file:blueprime-cross-store-0.2.0.tgz","types":"./dist/index.d.ts","engines":{"node":"^20.19.0 || >=22.12.0"},"exports":{".":{"import":{"types":"./dist/index.d.ts","default":"./dist/index.js"}},"./prisma":{"import":{"types":"./dist/prisma.d.ts","default":"./dist/prisma.js"}},"./typeorm":{"import":{"types":"./dist/typeorm.d.ts","default":"./dist/typeorm.js"}}},"scripts":{"test":"vitest run --passWithNoTests","build":"tsc -b","test:unit":"vitest run --passWithNoTests --exclude '**/*.integration.test.ts'","typecheck":"tsc -b"},"_npmUser":{"name":"blueprime-tech","email":"developers@blueprime.app"},"_resolved":"/tmp/26273b9c86278bcdb000bbbc770ad670/blueprime-cross-store-0.2.0.tgz","_integrity":"sha512-BznkuneUIFZHkLGfMgiysEz4/aKM8Qj/JkzrT1fiunHmsecRdXRB9M1ZeyxiZSSjeRDB6g/Ogl4bVH1KIxvEOQ==","repository":{"url":"git+https://github.com/BluePrime-Technologies/typeorm-timescaledb.git","type":"git","directory":"packages/cross-store"},"_npmVersion":"10.9.8","description":"Validated cross-store (@Resolve) references between TimescaleDB and another database.","directories":{},"sideEffects":false,"_nodeVersion":"22.23.1","dependencies":{"@blueprime/timescaledb-core":"0.5.0"},"publishConfig":{"access":"public"},"typesVersions":{"*":{"prisma":["./dist/prisma.d.ts"],"typeorm":["./dist/typeorm.d.ts"]}},"_hasShrinkwrap":false,"devDependencies":{"pg":"^8.21.0","prisma":"^6.0.0","typeorm":"^1.0.0","@prisma/client":"^6.0.0","testcontainers":"^12.0.1"},"peerDependencies":{"typeorm":"^0.3.20 || ^1.0.0","@prisma/client":"^5.0.0 || ^6.0.0"},"peerDependenciesMeta":{"typeorm":{"optional":true},"@prisma/client":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/cross-store_0.2.0_1784682597194_0.7327020121933785","host":"s3://npm-registry-packages-npm-production"}},"0.2.1":{"name":"@blueprime/cross-store","version":"0.2.1","keywords":["timescaledb","postgres","cross-database","referential-integrity","foreign-key","typeorm","prisma"],"license":"Apache-2.0","_id":"@blueprime/cross-store@0.2.1","maintainers":[{"name":"blueprime-tech","email":"developers@blueprime.app"}],"homepage":"https://github.com/BluePrime-Technologies/typeorm-timescaledb/tree/main/packages/cross-store#readme","bugs":{"url":"https://github.com/BluePrime-Technologies/typeorm-timescaledb/issues"},"dist":{"shasum":"f805d692e6dd94547deb969e4c5afdab2619edfa","tarball":"https://registry.npmjs.org/@blueprime/cross-store/-/cross-store-0.2.1.tgz","fileCount":60,"integrity":"sha512-dMlI7xJEBjaqCtfKb0H+J81QkaU7VSM+Tq8lJPNzomJ9lWsCLzPCGoRcFM/zfcvxk4ZfDH3XxP75EfIdgVe9Fg==","signatures":[{"sig":"MEYCIQDbi2a2kxIVmL59kUFxaCX/Jm5lTiUuFmcviJxts30o6QIhALtnz8Ja8WCnuS/+/VRgZLkCqwDbaoBWEicpn1y5fD+v","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":197817},"type":"module","_from":"file:blueprime-cross-store-0.2.1.tgz","types":"./dist/index.d.ts","engines":{"node":"^20.19.0 || >=22.12.0"},"exports":{".":{"import":{"types":"./dist/index.d.ts","default":"./dist/index.js"}},"./prisma":{"import":{"types":"./dist/prisma.d.ts","default":"./dist/prisma.js"}},"./typeorm":{"import":{"types":"./dist/typeorm.d.ts","default":"./dist/typeorm.js"}}},"scripts":{"test":"vitest run --passWithNoTests","build":"tsc -b","test:unit":"vitest run --passWithNoTests --exclude '**/*.integration.test.ts'","typecheck":"tsc -b"},"_npmUser":{"name":"blueprime-tech","email":"developers@blueprime.app"},"_resolved":"/tmp/0c70274f60dbd4293948387a0f3c0ffc/blueprime-cross-store-0.2.1.tgz","_integrity":"sha512-dMlI7xJEBjaqCtfKb0H+J81QkaU7VSM+Tq8lJPNzomJ9lWsCLzPCGoRcFM/zfcvxk4ZfDH3XxP75EfIdgVe9Fg==","repository":{"url":"git+https://github.com/BluePrime-Technologies/typeorm-timescaledb.git","type":"git","directory":"packages/cross-store"},"_npmVersion":"10.9.8","description":"Validated cross-store (@Resolve) references between TimescaleDB and another database.","directories":{},"sideEffects":false,"_nodeVersion":"22.23.1","dependencies":{"@blueprime/timescaledb-core":"0.6.0"},"publishConfig":{"access":"public"},"typesVersions":{"*":{"prisma":["./dist/prisma.d.ts"],"typeorm":["./dist/typeorm.d.ts"]}},"_hasShrinkwrap":false,"devDependencies":{"pg":"^8.21.0","prisma":"^6.0.0","typeorm":"^1.0.0","@prisma/client":"^6.0.0","testcontainers":"^12.0.1"},"peerDependencies":{"typeorm":"^0.3.20 || ^1.0.0","@prisma/client":"^5.0.0 || ^6.0.0"},"peerDependenciesMeta":{"typeorm":{"optional":true},"@prisma/client":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/cross-store_0.2.1_1785139022452_0.47122057818125085","host":"s3://npm-registry-packages-npm-production"}},"0.2.2":{"name":"@blueprime/cross-store","version":"0.2.2","description":"Validated cross-store (@Resolve) references between TimescaleDB and another database.","license":"Apache-2.0","type":"module","keywords":["timescaledb","postgres","cross-database","referential-integrity","foreign-key","typeorm","prisma"],"repository":{"type":"git","url":"git+https://github.com/BluePrime-Technologies/typeorm-timescaledb.git","directory":"packages/cross-store"},"homepage":"https://github.com/BluePrime-Technologies/typeorm-timescaledb/tree/main/packages/cross-store#readme","bugs":{"url":"https://github.com/BluePrime-Technologies/typeorm-timescaledb/issues"},"engines":{"node":"^20.19.0 || >=22.12.0"},"exports":{".":{"import":{"types":"./dist/index.d.ts","default":"./dist/index.js"}},"./typeorm":{"import":{"types":"./dist/typeorm.d.ts","default":"./dist/typeorm.js"}},"./prisma":{"import":{"types":"./dist/prisma.d.ts","default":"./dist/prisma.js"}}},"types":"./dist/index.d.ts","typesVersions":{"*":{"typeorm":["./dist/typeorm.d.ts"],"prisma":["./dist/prisma.d.ts"]}},"sideEffects":false,"dependencies":{"@blueprime/timescaledb-core":"0.6.1"},"peerDependencies":{"@prisma/client":"^5.0.0 || ^6.0.0","typeorm":"^0.3.20 || ^1.0.0"},"peerDependenciesMeta":{"@prisma/client":{"optional":true},"typeorm":{"optional":true}},"devDependencies":{"@prisma/client":"^6.0.0","pg":"^8.21.0","prisma":"^6.0.0","testcontainers":"^12.0.1","typeorm":"^1.0.0"},"publishConfig":{"access":"public"},"scripts":{"build":"tsc -b","typecheck":"tsc -b","test:unit":"vitest run --passWithNoTests --exclude '**/*.integration.test.ts'","test":"vitest run --passWithNoTests"},"_id":"@blueprime/cross-store@0.2.2","_integrity":"sha512-T48FuTdhtYWsrTtoBWs7utTRln7GgPjNZyEXGwAEl6ezc09nZzX4PxAt8eJzQwplBP5am8EUE/EnYOOvo1kXxQ==","_resolved":"/tmp/9760b4d8608bf3d73aded86d8a44bfb9/blueprime-cross-store-0.2.2.tgz","_from":"file:blueprime-cross-store-0.2.2.tgz","_nodeVersion":"22.23.1","_npmVersion":"10.9.8","dist":{"integrity":"sha512-T48FuTdhtYWsrTtoBWs7utTRln7GgPjNZyEXGwAEl6ezc09nZzX4PxAt8eJzQwplBP5am8EUE/EnYOOvo1kXxQ==","shasum":"4779ffbce35afc2c804c17004cde1012d8ffffad","tarball":"https://registry.npmjs.org/@blueprime/cross-store/-/cross-store-0.2.2.tgz","fileCount":60,"unpackedSize":198139,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQDzchw6WJ18cEkqftIM2V/cN3guiWwcndvLRhVEl6liOAIhAMXYPEqzwt6l59hgYpkIpZqOU2CZ7uYEamzAVBBaKJfW"}]},"_npmUser":{"name":"blueprime-tech","email":"developers@blueprime.app"},"directories":{},"maintainers":[{"name":"blueprime-tech","email":"developers@blueprime.app"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/cross-store_0.2.2_1785141523957_0.4231078714963561"},"_hasShrinkwrap":false}},"time":{"created":"2026-07-21T20:01:48.693Z","modified":"2026-07-27T08:38:44.315Z","0.1.0":"2026-07-21T20:01:49.048Z","0.2.0":"2026-07-22T01:09:57.335Z","0.2.1":"2026-07-27T07:57:02.603Z","0.2.2":"2026-07-27T08:38:44.132Z"},"bugs":{"url":"https://github.com/BluePrime-Technologies/typeorm-timescaledb/issues"},"license":"Apache-2.0","homepage":"https://github.com/BluePrime-Technologies/typeorm-timescaledb/tree/main/packages/cross-store#readme","keywords":["timescaledb","postgres","cross-database","referential-integrity","foreign-key","typeorm","prisma"],"repository":{"type":"git","url":"git+https://github.com/BluePrime-Technologies/typeorm-timescaledb.git","directory":"packages/cross-store"},"description":"Validated cross-store (@Resolve) references between TimescaleDB and another database.","maintainers":[{"name":"blueprime-tech","email":"developers@blueprime.app"}],"readme":"# @blueprime/cross-store\n\n> Validated cross-**database** `@Resolve` references — application-level referential integrity\n> between two _separate_ database instances (e.g. a TimescaleDB events store and a canonical\n> Postgres store) that cannot share a SQL foreign key.\n\nIt is **not** FDW / dblink / logical replication: integrity is enforced in the application against\nthe two connections it already holds. The guarantee is honest and best-effort — there is a TOCTOU\nwindow across instances, mitigated (not eliminated) by append-only reference targets, a\ncaller-transaction validate-then-write, and a reconciliation sweep. That is why this lives in a\npackage apart from the zero-bug ORM core.\n\n## Install\n\n```sh\nnpm install @blueprime/cross-store\n```\n\nShips **ESM-only** with full type definitions. Requires Node `^20.19.0 || >=22.12.0`. The ORM is an\n**optional peer** — install whichever adapter you use:\n\n```sh\nnpm install typeorm         # TypeORM / any pg-style SqlRunner target\nnpm install @prisma/client  # or a Prisma target\n```\n\n## The shape\n\n- **`ReferenceRegistry`** — the anti-injection allowlist of every referenceable `(store, table,\ncolumn)` (+ optional scope columns). Every identifier is validated at registration.\n\n  ```ts\n  import { ReferenceRegistry } from '@blueprime/cross-store';\n\n  const registry = new ReferenceRegistry()\n    .register({ store: 'canonical', table: 'accounts', column: 'id', targetIsAppendOnly: true })\n    .register({\n      store: 'canonical',\n      table: 'categories',\n      column: 'name',\n      scopeColumns: ['workspace_id'],\n      // `scopeColumns` is only an ALLOW-list, so a check that omits the scope entirely would\n      // resolve across every tenant. Listing it here makes tenant isolation fail CLOSED:\n      // an unscoped check raises SCOPE_VIOLATION instead of matching another tenant's row.\n      requiredScopeColumns: ['workspace_id'],\n    });\n  ```\n\n- **`resolveReferences(checks, { registry, adapters, validators })`** — the batched resolve engine\n  (one `findMany` per `(store, table, column, scope)` group; `ADAPTER_UNAVAILABLE` is **never**\n  collapsed into `not_found`). Pair with **`assertAllResolved(verdicts)`** to fail closed.\n- **Adapters** (structural — the ORM is never imported by the core):\n  - `@blueprime/cross-store/typeorm` — `DataSourceAdapter` over a structural `SqlRunner` (anything\n    with `query(sql, params)`, e.g. a `pg.Pool` or a TypeORM `DataSource`).\n  - `@blueprime/cross-store/prisma` — `PrismaAdapter` over a `PrismaClientLike` (`$queryRawUnsafe`).\n    Uses `col::text = ANY($1)` because Prisma binds parameters type-strictly.\n- **`@Resolve('store.table.column', { scope, validators, required })`** + `resolveEntities` — the\n  entity declaration surface (decorator).\n- **`createManyResolved` / `verifyReferences`** (`@blueprime/cross-store/typeorm`) — validate-then-write\n  inside the caller's transaction (with a save-time re-check that closes the value **and** scope TOCTOU\n  windows), and a reconciliation sweep that partitions `{ dangling, unavailable }`.\n\nDomain policy (the concrete validators, the concrete registry contents) is supplied by the\napplication; this package ships only the generic mechanism.\n\n## Error taxonomy\n\n`CrossStoreError` distinguishes `REFERENCE_NOT_FOUND` (the referenced row genuinely does not exist)\nfrom `ADAPTER_UNAVAILABLE` (the target store was unreachable — a transient failure that must **not**\nbe treated as a broken reference). A reconciliation sweep therefore reports a store outage under\n`unavailable`, never as a false `dangling`.\n\n## Status\n\nPre-1.0 (`0.2.x`). The `@Resolve` API surface is still settling — expect additive change. Tested\nagainst real Postgres/TimescaleDB via Testcontainers.\n\n## License\n\nApache-2.0 © BluePrime Technologies. Maintained by Miracle Adebunmi ([@madebunmi-prime](https://github.com/madebunmi-prime)).\n","readmeFilename":"README.md"}