{"id":15286086,"url":"https://github.com/ninofiliu/oa-client","last_synced_at":"2025-04-13T03:07:44.889Z","repository":{"id":44939283,"uuid":"258327118","full_name":"ninofiliu/oa-client","owner":"ninofiliu","description":"Flexible client helper for making and validating calls to OpenAPI backends. For Node and the browser. Runtime lib - no need for code generation!","archived":false,"fork":false,"pushed_at":"2023-12-29T15:38:07.000Z","size":537,"stargazers_count":48,"open_issues_count":1,"forks_count":2,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-03-26T20:11:28.417Z","etag":null,"topics":["openapi","openapi3","rest","swagger"],"latest_commit_sha":null,"homepage":"","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/ninofiliu.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}},"created_at":"2020-04-23T20:49:35.000Z","updated_at":"2024-07-22T09:37:45.000Z","dependencies_parsed_at":"2023-12-29T16:36:12.237Z","dependency_job_id":"e35ab847-81c6-4a7a-96ea-e800f3f9c7d6","html_url":"https://github.com/ninofiliu/oa-client","commit_stats":{"total_commits":94,"total_committers":3,"mean_commits":"31.333333333333332","dds":0.0957446808510638,"last_synced_commit":"ffafe0eead65ce3d26b5ecf4c475a36f3a82de58"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ninofiliu%2Foa-client","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ninofiliu%2Foa-client/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ninofiliu%2Foa-client/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ninofiliu%2Foa-client/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ninofiliu","download_url":"https://codeload.github.com/ninofiliu/oa-client/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248657918,"owners_count":21140846,"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","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":["openapi","openapi3","rest","swagger"],"created_at":"2024-09-30T15:10:25.163Z","updated_at":"2025-04-13T03:07:44.871Z","avatar_url":"https://github.com/ninofiliu.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# oa-client\n\nHarness all the power of your backend's OpenAPI v3 spec files by generating a client object in a few lines\n\n## Features\n\n🚀 Creates at runtime a client object in a few lines (read more in [Getting Started](#getting-started))\n\n```js\n// Creation\nimport { createClient } from 'oa-client';\nconst client = createClient(specs, callers, {\n  origin: 'https://my.api.com',\n  validationLevel: 'error',\n});\n// Usage\nclient[/* path */][/* method */](/* optional params */).then(apiResponse =\u003e { /* ... */ })\n```\n\n🚀 Optionally throws for invalid path, query, or body\n\n```yaml\n# OpenAPI specs\npaths:\n  /users/{userId}:\n    get:\n      parameters:\n        - in: path\n          name: userId\n          schema:\n            type: integer\n```\n\n```js\nclient[\"/users/{userId}\"].get({ pathParams: { userId: \"john\" } });\n// throws [oa-client:103] Data does not pass validation: data.userId should be an integer\n```\n\n🚀 Compiles the path and query params\n\n```js\nclient[\"/new-user/{job}\"].post({\n  pathParams: { job: \"director\" },\n  queryParams: { name: \"Gaspar Noé\" },\n});\n// calls /new-user/director?name=Gaspar+No%C3%A9\n```\n\n## Getting started\n\n### 1. Install the package\n\n```sh\nnpm install --save oa-client\n```\n\n### 2. Import the package\n\nThis package is isomorphic: it can be used both as an ESM or a CommonJS\n\n```js\n// ok\nimport { createClient } from \"oa-client\";\n// also ok\nconst { createClient } = require(\"oa-client\");\n```\n\n### 3. Have somewhere your OpenAPI specs as a JS object\n\nYou don't need to add anything compared to normal specs, except for an optional `.paths[path][method]['x-type']`, that defines the _caller_, more on them below. If this key is omitted, its value defaults to the request type (e.g. `\"get\"` or `\"post\"`).\n\nNote that `oa-client` does not resolve specs for you. If you have `$refs`, you should use a package like [json-schema-ref-parser](https://www.npmjs.com/package/@apidevtools/json-schema-ref-parser) to resolve them.\n\n```js\nconst specs = {\n  openapi: \"3.0.0\",\n  info: {\n    /* ... */\n  },\n  paths: {\n    \"/users/{userId}\": {\n      get: {\n        \"x-type\": \"authorizedGet\", // will use the \"authorizedGet\" caller\n        parameters: [\n          {\n            in: \"path\",\n            name: \"userId\",\n            required: true,\n            schema: {\n              type: \"integer\",\n            },\n          },\n        ],\n        responses: {\n          /* ... */\n        },\n      },\n    },\n    \"/status\": {\n      get: {\n        // no x-type -\u003e will use the \"get\" caller\n        responses: {\n          /* ... */\n        },\n      },\n    },\n  },\n};\n```\n\n### 4. Write your _callers_\n\nThese are generic functions that handle requests at the HTTP level.\n\nThey are not handled by this package, because they can be very different from one codebase to another; but usually you don't have to write a lot of them.\n\n`url` is an [URL](https://developer.mozilla.org/en-US/docs/Web/API/URL), `body` is a plain JS object.\n\n```js\nconst callers = {\n  get: async (url) =\u003e {\n    const resp = await fetch(url);\n    const json = await resp.json();\n    return json;\n  },\n  authorizedGet: async (url) =\u003e {\n    const headers = new Headers();\n    headers.append(\"Content-Type\", \"application/json\");\n    headers.append(\"Authorization\", `Bearer ${localStorage.token}`);\n    const resp = await fetch(url, { headers });\n    const json = await resp.json();\n    return json;\n  },\n  authorizedPost: async (url, body) =\u003e {\n    const headers = new Headers();\n    headers.append(\"Content-Type\", \"application/json\");\n    headers.append(\"Authorization\", `Bearer ${localStorage.token}`);\n    const resp = await fetch(url, {\n      method: \"POST\",\n      headers,\n      body: JSON.stringify(body),\n    });\n    const json = await resp.json();\n    return json;\n  },\n};\n```\n\n### 5. Create your client\n\nYou do this once and `client` can be used in the rest of your code afterward.\n\n`origin` defaults to `specs.servers[0].url`. Optional if it's defined, else required.\n\n`validationLevel` is one of `'off'` (default), `'warn'`, or `'error'`. It checks the path params, the query params, and the body against the schema present in the specs.\n\n```js\nconst client = createClient(specs, callers, {\n  origin: \"https://my.api.com\",\n  validationLevel: \"error\",\n});\n```\n\n### 6. Use your client\n\nThereafter, `oa-client` does all the work of building the full URL and validating input data for you!\n\nIn this example, this\n\n```js\nconst data = await client[\"/users/{userId}\"].get({\n  pathParams: { userId: 123 },\n});\n```\n\nis equivalent to\n\n```js\nconst url = new URL(\"https://my.api.com/users/123\");\nconst data = await callers.authorizedGet(url);\n```\n\n## Differences with openapi-client\n\nThe [openapi-client](https://github.com/mikestead/openapi-client) package is similar but accomplishes things differently.\n\n`openapi-client` is a **code generation** package. You use it as a command line so that it consumes OpenAPI specs and outputs code that will call your server. It is not ideal because you don't own and control all of your code, and it adds complexity.\n\n`oa-client` is simpler - it exposes `createClient`, a **factory** that take specs as input and builds the client at runtime. If your API updates, you don't have to write or generate a single line of code.\n\n`openapi-client` handles all the HTTP calls and authentication for you. That can seem powerful, but actually the system is _very_ rigid, even for small customizations, and doesn't cover all cases you'll face along the way.\n\nIn `oa-client`, you fully own your generic HTTP callers: you write them yourself, but you probably won't write more than five of them during your whole project lifetime: who needs more than get, post, authorized get, authorized post and file upload?\n\n```\n+-------------------------------+\n| Written with \u003c3 by Nino Filiu |\n|  Contributions are welcomed!  |\n+-------------------------------+\n         \\   ^__^\n          \\  (oo)\\_______\n             (__)\\       )\\/\\\n                 ||----w |\n                 ||     ||\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fninofiliu%2Foa-client","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fninofiliu%2Foa-client","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fninofiliu%2Foa-client/lists"}