{"id":22242968,"url":"https://github.com/mediamonks/jsonapi-client","last_synced_at":"2025-07-28T01:32:05.648Z","repository":{"id":35402610,"uuid":"217286181","full_name":"mediamonks/jsonapi-client","owner":"mediamonks","description":"TypeScript JSON:API client for the browser","archived":false,"fork":false,"pushed_at":"2023-12-11T08:39:11.000Z","size":26411,"stargazers_count":12,"open_issues_count":30,"forks_count":1,"subscribers_count":17,"default_branch":"main","last_synced_at":"2024-11-28T13:42:46.617Z","etag":null,"topics":["json-api","json-api-client","json-api-consumer"],"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/mediamonks.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":"2019-10-24T11:48:09.000Z","updated_at":"2024-11-12T19:10:52.000Z","dependencies_parsed_at":"2024-11-30T08:21:06.899Z","dependency_job_id":null,"html_url":"https://github.com/mediamonks/jsonapi-client","commit_stats":{"total_commits":146,"total_committers":6,"mean_commits":"24.333333333333332","dds":0.4178082191780822,"last_synced_commit":"267af75dae50958597e03a87807cd26bdef97161"},"previous_names":[],"tags_count":11,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mediamonks%2Fjsonapi-client","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mediamonks%2Fjsonapi-client/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mediamonks%2Fjsonapi-client/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mediamonks%2Fjsonapi-client/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mediamonks","download_url":"https://codeload.github.com/mediamonks/jsonapi-client/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":227850677,"owners_count":17829201,"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":["json-api","json-api-client","json-api-consumer"],"created_at":"2024-12-03T04:19:02.957Z","updated_at":"2024-12-03T04:19:03.448Z","avatar_url":"https://github.com/mediamonks.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# jsonapi-client\n\n## Install\n\n```sh\nyarn add @mediamonks/jsonapi-client\nnpm i -S @mediamonks/jsonapi-client\n```\n\n## Usage\n\n```typescript\nimport JSONAPI, { Attribute, Relationship } from '@mediamonks/jsonapi-client'\nimport { isString } from 'isntnt'\n\n// set up a Resource, passing the `type` and the endpoint path\nexport class Post extends JSONAPI.resource('Post', 'posts')\u003cPost\u003e {\n  @Attribute.required(isString) public title!: string\n  @Attribute.optional(isString) public content!: string | null\n  @Relationship.toOne(() =\u003e Author) public author!: Author | null\n  @Relationship.toMany(() =\u003e Comment) public comments!: Comment[]\n}\n\n// create a client\nconst url = new URL('http://www.example.com/api')\nconst client = JSONAPI.client(url)\n\n// create an endpoint\nconst endpoint = client.endpoint(Post)\n\n// get single item\nendpoint.getOne(id, {\n  fields: { [Post.type]: ['title, author']},\n  includes: { author: null },\n}).then(result =\u003e console.log('one', result))\n\n// get collection\nendpoint.getMany({\n  offset: 10,\n  limit: 3,\n  sort: ['title', '-author'],\n  filter: { 'author.id': authorId }\n}, {\n  fields: { [Post.type]: ['title, author']},\n  includes: { author: null },\n}).then(results =\u003e console.log('many', results))\n\n// create a new resource\nendpoint.create({\n  title: 'foo',\n  content: 'bar'\n}).then(result =\u003e console.log('new', result))\n\n// patch an existing resource\nendpoint.patch(id, {\n  title: 'foo',\n  content: 'bar'\n})\n\n// delete an existing resource\nendpoint.delete(id)\n```\n\n## Types\n\nBelow is a quick reference on the types you'll encounter or use on a daily basis.\n\n**Resource**\n\n* `ResourceId` - a `string`, alias for the resource id\n* `ResourceType` - a `string`, alias for the resource type\n* `ResourceIdentifier\u003cResourceType\u003e` - type for a basic resource with id/type fields\n* `AnyResource` - an alias for the above, to represent any resource\n* `ResourceConstructor\u003cAnyResource\u003e` - type for a resource constructor/class\n\n\n* `ResourceCreateValues\u003cAnyResource\u003e` - to type data objects to create a specific resource\n* `ResourcePatchValues\u003cAnyResource\u003e` - to type data objects to patch a specific resource\n\n\n* `ResourceParameters\u003cAnyResource\u003e` - a type that represents a resource filter with fields and includes\n\n\n**Endpoint**\n\n* `Endpoint\u003cAnyResource, ClientSetup\u003e` - to type an Endpoint, potentially for a specific resource\n* `EndpointResource\u003cEndpoint\u003cany, any\u003e\u003e` - a helper type to extract a Resource from an Endpoint\n\n\n* `FilteredResource\u003cAnyResource, ResourceParameters\u003cAnyResource\u003e\u003e` - to type a resource that only contains specific fields (both attributes and nested relationships).\n* `ClientSearchParameters\u003cClientSetup\u003e` - to type the collection query parameters for pagination, sorting, filtering, etc\n\n## Examples\n\n### Filters\n\nBasic example for fetching filtered resources.\n\n```typescript\n// create a filter\nconst postFilter = {\n  // It's good practise to specify which fields to return for all resources in the response.\n  // It's an object with the resource type as key, and an array with the fields as values.\n  // The field array should contain both attributes and relationships.\n  // A relationship specified here would only return the ResourceIdentifier (id/type), unless\n  // you also include the relationship below .\n  fields: {\n    [Post.type]: ['name', 'content', 'comments', 'author'],\n    [Comment.type]: ['title', 'author'],\n    [Author.type]: ['name', 'homepage'],\n  },\n\n  // Specify which relationship fields from the above defintion to include as additional resources.\n  // The nesting here should follow the one from the Resource field specification.\n  // Setting `null` means that resource won't include any others, while an object can be used\n  // to specify includes for that nested relationship, and can go many levels deep.\n  // As can be seen, author should be included on both the Post and the Comment.\n  // The includes object starts with the fields of the Resource to filter, which should\n  // also be placed as first Resource in the field list by convention\n  include: {\n    comments: {\n      author: null,\n    },\n    author: null,\n  },\n} as const\n// note the `as const` - that's needed for type checking\n\n// this type contains only the (nested) field specified in the filter above\ntype FilteredPost = FilteredResource\u003cPost, postFilter\u003e\n\nlet items: Array\u003cFilteredPost\u003e\n\n// the filter itself can be passed to the getOne/getMany methods\nendpoint.getMany({}, postFilter).then(result =\u003e {\n  items = result\n})\n```\n\nBasic example on how to specify function parameters\n\n```typescript\nconst postFilter = {\n  fields: {\n    [Post.type]: ['title', 'author'],\n    [Author.type]: ['name'],\n  },\n  include: { author: null },\n} as const\n\nfunction renderPost(post: FilteredResource\u003cPost, postFilter\u003e) {\n  // in here, only a few specific fields of `post` are used\n  // so it's good practise to use a filter instead of requesting the full Post type\n}\n\n// when not needing nested resources, a `Pick` can be used as well\nfunction renderPost(post: Pick\u003cPost, 'name' | 'author'\u003e) {\n  // in here, only a few specific fields of `post` are used\n  // so it's good practise to use a filter instead of requesting the full Post type\n}\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmediamonks%2Fjsonapi-client","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmediamonks%2Fjsonapi-client","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmediamonks%2Fjsonapi-client/lists"}