{"_id":"@c-a-f/core","_rev":"2-d112daa90cd97c0e5ce5f64cfe842406","name":"@c-a-f/core","dist-tags":{"latest":"1.0.4"},"versions":{"1.0.3":{"name":"@c-a-f/core","version":"1.0.3","keywords":["clean-architecture-frontend","clean-architecture","clean architecture frontend","caf","frontend","usecase","ploc","state-management","routing"],"author":{"name":"ali aslani","email":"aliaslani.mm@gmail.com"},"license":"MIT","_id":"@c-a-f/core@1.0.3","maintainers":[{"name":"ialiaslani","email":"aliaslani.mm@gmail.com"}],"homepage":"https://github.com/ialiaslani/caf#readme","bugs":{"url":"https://github.com/ialiaslani/caf/issues"},"dist":{"shasum":"36f10c232c2f1a6e86f88f4511b7a5de9f608631","tarball":"https://registry.npmjs.org/@c-a-f/core/-/core-1.0.3.tgz","fileCount":168,"integrity":"sha512-kQC6/m4ZRLzjMnOQESplg3nidTuMdRoEp6BLQEm6mxMokYWO20R9DArqmcyoIo8CaVbgHdIsnk1Ip8wOjo8gkw==","signatures":[{"sig":"MEYCIQDgj0uLIdvbzJdrVGBNSt6wiXDGprvbQ0bBDm2/rPiugwIhAPWjnmHQNYWtpMP8D/zPYtfxs8WAFDHFQmQqBne+UyCW","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":176473},"main":"./.build/index.js","type":"module","types":"./.build/index.d.ts","module":"./.build/index.js","engines":{"node":">=18.0.0"},"exports":{".":{"node":"./.build/index.js","types":"./.build/index.d.ts","import":"./.build/index.js","default":"./.build/index.js"},"./ports":{"node":"./.build/ports.js","types":"./.build/ports.d.ts","import":"./.build/ports.js","default":"./.build/ports.js"},"./container":{"node":"./.build/container.js","types":"./.build/container.d.ts","import":"./.build/container.js","default":"./.build/container.js"}},"gitHead":"ca2feba4757534a4a130717ea50c4df2e2ff01e6","scripts":{"test":"vitest run","build":"tsc --build","start":"tsc --watch","test:watch":"vitest","prepublishOnly":"npm run build"},"_npmUser":{"name":"ialiaslani","email":"aliaslani.mm@gmail.com"},"repository":{"url":"git+https://github.com/ialiaslani/caf.git","type":"git"},"_npmVersion":"10.9.2","description":"Clean Architecture Frontend (CAF) — domain-agnostic primitives: UseCase, Ploc, Pulse, ApiRequest, RouteManager. Build frontend apps with Clean Architecture.","directories":{},"_nodeVersion":"22.13.0","_hasShrinkwrap":false,"devDependencies":{"vitest":"^2.1.0"},"_npmOperationalInternal":{"tmp":"tmp/core_1.0.3_1771670980584_0.8339955315947158","host":"s3://npm-registry-packages-npm-production"}},"1.0.4":{"name":"@c-a-f/core","type":"module","version":"1.0.4","description":"Clean Architecture Frontend (CAF) — domain-agnostic primitives: UseCase, Ploc, Pulse, ApiRequest, RouteManager. Build frontend apps with Clean Architecture.","keywords":["clean-architecture-frontend","clean-architecture","clean architecture frontend","caf","frontend","usecase","ploc","state-management","routing"],"author":{"name":"ali aslani","email":"aliaslani.mm@gmail.com"},"license":"MIT","homepage":"https://docs-caf.vercel.app/docs/packages/core","bugs":{"url":"https://github.com/ialiaslani/caf/issues"},"repository":{"type":"git","url":"git+https://github.com/ialiaslani/caf.git"},"engines":{"node":">=18.0.0"},"main":"./.build/index.js","module":"./.build/index.js","types":"./.build/index.d.ts","exports":{".":{"types":"./.build/index.d.ts","import":"./.build/index.js","node":"./.build/index.js","default":"./.build/index.js"},"./container":{"types":"./.build/container.d.ts","import":"./.build/container.js","node":"./.build/container.js","default":"./.build/container.js"},"./ports":{"types":"./.build/ports.d.ts","import":"./.build/ports.js","node":"./.build/ports.js","default":"./.build/ports.js"}},"scripts":{"build":"tsc --build","start":"tsc --watch","prepublishOnly":"npm run build","test":"vitest run","test:watch":"vitest"},"devDependencies":{"vitest":"^2.1.0"},"_id":"@c-a-f/core@1.0.4","gitHead":"c754b6d68b1a5b1196bb202e70c962ea7c3de87e","_nodeVersion":"22.13.0","_npmVersion":"10.9.2","dist":{"integrity":"sha512-tBIbDlFyWromIadMKKjdsujRdLLRg/Zdvt1+nlFwjIzqzb0zW5xyqOB9uPb5Vu5pVdLQwqh2lS7rAyqNCRC8EQ==","shasum":"13adcef9f66481cc12dee7b162ccef81590db5a5","tarball":"https://registry.npmjs.org/@c-a-f/core/-/core-1.0.4.tgz","fileCount":168,"unpackedSize":176691,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIAJIzydicuieb+i+HxGR1oggHXxpqWKfKKFwdN2YFQ9LAiEAncqZZl/f7IKtZrLOsMjPJw2slERfvuF2CdQ4c9nHX7k="}]},"_npmUser":{"name":"ialiaslani","email":"aliaslani.mm@gmail.com"},"directories":{},"maintainers":[{"name":"ialiaslani","email":"aliaslani.mm@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/core_1.0.4_1771679775688_0.32238623286340906"},"_hasShrinkwrap":false}},"time":{"created":"2026-02-21T10:49:40.481Z","modified":"2026-02-21T13:16:15.979Z","1.0.3":"2026-02-21T10:49:40.742Z","1.0.4":"2026-02-21T13:16:15.846Z"},"bugs":{"url":"https://github.com/ialiaslani/caf/issues"},"author":{"name":"ali aslani","email":"aliaslani.mm@gmail.com"},"license":"MIT","homepage":"https://docs-caf.vercel.app/docs/packages/core","keywords":["clean-architecture-frontend","clean-architecture","clean architecture frontend","caf","frontend","usecase","ploc","state-management","routing"],"repository":{"type":"git","url":"git+https://github.com/ialiaslani/caf.git"},"description":"Clean Architecture Frontend (CAF) — domain-agnostic primitives: UseCase, Ploc, Pulse, ApiRequest, RouteManager. Build frontend apps with Clean Architecture.","maintainers":[{"name":"ialiaslani","email":"aliaslani.mm@gmail.com"}],"readme":"# @c-a-f/core\r\n\r\nDomain-agnostic primitives for clean architecture frontends: UseCase, Ploc, Pulse, ApiRequest, RouteManager.\r\n\r\n**Documentation:** [@c-a-f/core docs](https://docs-caf.vercel.app/docs/packages/core)\r\n\r\n## Installation\r\n\r\n```bash\r\nnpm install @c-a-f/core\r\n```\r\n\r\n## Usage\r\n\r\n### UseCase\r\n\r\nDefine application use cases that return `Promise<RequestResult<T>>`:\r\n\r\n```typescript\r\nimport { UseCase, RequestResult } from '@c-a-f/core';\r\n\r\ninterface LoginUserArgs {\r\n  username: string;\r\n  password: string;\r\n}\r\n\r\nclass LoginUser implements UseCase<[LoginUserArgs], { token: string }> {\r\n  async execute(args: LoginUserArgs): Promise<RequestResult<{ token: string }>> {\r\n    // Your login logic here\r\n    const result = await loginService.login(args);\r\n    return {\r\n      loading: pulse(false),\r\n      data: pulse(result),\r\n      error: pulse(null! as Error),\r\n    };\r\n  }\r\n}\r\n```\r\n\r\n### Ploc (Presentation Logic Component)\r\n\r\nCreate stateful presentation logic containers:\r\n\r\n```typescript\r\nimport { Ploc } from '@c-a-f/core';\r\n\r\ninterface CounterState {\r\n  count: number;\r\n  isLoading: boolean;\r\n}\r\n\r\nclass CounterPloc extends Ploc<CounterState> {\r\n  constructor() {\r\n    super({ count: 0, isLoading: false });\r\n  }\r\n\r\n  increment() {\r\n    this.changeState({ ...this.state, count: this.state.count + 1 });\r\n  }\r\n\r\n  subscribeToState(listener: (state: CounterState) => void) {\r\n    this.subscribe(listener);\r\n  }\r\n}\r\n\r\n// Usage\r\nconst counter = new CounterPloc();\r\ncounter.subscribe((state) => console.log('Count:', state.count));\r\ncounter.increment(); // Logs: Count: 1\r\n```\r\n\r\n### Pulse (Single Reactive Value)\r\n\r\nFor single reactive values:\r\n\r\n```typescript\r\nimport { pulse } from '@c-a-f/core';\r\n\r\nconst count = pulse(0);\r\ncount.subscribe((value) => console.log('Value:', value));\r\ncount.value = 5; // Logs: Value: 5\r\n```\r\n\r\n### ApiRequest\r\n\r\nWrap async requests with reactive loading/data/error state:\r\n\r\n```typescript\r\nimport { ApiRequest, IRequestHandler } from '@c-a-f/core';\r\n\r\n// Works with Promise (backward compatible)\r\nconst fetchUser = new ApiRequest(fetch('/api/user').then(r => r.json()));\r\n\r\n// Or with IRequestHandler for flexibility (real API, mocks, cached)\r\nclass ApiRequestHandler<T> implements IRequestHandler<T> {\r\n  constructor(private apiCall: () => Promise<T>) {}\r\n  async execute(): Promise<T> {\r\n    return await this.apiCall();\r\n  }\r\n}\r\n\r\nconst userRequest = new ApiRequest(\r\n  new ApiRequestHandler(() => fetch('/api/user').then(r => r.json()))\r\n);\r\n\r\nuserRequest.loading.subscribe((loading) => {\r\n  if (loading) console.log('Loading...');\r\n});\r\n\r\nuserRequest.data.subscribe((data) => {\r\n  console.log('User:', data);\r\n});\r\n\r\nawait userRequest.mutate();\r\n```\r\n\r\n### RouteManager\r\n\r\nCoordinate routing (requires a RouteRepository implementation from your framework):\r\n\r\n```typescript\r\nimport { RouteManager, RouteRepository } from '@c-a-f/core';\r\n\r\n// Your framework adapter implements RouteRepository\r\nconst routeRepository: RouteRepository = {\r\n  currentRoute: '/',\r\n  change: (route) => router.push(route),\r\n};\r\n\r\nconst routeManager = new RouteManager(routeRepository, {\r\n  loginPath: '/login',\r\n  isLoggedIn: () => !!localStorage.getItem('token'),\r\n});\r\n\r\nrouteManager.changeRoute('/dashboard');\r\nrouteManager.checkForLoginRoute(); // Redirects to /login if not authenticated\r\n```\r\n\r\n\r\n## Exports\r\n\r\n- `UseCase` — Interface for application use cases\r\n- `Ploc` — Abstract class for presentation logic containers\r\n- `Pulse` — Class for single reactive values\r\n- `pulse` — Factory function for creating Pulse instances\r\n- `ApiRequest` — Class for wrapping async requests\r\n- `RouteManager` — Class for coordinating routing\r\n- `RouteRepository` — Interface for routing system abstraction\r\n- `RouteManagerAuthOptions` — Interface for auth configuration\r\n- `RequestResult` — Type for use case results\r\n- `IRequest` — Type for async requests\r\n- `IApiClient` — Interface for API client implementations\r\n- `ApiRequestConfig` — Interface for API request configuration\r\n- `ApiResponse` — Interface for standard API response wrapper\r\n- `ApiError` — Interface for standard API error format\r\n- `HttpMethod` — Type for HTTP method types\r\n- `extractApiData` — Helper function to extract data from wrapped responses\r\n- `normalizeApiError` — Helper function to normalize errors\r\n- `IRequestHandler` — Interface for request handler implementations (allows swapping real API, mocks, cached)\r\n- `PromiseRequestHandler` — Adapter class to convert Promise<T> to IRequestHandler<T>\r\n- `toRequestHandler` — Helper function to normalize requests to IRequestHandler\r\n\r\n## Documentation\r\n\r\n- **[@c-a-f/core documentation](https://docs-caf.vercel.app/docs/packages/core)** — Package docs, usage, and API\r\n- **[Full API Documentation](../../docs/API.md)** — Complete API reference (repo)\r\n- **[Main Repository README](../../README.md)** — Architecture overview and getting started\r\n- **[Publishing Guide](../../docs/PUBLISHING.md)** — How to publish and consume packages\r\n- **[Versioning Strategy](../../docs/VERSIONING.md)** — Versioning approach\r\n\r\n## License\r\n\r\nMIT\r\n","readmeFilename":"README.md"}