{"_id":"@bmz_1/lambdi","_rev":"4-70f3bb0eed8335bb6167a4909568514a","name":"@bmz_1/lambdi","dist-tags":{"latest":"1.2.0"},"versions":{"1.0.0":{"name":"@bmz_1/lambdi","version":"1.0.0","keywords":["aws","lambda","di","dependency-injection","serverless","secrets-manager","env"],"author":{"name":"bmz"},"license":"MIT","_id":"@bmz_1/lambdi@1.0.0","maintainers":[{"name":"bmz_1","email":"boermate@gmail.com"}],"dist":{"shasum":"f8b1f0895d6aa9c9846eaf940059a8ebbb181857","tarball":"https://registry.npmjs.org/@bmz_1/lambdi/-/lambdi-1.0.0.tgz","fileCount":6,"integrity":"sha512-H3EfJEIAo5c3cPCddMK830Si+G16mHylo2t9CZHx1OQ/C9Ol09SWAGlqIZRH7nNVswmsgqIgkXmNcgOsRir6dQ==","signatures":[{"sig":"MEYCIQCGyFvrAn9wCre545K+5lYqLaJ4uCYjsEO/DmzxjF3MGAIhANZZCilD3dHm5Ys+9+K/HLwBGAQVYXGEP0jD0D3o6zbz","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":7504},"main":"dist/index.cjs","type":"module","types":"./dist/index.d.ts","exports":{"import":"./dist/index.mjs","require":"./dist/index.cjs"},"scripts":{"test":"vitest --run","build":"node build.mjs && tsc --project tsconfig.json","test:watch":"vitest","test:coverage":"vitest run --coverage","prepublishOnly":"npm run build"},"_npmUser":{"name":"bmz_1","email":"boermate@gmail.com"},"_npmVersion":"10.9.2","description":"Ultra‑light DI, env and secret helpers for AWS Lambda with zero cold‑start tax.","directories":{},"_nodeVersion":"22.14.0","_hasShrinkwrap":false,"devDependencies":{"vitest":"^3.1.2","typescript":"^5.8.3","@types/node":"^22.15.3","@vitest/coverage-v8":"^3.1.2"},"peerDependencies":{"@aws-sdk/client-secrets-manager":"^3.799.0"},"_npmOperationalInternal":{"tmp":"tmp/lambdi_1.0.0_1746196653661_0.26497679729301526","host":"s3://npm-registry-packages-npm-production"}},"1.0.4":{"name":"@bmz_1/lambdi","version":"1.0.4","keywords":["aws","lambda","di","dependency-injection","serverless","secrets-manager","env"],"author":{"name":"bmz"},"license":"MIT","_id":"@bmz_1/lambdi@1.0.4","maintainers":[{"name":"bmz_1","email":"boermate@gmail.com"}],"homepage":"https://github.com/bmz1/lambdi#readme","bugs":{"url":"https://github.com/bmz1/lambdi/issues"},"dist":{"shasum":"a7e7829a334b4aa6f636c67712ac9ced32f2c0fc","tarball":"https://registry.npmjs.org/@bmz_1/lambdi/-/lambdi-1.0.4.tgz","fileCount":6,"integrity":"sha512-hD8uXqojiU/gJY29aJGqTei7HH9D7piAi/mZ3vLfnnwGVuB8DrIJUO2Kp6f4V2uaraRu8XZsQVZWQM3r+dmiAA==","signatures":[{"sig":"MEUCIBFwzgGQImhLUVuwSiuWvv0/Hne7OwSjtb8DwpFHwlOTAiEA7CPRSbaA5YoqaBIF1wqLyZ5sHG0/I0as12uoeuOxnWY=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@bmz_1%2flambdi@1.0.4","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":7529},"main":"dist/index.cjs","type":"module","types":"dist/index.d.ts","exports":{"import":"./dist/index.mjs","require":"./dist/index.cjs"},"gitHead":"5a54dbecc9c216595adae8a6f47cb957d76ef2f7","scripts":{"test":"vitest --run","build":"node build.mjs && tsc --project tsconfig.json","test:watch":"vitest","test:coverage":"vitest run --coverage","prepublishOnly":"npm run build"},"_npmUser":{"name":"bmz_1","email":"boermate@gmail.com"},"repository":{"url":"git+https://github.com/bmz1/lambdi.git","type":"git"},"_npmVersion":"10.8.2","description":"Ultra‑light DI, env and secret helpers for AWS Lambda with zero cold‑start tax.","directories":{},"_nodeVersion":"20.19.1","_hasShrinkwrap":false,"devDependencies":{"vitest":"^3.1.2","typescript":"^5.8.3","@types/node":"^22.15.3","@vitest/coverage-v8":"^3.1.2"},"_npmOperationalInternal":{"tmp":"tmp/lambdi_1.0.4_1746199565613_0.9834217879174476","host":"s3://npm-registry-packages-npm-production"}},"1.1.1":{"name":"@bmz_1/lambdi","version":"1.1.1","keywords":["aws","lambda","di","dependency-injection","serverless","env"],"author":{"name":"bmz"},"license":"MIT","_id":"@bmz_1/lambdi@1.1.1","maintainers":[{"name":"bmz_1","email":"boermate@gmail.com"}],"homepage":"https://github.com/bmz1/lambdi#readme","bugs":{"url":"https://github.com/bmz1/lambdi/issues"},"dist":{"shasum":"6512988d33fc41d167a9c263fe320d927ea265f2","tarball":"https://registry.npmjs.org/@bmz_1/lambdi/-/lambdi-1.1.1.tgz","fileCount":8,"integrity":"sha512-EEvlBD9Ib8zfHDGoaONzWv/NO25ZM+LNQwM8FZVhpdS+qtRrlXWPTbLhb3+PZTsAz5QKNMUV1tow/AxvlmjZKA==","signatures":[{"sig":"MEQCIA+ngbnRBJzVRiQkbaHCgqFbF+kHUZA83MSoVYmaPp3GAiBx/tjXnyg1Nynll9cWBaydlMcRkXYz8olvKj3qBUjtyQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@bmz_1%2flambdi@1.1.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":9919},"type":"module","types":"dist/index.d.ts","exports":{".":"./dist/index.mjs","./di":"./dist/container.js","./loadenv":"./dist/loadenv.js"},"gitHead":"c19e336e1f1d8626ba4322304f1a48bcc578e077","scripts":{"test":"vitest --run","build":"node build.mjs && tsc --project tsconfig.json","test:watch":"vitest","test:coverage":"vitest run --coverage","prepublishOnly":"npm run build"},"_npmUser":{"name":"bmz_1","email":"boermate@gmail.com"},"repository":{"url":"git+https://github.com/bmz1/lambdi.git","type":"git"},"_npmVersion":"10.8.2","description":"Ultra‑light DI, and env helpers for AWS Lambda with zero cold‑start tax.","directories":{},"sideEffects":false,"_nodeVersion":"20.19.1","typesVersions":{"*":{"di":["dist/container.d.ts"],"loadenv":["dist/loadenv.d.ts"]}},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^3.1.2","@zod/mini":"^4.0.0-beta.20250503T014749","typescript":"^5.8.3","@types/node":"^22.15.3","@vitest/coverage-v8":"^3.1.2"},"peerDependencies":{"@zod/mini":"^4.0.0-beta.20250503T014749"},"_npmOperationalInternal":{"tmp":"tmp/lambdi_1.1.1_1746292141451_0.46244305833618893","host":"s3://npm-registry-packages-npm-production"}},"1.2.0":{"name":"@bmz_1/lambdi","version":"1.2.0","type":"module","types":"dist/index.d.ts","typesVersions":{"*":{"di":["dist/container.d.ts"],"loadenv":["dist/loadenv.d.ts"]}},"exports":{".":"./dist/index.mjs","./di":"./dist/container.js","./loadenv":"./dist/loadenv.js"},"description":"Ultra‑light DI, and env helpers for AWS Lambda with zero cold‑start tax.","keywords":["aws","lambda","di","dependency-injection","serverless","env"],"author":{"name":"bmz"},"license":"MIT","scripts":{"build":"node build.mjs && tsc --project tsconfig.json","prepublishOnly":"npm run build","test":"vitest --run","test:watch":"vitest","test:coverage":"vitest run --coverage"},"devDependencies":{"@zod/mini":"^4.0.0-beta.20250503T014749","@types/node":"^22.15.3","@vitest/coverage-v8":"^3.1.2","typescript":"^5.8.3","vitest":"^3.1.2"},"repository":{"type":"git","url":"git+https://github.com/bmz1/lambdi.git"},"peerDependencies":{"@zod/mini":"^4.0.0-beta.20250503T014749"},"sideEffects":false,"_id":"@bmz_1/lambdi@1.2.0","gitHead":"79b60379710034b40de5b9a3fc59fec014b3ed2d","bugs":{"url":"https://github.com/bmz1/lambdi/issues"},"homepage":"https://github.com/bmz1/lambdi#readme","_nodeVersion":"20.19.1","_npmVersion":"10.8.2","dist":{"integrity":"sha512-bw21/kz/jWaK6ckKDfDl+bezrDl9w8vKHPS9xNTFzS/xVVlvk5vFiaiZ6uOFzLm7eDO96cVXMcaVjyNjl7QyIg==","shasum":"857e443ca92dc9cedd314e755b14c228e232f9d9","tarball":"https://registry.npmjs.org/@bmz_1/lambdi/-/lambdi-1.2.0.tgz","fileCount":8,"unpackedSize":15865,"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@bmz_1%2flambdi@1.2.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQDlyaQqPC9rVt0GdNHe1KM2HnIQZqPvg8iwjW1V8T9qpwIhAIH+zZHN9cYLVKmYCgURe5WJ5M4V36Y7X91iFP1cbl9x"}]},"_npmUser":{"name":"bmz_1","email":"boermate@gmail.com"},"directories":{},"maintainers":[{"name":"bmz_1","email":"boermate@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/lambdi_1.2.0_1746778939672_0.47004073554342796"},"_hasShrinkwrap":false}},"time":{"created":"2025-05-02T14:37:33.515Z","modified":"2025-05-09T08:22:20.246Z","1.0.0":"2025-05-02T14:37:33.865Z","1.0.4":"2025-05-02T15:26:05.814Z","1.1.1":"2025-05-03T17:09:01.686Z","1.2.0":"2025-05-09T08:22:19.846Z"},"bugs":{"url":"https://github.com/bmz1/lambdi/issues"},"author":{"name":"bmz"},"license":"MIT","homepage":"https://github.com/bmz1/lambdi#readme","keywords":["aws","lambda","di","dependency-injection","serverless","env"],"repository":{"type":"git","url":"git+https://github.com/bmz1/lambdi.git"},"description":"Ultra‑light DI, and env helpers for AWS Lambda with zero cold‑start tax.","maintainers":[{"name":"bmz_1","email":"boermate@gmail.com"}],"readme":"# `@bmz_1/lambdi`\n\n![Coverage](https://img.shields.io/badge/coverage-100%25-brightgreen?style=flat-square)\n\nUltra‑light **dependency‑injection container** and **environment variable loader/validator** for AWS Lambda — zero cold‑start tax, zero runtime dependencies.\n\n> **λ + DI = lambdi** – pronounced “lam‑dee”.\n\n---\n\n## Packages\n\n- **`container`**: Ultra-light, type-safe dependency injection for AWS Lambda (and beyond)\n- **`loadenv`**: Fast, type-safe environment variable validation using [Zod Mini](https://github.com/colinhacks/zod-mini)\n\n---\n\n## Table of Contents\n\n- [Bundle sizes](#-bundle-sizes-esm-only)\n- [ESM-only exports](#-esm-only-exports)\n- [Why lambdi?](#why-lambdi)\n- [Features](#features)\n- [Installation](#installation)\n- [Quick start: Dependency Injection (`container`)](#quick-start)\n- [Environment variable validation (`loadenv`)](#environment-variable-validation-loadenv)\n- [API](#api)\n- [Example: Scoped per-request objects](#example-scoped-per-request-objects)\n- [Testing pattern](#testing-pattern)\n- [License](#license)\n\n---\n\n## 📦 Bundle sizes (ESM only)\n\n```\nBuild complete: dist/index.{mjs}, dist/container.js, dist/loadenv.js\n  • dist/index.mjs:    17.3 KB\n  • dist/container.js: 598 B\n  • dist/loadenv.js:   16.8 KB\n```\n\n---\n\n## 📦 ESM-only exports\n\nAll entrypoints are ESM, with subpath exports for each module:\n\n```json\n\"exports\": {\n  \".\": \"./dist/index.mjs\",\n  \"./di\": \"./dist/container.js\",\n  \"./loadenv\": \"./dist/loadenv.js\"\n}\n```\n\n**Import examples:**\n\n```js\n// Main entry (everything)\nimport { container, token, loadenv, envSchema } from '@bmz_1/lambdi';\n\n// Dependency Injection only\nimport { container, token } from '@bmz_1/lambdi/di';\n\n// Environment helpers only\nimport { loadenv, envSchema } from '@bmz_1/lambdi/loadenv';\n```\n\n---\n\n## Why lambdi?\n\n| Pain point                                             | lambdi’s fix                                                   | Cost                   |\n| ------------------------------------------------------ | -------------------------------------------------------------- | ---------------------- |\n| Heavy AWS clients re‑initialised every warm invocation | Process‑wide **singleton container** caches them automatically | < 1 µs per `resolve()` |\n| DI frameworks add 400 KB to bundle                     | `lambdi` dual build is **< 8 KB gzipped**                      | No cold‑start hit      |\n| Key‑string collisions between libraries                | **Typed tokens** (unique `symbol`s) stop clashes               | Compile‑time safety    |\n| Resource leaks in tests                                | Optional **`disposeAll()`** cleans up                          | Single loop call       |\n| Hard‑to‑mock singletons                                | `createScope()` spins fresh child containers                   | Zero extra deps        |\n\n---\n\n## Features\n\n* 🐑 **Singleton DI container** that survives warm Lambda invocations\n* 🔑 **Type‑safe tokens** prevent collisions & give IntelliSense\n* ⚡ **Promise deduplication** – async factories run once even under high concurrency\n* 🧹 **Disposal hooks & scoped containers** for clean tests and per‑request objects\n* 🪶 **Tiny bundle** – < 8 KB gzipped, no runtime deps\n\n---\n\n## Installation\n\n```bash\nnpm install @bmz_1/lambdi\n```\n\n> Node 20+ is required (matches current AWS Lambda runtimes).\n\n---\n\n## Quick start: Dependency Injection (`container`)\n\n```ts\nimport { container, token } from '@bmz_1/lambdi';\nimport { DynamoDBClient } from '@aws-sdk/client-dynamodb';\n\n// create a typed token once – no string collisions\nconst DDB = token<DynamoDBClient>('ddb');\n\n// Register dependencies at startup (cold start)\ncontainer.register(DDB, () => new DynamoDBClient({ region: 'us-east-1' }));\n\nexport const handler = async () => {\n  // Resolve previously registered dependency - cached for warm invocations\n  const ddb = await container.resolve(DDB);\n\n  /* … use ddb … */\n  return { ok: true };\n};\n```\n\n---\n\n## Quick start: Environment variable validation (`loadenv`)\n\nValidate and type-check your environment variables at startup using Zod Mini schemas.\n\n- Throws if any required variable is missing or invalid.\n- Returns a fully typed, validated object.\n- Works with both main and subpath imports.\n\n**Usage:**\n\n```ts\nimport { loadenv, envSchema } from '@bmz_1/lambdi';\n// or: import { loadenv, envSchema } from '@bmz_1/lambdi/loadenv';\nimport * as z from '@zod/mini';\n\nconst schema = envSchema({\n  DATABASE_URL: z.string(),\n  PORT: z.string().optional(),\n  DEBUG: z.boolean().optional(),\n});\n\nconst env = loadenv(schema);\n// env.DATABASE_URL is string\n// env.PORT is string | undefined\n// env.DEBUG is boolean | undefined\n\nconsole.log('Database URL:', env.DATABASE_URL);\n```\n\nYou can also pass a custom source object (e.g., for tests):\n\n```ts\nconst env = loadenv(schema, { DATABASE_URL: 'sqlite://:memory:' });\n```\n\n---\n\n## API\n\n### Dependency Injection (`container`)\n\n| Item                                    | Description                                       |\n| --------------------------------------- | ------------------------------------------------- |\n| `container`                             | Process‑wide singleton `Container` instance       |\n| `token<T>(description)`                 | Create an `InjectionToken<T>` (unique `symbol`)   |\n| `container.register(token, factory, options?)` | Register a factory function for a token          |\n| `container.registerValue(token, value, options?)` | Register an existing value for a token         |\n| `container.resolve(token)`              | Resolve a previously registered dependency        |\n| `container.createScope()`               | Child container inheriting parent singletons      |\n| `container.disposeAll()`                | Run disposers, clear cache (useful in tests)      |\n| `FactoryOptions.dispose(value)`         | Optional disposer registered per singleton        |\n\n### Environment Variable Loader (`loadenv`)\n\n| Item                      | Description                                                   |\n|---------------------------|---------------------------------------------------------------|\n| `loadenv(schema, [src])`  | Validate and load env vars from `process.env` or custom src   |\n| `envSchema(defs)`         | Build a Zod Mini schema for your environment variables         |\n\n---\n\n## Example: Scoped per‑request objects\n\n```ts\nimport { container, token } from '@bmz_1/lambdi';\nimport { v4 as uuid } from 'uuid';\n\nconst REQUEST_ID = token<string>('request‑id');\n\nexport const handler = async (event) => {\n  const scope = container.createScope();\n  scope.register(REQUEST_ID, () => uuid());\n  \n  return doWork(event, scope);\n};\n\nasync function doWork(event, scope) {\n  const reqId = await scope.resolve(REQUEST_ID);\n  console.log('request', reqId, event.body);\n}\n```\n\n---\n\n## Testing pattern\n\n```ts\nimport { beforeEach, afterEach, it, expect } from 'vitest';\nimport { Container, token } from '@bmz_1/lambdi';\n\nconst DUMMY = token<number>('dummy');\nlet c: Container;\n\nbeforeEach(() => {\n  c = new Container();\n});\n\nafterEach(async () => {\n  await c.disposeAll();\n});\n\nit('returns same instance', async () => {\n  c.register(DUMMY, () => 42);\n  const value = await c.resolve(DUMMY);\n  const again = await c.resolve(DUMMY);\n  expect(again).toBe(value);\n});\n```\n\n---\n\n## License\n\nMIT © 2025 BMZ\n","readmeFilename":"README.md"}