{"_id":"@pothos/selection-mapper","name":"@pothos/selection-mapper","dist-tags":{"latest":"0.1.0"},"versions":{"0.1.0":{"name":"@pothos/selection-mapper","version":"0.1.0","description":"shared selection-to-query walker for Pothos ORM plugins","main":"./lib/index.js","types":"./dts/index.d.ts","module":"./esm/index.js","exports":{"import":{"default":"./esm/index.js"},"require":{"types":"./dts/index.d.ts","default":"./lib/index.js"}},"repository":{"type":"git","url":"git+https://github.com/hayes/pothos.git","directory":"packages/selection-mapper"},"author":{"name":"Michael Hayes"},"license":"ISC","keywords":["pothos","graphql","schema","typescript","plugin"],"publishConfig":{"access":"public","provenance":true},"peerDependencies":{"@pothos/core":"*","graphql":"^16.10.0 || ^17.0.0"},"devDependencies":{"graphql":"^17.0.1","graphql-tag":"^2.12.6","vitest":"^4.1.4","@pothos/core":"4.14.0","@pothos/test-utils":"2.2.1"},"scripts":{"type":"tsc --project tsconfig.type.json","build":"pnpm build:clean && pnpm build:cjs && pnpm build:dts && pnpm build:esm","build:clean":"git clean -dfX esm lib","build:cjs":"swc src -d lib --config-file .swcrc -C module.type=commonjs --strip-leading-paths","build:esm":"cp -r dts/* esm/ && swc src -d esm --config-file .swcrc -C module.type=es6 --strip-leading-paths","build:dts":"tsc","test":"pnpm vitest run"},"_id":"@pothos/selection-mapper@0.1.0","bugs":{"url":"https://github.com/hayes/pothos/issues"},"homepage":"https://github.com/hayes/pothos#readme","_integrity":"sha512-CAXsJDqmYU+u9OLHHsJHd1jNp+mLjG8yXxxpW1ovQrsXbNIds8r2AUoIwlbOnIznWSAuonlChZjPk6EEaah0mA==","_resolved":"/tmp/pothos-selection-mapper-release-artifacts/pothos-selection-mapper-0.1.0.tgz","_from":"file:/tmp/pothos-selection-mapper-release-artifacts/pothos-selection-mapper-0.1.0.tgz","_nodeVersion":"26.7.0","_npmVersion":"11.19.0","dist":{"integrity":"sha512-CAXsJDqmYU+u9OLHHsJHd1jNp+mLjG8yXxxpW1ovQrsXbNIds8r2AUoIwlbOnIznWSAuonlChZjPk6EEaah0mA==","shasum":"2fc934a48863c079825b3d06875a3c717f295b61","tarball":"https://registry.npmjs.org/@pothos/selection-mapper/-/selection-mapper-0.1.0.tgz","fileCount":86,"unpackedSize":450713,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCIEiUXg7VPRv375vjLPZSC/dwFHhL2oC+4xrCrPAfE4JdAiAJ0HoJdUmWBphKypNu6ptq1pLAaigp8gvtWwDAHC+R3Q=="}]},"_npmUser":{"name":"hayes","email":"michael@hayes.io"},"directories":{},"maintainers":[{"name":"hayes","email":"michael@hayes.io"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/selection-mapper_0.1.0_1789111156290_0.05184128833834434"},"_hasShrinkwrap":false}},"time":{"created":"2026-09-11T07:19:16.122Z","0.1.0":"2026-09-11T07:19:16.480Z","modified":"2026-09-11T07:19:16.743Z"},"maintainers":[{"name":"hayes","email":"michael@hayes.io"}],"description":"shared selection-to-query walker for Pothos ORM plugins","homepage":"https://github.com/hayes/pothos#readme","keywords":["pothos","graphql","schema","typescript","plugin"],"repository":{"type":"git","url":"git+https://github.com/hayes/pothos.git","directory":"packages/selection-mapper"},"author":{"name":"Michael Hayes"},"bugs":{"url":"https://github.com/hayes/pothos/issues"},"license":"ISC","readme":"# @pothos/selection-mapper\n\nThe selection-to-query walker shared by `@pothos/plugin-prisma` and `@pothos/plugin-drizzle`. It\nturns the selection set a resolver receives into the ORM plugin's own query format — through\nfragments, variants, directives and indirect includes — and records the loader mappings the\nplugins' field resolvers look up at resolve time.\n\nThis package is an implementation detail of those plugins. Its exports exist for them and change\nwith them: it is not a supported public API, and its versions carry no compatibility promise of\ntheir own. Use the plugins.\n\nThe surface is what those plugins import and nothing more: `Plan` (with the statics `Plan.fromInfo`\nand `Plan.forParentRow`), `Adapter` and `NodeAdapter`, the loader-map helpers (`cacheKey`,\n`getLoaderMapping`, `setFieldMapping`, `setLoaderMappings`, `setRowFieldMapping`,\n`setRowMappings`), `selectedFieldNames` and `deepEqual`. Turning a plan into the query a resolver\nis handed is each plugin's own job — prisma's `queryFromInfo` and drizzle's differ — so neither of\nthem is here.\n\n## Vocabulary\n\n- **Selection** — what the GraphQL document asks for: a `SelectionNode`, a selection set, a\n  fragment. Always the input side; graphql-js owns the word.\n- **Query** — what the ORM is told to load, in the ORM's own format (prisma\n  `{ select, include, ...args }`, drizzle `DBQueryConfig`). Opaque to the walker, which hands\n  queries to the adapter and returns what the adapter serializes. The `Query` type parameter.\n- **Model** — the adapter's description of one table or prisma model. One object per model, so\n  model identity is model equality.\n- **Node** — one level of the query being built (a model, its columns, its relations, its computed\n  values), and the tree of them one root accumulates into. The adapter owns the shape; the walker\n  reads only `node.model`.\n- **Plan** — what a traversal collected for one root: the model it loads, the selection it starts\n  from, and the merges it collected, in order. A plan holds no node.\n- **Merge** — one item in a plan's list: a type's selection, a variant's, a nested selection's\n  relation query, or a field's, each with the query the adapter produced for it.\n- **Play** — to fold a plan's merges into a fresh node, in order, behind a seed selection. Every\n  merge is offered to the node being built, so this is where one is accepted or rejected and the\n  only place a mapping is recorded. A plan can be played any number of times, behind a different\n  seed each time, and a play owns its node, so a caller may merge into what it gets back.\n- **Computed value** — what a node holds that is neither a column nor a relation: a value the ORM\n  computes per row (prisma's `_count` keys, drizzle's `extras`). `node.computed` in the shared\n  contract; each ORM keeps its own word for it in what its users read.\n- **Mapping** — what a play records for a field whose merge it took, so the field's resolver can\n  find its data in the loaded row; absent means the resolver loads its own data.\n- **Position** — where a field is: a link of `{ parent, type, field, node }` running back to the\n  field an entry point was called for, handed to a select function and recorded with the field's\n  mapping.\n\n## The adapter contract\n\nAn ORM plugin subclasses `Adapter<Model, Query, NodeType>`. Six members must be answered: three\ntranslate the schema — `modelFor` (a type's `Model`), `typeSelection` and `fieldSelection` (what a\ntype and a field select, in the ORM's own `Query` format) — and three accumulate — `createNode`\nfor a model, `mergeQuery` into one, `toQuery` for the node written back. The traversal reads\nnothing of a node but its `model`, and nothing of a query at all.\n\nThe four members below those are the merge rules, and each is inherited with the answer an adapter\nthat never shares a slot between two consumers wants: `canMergeQuery` is true, `firstConflict` is\nnone, and `mergeNode` and `canMergeNode` round-trip through `toQuery`. `canMergeQuery` and\n`firstConflict` ask the same thing of different callers: one is the yes or no a play gates a merge\non, the other names the first offending key for an error message. An adapter that gives every\nconsumer its own slot therefore writes six methods and nothing more.\n\n`MergeOptions` says how one merge differs from a plain one: `asQuery` (a relation query adds no\ncolumns), `lenient` (conflicting keys are left out rather than refused), `ignoreArgs` (the node's\nown top-level arguments are not compared), and the `alias` the query came from, so an adapter may\nmerge same-named relations into one node (prisma, drizzle) or keep one slot per selected field.\n`skipDeferredFragments` defaults to true.\n\n`NodeAdapter<Model, Query>` is what the prisma and drizzle adapters extend: the node tree of\n`node.ts` (columns, relations, computed values, arguments) with every merge rule this package\nowns. A subclass writes `visitQuery`, the key loop of its own query, reported key by key to a\n`QueryVisitor`; `toQuery`, the node written back; and optionally `computedConflicts` when its\ncomputed values are not compared by value — three methods on top of the three translation ones.\nThe visitor is reused down the tree, so a merge allocates only what the subclass's own key loop\nalready allocated. An ORM whose query is not a tree of columns, relations and computed values\nextends `Adapter` directly.\n\n## What an adapter must uphold\n\n- A field's `query` may be async, and what is built from it is then a promise. Every API that\n  takes one returns a `MaybePromise`, and a caller either awaits it or hands it on.\n- A merge holds the query the adapter produced for it by reference, and a play merges that same\n  object however many times the plan is played. A select function that returns a query and then\n  mutates it changes what a later play builds. Nothing copies it, because a query is opaque to\n  this package and could only be copied by round-tripping it through the adapter on every field.\n- Every play records its loader mappings on the request context, which pothos requires to be an\n  object; an adapter whose resolvers read a loaded row another way simply never looks them up.\n- Every select function is handed the `Position` of the field it plans: the field's node, the type\n  it was walked on, and a link to the position of the field the plan hangs beneath. The walker\n  reads none of it — an adapter that wants a path or a list of segments walks `parent` and\n  materializes its own — and records it with the field's mapping, so a resolver can ask the same\n  question the select path asked.\n","readmeFilename":"README.md","_rev":"1-2663e6758a290222100e45c3717610a2"}