{"id":21043366,"url":"https://github.com/crystallizeapi/node-service-api-router","last_synced_at":"2025-10-05T12:32:58.760Z","repository":{"id":57681828,"uuid":"479641736","full_name":"CrystallizeAPI/node-service-api-router","owner":"CrystallizeAPI","description":null,"archived":false,"fork":false,"pushed_at":"2025-07-31T08:44:33.000Z","size":24,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-08-08T14:59:33.779Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://crystallizeapi.github.io/libraries/","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/CrystallizeAPI.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2022-04-09T06:39:33.000Z","updated_at":"2025-07-31T08:44:36.000Z","dependencies_parsed_at":"2025-10-05T12:32:25.134Z","dependency_job_id":null,"html_url":"https://github.com/CrystallizeAPI/node-service-api-router","commit_stats":null,"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"purl":"pkg:github/CrystallizeAPI/node-service-api-router","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CrystallizeAPI%2Fnode-service-api-router","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CrystallizeAPI%2Fnode-service-api-router/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CrystallizeAPI%2Fnode-service-api-router/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CrystallizeAPI%2Fnode-service-api-router/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/CrystallizeAPI","download_url":"https://codeload.github.com/CrystallizeAPI/node-service-api-router/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CrystallizeAPI%2Fnode-service-api-router/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":278457230,"owners_count":25989952,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-10-05T02:00:06.059Z","response_time":54,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-19T14:12:35.480Z","updated_at":"2025-10-05T12:32:58.749Z","avatar_url":"https://github.com/CrystallizeAPI.png","language":"TypeScript","readme":"# Node Service API Router\n\nThis lib is deprecated and will be archived January 1st, 2026.\n\n----\n\nThis is the entry point of your Service API when you decide to use this library.\n\n## Installation\n\nWith NPM:\n\n```bash\nnpm install @crystallize/node-service-api-router\n```\n\nWith Yarn:\n\n```bash\nyarn add @crystallize/node-service-api-router\n```\n\n## Usage\n\nHere is what a valid _index.ts_ would look like with only one endpoint.\n\n```typescript\nimport {\n    createServiceApiApp,\n    ValidatingRequestRouting,\n    StandardRouting,\n    authenticatedMiddleware,\n} from '@crystallize/node-service-api-router';\nimport Koa from 'koa';\nconst routes: StandardRouting = {\n    '/': {\n        get: {\n            handler: async (ctx: Koa.Context) =\u003e {\n                ctx.body = { msg: `Crystallize Service API - Tenant ${process.env.CRYSTALLIZE_TENANT_IDENTIFIER}` };\n            },\n        },\n    },\n};\nconst bodyConvertedRoutes: ValidatingRequestRouting = {};\nconst { run } = createServiceApiApp(bodyConvertedRoutes, routes, authenticatedMiddleware(`${process.env.JWT_SECRET}`));\nrun(process.env.PORT ? parseInt(process.env.PORT) : 3000);\n```\n\nThis is using [Koa JS](https://koajs.com/) for the Middleware management.\n\nNote: CORS is managed in this library.\n\n## StandardRouting\n\nStandard routes are standard by definition, nothing specific to understand. You get access to the request (and more) through the Koa.Context and you need to set the Body. (alias of _ctx.response.body_)\n\n## ValidatingRequestRouting\n\nThis is where this library takes all its meaning. It does not provide any features by itself, but it enables a concept.\n\n```typescript\nconst bodyConvertedRoutes: ValidatingRequestRouting = {\n    '/my/endpoint': {\n        post: {\n            schema: requestInputSchema,\n            handler: requestInputHandler,\n            args: (context: any) =\u003e {};\n        }\n    }\n}\n```\n\nIt means on the `'/my/endpoint'` endpoint, the API Router will intercept the request, check and validate the entry against requestInputSchema, run the `args` function to get handler’s arguments to finally execute the handler when it validates.\n\nBut the response is not returned yet, so you can still extend it in the standard routes:\n\n```typescript\nconst routes: StandardRouting = {\n    '/cart': {\n        post: {\n            handler: async (ctx: Koa.Context) =\u003e {\n                const cart = ctx.body as Cart;\n                ctx.body = {\n                    ...cart,\n                    hello: 'world',\n                };\n            },\n        },\n    },\n};\nconst bodyConvertedRoutes: ValidatingRequestRouting = {\n    '/cart': {\n        post: {\n            schema: cartPayload,\n            handler: handleCartRequestPayload,\n            args: (context: Koa.Context): any =\u003e {},\n        },\n    },\n};\n```\n\nWith this code, if the Request validates against _cartRequest_, the body of the request will be converted to a Cart. And the standard route can still do whatever it wants, knowing the _ctx.body_ is a Cart. In this example, we add a property to the response.\n\n## Why\n\nThis enables the next library: [Node Service API Request Handlers](https://crystallize.com/learn/open-source/sdks-and-libraries/node-service-api-request-handlers) which provides many highly customizable schemas and handlers (like the Cart mentioned above) so you can get started in minutes and you can extend them to make your Service API yours!\n\n## Authentification\n\nLibrary comes with a default Authentication middleware. For each route that you describe, you have a boolean attribute named `authenticated` which is by default set to `false`.\n\n```typescript\n'/echo': {\n    post: {\n        handler: async (ctx: Koa.Context) =\u003e {\n            ctx.body = {\n                echoed: ctx.request.body\n            }\n        }\n    }\n},\n'/authenticated/echo': {\n    post: {\n        authenticated: true,\n        handler: async (ctx: Koa.Context) =\u003e {\n            ctx.body = {\n                echoed: ctx.request.body,\n                user: ctx.user\n            }\n        }\n    }\n},\n```\n\nIn this example `/authenticated/echo` will be accessible with a valid authentication.\n\n### How does that work?\n\nFirst, the middleware is passed to the router via Dependency Injection, therefore you can also provide your own.\n\n```javascript\nconst { run, router } = createServiceApiApp(\n    bodyConvertedRoutes,\n    routes,\n    authenticatedMiddleware(`${process.env.JWT_SECRET}`),\n);\n```\n\nThe [authenticatedMiddleware provided by the library is simple](https://github.com/CrystallizeAPI/libraries/blob/main/components/node-service-api-router/src/core/middlewares.ts#L14):\n\n-   it will check the existence of a cookie name: **jwt**\n-   if that cookie exists, then it will decode it and check its signature. (That’s why you pass the _JWT_SECRET_)\n-   and it will check the `sub` property of the payload to be: _isLoggedInOnServiceApiToken_\n\nNote: The last check is to be consistent with the provided [MagickLink feature](https://github.com/CrystallizeAPI/libraries/blob/main/components/node-service-api-request-handlers/src/magicklink/handlers.ts#L31).\n\nIf one of the checks fails, the router will return a 401 error.\n\nOnce again, all is extendable. You may or may not use the **authenticatedMiddleware** and you can certainly pass your own to do your own logic.\n\n[crystallizeobject]: crystallize_marketing|folder|62561a1ab30ff82a1f664931\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcrystallizeapi%2Fnode-service-api-router","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcrystallizeapi%2Fnode-service-api-router","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcrystallizeapi%2Fnode-service-api-router/lists"}