{"_id":"@bernierllc/content-flow-adapter","_rev":"4-d5800d0ccb7f733b8a3253e36964d6e8","name":"@bernierllc/content-flow-adapter","dist-tags":{"latest":"0.2.3"},"versions":{"0.0.0":{"name":"@bernierllc/content-flow-adapter","version":"0.0.0","keywords":["oidc","trusted-publishing","setup"],"_id":"@bernierllc/content-flow-adapter@0.0.0","maintainers":[{"name":"alikhan410","email":"mczeyo@gmail.com"},{"name":"mkbernier","email":"mkbernier@gmail.com"}],"dist":{"shasum":"1ada551fdfd1b6244720ed0fbfb26fa16fb363fa","tarball":"https://registry.npmjs.org/@bernierllc/content-flow-adapter/-/content-flow-adapter-0.0.0.tgz","fileCount":2,"integrity":"sha512-OFAvXYhntR7EJsWMLKUlhWyb2y1K/Vtd1pnU5650GOxqSFaNyBCfo8eUXeFZWYrwt6R4iLMS6Cq1+mEvytykSQ==","signatures":[{"sig":"MEUCICHK5SfsDTR+kQVWHAStqxFsUtu+Mt7mx7f0ZJp/g14eAiEA2Oh9AwyJL0BXhs4pDKsIyZtkdrSccf782ZrBSb4A8xM=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":2091},"_npmUser":{"name":"mkbernier","email":"mkbernier@gmail.com"},"_npmVersion":"11.19.0","description":"OIDC trusted publishing setup package for @bernierllc/content-flow-adapter","directories":{},"_nodeVersion":"26.7.0","_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/content-flow-adapter_0.0.0_1787172202881_0.3091123512453118","host":"s3://npm-registry-packages-npm-production"}},"0.2.1":{"name":"@bernierllc/content-flow-adapter","version":"0.2.1","keywords":["content","flow-engine","adapter","kanban","pipeline","bernierllc","service"],"author":{"name":"Bernier LLC"},"license":"SEE LICENSE IN LICENSE","_id":"@bernierllc/content-flow-adapter@0.2.1","maintainers":[{"name":"alikhan410","email":"mczeyo@gmail.com"},{"name":"mkbernier","email":"mkbernier@gmail.com"}],"dist":{"shasum":"4adcf9c4b0a0866d523135c2ada6c8d428e09e34","tarball":"https://registry.npmjs.org/@bernierllc/content-flow-adapter/-/content-flow-adapter-0.2.1.tgz","fileCount":13,"integrity":"sha512-lJlXUaKeQ+kKk8jE5Dq6FYozT5OdVfB29arsHSS+hf3qgVRPhPTZSOkcHSozT7WPvWNh8oMhmYBKapQsg7pypA==","signatures":[{"sig":"MEQCIBybbhodMPSklV9PJmE1+W0FRH+1zAgL9+LkckwTO6v/AiBm0st6hSJXEmiwCiTzYSZSh75pque8K7+O81ooKj7qwQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":39450},"main":"dist/index.js","_from":"file:bernierllc-content-flow-adapter-0.2.1.tgz","types":"dist/index.d.ts","engines":{"node":">=16"},"scripts":{"lint":"eslint src __tests__ --ext .ts","test":"jest","build":"tsc","clean":"rimraf dist","prebuild":"npm run clean","test:run":"jest","test:coverage":"jest --coverage"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:5f212c09-f04e-4a81-9073-dc02d54df2f2"}},"_resolved":"/home/runner/work/tools/tools/packages/service/content-flow-adapter/bernierllc-content-flow-adapter-0.2.1.tgz","_integrity":"sha512-lJlXUaKeQ+kKk8jE5Dq6FYozT5OdVfB29arsHSS+hf3qgVRPhPTZSOkcHSozT7WPvWNh8oMhmYBKapQsg7pypA==","bernierllc":{"integration":{"logger":true,"neverhub":true,"docsIntegration":true}},"_npmVersion":"12.0.2","description":"Optional bridge that mirrors content items and editorial stage changes into @bernierllc/flow-engine flows — kanban visualization, flow analytics, and Nevar automation for the content manager with zero hard coupling","directories":{},"_nodeVersion":"24.19.0","dependencies":{"@bernierllc/logger":"1.7.1","@bernierllc/flow-types":"0.4.0","@bernierllc/neverhub-adapter":"0.4.1"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^29.5.0","rimraf":"^5.0.0","ts-jest":"^29.1.0","typescript":"^5.0.0","@types/jest":"^29.5.0","@types/node":"^20.0.0","@bernierllc/flow-engine":"0.4.1","@bernierllc/flow-storage":"0.4.1"},"peerDependencies":{"@bernierllc/flow-engine":"0.4.1","@bernierllc/content-project-manager":"0.7.3","@bernierllc/content-workflow-service":"0.6.1"},"peerDependenciesMeta":{"@bernierllc/flow-engine":{"optional":true},"@bernierllc/content-project-manager":{"optional":true},"@bernierllc/content-workflow-service":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/content-flow-adapter_0.2.1_1787246945782_0.7009818048037622","host":"s3://npm-registry-packages-npm-production"}},"0.2.2":{"name":"@bernierllc/content-flow-adapter","version":"0.2.2","keywords":["content","flow-engine","adapter","kanban","pipeline","bernierllc","service"],"author":{"name":"Bernier LLC"},"license":"SEE LICENSE IN LICENSE","_id":"@bernierllc/content-flow-adapter@0.2.2","maintainers":[{"name":"alikhan410","email":"mczeyo@gmail.com"},{"name":"mkbernier","email":"mkbernier@gmail.com"}],"dist":{"shasum":"bc555c27ed039365c1def6f7afbe84b17673782f","tarball":"https://registry.npmjs.org/@bernierllc/content-flow-adapter/-/content-flow-adapter-0.2.2.tgz","fileCount":13,"integrity":"sha512-kvDSTzNkATr8oV5l9mF3DAjdO2QIfbJMZO0Q41t+tg2YJ67YMI7wBo+lCqWVxeuYimeRX1zHGP1swl6njwnROw==","signatures":[{"sig":"MEYCIQDglcyUTKcD3EPmYFA0MwHVk9TqyjXu+G6uViF42JNo8AIhAL2d71u21NXouKCV/YYRyA0s3JK/WRADijH0czHLXqyA","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEQCIEENPVjnl/EC/DGCym0RPpCGK79LyHbCwgZNeRdaF25rAiBvC56u5wTvDS+ApZyX+87KSc9Df2K7EECcUXRTn5QL0g==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":39450},"main":"dist/index.js","_from":"file:bernierllc-content-flow-adapter-0.2.2.tgz","types":"dist/index.d.ts","engines":{"node":">=16"},"scripts":{"lint":"eslint src __tests__ --ext .ts","test":"jest","build":"tsc","clean":"rimraf dist","prebuild":"npm run clean","test:run":"jest","test:coverage":"jest --coverage"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"5f212c09-f04e-4a81-9073-dc02d54df2f2"}},"_resolved":"/home/runner/work/tools/tools/packages/service/content-flow-adapter/bernierllc-content-flow-adapter-0.2.2.tgz","_integrity":"sha512-kvDSTzNkATr8oV5l9mF3DAjdO2QIfbJMZO0Q41t+tg2YJ67YMI7wBo+lCqWVxeuYimeRX1zHGP1swl6njwnROw==","bernierllc":{"integration":{"logger":true,"neverhub":true,"docsIntegration":true}},"_npmVersion":"12.2.0","description":"Optional bridge that mirrors content items and editorial stage changes into @bernierllc/flow-engine flows — kanban visualization, flow analytics, and Nevar automation for the content manager with zero hard coupling","directories":{},"_nodeVersion":"24.21.0","dependencies":{"@bernierllc/logger":"1.7.1","@bernierllc/flow-types":"0.4.0","@bernierllc/neverhub-adapter":"0.4.1"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^29.5.0","rimraf":"^5.0.0","ts-jest":"^29.1.0","typescript":"^5.0.0","@types/jest":"^29.5.0","@types/node":"^20.0.0","@bernierllc/flow-engine":"0.4.2","@bernierllc/flow-storage":"0.4.1"},"peerDependencies":{"@bernierllc/flow-engine":"0.4.2","@bernierllc/content-project-manager":"0.7.3","@bernierllc/content-workflow-service":"0.6.1"},"peerDependenciesMeta":{"@bernierllc/flow-engine":{"optional":true},"@bernierllc/content-project-manager":{"optional":true},"@bernierllc/content-workflow-service":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/content-flow-adapter_0.2.2_1790882490485_0.8685996995712768","host":"s3://npm-registry-packages-npm-production"}},"0.2.3":{"_id":"@bernierllc/content-flow-adapter@0.2.3","dist":{"shasum":"88d30d2d285243bc568f4867e09361706430dd21","tarball":"https://registry.npmjs.org/@bernierllc/content-flow-adapter/-/content-flow-adapter-0.2.3.tgz","fileCount":13,"integrity":"sha512-WptaNflPS1XdSVFjKof8KDUnG1q/SjS2cqqpU25QSCGc3x9fNOWQNrJgI9gdLJcpMvxK3avLAucaqNBTc8NdNQ==","signatures":[{"sig":"MEUCIQDUhtSLLAJDLYFcnQUkb6iZOGhOu6Gzssc3kheNSIa8oAIgOpVWI4Qj4dlLeHShrpvMlAa9jfhBbfRWJyc7azVuuAA=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQD8UlG5e7J/c/RddpujPCFueJTjyIHcOGK6c3hBsh2idgIhAJMdbak6e31k7MgR/vCdYWPjZ5gMSp9WOgERRmlEjuY+"}],"unpackedSize":39456},"main":"dist/index.js","name":"@bernierllc/content-flow-adapter","_from":"file:bernierllc-content-flow-adapter-0.2.3.tgz","types":"dist/index.d.ts","author":{"name":"Bernier LLC"},"engines":{"node":">=16"},"license":"SEE LICENSE IN LICENSE","scripts":{"lint":"eslint src __tests__ --ext .ts","test":"jest","build":"tsc","clean":"rimraf dist","prebuild":"npm run clean","test:run":"jest","test:coverage":"jest --coverage"},"version":"0.2.3","_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"5f212c09-f04e-4a81-9073-dc02d54df2f2"}},"keywords":["content","flow-engine","adapter","kanban","pipeline","bernierllc","service"],"_resolved":"/home/runner/work/tools/tools/packages/service/content-flow-adapter/bernierllc-content-flow-adapter-0.2.3.tgz","_integrity":"sha512-WptaNflPS1XdSVFjKof8KDUnG1q/SjS2cqqpU25QSCGc3x9fNOWQNrJgI9gdLJcpMvxK3avLAucaqNBTc8NdNQ==","bernierllc":{"integration":{"logger":true,"neverhub":true,"docsIntegration":true}},"_npmVersion":"12.2.0","description":"Optional bridge that mirrors content items and editorial stage changes into @bernierllc/flow-engine flows — kanban visualization, flow analytics, and Nevar automation for the content manager with zero hard coupling","directories":{},"maintainers":[{"name":"alikhan410","email":"mczeyo@gmail.com"},{"name":"mkbernier","email":"mkbernier@gmail.com"}],"_nodeVersion":"24.21.0","dependencies":{"@bernierllc/logger":"^1.7.1","@bernierllc/flow-types":"^0.4.0","@bernierllc/neverhub-adapter":"^0.4.1"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^29.5.0","rimraf":"^5.0.0","ts-jest":"^29.1.0","typescript":"^5.0.0","@types/jest":"^29.5.0","@types/node":"^20.0.0","@bernierllc/flow-engine":"0.4.3","@bernierllc/flow-storage":"0.4.2"},"peerDependencies":{"@bernierllc/flow-engine":"^0.4.3","@bernierllc/content-project-manager":"^0.7.4","@bernierllc/content-workflow-service":"^0.6.2"},"peerDependenciesMeta":{"@bernierllc/flow-engine":{"optional":true},"@bernierllc/content-project-manager":{"optional":true},"@bernierllc/content-workflow-service":{"optional":true}},"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/content-flow-adapter_0.2.3_1790884136265_0.7697164675840753"}}},"time":{"created":"2026-08-19T20:43:22.675Z","modified":"2026-10-01T19:48:56.515Z","0.0.0":"2026-08-19T20:43:23.014Z","0.2.1":"2026-08-20T17:29:05.956Z","0.2.2":"2026-10-01T19:21:30.580Z","0.2.3":"2026-10-01T19:48:56.345Z"},"author":{"name":"Bernier LLC"},"license":"SEE LICENSE IN LICENSE","keywords":["content","flow-engine","adapter","kanban","pipeline","bernierllc","service"],"description":"Optional bridge that mirrors content items and editorial stage changes into @bernierllc/flow-engine flows — kanban visualization, flow analytics, and Nevar automation for the content manager with zero hard coupling","maintainers":[{"name":"alikhan410","email":"mczeyo@gmail.com"},{"name":"mkbernier","email":"mkbernier@gmail.com"}],"readme":"# @bernierllc/content-flow-adapter\n\n**Optional bridge that mirrors content items and editorial stage changes into [@bernierllc/flow-engine](../flow-engine) flows.**\n\nInstall it and your content pipeline shows up as a flow: kanban visualization via `flow-board-ui`, analytics via `flow-metrics`, automation via Nevar triggers. Don't install it and nothing changes — the content stack has **zero dependency** on the flow stack, and vice versa. Both sides are injected through duck-typed ports, so the adapter is the only place the two domains meet.\n\n## Install\n\n```bash\nnpm install @bernierllc/content-flow-adapter @bernierllc/flow-engine @bernierllc/flow-storage\n```\n\n`@bernierllc/flow-engine` (and the content packages) are **optional peer dependencies** — you bring whichever sides you use.\n\n## Quick start\n\n```typescript\nimport { createFlowEngine } from '@bernierllc/flow-engine';\nimport { InMemoryFlowStorage } from '@bernierllc/flow-storage';\nimport { createContentFlowAdapter } from '@bernierllc/content-flow-adapter';\n\nconst engine = createFlowEngine({ storage: new InMemoryFlowStorage() });\nawait engine.start();\n\nconst adapter = createContentFlowAdapter({ flowEngine: engine });\nawait adapter.initialize(); // registers with NeverHub (if present) + ensures the flow definition\n\n// Wire your content event sources (both optional, both detachable):\nconst detachWorkflow = adapter.attachWorkflowService(contentWorkflowService);\nconst detachCpm = adapter.attachContentProjectManager(contentProjectManager);\n```\n\nFrom then on, `stage_transitioned` events mirror into the flow (unknown content is auto-tracked), `content:added` starts tracking, `content:removed` archives. You can also drive it manually:\n\n```typescript\nawait adapter.trackContent({ id: 'post-1', title: 'Launch post', contentType: 'blog-post' });\nawait adapter.syncContentStage('post-1', 'review', { actorId: 'editor-1', actorType: 'user' });\nconst status = await adapter.getContentFlowStatus('post-1'); // { item, history }\nawait adapter.untrackContent('post-1'); // archives the flow item\n```\n\n## Bidirectional mode (board moves → content system)\n\n```typescript\nconst adapter = createContentFlowAdapter({\n  flowEngine: engine,\n  syncDirection: 'bidirectional',\n  onFlowTransition: async (contentId, toStageKey, record) => {\n    await contentWorkflowService.transitionStage({\n      contentId,\n      targetStageId: toStageKey,\n      userId: record.actorId,\n    });\n  },\n});\n// feed flow-side transitions (e.g. from a board UI) into:\nawait adapter.handleFlowTransition(record);\n```\n\nEcho suppression is built in: the adapter stamps its own writes with `metadata.source = '@bernierllc/content-flow-adapter'` and ignores them coming back, plus a time-window guard for unstamped echoes. Genuine ping-pong raises `SYNC_LOOP_DETECTED`.\n\n## The default flow\n\n`createDefaultContentFlowDefinition()` mirrors the standard editorial lifecycle:\n\n```\ndraft → review → approved → scheduled → publishing → published (terminal)\nreview → draft (reject) · publishing → failed → publishing (retry) · archived\n```\n\nStage keys match the content stack's status vocabulary (`ContentStatus` + `ContentState`), so the default `DEFAULT_CONTENT_STAGE_MAPPING` is an identity map. Override either:\n\n```typescript\ncreateContentFlowAdapter({\n  flowEngine: engine,\n  flowDefinition: myCustomCreateFlowInput,          // replace the whole flow\n  mapping: { stages: { live: 'published' }, fallbackStageKey: 'draft' },\n});\n```\n\n## Ports (duck-typed)\n\n| Port | Satisfied by | Used for |\n|------|-------------|----------|\n| `FlowEngineLike` | `@bernierllc/flow-engine`'s `FlowEngine` | all flow operations |\n| `WorkflowEventSourceLike` | `@bernierllc/content-workflow-service` (`onEvent`/`offEvent`) | mirroring stage transitions |\n| `ContentEventEmitterLike` | `@bernierllc/content-project-manager` (extends `@bernierllc/event-emitter`) | track/untrack on add/remove |\n| `ContentRef` | client `Content`, `WorkflowContent`, or any `{ id }` | tracking input |\n\n## Error Handling\n\nAll errors are `ContentFlowAdapterError` with ES2022 `Error.cause` chains.\n\n| Class | Code | Description | Retryable |\n|-------|------|-------------|-----------|\n| ContentFlowAdapterError | `CONTENT_FLOW_ADAPTER_ERROR` | Generic/wrapped engine failure | Depends on cause |\n| ContentFlowAdapterError | `FLOW_NOT_INITIALIZED` | Used before `initialize()` | No — call `initialize()` |\n| ContentFlowAdapterError | `CONTENT_NOT_TRACKED` | Sync/untrack on unknown content | No — `trackContent()` first |\n| ContentFlowAdapterError | `STAGE_MAPPING_ERROR` | Unmapped stage, no fallback | No — fix mapping |\n| ContentFlowAdapterError | `TRANSITION_FAILED` | Engine or callback rejected the transition | Sometimes — check cause |\n| ContentFlowAdapterError | `SYNC_LOOP_DETECTED` | Ping-pong between the two systems | No — fix wiring |\n| ContentFlowAdapterError | `INVALID_CONFIG` | Bad constructor config | No |\n\nEvent-driven mirroring (`attach*`) is fire-and-forget: failures are logged, never thrown — the same precedent as flow-engine's Nevar emission.\n\n## NeverHub\n\nAuto-detected at `initialize()` (standard `NEVERHUB_*` env vars). Fully functional without it.\n\n## License\n\nSEE LICENSE IN LICENSE — Copyright (c) 2025 Bernier LLC. Limited-use license.\n","readmeFilename":"README.md"}