{"_id":"@animalab-netizen/typescript-ode","name":"@animalab-netizen/typescript-ode","dist-tags":{"latest":"0.2.0"},"versions":{"0.2.0":{"name":"@animalab-netizen/typescript-ode","version":"0.2.0","description":"Opinionated delivery engine for TypeScript applications.","type":"module","main":"./dist/index.js","types":"./dist/index.d.ts","homepage":"https://github.com/animalab-netizen/typescript-ode","repository":{"type":"git","url":"git+https://github.com/animalab-netizen/typescript-ode.git"},"bugs":{"url":"https://github.com/animalab-netizen/typescript-ode/issues"},"publishConfig":{"access":"public"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"scripts":{"build":"tsc -p tsconfig.json","prepare":"npm run build","test":"npm run build && node --test tests/*.test.mjs"},"keywords":["ode","typescript","architecture","usecase","mvvm","workflow","delivery-engine"],"author":{"name":"ÂnimaLab","email":"animalab.desenvolvimento@gmail.com"},"license":"Apache-2.0","gitHead":"c2344d3939c4b56f72eefb0c30f030e7cdfa200a","_id":"@animalab-netizen/typescript-ode@0.2.0","_nodeVersion":"26.3.0","_npmVersion":"11.16.0","dist":{"integrity":"sha512-a23HPyBFqPuFqWNCbXsm+wbjioARWgk/SCO2XvsBO5gFGNSEZiFnbaq8gLBZOTWTGNdrYBzm23Hf7I8wPLpK4Q==","shasum":"f633b8f72be88d4367a4eedf41372d143676f35e","tarball":"https://registry.npmjs.org/@animalab-netizen/typescript-ode/-/typescript-ode-0.2.0.tgz","fileCount":31,"unpackedSize":32359,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCICyi3p20bRA8Qw+RB/tqL+Chl+B4WHeiP9au0mFMkwkhAiEA3pImPIEbdJvuJ2SpRnNjHAJkptZqo4zX1uIQ20wy0W0="}]},"_npmUser":{"name":"animalab-netizen","email":"animalab.desenvolvimento@gmail.com"},"directories":{},"maintainers":[{"name":"animalab-netizen","email":"animalab.desenvolvimento@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/typescript-ode_0.2.0_1781964910064_0.5339890905761024"},"_hasShrinkwrap":false}},"time":{"created":"2026-06-20T14:15:09.842Z","0.2.0":"2026-06-20T14:15:10.190Z","modified":"2026-06-20T14:15:10.422Z"},"maintainers":[{"name":"animalab-netizen","email":"animalab.desenvolvimento@gmail.com"}],"description":"Opinionated delivery engine for TypeScript applications.","homepage":"https://github.com/animalab-netizen/typescript-ode","keywords":["ode","typescript","architecture","usecase","mvvm","workflow","delivery-engine"],"repository":{"type":"git","url":"git+https://github.com/animalab-netizen/typescript-ode.git"},"author":{"name":"ÂnimaLab","email":"animalab.desenvolvimento@gmail.com"},"bugs":{"url":"https://github.com/animalab-netizen/typescript-ode/issues"},"license":"Apache-2.0","readme":"# @animalab-netizen/typescript-ode\n\n`@animalab-netizen/typescript-ode` is the web and server-side counterpart of the ODE architecture style.\n\nThe package provides a compact architectural runtime for:\n\n- use case execution\n- delivery and result orchestration\n- guard-first dispatch flow\n- typed output publication\n- lightweight MVVM-style channels for viewmodel driven interfaces\n\nThe goal is to make application flow easier to standardize, easier to inspect, and less vulnerable to common mistakes around asynchronous delivery, branching orchestration and UI-facing state transitions.\n\n## Repository\n\n- source: [github.com/animalab-netizen/typescript-ode](https://github.com/animalab-netizen/typescript-ode)\n\n## Status\n\n`@animalab-netizen/typescript-ode` is prepared as a standalone publishable package and is intended to be consumed by web examples such as `typescript-ode-consumer`.\n\nThe package is maintained by ÂnimaLab and is being positioned as the TypeScript member of the same ODE family already expressed in Kotlin and Swift.\n\n## Coordinates\n\nCurrent coordinates:\n\n- package: `@animalab-netizen/typescript-ode`\n- version: `0.2.0`\n\nInstallation:\n\n```bash\nnpm install @animalab-netizen/typescript-ode\n```\n\n## Public API\n\nThe intended public surface of `@animalab-netizen/typescript-ode` is centered on these concepts:\n\n- `UseCase<P, R>`\n- `UseCaseDispatcher`\n- `Output`, `ValueOutput`, `ErrorOutput`, `EmptyOutput`, `Outputs`\n- `BaseViewModel`\n- `Channel`\n- `Controller`\n- `ControllerFactory`\n- `SequenceUseCase`\n- `ChainUseCase`\n- `HttpError`, `ConnectionError`, `GuardRejectedError`, `UnexpectedResponseError`\n\nInternal helpers should not be treated as product contract and may change without notice.\n\n## API Stability Notes\n\nCurrent guidance:\n\n- prefer matching on the explicit `Output` hierarchy instead of treating delivery as raw values and thrown exceptions\n- keep guard logic inside the use case instead of distributing pre-validation across views and services\n- use `BaseViewModel` channels as explicit delivery surfaces when the package is consumed from UI code\n- do not couple application code to internal implementation details of dispatch sequencing\n\nThe preferred mental model for delivery handling is:\n\n```ts\nswitch (output.kind) {\n  case \"value\":\n    render(output.value);\n    break;\n  case \"error\":\n    handleError(output.error);\n    break;\n  case \"empty\":\n    break;\n}\n```\n\n## Core Concepts\n\n### 1. UseCase\n\n`UseCase<P, R>` is the main business execution abstraction.\n\nIt provides a standard lifecycle for:\n\n- input validation via `guard`\n- execution via `execute`\n- result normalization via `onResult`\n- failure handling via `onError`\n\nThis helps teams keep business flow explicit instead of re-implementing orchestration rules in controllers, hooks, or service layers.\n\n### 2. Dispatcher\n\n`UseCaseDispatcher` executes use cases and optionally emits the resulting `Output` to a listener.\n\nThis gives consumers a single, predictable way to trigger business work and receive typed delivery.\n\n### 3. Outputs\n\n`@animalab-netizen/typescript-ode` uses an explicit output hierarchy:\n\n- `ValueOutput<T>`\n- `ErrorOutput<T>`\n- `EmptyOutput`\n\nThe `Outputs` helper provides convenient constructors while keeping the final delivery contract typed and readable.\n\n### 4. ChainUseCase\n\n`ChainUseCase` is intended for a two-step flow where the first successful result provides the context for the second step.\n\nThis is useful when:\n\n- a first entity must be resolved before comparing or enriching it\n- a direct one-shot use case would hide meaningful orchestration\n\n### 5. SequenceUseCase\n\n`SequenceUseCase` is intended for ordered execution across three or more entries.\n\nIt keeps the request order explicit in the final delivery, which is especially useful for comparison and showcase scenarios.\n\n### 6. BaseViewModel\n\n`BaseViewModel` provides:\n\n- typed channel creation\n- observation registration\n- output publication through named channels\n- direct use case dispatch into a chosen channel\n\nThis is the bridge between business flow and browser or UI-facing consumers when a viewmodel style is preferred.\n\n## Basic Examples\n\n### Direct UseCase\n\n```ts\nimport { UseCase } from \"@animalab-netizen/typescript-ode\";\n\nclass LoadPokemonUseCase extends UseCase<string, string> {\n  protected override async execute(name: string): Promise<string> {\n    return `spotlight:${name}`;\n  }\n}\n```\n\n### Guarded UseCase\n\n```ts\nimport { GuardRejectedError, UseCase } from \"@animalab-netizen/typescript-ode\";\n\nclass ComparePokemonUseCase extends UseCase<{ left: string; right: string }, string> {\n  protected override guard(param: { left: string; right: string }) {\n    if (!param.left || !param.right || param.left === param.right) {\n      return {\n        allowed: false,\n        error: new GuardRejectedError(\"Comparison requires two distinct pokemon.\"),\n      };\n    }\n\n    return { allowed: true };\n  }\n\n  protected override async execute(param: { left: string; right: string }): Promise<string> {\n    return `${param.left} vs ${param.right}`;\n  }\n}\n```\n\n### ViewModel Example\n\n```ts\nimport { BaseViewModel, type OutputOf, UseCase } from \"@animalab-netizen/typescript-ode\";\n\nclass LoadNameUseCase extends UseCase<void, string> {\n  protected override async execute(): Promise<string> {\n    return \"pikachu\";\n  }\n}\n\nclass DemoViewModel extends BaseViewModel {\n  readonly channel = this.channel<OutputOf<string>>(\"name\");\n\n  async load() {\n    await this.dispatchUseCase(undefined, new LoadNameUseCase(), this.channel);\n  }\n}\n```\n\n### Channel Observation\n\n```ts\nconst viewModel = new DemoViewModel();\n\nconst stop = viewModel.observe(viewModel.channel, (output) => {\n  if (output.kind === \"value\") {\n    console.log(output.value);\n  }\n});\n\nawait viewModel.load();\nstop();\n```\n\n## Publishing\n\nLocal validation:\n\n```bash\nnpm run build\nnpm test\n```\n\nPublic publication target:\n\n```bash\nnpm publish --access public\n```\n\nSee [PUBLICATION.md](/Users/caiosanchezchristino/Desktop/ode-projects/typescript-ode/PUBLICATION.md) for the release checklist and packaging notes.\n\n## Compatibility Notes\n\nThe package targets modern TypeScript and ESM-based JavaScript runtimes.\n\nCurrent assumptions:\n\n- TypeScript 6 for local build and declaration emission\n- Node.js 20+ for repository validation\n- modern bundlers or ESM-capable runtimes when consumed from apps\n\nIf you consume the package from another project, keep your TypeScript and module settings reasonably aligned with the published artifact.\n\n## Contributing\n\nSee [CONTRIBUTING.md](/Users/caiosanchezchristino/Desktop/ode-projects/typescript-ode/CONTRIBUTING.md).\n\n## Changelog\n\nSee [CHANGELOG.md](/Users/caiosanchezchristino/Desktop/ode-projects/typescript-ode/CHANGELOG.md).\n\n## Maintainer\n\n- name: `ÂnimaLab`\n- email: `animalab.desenvolvimento@gmail.com`\n\n## License\n\nThis project is licensed under Apache-2.0. See [LICENSE](/Users/caiosanchezchristino/Desktop/ode-projects/typescript-ode/LICENSE).\n\n## UseCase Guide\n\nSee [USECASE_GUIDE.md](/Users/caiosanchezchristino/Desktop/ode-projects/typescript-ode/USECASE_GUIDE.md) for combinations, adoption guidance and common implementation doubts.\n","readmeFilename":"README.md","_rev":"1-8b6c0faa1842130ef32f887a847e32e5"}