{"_id":"@bernierllc/nevar-graph-adapter-prisma","_rev":"2-7a77326d24877b6642c2f34f71c041fa","name":"@bernierllc/nevar-graph-adapter-prisma","dist-tags":{"latest":"0.1.1"},"versions":{"0.0.1":{"name":"@bernierllc/nevar-graph-adapter-prisma","version":"0.0.1","license":"SEE LICENSE IN README.md","_id":"@bernierllc/nevar-graph-adapter-prisma@0.0.1","maintainers":[{"name":"alikhan410","email":"mczeyo@gmail.com"},{"name":"mkbernier","email":"mkbernier@gmail.com"}],"dist":{"shasum":"d29b45d82a8bac8389486256b8bd0c99c190ddbe","tarball":"https://registry.npmjs.org/@bernierllc/nevar-graph-adapter-prisma/-/nevar-graph-adapter-prisma-0.0.1.tgz","fileCount":2,"integrity":"sha512-8rYHqzCTnui/qLtkiTHwUXEBWYduX94Qy7nvYvzgv3bRAbAwQ+BXroWRysK7dtK72+MclwyUjQBd3dGRrWNMAw==","signatures":[{"sig":"MEYCIQDeNODV0Ga+9BxuiN3F9AXAFidHUaIKeXLZTqypJax0EQIhAJkn1bKUS9dkIZtLAlHWLxM1hr3GrpCWuOgXW84UZ3FV","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":403},"_npmUser":{"name":"mkbernier","email":"mkbernier@gmail.com"},"_npmVersion":"11.12.1","description":"Placeholder for OIDC trusted-publisher bootstrap. Real release follows via GitHub Actions.","directories":{},"_nodeVersion":"25.9.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/nevar-graph-adapter-prisma_0.0.1_1779119036992_0.9303048908765204","host":"s3://npm-registry-packages-npm-production"}},"0.1.1":{"name":"@bernierllc/nevar-graph-adapter-prisma","version":"0.1.1","description":"Prisma storage backend for Nevar Graph — implements GraphStorageAdapter against a real Postgres database","main":"dist/index.js","types":"dist/index.d.ts","keywords":["nevar","graph","storage","adapter","prisma","postgres","bernierllc"],"author":{"name":"Bernier LLC"},"license":"SEE LICENSE IN LICENSE","dependencies":{"uuid":"^9.0.0","@bernierllc/nevar-graph-types":"0.1.2","@bernierllc/nevar-graph-storage":"0.1.1"},"devDependencies":{"@prisma/client":"^5.0.0","prisma":"^5.0.0","@types/jest":"^29.5.0","@types/node":"^20.0.0","@types/uuid":"^9.0.0","@typescript-eslint/eslint-plugin":"^6.0.0","@typescript-eslint/parser":"^6.0.0","eslint":"^8.0.0","jest":"^29.5.0","ts-jest":"^29.1.0","typescript":"^5.0.0"},"publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"scripts":{"build":"tsc","test":"jest","test:run":"jest","test:coverage":"jest --coverage","lint":"eslint src __tests__ --ext .ts","clean":"rm -rf dist","db:push":"prisma db push --schema=prisma/schema.prisma","db:migrate":"prisma migrate deploy --schema=prisma/schema.prisma"},"_id":"@bernierllc/nevar-graph-adapter-prisma@0.1.1","_integrity":"sha512-js+vqRQaB9NoSn8XqJonq0CKU/uVHOnUv/6Bg47KHDsivMgbmaKorNKcHt0beuCVVNGWR4cdiZysa7VABdVwwg==","_resolved":"/private/var/folders/r0/wspnzd1s18sfjy10ffyv2qxw0000gn/T/e6b1cc5298653fff766eb720aea6b9ee/bernierllc-nevar-graph-adapter-prisma-0.1.1.tgz","_from":"file:bernierllc-nevar-graph-adapter-prisma-0.1.1.tgz","_nodeVersion":"25.9.0","_npmVersion":"11.12.1","dist":{"integrity":"sha512-js+vqRQaB9NoSn8XqJonq0CKU/uVHOnUv/6Bg47KHDsivMgbmaKorNKcHt0beuCVVNGWR4cdiZysa7VABdVwwg==","shasum":"a0ccd169c837ae8da686bd064a8589bb1e321dcf","tarball":"https://registry.npmjs.org/@bernierllc/nevar-graph-adapter-prisma/-/nevar-graph-adapter-prisma-0.1.1.tgz","fileCount":25,"unpackedSize":54859,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQCyg5HuxZxwz96Gg6uLboHAzwBnscQllS/SiatqcvaAMgIhAOZ/l5YJNfNbcrSAfWQkDlBlMa3tmcPX6KUnqGthlOMt"}]},"_npmUser":{"name":"mkbernier","email":"mkbernier@gmail.com"},"directories":{},"maintainers":[{"name":"alikhan410","email":"mczeyo@gmail.com"},{"name":"mkbernier","email":"mkbernier@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/nevar-graph-adapter-prisma_0.1.1_1779127325820_0.07005612888649826"},"_hasShrinkwrap":false}},"time":{"created":"2026-05-18T15:43:56.886Z","modified":"2026-05-18T18:02:06.159Z","0.0.1":"2026-05-18T15:43:57.116Z","0.1.1":"2026-05-18T18:02:05.990Z"},"license":"SEE LICENSE IN LICENSE","description":"Prisma storage backend for Nevar Graph — implements GraphStorageAdapter against a real Postgres database","maintainers":[{"name":"alikhan410","email":"mczeyo@gmail.com"},{"name":"mkbernier","email":"mkbernier@gmail.com"}],"readme":"# @bernierllc/nevar-graph-adapter-prisma\n\nPrisma storage backend for Nevar Graph. Implements `GraphStorageAdapter` from `@bernierllc/nevar-graph-storage` using a real PostgreSQL database via Prisma.\n\n## Installation\n\n```bash\npnpm add @bernierllc/nevar-graph-adapter-prisma\n```\n\n## Usage\n\n```typescript\nimport { PrismaClient } from '@prisma/client';\nimport { PrismaGraphStorageAdapter } from '@bernierllc/nevar-graph-adapter-prisma';\n\nconst prisma = new PrismaClient();\nconst storage = new PrismaGraphStorageAdapter(prisma);\n\n// Create a graph definition\nconst graph = await storage.createGraph({\n  name: 'Notify on publish',\n  description: 'Sends notifications when content is published',\n  ownerType: 'organization',\n  ownerId: 'org-123',\n  triggerKey: 'event:content.published',\n  rootNodeIds: ['node-send-email'],\n  nodes: [\n    {\n      id: 'node-send-email',\n      actionType: 'action:send-email',\n      config: { to: 'team@example.com', template: 'published' },\n    },\n  ],\n  edges: [],\n  metadata: {},\n});\n\n// Idempotency check before starting a run (TTL: 5 minutes)\nconst existing = await storage.findRecentRunByIdempotencyKey(\n  'sha256-of-trigger-payload',\n  5 * 60 * 1000\n);\nif (existing) {\n  console.log('Duplicate trigger, skipping:', existing.id);\n}\n\n// Create an execution run\nconst run = await storage.createRun({\n  graphDefinitionId: graph.id,\n  triggerKey: 'event:content.published',\n  triggerPayload: { postId: '456', authorId: 'user-789' },\n  status: 'running',\n  startedAt: new Date(),\n  completedAt: null,\n  parentRunId: null,\n  idempotencyKey: 'sha256-of-trigger-payload',\n});\n```\n\n## API\n\nAll methods implement the `GraphStorageAdapter` interface from `@bernierllc/nevar-graph-storage`. See that package for full interface documentation.\n\n### Graph Definitions\n\n| Method | Description |\n|--------|-------------|\n| `createGraph(def)` | Persists a new graph definition. Generates `id`, `createdAt`, `updatedAt`. |\n| `getGraph(id)` | Returns the graph or `null`. Returns soft-deleted graphs too. |\n| `updateGraph(id, patch)` | Applies a partial patch. Updates `updatedAt`. Throws if not found. |\n| `listGraphs(filter)` | Filters by `triggerKey`, `ownerId`, and `includeDeleted` (default: false). |\n| `deleteGraph(id)` | Soft-deletes by setting `isDeleted: true`. Throws if not found. |\n\n### Graph Runs\n\n| Method | Description |\n|--------|-------------|\n| `createRun(run)` | Persists a new run. Generates `id`. |\n| `findRecentRunByIdempotencyKey(key, ttlMs)` | Returns a recent matching run within the TTL, or `null`. |\n| `updateRun(id, patch)` | Applies a partial patch. Throws if not found. |\n| `getRun(id)` | Returns the run or `null`. |\n| `listRunsForGraph(graphId, opts?)` | Lists runs newest-first. Supports `limit` and `status` filters. |\n\n### Step Records\n\n| Method | Description |\n|--------|-------------|\n| `appendStep(record)` | Appends a step record. Generates `id`. |\n| `listStepsForRun(runId)` | Returns all step records for a run, ordered by `startedAt` ascending. |\n\n## Schema Fragment\n\nCopy the Prisma models from the published schema fragment into your `schema.prisma`:\n\n```\nnode_modules/@bernierllc/nevar-graph-adapter-prisma/prisma/fragments/nevar-graph.prisma\n```\n\nAfter adding the models, run:\n\n```bash\nnpx prisma migrate dev --name add_nevar_graph_tables\n```\n\nThe fragment adds three tables: `nevar_graph_definitions`, `nevar_graph_runs`, `nevar_graph_step_records`.\n\n## DATABASE_URL Setup\n\nSet `DATABASE_URL` pointing to your PostgreSQL database:\n\n```bash\nDATABASE_URL=\"postgresql://user:password@localhost:5432/mydb\"\n```\n\n`DATABASE_URL` must be present at process startup. The application will hard-fail if it is missing when `PrismaClient` is constructed.\n\n## Errors\n\nAll Prisma errors are wrapped in `NevarGraphStorageError` from `@bernierllc/nevar-graph-storage` with ES2022 `cause` chaining. A package-specific `NevarGraphPrismaError` is also available:\n\n```typescript\nimport { NevarGraphPrismaError } from '@bernierllc/nevar-graph-adapter-prisma';\n\nconst err = new NevarGraphPrismaError('Connection failed', {\n  cause: originalError,\n  code: 'CONNECTION_FAILED',\n  context: { host: 'localhost', port: 5432 },\n});\n```\n\n## Running Conformance Tests\n\n```bash\n# 1. Create test database\ncreatedb nevar_graph_test\n\n# 2. Push schema\nDATABASE_URL=postgresql://user@localhost:5432/nevar_graph_test \\\n  pnpm --filter @bernierllc/nevar-graph-adapter-prisma db:push\n\n# 3. Run tests\nDATABASE_URL=postgresql://user@localhost:5432/nevar_graph_test \\\n  pnpm --filter @bernierllc/nevar-graph-adapter-prisma test:coverage\n```\n\n## Integrations\n\n### Logger integration\nLogger integration is consumer-driven. This is a low-level storage adapter — logging is the responsibility of the calling service layer, not the adapter itself. All Prisma errors are wrapped in `NevarGraphStorageError` / `NevarGraphPrismaError` with ES2022 `cause` chains, so consumers can use `@bernierllc/logger` (`getErrorChain`, `formatErrorChain`) at the call site:\n\n```typescript\nimport { getErrorChain } from '@bernierllc/logger';\n\ntry {\n  await storage.createRun(runInput);\n} catch (err) {\n  logger.error('graph run creation failed', { chain: getErrorChain(err) });\n  throw err;\n}\n```\n\n### NeverHub integration\nNeverHub integration is N/A at this layer — the adapter is a utility service (storage backend), not a service orchestrator. NeverHub registration is owned by the consuming orchestrator (`@bernierllc/nevar-graph-executor` and the `nevar` suite). This adapter operates purely as a data layer with no side effects beyond Prisma operations against `DATABASE_URL`.\n\n### Graceful degradation\nGraceful degradation is built in by design:\n\n- The adapter has no optional integrations of its own — when NeverHub or external logging is unavailable, storage operations continue normally.\n- The structural `NevarGraphPrismaClient` interface means consumers can swap in test doubles without importing `@prisma/client`.\n- Errors are surfaced as typed exceptions with full `cause` chains rather than silently swallowed, letting consumers decide retry/log/abort policy.\n\n## Structural Client Interface\n\nThe adapter accepts any object satisfying `NevarGraphPrismaClient`:\n\n```typescript\nimport type { NevarGraphPrismaClient } from '@bernierllc/nevar-graph-adapter-prisma';\n```\n\nThis allows the adapter to be used without importing `@prisma/client` at the type level.\n\n## License\n\nCopyright (c) 2025 Bernier LLC. Limited-use license — see `LICENSE`.\n","readmeFilename":"README.md","keywords":["nevar","graph","storage","adapter","prisma","postgres","bernierllc"],"author":{"name":"Bernier LLC"}}