{"id":13481386,"url":"https://github.com/zaqqaz/ng2-rest-api","last_synced_at":"2025-07-09T12:40:58.028Z","repository":{"id":95794889,"uuid":"55294602","full_name":"zaqqaz/ng2-rest-api","owner":"zaqqaz","description":":red_circle: Rest API provider for angular 2. ","archived":false,"fork":false,"pushed_at":"2016-11-07T09:25:14.000Z","size":365,"stargazers_count":209,"open_issues_count":0,"forks_count":11,"subscribers_count":9,"default_branch":"master","last_synced_at":"2024-10-30T15:50:43.722Z","etag":null,"topics":[],"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/zaqqaz.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}},"created_at":"2016-04-02T13:00:04.000Z","updated_at":"2024-01-04T16:03:58.000Z","dependencies_parsed_at":null,"dependency_job_id":"c6f8a2b3-930b-4e8b-a4d5-81fd2dc40509","html_url":"https://github.com/zaqqaz/ng2-rest-api","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zaqqaz%2Fng2-rest-api","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zaqqaz%2Fng2-rest-api/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zaqqaz%2Fng2-rest-api/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zaqqaz%2Fng2-rest-api/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/zaqqaz","download_url":"https://codeload.github.com/zaqqaz/ng2-rest-api/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":224192424,"owners_count":17271231,"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":[],"created_at":"2024-07-31T17:00:51.393Z","updated_at":"2024-11-11T23:34:54.239Z","avatar_url":"https://github.com/zaqqaz.png","language":"TypeScript","funding_links":[],"categories":["Uncategorized"],"sub_categories":["Uncategorized"],"readme":"# ng2-rest-api\n\nNg2-rest-api - is a rest api provider for angular 2 for http actions request to server and instantiate models.\n- Describe api to define endpoints and actions\n- Improves code-reusability by separating configuration from code that does actual work.\n- That simplifies common GET, POST, DELETE, and UPDATE requests.\n- Use a parameterized URLs.\n- Easy headers read.\n- Cache requests (todo)\n\nIf you need - you can get plain text response (It is sometimes convenient, but do not overdo it)\n\nFor Angular 1: https://github.com/zaqqaz/ng-rest-api\n\n![directive](https://cloud.githubusercontent.com/assets/2823336/19967580/9fa019e8-a1d9-11e6-827e-370232277c0d.png)\n\n## Installation\n\nTo install this library, run:\n\n```bash\n$ npm install ng2-rest-api --save\n```\n\n## NEXT STEPS\n1. Describe models\n2. Create config\n3. Add to @NgModule and execute static method *configure*.\n5. Advice: use ApiProvider only in managers/services not from controllers.\n6. *Enjoy!*\n\n## Config\n\nYou should describe endpoints and http Actions.\nNg2-rest-api already had config for popular actions (get(GET),query(GET, array), update(PUT), patch(PATCH), remove(DELETE)).\nBut if you need you can override them and add any others.\n\n![directive](https://cloud.githubusercontent.com/assets/2823336/19968023/63ec14f4-a1db-11e6-818c-9f22cae7107d.png)\n\n\n### Let's look at the interfaces for config:\n\n**ApiConfig**\n```typescript\ninterface ApiConfig {\n  baseUrl: string,  // e.g. http://example.com:8080/api\n  endpoints: Endpoint[]\n}\n```\n\n**Endpoint**\n```typescript\ninterface Endpoint {\n  name: OpaqueToken; // The name of emdpoint.\n  route: string; // A parameterized part of URL\n  model?: any; // {Object} - model on which will be mapped response, if no - return JSON object.\n  actions?: Action[]; // Hash with declaration of custom actions that will be available in addition to the default set of default actions.\n}\n```\n\n**route** -\nA parameterized part of URL template with parameters prefixed by : as in `/user/:username`.\nIf you are using a url with a suffix, just add the suffix, like this:\n`'/resource.json'` or `'/:id.json'` or even `'/resource/:resource_id.:format'`\nIf the parameter before the suffix is empty, `:resource_id` in this case, then the `/.` will be collapsed down to a single ..\nIf you need this sequence to appear and not collapse then you can escape it with `/\\.`.\n\n**Action**\n```typescript\ninterface Action {\n   name: string, // The name of action.\n   method: string, // Case insensitive HTTP method (e.g. GET, POST, PUT, DELETE, JSONP, etc).\n   instantiateModel?: boolean, // need do instatiate model ? default - true; if no - return plain text response.\n   isArray?: boolean, // If true then the returned object for this action is an array,\n   headersForReading?: Array\u003cstring\u003e, // Headers which need read\n   params?: any, // Optional set of pre-bound parameters for this action\n   cache?: any // todo\n }\n```\n---\n\n**params** -\nDefault values for url parameters. These can be overridden in actions methods.\nIf a parameter value is a function, it will be called every time a param value needs to be obtained for a request (unless the param was overridden).\nThe function will be passed the current data value as an argument.\nEach key value in the parameter object is first bound to url template if present and then any excess keys are appended to the url search query after the ?.\nGiven a template `/path/:verb` and parameter `{verb:'greet', salutation:'Hello'}` results in URL `/path/greet?salutation=Hello`.\nIf the parameter value is prefixed with `@`, then the value for that parameter will be extracted from the corresponding property on the data object (provided when calling a \"non-GET\" action method).\nFor example, if the defaultParam object is `{someParam: '@someProp'}` then the value of someParam will be data.someProp.\nNote that the parameter will be ignored, when calling a \"GET\" action method (i.e. an action method that does not accept a request body)\n\n## How to use\n```\n// api: ApiProvider\n// endpointName: {OpaqueToken} - endpoint name from config.\n// actionName: {string} - default action name or any from config.\n// body: {object} - body data for POST request. If is GET request body use as params\n// params: {object} - additional params which will be mixed with pre-bound parameters for this action and override them if will has the same key.\nthis.api.endpoint(endpointName).action(actionName', body, params);\n```\n\n\n## Examples:\n**Model**\n```typescript\nimport {Image} from 'api/models/Image';\n\nexport class Post {\n  id?: number;\n  title: string;\n  description: string;\n  content: string;\n  image: Image | any;\n\n  constructor({id, title, description, content, image}:\n              {id?: number, title: string, description: string, content: string, image: Image|any}) {\n    this.id = id;\n    this.title = title;\n    this.description = description;\n    this.content = content;\n    this.image = new Image(image);\n  }\n\n  beforeSave() {\n    if (this.image) {\n      this.image = this.image.id;\n    }\n  }\n}\n\n```\n**Config:**\n```typescript\nimport {OpaqueToken} from \"@angular/core\";\nimport {Post} from \"api/models/Post\";\n\n// endpoints\nexport const POSTS = new OpaqueToken('POSTS');\n\n// config\nexport const apiConfig = {\n  baseUrl: 'http://localhost:3000',\n  endpoints: [\n    {\n      name: POSTS,\n      model: Post,\n      route: '/posts/:id',\n      actions: [\n        {\n          name: 'query',\n          method: 'GET',\n          isArray: true,\n          headersForReading: ['X-Total-Count'],\n          params: {limit: 10}\n        }\n      ]\n    }\n  ]\n};\n```\n**@NgModule**\n```typescript\nimport {BrowserModule} from '@angular/platform-browser';\nimport {NgModule} from '@angular/core';\nimport {FormsModule} from '@angular/forms';\nimport {HttpModule} from '@angular/http';\n\nimport {AppComponent} from './app.component';\nimport {MainComponent} from './endpoints/main/main.component';\nimport {RouterModule} from '@angular/router';\nimport {routes} from './app.routes'\nimport {TypingCarouselDirective} from \"./endpoints/main/typing-carousel.directive\";\nimport {LoaderComponent} from './shared/loader/loader.component';\nimport {Ng2RestApiModule, ApiProvider} from \"ng2-rest-api\";\nimport {apiConfig} from \"api/config\";\n\nimport {PostsManager} from './api/services/PostsManager';\nimport { PostsComponent } from './endpoints/posts/posts.component';\n\n@NgModule({\n  declarations: [\n    AppComponent,\n    MainComponent,\n    TypingCarouselDirective,\n    LoaderComponent,\n    PostsComponent\n  ],\n  imports: [\n    BrowserModule,\n    FormsModule,\n    HttpModule,\n    RouterModule.forRoot(routes),\n    Ng2RestApiModule.configure(apiConfig)\n  ],\n  providers: [ApiProvider, PostsManager],\n  bootstrap: [AppComponent]\n})\nexport class AppModule {\n}\n```\n**Service**\n```typescript\nimport {ApiProvider} from \"ng2-rest-api\";\nimport {POSTS} from \"api/config\";\nimport {Injectable} from \"@angular/core\";\nimport {Post} from \"api/models/Post\";\n\n@Injectable()\nexport class PostsManager {\n  constructor(private api: ApiProvider) {\n  }\n\n  getPost(id: number) {\n    return this.api.endpoint(POSTS).action('get', {id});\n  }\n\n  queryPosts(query: string, offset: number) {\n    return this.api.endpoint(POSTS).action('query', {query, offset});\n  }\n\n  savePost(post: Post) {\n    return post.id ? this.api.endpoint(POSTS).action('update', post) : this.api.endpoint(POSTS).action('save', post);\n  }\n}\n```\n**Controller**\n```typescript\nimport {Component, OnInit} from '@angular/core';\nimport {PostsManager} from 'api/services/PostsManager';\nimport {Post} from 'api/models/Post';\nimport {Image} from 'api/models/Image';\n\n@Component({\n  selector: 'app-post',\n  templateUrl: './post.component.html',\n  styleUrls: ['./post.component.scss']\n})\nexport class PostComponent implements OnInit {\n\n  constructor(private postsManager: PostsManager) {}\n\n  example() {\n    // search 'evolution' posts with offset = 0\n    this.postsManager.queryPosts('evolution', 0).subscribe(([posts, headers]) =\u003e {\n      this.total = headers['X-Total-Count'];\n      this.posts = posts;\n      console.log('Response', this.posts, 'X-Total-Count', this.total);\n    });\n\n    // get post with id 1\n    this.postsManager.getPost(1).subscribe(post =\u003e {\n      console.log('SINGLE', post);\n\n      // update post\n      post.content = 'updated content';\n      this.postsManager.savePost(post).subscribe(p =\u003e console.log('updated'));\n    });\n\n    // create new post\n    this.postsManager.savePost(new Post({\n      title: 'test',\n      description: \"test\",\n      content: 'test',\n      image: new Image({id: 1, src: ''})\n    })).subscribe(p =\u003e console.log('saved'));\n  }\n}\n```\n## To Do\n- Improve documentation.\n- Cache\n- Add tests\n- Method to set headers for all actions, and for specific. (Authorization token etc.)\n\n## Cache\nWill be implemented soon.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzaqqaz%2Fng2-rest-api","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fzaqqaz%2Fng2-rest-api","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzaqqaz%2Fng2-rest-api/lists"}