{"_id":"@arsams/mockkit","name":"@arsams/mockkit","dist-tags":{"latest":"0.0.1"},"versions":{"0.0.1":{"name":"@arsams/mockkit","version":"0.0.1","description":"Framework-agnostic toolkit for MSW mocking.","keywords":["msw","mocking","api","testing","mock-service-worker","framework-agnostic"],"author":{"name":"Arsam"},"license":"MIT","main":"./dist/index.js","module":"./dist/index.mjs","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.js"},"./browser":{"types":"./dist/browser.d.ts","import":"./dist/browser.mjs","require":"./dist/browser.js"},"./node":{"types":"./dist/node.d.ts","import":"./dist/node.mjs","require":"./dist/node.js"}},"sideEffects":["**/*.css"],"scripts":{"build":"tsup","dev":"tsup --watch"},"repository":{"type":"git","url":"git+https://github.com/arsams/mockkit.git"},"bugs":{"url":"https://github.com/arsams/mockkit/issues"},"homepage":"https://github.com/arsams/mockkit#readme","publishConfig":{"access":"public"},"dependencies":{"@nanostores/persistent":"^1.2.0","dayjs":"^1.11.19","msw":"^2.0.11","nanostores":"^1.1.0"},"devDependencies":{"@eslint/js":"^9.39.1","@eslint/json":"^0.14.0","@eslint/markdown":"^7.5.1","@repo/eslint-config":"workspace:*","@repo/typescript-config":"workspace:*","@types/node":"^24.10.1","eslint":"^9.39.1","globals":"^16.5.0","prettier":"^3.7.4","tsup":"^8.0.0","typescript":"^5.0.0","typescript-eslint":"^8.48.1"},"gitHead":"2fc81e1c0d3209d8f59f9b4f99541faf223cd7c1","_id":"@arsams/mockkit@0.0.1","_nodeVersion":"25.1.0","_npmVersion":"11.6.2","dist":{"integrity":"sha512-UMpDJAYZx4cPV4mH5mC6/Vh1k1Hzv9RF+vvx3DfpgJB+k+vtHdxOL0vePuwxngAzoVYQQAcP41NF9vGdPz+8Cg==","shasum":"46db9692a86985f152c3ae68b5387de50610da61","tarball":"https://registry.npmjs.org/@arsams/mockkit/-/mockkit-0.0.1.tgz","fileCount":21,"unpackedSize":362117,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIDrF7cmU8k3XHRl+qzDxwEAhUn1GCTgs54fG6Tx0o1o9AiEAyQ5remNVNDAe6XLAsCVh2Bm5ZJlR7PKGya59Jc8xucs="}]},"_npmUser":{"name":"arsamsarabi","email":"arsamsarabi@me.com"},"directories":{},"maintainers":[{"name":"arsamsarabi","email":"arsamsarabi@me.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/mockkit_0.0.1_1765106321965_0.8654864004838911"},"_hasShrinkwrap":false}},"time":{"created":"2025-12-07T11:18:41.907Z","0.0.1":"2025-12-07T11:18:42.121Z","modified":"2025-12-07T11:18:42.428Z"},"maintainers":[{"name":"arsamsarabi","email":"arsamsarabi@me.com"}],"description":"Framework-agnostic toolkit for MSW mocking.","homepage":"https://github.com/arsams/mockkit#readme","keywords":["msw","mocking","api","testing","mock-service-worker","framework-agnostic"],"repository":{"type":"git","url":"git+https://github.com/arsams/mockkit.git"},"author":{"name":"Arsam"},"bugs":{"url":"https://github.com/arsams/mockkit/issues"},"license":"MIT","readme":"# @arsams/mockkit\n\nFramework-agnostic toolkit for API mocking with [MSW](https://mswjs.io/). Provides a centralized, controllable mocking system that works in any JavaScript/TypeScript environment.\n\nFor React integrations (hooks and control panel components), see [@arsams/mockkit-react](../mokkit-react/README.md).\n\n## Features\n\n- **Framework-agnostic core** - Works in browser, Node.js, or any JS/TS environment\n- **Centralized configuration** - Single source of truth for all mocking behavior\n- **Response variants** - Support for success, error, empty, slow, and offline modes\n- **Scenarios** - Group multiple route configurations together\n- **Tree-shakeable** - Import only what you need\n- **Type-safe** - Full TypeScript support\n- **Zero dependencies** (except MSW) - Minimal bundle size\n\n## Installation\n\n```bash\npnpm install @arsams/mockkit msw\n```\n\nFor React support, install the separate React package:\n\n```bash\npnpm install @arsams/mockkit-react @arsams/mockkit msw react react-dom\n```\n\n## Quick Start\n\n**Important:** This library does not provide default handlers, scenarios, or stream sequences. You must create and register your own before using the library.\n\n### 1. Create Handlers\n\n```typescript\n// src/mocks/handlers.ts\nimport { buildRestHandler } from \"@arsams/mockkit\";\nimport { HttpResponse } from \"msw\";\n\nexport const fetchWeatherHandler = buildRestHandler({\n  id: \"weather.fetch\",\n  method: \"get\",\n  path: \"/api/weather\",\n  label: \"Fetch Weather\",\n  variants: {\n    success: () =>\n      HttpResponse.json({\n        location: \"San Francisco, CA\",\n        temperature: 22,\n        condition: \"sunny\",\n        humidity: 65,\n        windSpeed: 15,\n      }),\n    error: () =>\n      HttpResponse.json(\n        { error: \"Failed to fetch weather data\" },\n        { status: 500 },\n      ),\n    empty: () => HttpResponse.json({}),\n  },\n});\n\nexport const handlers = [fetchWeatherHandler];\n```\n\n**Note:** You must export your handlers array and import it in your setup files (see steps 2 and 3 below).\n\n### 2. Register Scenarios and Stream Sequences (Optional)\n\n```typescript\n// src/mocks/scenarios.ts\nimport { addScenario } from \"@arsams/mockkit\";\n\n// Register scenarios before initializing the worker/server\naddScenario(\"success\", {\n  title: \"All Success\",\n  routes: {\n    \"weather.fetch\": { mode: \"success\" },\n  },\n});\n\naddScenario(\"errorState\", {\n  title: \"All Errors\",\n  routes: {\n    \"weather.fetch\": { mode: \"error\" },\n  },\n});\n```\n\n```typescript\n// src/mocks/streamSequences.ts\nimport { addStreamSequence } from \"@arsams/mockkit\";\nimport { createMockEvent } from \"@arsams/mockkit\";\n\n// Register stream sequences before initializing the worker/server\naddStreamSequence(\"weatherCurrentConditions\", {\n  title: \"Current Weather Conditions\",\n  events: [\n    {\n      event: createMockEvent(\"weather_CurrentConditions\", {\n        RunStatus: 0,\n        resultJson: JSON.stringify({\n          temperature: 22,\n          condition: \"sunny\",\n          location: \"San Francisco, CA\",\n        }),\n      }),\n    },\n  ],\n});\n```\n\n### 3. Browser Setup\n\n```typescript\n// src/mocks/browser.ts\nimport { startMockWorker } from \"@arsams/mockkit/browser\";\nimport { handlers } from \"./handlers\";\n// Import your scenarios and stream sequences to register them\nimport \"./scenarios\";\nimport \"./streamSequences\";\n\nexport async function initMocks() {\n  if (import.meta.env.DEV) {\n    await startMockWorker({\n      handlers,\n      // Optional: apply a scenario you've registered\n      initialScenario: \"success\",\n      quiet: false,\n    });\n  }\n}\n```\n\n```typescript\n// main.tsx\nimport { initMocks } from \"./mocks/browser\";\n\ninitMocks().then(() => {\n  ReactDOM.createRoot(document.getElementById(\"root\")!).render(<App />);\n});\n```\n\n### 4. Node/Test Setup\n\n```typescript\n// vitest.setup.ts or jest.setup.ts\nimport { setupMockServer } from \"@arsams/mockkit/node\";\nimport { handlers } from \"./mocks/handlers\";\n// Import your scenarios and stream sequences to register them\nimport \"./mocks/scenarios\";\nimport \"./mocks/streamSequences\";\n\nconst server = setupMockServer({\n  handlers,\n  // Optional: apply a scenario you've registered\n  initialScenario: \"success\",\n});\n\nbeforeAll(() => server.listen({ onUnhandledRequest: \"bypass\" }));\nafterEach(() => server.resetHandlers());\nafterAll(() => server.close());\n```\n\n### 5. Use in Your App\n\n```typescript\n// Framework-agnostic usage\nimport { $mockConfigState, setRouteMode } from \"@arsams/mockkit\";\n\n// Get current state\nconst state = $mockConfigState.get();\nconsole.log(state.enabled); // true\n\n// Change response mode\nsetRouteMode(\"weather.fetch\", \"error\");\n\n// Subscribe to changes\nimport { onMount } from \"nanostores\";\nconst unsubscribe = onMount($mockConfigState, () => {\n  console.log(\"Store updated:\", $mockConfigState.get());\n});\n```\n\n### 6. React Integration (Optional)\n\nIf you're using React, install and use `@arsams/mockkit-react`:\n\n```typescript\n// Install: pnpm install @arsams/mockkit-react\nimport { useStore, MSWControlPanel } from \"@arsams/mockkit-react\";\n\nfunction App() {\n  const enabled = useStore((state) => state.enabled);\n  \n  return (\n    <>\n      <YourApp />\n      {import.meta.env.DEV && <MSWControlPanel />}\n    </>\n  );\n}\n```\n\nSee the [@arsams/mockkit-react documentation](../mokkit-react/README.md) for more details.\n\n## Core Concepts\n\n### Response Modes\n\nEach handler can respond in multiple modes:\n\n- `success` - Happy-path response with realistic data\n- `error` - Error response (4xx/5xx)\n- `empty` - Success response with no data\n- `slow` - Delayed response for testing loading states\n- `offline` - Simulated network failure\n\n### Scenarios\n\nScenarios group multiple route configurations together:\n\n```typescript\nimport { addScenario } from \"@arsams/mockkit\";\n\naddScenario(\"errorState\", {\n  title: \"All Errors\",\n  routes: {\n    \"weather.fetch\": { mode: \"error\" },\n    \"weather.forecast\": { mode: \"error\" },\n  },\n});\n\n// Apply scenario\nimport { setScenario } from \"@arsams/mockkit\";\nsetScenario(\"errorState\");\n```\n\n### Route Configuration\n\nRoutes are automatically registered when handlers are accessed. You can configure them programmatically:\n\n```typescript\nimport { setRouteConfig, enableRoute, disableRoute } from \"@arsams/mockkit\";\n\n// Configure a route\nsetRouteConfig(\"weather.fetch\", {\n  enabled: true,\n  mode: \"error\",\n  label: \"Fetch Weather\",\n});\n\n// Enable/disable routes\nenableRoute(\"weather.fetch\");\ndisableRoute(\"weather.forecast\");\n```\n\n## API Reference\n\n### Core Exports (`@arsams/mockkit`)\n\n#### Store and State Management\n\n- `$mockConfigState` - Framework-agnostic store instance (nanostores atom)\n- `$scenarios` - Store containing all registered scenarios\n- `$currentScenario` - Store containing the currently active scenario name (or null)\n- `$streamEventSequences` - Store containing all registered stream sequences\n- `$activeStream` - Store containing the currently active stream sequence name (or null)\n\n#### Store Actions\n\n- `setGlobalEnabled(enabled: boolean)` - Enable/disable all mocking\n- `setLogRequests(enabled: boolean)` - Enable/disable request logging\n- `setRouteMode(routeId: string, mode: ResponseMode)` - Set response mode for a route\n- `enableRoute(routeId: string)` - Enable a specific route\n- `disableRoute(routeId: string)` - Disable a specific route\n- `setRouteConfig(routeId: string, config: Partial<RouteConfig>)` - Configure a route\n- `getRouteMode(routeId: string)` - Get the current response mode for a route\n- `isRouteEnabled(routeId: string)` - Check if a route is enabled\n- `getRouteConfig(routeId: string)` - Get the full configuration for a route\n\n#### Scenario Management\n\n- `addScenario(name: string, config: ScenarioConfig)` - Register a scenario (must be called before `startMockWorker` or `setupMockServer`)\n- `getScenario(name: string)` - Get a scenario by name\n- `getAllScenarios()` - Get all registered scenarios\n- `setScenario(name: string)` - Apply a registered scenario\n- `clearScenario()` - Clear the current scenario\n\n#### Stream Sequence Management\n\n- `addStreamSequence(name: string, config: StreamEventSequence)` - Register a stream sequence (must be called before `startMockWorker` or `setupMockServer`)\n- `getStreamSequence(name: string)` - Get a stream sequence by name\n- `getAllStreamSequences()` - Get all registered stream sequences\n- `setActiveStreamSequence(name: string | null)` - Set the active stream sequence\n- `clearActiveStreamSequence()` - Clear the active stream sequence\n\n#### Handler Builders\n\n- `buildRestHandler(config: RestHandlerConfig)` - Build an MSW REST handler\n\n#### Utilities\n\n- `logger` - Logger instance for logging (respects `logRequests` setting)\n- `print` - Convenience logger methods (info, warn, error, system.*)\n- `createUnhandledRequestWarning` - Function for handling unhandled MSW requests\n- `createMockEvent`, `createStreamEvent`, `createWeatherCurrentConditionsEvent`, etc. - Stream event creation utilities\n\n#### Types\n\n- `ResponseMode` - Type for response modes: \"success\" | \"error\" | \"empty\" | \"slow\" | \"offline\"\n- `RouteConfig` - Type for route configuration\n- `ScenarioConfig` - Type for scenario configuration\n- `StreamEventSequence` - Type for stream event sequence configuration\n- `MockConfigState` - Type for the mock config store state\n\n### Browser Exports (`@arsams/mockkit/browser`)\n\n- `startMockWorker(options: StartMockWorkerOptions)` - Start MSW worker in browser\n  - `options.handlers` - Array of MSW handlers (required)\n  - `options.initialScenario?` - Initial scenario to apply (optional)\n  - `options.quiet?` - Suppress MSW startup messages (optional, default: false)\n\n### Node Exports (`@arsams/mockkit/node`)\n\n- `setupMockServer(options: SetupMockServerOptions)` - Setup MSW server for Node/testing\n  - `options.handlers` - Array of MSW handlers (required)\n  - `options.initialScenario?` - Initial scenario to apply (optional)\n\n\n## Examples\n\n### Complete Example\n\nHere's a complete example showing how to set up handlers, scenarios, and stream sequences:\n\n```typescript\n// src/mocks/handlers.ts\nimport { buildRestHandler } from \"@arsams/mockkit\";\nimport { HttpResponse } from \"msw\";\n\nexport const fetchWeatherHandler = buildRestHandler({\n  id: \"weather.fetch\",\n  method: \"get\",\n  path: \"/api/weather\",\n  variants: {\n    success: () =>\n      HttpResponse.json({\n        location: \"San Francisco, CA\",\n        temperature: 22,\n        condition: \"sunny\",\n      }),\n    error: () =>\n      HttpResponse.json({ error: \"Failed to fetch weather\" }, { status: 500 }),\n  },\n});\n\nexport const handlers = [fetchWeatherHandler];\n```\n\n```typescript\n// src/mocks/scenarios.ts\nimport { addScenario } from \"@arsams/mockkit\";\n\naddScenario(\"success\", {\n  title: \"All Success\",\n  routes: {\n    \"weather.fetch\": { mode: \"success\" },\n  },\n});\n\naddScenario(\"errorState\", {\n  title: \"All Errors\",\n  routes: {\n    \"weather.fetch\": { mode: \"error\" },\n  },\n});\n```\n\n```typescript\n// src/mocks/streamSequences.ts\nimport { addStreamSequence } from \"@arsams/mockkit\";\nimport { createMockEvent } from \"@arsams/mockkit\";\n\naddStreamSequence(\"weatherCurrentConditions\", {\n  title: \"Current Weather Conditions\",\n  events: [\n    {\n      event: createMockEvent(\"weather_CurrentConditions\", {\n        RunStatus: 0,\n        resultJson: JSON.stringify({\n          location: \"San Francisco, CA\",\n          temperature: 22,\n          condition: \"sunny\",\n        }),\n      }),\n    },\n  ],\n});\n```\n\n```typescript\n// src/mocks/browser.ts\nimport { startMockWorker } from \"@arsams/mockkit/browser\";\nimport { handlers } from \"./handlers\";\nimport \"./scenarios\";\nimport \"./streamSequences\";\n\nexport async function initMocks() {\n  if (import.meta.env.DEV) {\n    await startMockWorker({\n      handlers,\n      initialScenario: \"success\",\n    });\n  }\n}\n```\n\n## Framework-Agnostic Design\n\nThe core functionality is completely framework-agnostic:\n\n- **Store** - Vanilla JavaScript event emitter, no React dependencies\n- **Builders** - Work with any framework\n- **Types** - Pure TypeScript, no framework assumptions\n\nFor React support, use the separate [@arsams/mockkit-react](../mokkit-react/README.md) package. The core package is framework-agnostic and can be used in Vue, Svelte, Angular, or plain JavaScript.\n\n## License\n\nMIT\n\n## Contributing\n\nSee [CONTRIBUTING.md](./CONTRIBUTING.md) for guidelines.\n","readmeFilename":"README.md","_rev":"1-80862da409849ab246da6fb5af63795b"}