{"_id":"@atarashi/plugin-kit","name":"@atarashi/plugin-kit","dist-tags":{"latest":"1.0.0"},"versions":{"1.0.0":{"name":"@atarashi/plugin-kit","version":"1.0.0","description":"Types and test helpers for third-party Atarashi blueprint authors.","type":"module","license":"MIT","author":"Gautam Suthar <iamgautamsuthar@gmail.com> (https://www.github.com/callmegautam)","repository":{"type":"git","url":"git+https://github.com/callmegautam/atarashi.git","directory":"packages/plugin-kit"},"homepage":"https://github.com/callmegautam/atarashi/tree/main/packages/plugin-kit#readme","bugs":{"url":"https://github.com/callmegautam/atarashi/issues"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./package.json":"./package.json"},"main":"./dist/index.js","types":"./dist/index.d.ts","engines":{"node":">=20.11"},"dependencies":{"handlebars":"^4.7.8","zod":"^3.25.76","@atarashi/core":"1.0.0","@atarashi/registry":"1.0.0","@atarashi/schema":"1.0.0"},"publishConfig":{"access":"public"},"scripts":{"build":"tsup","typecheck":"tsc --noEmit -p tsconfig.json","test":"vitest run --coverage","clean":"rm -rf dist .turbo"},"_nodeVersion":"26.2.0","_id":"@atarashi/plugin-kit@1.0.0","dist":{"integrity":"sha512-yAGhaxMkgEu2YO3DoSi8nkmLPDai4guByj4ZXH9XCiuORFFfWfrESORmfjLkOblIG1BTyTJHqUm4SsDfv635Sw==","shasum":"8fb9109b97b356af06710d5649655eb40310426a","tarball":"https://registry.npmjs.org/@atarashi/plugin-kit/-/plugin-kit-1.0.0.tgz","fileCount":6,"unpackedSize":84250,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQDyFUG2Fb1zZJTPPJdOwxSfInLotkY/hN6S+cF8dIVw5QIgBYoRHO/n6wz07s8YocQW5yHkkoCERDJ5EkcLPcm+iQQ="}]},"_npmUser":{"name":"iamgautamsuthar","email":"iamgautamsuthar@gmail.com"},"directories":{},"maintainers":[{"name":"iamgautamsuthar","email":"iamgautamsuthar@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/plugin-kit_1.0.0_1789054553533_0.3135806488692432"},"_hasShrinkwrap":false}},"time":{"created":"2026-09-10T15:35:53.311Z","1.0.0":"2026-09-10T15:35:53.669Z","modified":"2026-09-10T15:35:53.993Z"},"maintainers":[{"name":"iamgautamsuthar","email":"iamgautamsuthar@gmail.com"}],"description":"Types and test helpers for third-party Atarashi blueprint authors.","homepage":"https://github.com/callmegautam/atarashi/tree/main/packages/plugin-kit#readme","repository":{"type":"git","url":"git+https://github.com/callmegautam/atarashi.git","directory":"packages/plugin-kit"},"author":"Gautam Suthar <iamgautamsuthar@gmail.com> (https://www.github.com/callmegautam)","bugs":{"url":"https://github.com/callmegautam/atarashi/issues"},"license":"MIT","readme":"# @atarashi/plugin-kit\n\nEverything you need to write, test and validate a third-party Atarashi\nblueprint. This is the only Atarashi package a blueprint author depends on, and\nit is a build- and test-time dependency: nothing in it is loaded by the projects\nyour blueprint generates.\n\n```bash\npnpm add -D @atarashi/plugin-kit\n```\n\n```ts\n// blueprint.ts\nimport { defineBlueprint, toManifestJson } from '@atarashi/plugin-kit';\n\nexport default defineBlueprint({\n    id: 'acme/redis',\n    version: '1.0.0',\n    description: 'Redis client wired to the app lifecycle.',\n    provides: ['cache', 'cache:redis'],\n    conflicts: ['cache'],\n    files: [{ from: 'templates/redis.ts.hbs', to: 'src/lib/redis.ts' }],\n    dependencies: { ioredis: '^5.4.1' },\n    env: [{ key: 'REDIS_URL', sample: 'redis://localhost:6379' }],\n});\n```\n\n`defineBlueprint` validates as it returns, so an invalid manifest **throws at\nbuild time** rather than failing for whoever installs your blueprint.\n`toManifestJson` serialises the fully defaulted manifest to the `blueprint.json`\nthe registry reads.\n\n## What you get\n\n| Export | Purpose |\n|---|---|\n| `defineBlueprint` / `definePreset` | Validate and fully default an authored manifest. Throws on an invalid definition. |\n| `toManifestJson` | Serialise a manifest to canonical `blueprint.json` text. |\n| `defineHooks` | Type a hook module's `beforeRender` / `afterRender` / `afterPlan`. |\n| `validateBlueprint` | Run the same conformance checks that gate a first-party release. |\n| `Catalogue` | A `BlueprintSource` over a directory of blueprints, for tests. |\n| `makeSpec` / `specForPreset` | Build a `ProjectSpec` the way the CLI would. |\n| `planFor` / `expectPlan` | Generate a plan: `Result` for asserting on failures, throwing for the happy path. |\n| `fileAt` / `hasFile` / `dependencyRange` | Assert on one generated file or one resolved dependency range. |\n| `FIXED_NOW` / `FIXED_VERSION` | Frozen clock and version, so snapshots stay byte-identical. |\n\nManifest and plan types (`BlueprintManifest`, `GenerationPlan`, `ProjectSpec`,\n`Contribution`, `FileEntry`, `Prompt` and the rest) are re-exported from\n`@atarashi/schema`, so you never import it directly.\n\n## Testing a blueprint\n\nThe harness generates a real plan in memory. Nothing touches disk, so a test is\nas fast as a unit test and asserts on the actual composed output.\n\n```ts\nimport { Catalogue, dependencyRange, expectPlan, fileAt, makeSpec } from '@atarashi/plugin-kit';\n\nconst catalogue = new Catalogue('./blueprints');\n\nit('registers the client when composed with express', async () => {\n    const spec = makeSpec(['core/node-ts', 'http/express', 'acme/redis']);\n    const plan = await expectPlan(catalogue, spec);\n\n    expect(fileAt(plan, 'src/lib/redis.ts')).toContain('new Redis(');\n    expect(dependencyRange(plan, 'ioredis')).toBe('^5.4.1');\n});\n```\n\nUse `planFor` instead of `expectPlan` when the failure *is* the assertion:\n\n```ts\nconst result = await planFor(catalogue, makeSpec(['acme/redis', 'acme/memcached']));\nexpect(result.ok).toBe(false);\nexpect(result.error.diagnostics[0].code).toBe('CAPABILITY_CONFLICT');\n```\n\n## Validating before you publish\n\n`validateBlueprint` is the implementation the first-party catalogue is gated on,\nnot a reduced copy of it. It checks the manifest, every `when` expression, every\ntemplate's Handlebars syntax, declared-versus-referenced prompts and env keys,\nand the dependency allowlist.\n\n```ts\nimport { validateBlueprint } from '@atarashi/plugin-kit';\n\nconst report = await validateBlueprint('./blueprints/acme/redis');\nif (!report.ok) {\n    for (const p of report.problems) console.error(`${p.severity}: ${p.check}: ${p.message}`);\n}\n```\n\nA standalone blueprint cannot know what it will compose with, so references it\ndoes not declare itself are warnings by default. Pass `knownPromptNames` and\n`knownEnvKeys` when you are validating a whole collection and can be strict.\n\n## Publishing\n\nPoint the `atarashi` field at the directory holding `blueprint.json`. The\ndirectory name itself is free; the id comes from the manifest.\n\n```json\n{\n    \"name\": \"atarashi-blueprint-redis\",\n    \"version\": \"1.0.0\",\n    \"atarashi\": \"./blueprint\",\n    \"files\": [\"blueprint\"],\n    \"devDependencies\": { \"@atarashi/plugin-kit\": \"^1.0.0\" }\n}\n```\n\nThe package name must match `atarashi-blueprint-<name>` (optionally scoped);\nthat pattern is what `--add npm:atarashi-blueprint-redis` resolves against.\n\nThird-party blueprints are not second-class: they use the same format and the\nsame validator as the first-party ones. Their hooks are sandboxed and require\nexplicit consent, and they may only draw dependencies from the reviewed\nallowlist. See\n[Authoring blueprints](https://github.com/callmegautam/atarashi/blob/main/docs/guide/authoring-blueprints.md)\nand the\n[plugin API reference](https://github.com/callmegautam/atarashi/blob/main/docs/guide/plugin-api.md).\n","readmeFilename":"","_rev":"1-eb9974d0e68c1d73ae0cf1164d246609"}