diff --git a/.changeset/config.json b/.changeset/config.json index dcd3d8b..e98e6e7 100644 --- a/.changeset/config.json +++ b/.changeset/config.json @@ -1,11 +1,11 @@ { - "$schema": "https://unpkg.com/@changesets/config@3.0.0/schema.json", - "changelog": "@changesets/cli/changelog", - "commit": false, - "fixed": [], - "linked": [], - "access": "public", - "baseBranch": "master", - "updateInternalDependencies": "patch", - "ignore": [] + "$schema": "https://unpkg.com/@changesets/config@3.0.0/schema.json", + "changelog": "@changesets/cli/changelog", + "commit": false, + "fixed": [], + "linked": [], + "access": "public", + "baseBranch": "master", + "updateInternalDependencies": "patch", + "ignore": [] } diff --git a/.gitignore b/.gitignore index cc7b141..0d227a6 100644 --- a/.gitignore +++ b/.gitignore @@ -1,32 +1,192 @@ -# See https://docs.github.com/get-started/getting-started-with-git/ignoring-files for more about ignoring files. - -# Compiled output -/dist -/tmp -/out-tsc -/bazel-out - -# Node -/node_modules -npm-debug.log -yarn-error.log - -# IDEs and editors -.idea/ -.project -.classpath -.c9/ -*.launch -.settings/ -*.sublime-workspace - -# Visual Studio Code -.vscode/* -!.vscode/settings.json -!.vscode/tasks.json -!.vscode/launch.json -!.vscode/extensions.json -.history/* +# Based on https://raw.githubusercontent.com/github/gitignore/main/Node.gitignore + +# Logs + +logs +_.log +npm-debug.log_ +yarn-debug.log* +yarn-error.log* +lerna-debug.log* +.pnpm-debug.log* + +# Caches + +.cache + +# Diagnostic reports (https://nodejs.org/api/report.html) + +report.[0-9]_.[0-9]_.[0-9]_.[0-9]_.json + +# Runtime data + +pids +_.pid +_.seed +*.pid.lock + +# Directory for instrumented libs generated by jscoverage/JSCover + +lib-cov + +# Coverage directory used by tools like istanbul + +coverage +*.lcov + +# Playwright +/test-results/ +/tests/coverage-report + +# nyc test coverage + +.nyc_output + +# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) + +.grunt + +# Bower dependency directory (https://bower.io/) + +bower_components + +# node-waf configuration + +.lock-wscript + +# Compiled binary addons (https://nodejs.org/api/addons.html) + +build/Release + +# Dependency directories + +node_modules/ +jspm_packages/ + +# Snowpack dependency directory (https://snowpack.dev/) + +web_modules/ + +# TypeScript cache + +*.tsbuildinfo + +# Optional npm cache directory + +.npm + +# Optional eslint cache + +.eslintcache + +# Optional stylelint cache + +.stylelintcache + +# Microbundle cache + +.rpt2_cache/ +.rts2_cache_cjs/ +.rts2_cache_es/ +.rts2_cache_umd/ + +# Optional REPL history + +.node_repl_history + +# Output of 'npm pack' + +*.tgz + +# Yarn Integrity file + +.yarn-integrity + +# dotenv environment variable files + +.env +.env.development.local +.env.test.local +.env.production.local +.env.local + +# parcel-bundler cache (https://parceljs.org/) + +.parcel-cache + +# Next.js build output + +.next +out + +# Nuxt.js build / generate output + +.nuxt +dist + +# Gatsby files + +# Comment in the public line in if your project uses Gatsby and not Next.js + +# https://nextjs.org/blog/next-9-1#public-directory-support + +# public + +# vuepress build output + +.vuepress/dist + +# vuepress v2.x temp and cache directory + +.temp + +# Docusaurus cache and generated files + +.docusaurus + +# Serverless directories + +.serverless/ + +# FuseBox cache + +.fusebox/ + +# DynamoDB Local files + +.dynamodb/ + +# TernJS port file + +.tern-port + +# Stores VSCode versions used for testing VSCode extensions + +.vscode-test + +# yarn v2 + +.yarn/cache +.yarn/unplugged +.yarn/build-state.yml +.yarn/install-state.gz +.pnp.* + +# IntelliJ based IDEs +.idea + +# Finder (MacOS) folder config +.DS_Store + +# SvelteKit build / generate output +**/node_modules +**/.turbo +**/dist +**/build +**/.next +**/.svelte-kit +**/vite.config.js.timestamp-* +**/vite.config.ts.timestamp-* # Miscellaneous /.angular/cache @@ -36,7 +196,3 @@ yarn-error.log /libpeerconnection.log testem.log /typings - -# System files -.DS_Store -Thumbs.db diff --git a/.vscode/extensions.json b/.vscode/extensions.json index 77b3745..7b25192 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -1,4 +1,3 @@ { - // For more information, visit: https://go.microsoft.com/fwlink/?linkid=827846 - "recommendations": ["angular.ng-template"] + "recommendations": ["angular.ng-template"] } diff --git a/.vscode/launch.json b/.vscode/launch.json deleted file mode 100644 index 925af83..0000000 --- a/.vscode/launch.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 - "version": "0.2.0", - "configurations": [ - { - "name": "ng serve", - "type": "chrome", - "request": "launch", - "preLaunchTask": "npm: start", - "url": "http://localhost:4200/" - }, - { - "name": "ng test", - "type": "chrome", - "request": "launch", - "preLaunchTask": "npm: test", - "url": "http://localhost:9876/debug.html" - } - ] -} diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..4103d58 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,19 @@ +{ + "editor.defaultFormatter": "biomejs.biome", + "editor.codeActionsOnSave": { + "source.organizeImports": "explicit", + "source.fixAll.biome": "explicit" + }, + "[svelte]": { + "editor.defaultFormatter": "svelte.svelte-vscode" + }, + "[dotenv]": { + "editor.defaultFormatter": "foxundermoon.shell-format" + }, + "[postcss]": { + "editor.defaultFormatter": "esbenp.prettier-vscode" + }, + "[shellscript]": { + "editor.defaultFormatter": "foxundermoon.shell-format" + } +} diff --git a/.vscode/tasks.json b/.vscode/tasks.json deleted file mode 100644 index a298b5b..0000000 --- a/.vscode/tasks.json +++ /dev/null @@ -1,42 +0,0 @@ -{ - // For more information, visit: https://go.microsoft.com/fwlink/?LinkId=733558 - "version": "2.0.0", - "tasks": [ - { - "type": "npm", - "script": "start", - "isBackground": true, - "problemMatcher": { - "owner": "typescript", - "pattern": "$tsc", - "background": { - "activeOnStart": true, - "beginsPattern": { - "regexp": "(.*?)" - }, - "endsPattern": { - "regexp": "bundle generation complete" - } - } - } - }, - { - "type": "npm", - "script": "test", - "isBackground": true, - "problemMatcher": { - "owner": "typescript", - "pattern": "$tsc", - "background": { - "activeOnStart": true, - "beginsPattern": { - "regexp": "(.*?)" - }, - "endsPattern": { - "regexp": "bundle generation complete" - } - } - } - } - ] -} diff --git a/angular.json b/angular.json index 7168d91..36df511 100644 --- a/angular.json +++ b/angular.json @@ -1,40 +1,37 @@ { - "$schema": "./node_modules/@angular/cli/lib/config/schema.json", - "version": 1, - "newProjectRoot": "packages", - "projects": { - "ngx-grs": { - "projectType": "library", - "root": "packages/ngx-grs", - "sourceRoot": "packages/ngx-grs/src", - "prefix": "lib", - "architect": { - "build": { - "builder": "@angular-devkit/build-angular:ng-packagr", - "options": { - "project": "packages/ngx-grs/ng-package.json" - }, - "configurations": { - "production": { - "tsConfig": "packages/ngx-grs/tsconfig.lib.prod.json" - }, - "development": { - "tsConfig": "packages/ngx-grs/tsconfig.lib.json" - } - }, - "defaultConfiguration": "production" - }, - "test": { - "builder": "@angular-devkit/build-angular:karma", - "options": { - "tsConfig": "packages/ngx-grs/tsconfig.spec.json", - "polyfills": [ - "zone.js", - "zone.js/testing" - ] - } - } - } - } - } + "$schema": "./node_modules/@angular/cli/lib/config/schema.json", + "version": 1, + "newProjectRoot": "packages", + "projects": { + "ngx-grs": { + "projectType": "library", + "root": "packages/ngx-grs", + "sourceRoot": "packages/ngx-grs/src", + "prefix": "lib", + "architect": { + "build": { + "builder": "@angular-devkit/build-angular:ng-packagr", + "options": { + "project": "packages/ngx-grs/ng-package.json" + }, + "configurations": { + "production": { + "tsConfig": "packages/ngx-grs/tsconfig.lib.prod.json" + }, + "development": { + "tsConfig": "packages/ngx-grs/tsconfig.lib.json" + } + }, + "defaultConfiguration": "production" + }, + "test": { + "builder": "@angular-devkit/build-angular:karma", + "options": { + "tsConfig": "packages/ngx-grs/tsconfig.spec.json", + "polyfills": ["zone.js", "zone.js/testing"] + } + } + } + } + } } diff --git a/biome.json b/biome.json index 126ca2a..93c5290 100644 --- a/biome.json +++ b/biome.json @@ -1,5 +1,5 @@ { - "$schema": "./node_modules/@biomejs/biome/configuration_schema.json", + "$schema": "./node_modules/@biomejs/biome/configuration_schema.json", "vcs": { "enabled": true, "clientKind": "git", @@ -12,7 +12,11 @@ "useFilenamingConvention": "off", "noDefaultExport": "off", "useNamingConvention": "off", - "noNamespaceImport": "off" + "noNamespaceImport": "off", + "noParameterProperties": "off" + }, + "suspicious": { + "noExplicitAny": "off" }, "performance": { "noBarrelFile": "off", @@ -35,5 +39,17 @@ "formatter": { "quoteStyle": "single" } - } + }, + "overrides": [ + { + "include": ["*.spec.ts"], + "linter": { + "rules": { + "correctness": { + "noUndeclaredVariables": "off" + } + } + } + } + ] } diff --git a/bun.lockb b/bun.lockb index 0a6e25b..9d93087 100755 Binary files a/bun.lockb and b/bun.lockb differ diff --git a/lefthook.yml b/lefthook.yml new file mode 100644 index 0000000..7a1e79c --- /dev/null +++ b/lefthook.yml @@ -0,0 +1,11 @@ +pre-push: + commands: + check: + glob: "*.{js,ts,cjs,mjs,d.cts,d.mts,jsx,tsx,json,jsonc}" + run: bunx biome check --no-errors-on-unmatched --files-ignore-unknown=true {push_files} + +pre-commit: + commands: + check: + glob: "*.{js,ts,cjs,mjs,d.cts,d.mts,jsx,tsx,json,jsonc}" + run: bunx biome check --apply --no-errors-on-unmatched --files-ignore-unknown=true {staged_files} && git update-index --again diff --git a/package.json b/package.json index 19bed12..123aa0c 100644 --- a/package.json +++ b/package.json @@ -1,45 +1,46 @@ { - "name": "ngx-generic-rest-service", - "private": true, - "scripts": { - "ng": "ng", - "build": "ng build", - "watch": "ng build --watch --configuration development", - "test": "ng test --watch=false --browsers ChromeHeadless", - "lint": "biome lint --apply .", - "format": "biome format --write . && prettier --write 'src/**/*.svelte'", - "ci:version": "changeset version && git add --all", - "ci:release": "changeset tag && changeset publish" - }, - "workspaces": ["packages/*"], - "dependencies": { - "@angular/animations": "^17.3.0", - "@angular/common": "^17.3.0", - "@angular/compiler": "^17.3.0", - "@angular/core": "^17.3.0", - "@angular/forms": "^17.3.0", - "@angular/platform-browser": "^17.3.0", - "@angular/platform-browser-dynamic": "^17.3.0", - "@angular/router": "^17.3.0", - "rxjs": "~7.8.0", - "tslib": "^2.3.0", - "zone.js": "~0.14.3" - }, - "devDependencies": { - "@angular-devkit/build-angular": "^17.3.7", - "@angular/cli": "^17.3.7", - "@angular/compiler-cli": "^17.3.0", - "@types/jasmine": "~5.1.0", - "@biomejs/biome": "^1.7.3", - "@changesets/cli": "^2.27.1", - "@types/bun": "^1.1.1", - "jasmine-core": "~5.1.0", - "karma": "~6.4.0", - "karma-chrome-launcher": "~3.2.0", - "karma-coverage": "~2.2.0", - "karma-jasmine": "~5.1.0", - "karma-jasmine-html-reporter": "~2.1.0", - "ng-packagr": "^17.3.0", - "typescript": "~5.4.2" - } + "name": "ngx-generic-rest-service", + "private": true, + "scripts": { + "ng": "ng", + "build": "ng build", + "watch": "ng build --watch --configuration development", + "test": "ng test --watch=false --browsers ChromeHeadless", + "lint": "biome lint --apply .", + "format": "biome format --write .", + "ci:version": "changeset version && git add --all", + "ci:release": "changeset tag && changeset publish" + }, + "workspaces": ["packages/*"], + "dependencies": { + "@angular/animations": "^17.3.0", + "@angular/common": "^17.3.0", + "@angular/compiler": "^17.3.0", + "@angular/core": "^17.3.0", + "@angular/forms": "^17.3.0", + "@angular/platform-browser": "^17.3.0", + "@angular/platform-browser-dynamic": "^17.3.0", + "@angular/router": "^17.3.0", + "rxjs": "~7.8.0", + "tslib": "^2.3.0", + "zone.js": "~0.14.3" + }, + "devDependencies": { + "@angular-devkit/build-angular": "^17.3.7", + "@angular/cli": "^17.3.7", + "@angular/compiler-cli": "^17.3.0", + "@biomejs/biome": "^1.7.3", + "@changesets/cli": "^2.27.1", + "@types/bun": "^1.1.1", + "@types/jasmine": "~5.1.0", + "jasmine-core": "~5.1.0", + "karma": "~6.4.0", + "karma-chrome-launcher": "~3.2.0", + "karma-coverage": "~2.2.0", + "karma-jasmine": "~5.1.0", + "karma-jasmine-html-reporter": "~2.1.0", + "lefthook": "^1.6.10", + "ng-packagr": "^17.3.0", + "typescript": "~5.4.2" + } } diff --git a/packages/ngx-grs/ng-package.json b/packages/ngx-grs/ng-package.json index 130327e..2b158c8 100644 --- a/packages/ngx-grs/ng-package.json +++ b/packages/ngx-grs/ng-package.json @@ -1,7 +1,7 @@ { - "$schema": "../../node_modules/ng-packagr/ng-package.schema.json", - "dest": "../../dist/ngx-grs", - "lib": { - "entryFile": "src/public-api.ts" - } -} \ No newline at end of file + "$schema": "../../node_modules/ng-packagr/ng-package.schema.json", + "dest": "../../dist/ngx-grs", + "lib": { + "entryFile": "src/public-api.ts" + } +} diff --git a/packages/ngx-grs/package.json b/packages/ngx-grs/package.json index 47ec4ff..8fea190 100644 --- a/packages/ngx-grs/package.json +++ b/packages/ngx-grs/package.json @@ -1,33 +1,27 @@ { - "name": "ngx-grs", - "version": "0.1.1", - "description": "Generic REST service for Angular", - "author": "jm2097", - "publishConfig": { - "access": "public" - }, - "repository": { - "type": "git", - "url": "https://github.com/juanmesa2097/ngx-generic-rest-service.git" - }, - "bugs": { - "url": "https://github.com/juanmesa2097/ngx-generic-rest-service/issues" - }, - "homepage": "https://github.com/juanmesa2097/ngx-generic-rest-service", - "keywords": [ - "angular", - "service", - "restful", - "rest", - "api" - ], - "license": "MIT", - "peerDependencies": { - "@angular/common": "^17.3.0", - "@angular/core": "^17.3.0" - }, - "dependencies": { - "tslib": "^2.3.0" - }, - "sideEffects": false + "name": "ngx-grs", + "version": "0.1.1", + "description": "Generic REST service for Angular", + "author": "jm2097", + "publishConfig": { + "access": "public" + }, + "repository": { + "type": "git", + "url": "https://github.com/juanmesa2097/ngx-generic-rest-service.git" + }, + "bugs": { + "url": "https://github.com/juanmesa2097/ngx-generic-rest-service/issues" + }, + "homepage": "https://github.com/juanmesa2097/ngx-generic-rest-service", + "keywords": ["angular", "service", "restful", "rest", "api"], + "license": "MIT", + "peerDependencies": { + "@angular/common": "^17.3.0", + "@angular/core": "^17.3.0" + }, + "dependencies": { + "tslib": "^2.3.0" + }, + "sideEffects": false } diff --git a/packages/ngx-grs/src/lib/ngx-generic-rest.service.spec.ts b/packages/ngx-grs/src/lib/ngx-generic-rest.service.spec.ts index 6e477c4..b7a33e4 100644 --- a/packages/ngx-grs/src/lib/ngx-generic-rest.service.spec.ts +++ b/packages/ngx-grs/src/lib/ngx-generic-rest.service.spec.ts @@ -1,688 +1,645 @@ import { HttpHeaders, HttpParams } from '@angular/common/http'; -import { - HttpClientTestingModule, - HttpTestingController, -} from '@angular/common/http/testing'; +import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing'; import { inject, TestBed } from '@angular/core/testing'; import { extractRequestOptions } from './ngx-generic-rest.utils'; import { type TestEntity, TestService } from './test-setup'; describe('NgxGenericRestService', () => { - describe('config', () => { - beforeEach(() => { - TestBed.configureTestingModule({ - providers: [TestService], - imports: [HttpClientTestingModule], - }); - }); - - it('should be created', inject( - [TestService], - (testService: TestService) => { - expect(testService).toBeTruthy(); - } - )); - - it(`should return 'inline-base-url/inline-resource-name' when url accesor is called`, inject( - [TestService], - (testService: TestService) => { - const apiUrl = testService.url; - const expectedUrl = 'inline-base-url/inline-resource-name'; - expect(apiUrl).toBe(expectedUrl); - } - )); - }); - - describe('utils', () => { - it('should extract HttpRequestOptions from any object', () => { - const mockObject = { - successMsg: 'Operation successful', - errorMsg: 'Operation failed', - urlPostfix: 'bar/foo', - headers: { 'x-foo': 'foo', 'x-bar': 'bar' }, - params: { foo: 'foo', bar: 'bar' }, - observe: 'body', - reportProgress: false, - responseType: 'json', - withCredentials: false, - }; - - const expectedRequestOptions = { - headers: { 'x-foo': 'foo', 'x-bar': 'bar' }, - params: { foo: 'foo', bar: 'bar' }, - observe: 'body', - reportProgress: false, - responseType: 'json', - withCredentials: false, - }; - - const requestOptions = extractRequestOptions(mockObject); - expect(requestOptions).toEqual(expectedRequestOptions); - }); - - it(`should return empty object if there's no common properties between HttpRequestOptions & object`, () => { - const mockObject = { - foo: 'foo', - bar: 'bar', - }; - - const expectedRequestOptions = {}; - - const requestOptions = extractRequestOptions(mockObject); - expect(requestOptions).toEqual(expectedRequestOptions); - }); - }); - - describe('list', () => { - beforeEach(() => { - TestBed.configureTestingModule({ - providers: [TestService], - imports: [HttpClientTestingModule], - }); - }); - - it('should return result from request', inject( - [TestService, HttpTestingController], - (testService: TestService, httpMock: HttpTestingController) => { - const dummyData: TestEntity[] = [ - { id: 1, foo: 'foo', bar: 1 }, - { id: 2, foo: 'bar', bar: 2 }, - ]; - - testService.list().subscribe((result) => { - expect(result).toEqual(dummyData); - }); - - const request = httpMock.expectOne(testService.url); - request.flush(dummyData); - } - )); - - it('should rewrite request URL when called with config.rewrite', inject( - [TestService, HttpTestingController], - (testService: TestService, httpMock: HttpTestingController) => { - const dummyUrl = 'dummy-url'; - testService.list({ urlRewrite: dummyUrl }).subscribe(); - const request = httpMock.expectOne(dummyUrl); - request.flush([]); - } - )); - - it('should add postfix to request URL when called with config.urlPostfix', inject( - [TestService, HttpTestingController], - (testService: TestService, httpMock: HttpTestingController) => { - const dummyPostfix = 'foo/0/bar/1'; - const expectedUrl = `${testService.url}/${dummyPostfix}`; - testService.list({ urlPostfix: dummyPostfix }).subscribe(); - const request = httpMock.expectOne((req) => req.url === expectedUrl); - request.flush([]); - } - )); - - it(`should map request's response to desired result when called with config.mapResponseFn`, inject( - [TestService, HttpTestingController], - (testService: TestService, httpMock: HttpTestingController) => { - const dummyResponse: { data: TestEntity[]; count: number } = { - data: [ - { id: 1, foo: 'foo', bar: 1 }, - { id: 2, foo: 'bar', bar: 2 }, - ], - count: 2, - }; - - testService - .list({ - mapFn: (res) => res.data, - }) - .subscribe((result) => { - expect(result).toEqual(dummyResponse.data); - }); - - const request = httpMock.expectOne(testService.url); - request.flush(dummyResponse); - } - )); - - it(`should transform request's result to desired result when called with config.mapResponseFn`, inject( - [TestService, HttpTestingController], - (testService: TestService, httpMock: HttpTestingController) => { - const dummyData: TestEntity[] = [ - { id: 1, foo: 'foo', bar: 1 }, - { id: 2, foo: 'bar', bar: 2 }, - ]; - - const expectedResult = [ - { name: 'foo', age: 18 }, - { name: 'bar', age: 18 }, - ]; - - testService - .list({ - mapFn: (res) => - res.map((entity: TestEntity) => ({ name: entity.foo, age: 18 })), - }) - .subscribe((result) => { - expect(result).toEqual(expectedResult); - }); - - const request = httpMock.expectOne(testService.url); - request.flush(dummyData); - } - )); - - it('should add headers to request when called with config.headers', inject( - [TestService, HttpTestingController], - (testService: TestService, httpMock: HttpTestingController) => { - const headers = new HttpHeaders() - .set('x-foo', 'foo') - .set('x-bar', 'bar'); - testService.list({ headers }).subscribe(); - - const request = httpMock.expectOne(testService.url); - expect(request.request.headers.get('x-foo')).toBe('foo'); - expect(request.request.headers.get('x-bar')).toBe('bar'); - request.flush([]); - } - )); - - it('should add params to request when called with config.params', inject( - [TestService, HttpTestingController], - (testService: TestService, httpMock: HttpTestingController) => { - const params = new HttpParams().set('foo', 'foo').set('bar', 'bar'); - testService.list({ params }).subscribe(); - const request = httpMock.expectOne( - (req) => req.url === testService.url - ); - expect(request.request.params.get('foo')).toEqual('foo'); - expect(request.request.params.get('bar')).toEqual('bar'); - request.flush([]); - } - )); - }); - - describe('single', () => { - beforeEach(() => { - TestBed.configureTestingModule({ - providers: [TestService], - imports: [HttpClientTestingModule], - }); - }); - - it('should return result from request', inject( - [TestService, HttpTestingController], - (testService: TestService, httpMock: HttpTestingController) => { - const dummyId = 1; - const dummyData: TestEntity = { id: dummyId, foo: 'foo', bar: 1 }; - - testService.single(dummyId).subscribe((result) => { - expect(result).toEqual(dummyData); - }); - - const request = httpMock.expectOne(`${testService.url}/${dummyId}`); - request.flush(dummyData); - } - )); - - it('should rewrite request URL when called with config.rewrite', inject( - [TestService, HttpTestingController], - (testService: TestService, httpMock: HttpTestingController) => { - const dummyId = 1; - const dummyUrl = 'dummy-url'; - testService.single(dummyId, { urlRewrite: dummyUrl }).subscribe(); - const request = httpMock.expectOne(dummyUrl); - request.flush([]); - } - )); - - it('should add postfix to request URL when called with config.urlPostfix', inject( - [TestService, HttpTestingController], - (testService: TestService, httpMock: HttpTestingController) => { - const dummyId = 1; - const dummyPostfix = 'foo/0/bar/1'; - const expectedUrl = `${testService.url}/${dummyId}/${dummyPostfix}`; - testService.single(dummyId, { urlPostfix: dummyPostfix }).subscribe(); - const request = httpMock.expectOne((req) => req.url === expectedUrl); - request.flush([]); - } - )); - - it(`should map request's response to desired result when called with config.mapResponseFn`, inject( - [TestService, HttpTestingController], - (testService: TestService, httpMock: HttpTestingController) => { - const dummyId = 1; - const dummyResponse: { data: TestEntity[]; count: number } = { - data: [ - { id: 1, foo: 'foo', bar: 1 }, - { id: 2, foo: 'bar', bar: 2 }, - ], - count: 2, - }; - - testService - .single(dummyId, { - mapFn: (res) => res.data, - }) - .subscribe((result) => { - expect(result).toEqual(dummyResponse.data); - }); - - const request = httpMock.expectOne(`${testService.url}/${dummyId}`); - request.flush(dummyResponse); - } - )); - - it(`should transform request's result to desired result when called with config.mapResponseFn`, inject( - [TestService, HttpTestingController], - (testService: TestService, httpMock: HttpTestingController) => { - const dummyId = 1; - const dummyData: TestEntity[] = [ - { id: 1, foo: 'foo', bar: 1 }, - { id: 2, foo: 'bar', bar: 2 }, - ]; - - const expectedResult = [ - { name: 'foo', age: 18 }, - { name: 'bar', age: 18 }, - ]; - - testService - .single(dummyId, { - mapFn: (res) => - res.map((entity: TestEntity) => ({ name: entity.foo, age: 18 })), - }) - .subscribe((result) => { - expect(result).toEqual(expectedResult); - }); - - const request = httpMock.expectOne(`${testService.url}/${dummyId}`); - request.flush(dummyData); - } - )); - - it('should add headers to request when called with config.headers', inject( - [TestService, HttpTestingController], - (testService: TestService, httpMock: HttpTestingController) => { - const dummyId = 1; - const headers = new HttpHeaders() - .set('x-foo', 'foo') - .set('x-bar', 'bar'); - testService.single(dummyId, { headers }).subscribe(); - - const request = httpMock.expectOne(`${testService.url}/${dummyId}`); - expect(request.request.headers.get('x-foo')).toBe('foo'); - expect(request.request.headers.get('x-bar')).toBe('bar'); - request.flush([]); - } - )); - - it('should add params to request when called with config.params', inject( - [TestService, HttpTestingController], - (testService: TestService, httpMock: HttpTestingController) => { - const dummyId = 1; - const params = new HttpParams().set('foo', 'foo').set('bar', 'bar'); - testService.single(dummyId, { params }).subscribe(); - const request = httpMock.expectOne( - (req) => req.url === `${testService.url}/${dummyId}` - ); - expect(request.request.params.get('foo')).toEqual('foo'); - expect(request.request.params.get('bar')).toEqual('bar'); - request.flush([]); - } - )); - }); - - describe('add', () => { - beforeEach(() => { - TestBed.configureTestingModule({ - providers: [TestService], - imports: [HttpClientTestingModule], - }); - }); - - it('should return result from request', inject( - [TestService, HttpTestingController], - (testService: TestService, httpMock: HttpTestingController) => { - const dummyEntity: TestEntity = { foo: 'foo', bar: 999 }; - testService.add(dummyEntity).subscribe((result) => { - expect(result).toEqual(dummyEntity); - }); - const request = httpMock.expectOne(testService.url); - request.flush(dummyEntity); - } - )); - - it('should rewrite request URL when called with config.rewrite', inject( - [TestService, HttpTestingController], - (testService: TestService, httpMock: HttpTestingController) => { - const dummyEntity: TestEntity = { foo: 'foo', bar: 999 }; - const dummyUrl = 'dummy-url'; - testService - .add(dummyEntity, { urlRewrite: dummyUrl }) - .subscribe(); - const request = httpMock.expectOne(dummyUrl); - request.flush([]); - } - )); - - it('should add postfix to request URL when called with config.urlPostfix', inject( - [TestService, HttpTestingController], - (testService: TestService, httpMock: HttpTestingController) => { - const dummyEntity: TestEntity = { foo: 'foo', bar: 999 }; - const dummyPostfix = 'foo/0/bar/1'; - const expectedUrl = `${testService.url}/${dummyPostfix}`; - testService - .add(dummyEntity, { urlPostfix: dummyPostfix }) - .subscribe(); - const request = httpMock.expectOne((req) => req.url === expectedUrl); - request.flush([]); - } - )); - - it(`should map request's response to desired result when called with config.mapResponseFn`, inject( - [TestService, HttpTestingController], - (testService: TestService, httpMock: HttpTestingController) => { - const dummyEntity: TestEntity = { foo: 'foo', bar: 999 }; - - const dummyResponse: { - succeeded: boolean; - message: string; - result: TestEntity; - } = { - succeeded: true, - message: 'OK', - result: { id: 1, foo: 'foo', bar: 999 }, - }; - - testService - .add(dummyEntity, { - mapFn: (res) => res.result, - }) - .subscribe((result) => { - expect(result).toEqual(dummyResponse.result); - }); - - const request = httpMock.expectOne(testService.url); - request.flush(dummyResponse); - } - )); - - it('should add headers to request when called with config.headers', inject( - [TestService, HttpTestingController], - (testService: TestService, httpMock: HttpTestingController) => { - const dummyEntity: TestEntity = { foo: 'foo', bar: 999 }; - const headers = new HttpHeaders() - .set('x-foo', 'foo') - .set('x-bar', 'bar'); - testService.add(dummyEntity, { headers }).subscribe(); - - const request = httpMock.expectOne(testService.url); - expect(request.request.headers.get('x-foo')).toBe('foo'); - expect(request.request.headers.get('x-bar')).toBe('bar'); - request.flush([]); - } - )); - - it('should add params to request when called with config.params', inject( - [TestService, HttpTestingController], - (testService: TestService, httpMock: HttpTestingController) => { - const dummyEntity: TestEntity = { foo: 'foo', bar: 999 }; - const params = new HttpParams().set('foo', 'foo').set('bar', 'bar'); - testService.add(dummyEntity, { params }).subscribe(); - - const request = httpMock.expectOne( - (req) => req.url === testService.url - ); - expect(request.request.params.get('foo')).toEqual('foo'); - expect(request.request.params.get('bar')).toEqual('bar'); - request.flush([]); - } - )); - }); - - describe('update', () => { - beforeEach(() => { - TestBed.configureTestingModule({ - providers: [TestService], - imports: [HttpClientTestingModule], - }); - }); - - it('should return result from request', inject( - [TestService, HttpTestingController], - (testService: TestService, httpMock: HttpTestingController) => { - const dummyId = 1; - const dummyEntity: TestEntity = { foo: 'foo', bar: 999 }; - const expectedResult = { id: dummyId, ...dummyEntity }; - - testService - .update(dummyId, dummyEntity) - .subscribe((result) => { - expect(result).toEqual(expectedResult); - }); - - const request = httpMock.expectOne(`${testService.url}/${dummyId}`); - request.flush(expectedResult); - } - )); - - it('should rewrite request URL when called with config.rewrite', inject( - [TestService, HttpTestingController], - (testService: TestService, httpMock: HttpTestingController) => { - const dummyId = 1; - const dummyEntity: TestEntity = { foo: 'foo', bar: 999 }; - const dummyUrl = 'dummy-url'; - - testService - .update(dummyId, dummyEntity, { urlRewrite: dummyUrl }) - .subscribe(); - - const request = httpMock.expectOne(dummyUrl); - request.flush([]); - } - )); - - it('should add postfix to request URL when called with config.urlPostfix', inject( - [TestService, HttpTestingController], - (testService: TestService, httpMock: HttpTestingController) => { - const dummyId = 1; - const dummyEntity: TestEntity = { foo: 'foo', bar: 999 }; - const dummyPostfix = 'foo/0/bar/1'; - const expectedUrl = `${testService.url}/${dummyId}/${dummyPostfix}`; - - testService - .update(dummyId, dummyEntity, { - urlPostfix: dummyPostfix, - }) - .subscribe(); - - const request = httpMock.expectOne((req) => req.url === expectedUrl); - request.flush([]); - } - )); - - it(`should map request's response to desired result when called with config.mapResponseFn`, inject( - [TestService, HttpTestingController], - (testService: TestService, httpMock: HttpTestingController) => { - const dummyId = 1; - const dummyEntity: TestEntity = { foo: 'foo', bar: 999 }; - - const dummyResponse: { - succeeded: boolean; - message: string; - result: TestEntity; - } = { - succeeded: true, - message: 'OK', - result: { id: 1, foo: 'foo', bar: 999 }, - }; - - testService - .update(dummyId, dummyEntity, { - mapFn: (res) => res.result, - }) - .subscribe((result) => { - expect(result).toEqual(dummyResponse.result); - }); - - const request = httpMock.expectOne(`${testService.url}/${dummyId}`); - request.flush(dummyResponse); - } - )); - - it('should add headers to request when called with config.headers', inject( - [TestService, HttpTestingController], - (testService: TestService, httpMock: HttpTestingController) => { - const dummyId = 1; - const dummyEntity: TestEntity = { foo: 'foo', bar: 999 }; - const headers = new HttpHeaders() - .set('x-foo', 'foo') - .set('x-bar', 'bar'); - testService - .update(dummyId, dummyEntity, { headers }) - .subscribe(); - - const request = httpMock.expectOne(`${testService.url}/${dummyId}`); - expect(request.request.headers.get('x-foo')).toBe('foo'); - expect(request.request.headers.get('x-bar')).toBe('bar'); - request.flush([]); - } - )); - - it('should add params to request when called with config.params', inject( - [TestService, HttpTestingController], - (testService: TestService, httpMock: HttpTestingController) => { - const dummyId = 1; - const dummyEntity: TestEntity = { foo: 'foo', bar: 999 }; - const params = new HttpParams().set('foo', 'foo').set('bar', 'bar'); - testService - .update(dummyId, dummyEntity, { params }) - .subscribe(); - - const request = httpMock.expectOne( - (req) => req.url === `${testService.url}/${dummyId}` - ); - expect(request.request.params.get('foo')).toEqual('foo'); - expect(request.request.params.get('bar')).toEqual('bar'); - request.flush([]); - } - )); - }); - - describe('delete', () => { - beforeEach(() => { - TestBed.configureTestingModule({ - providers: [TestService], - imports: [HttpClientTestingModule], - }); - }); - - it('should return result from request', inject( - [TestService, HttpTestingController], - (testService: TestService, httpMock: HttpTestingController) => { - const dummyId = 1; - const dummyEntity: TestEntity = { id: 1, foo: 'foo', bar: 999 }; - - testService.delete(dummyId).subscribe((result) => { - expect(result).toEqual(dummyEntity); - }); - - const request = httpMock.expectOne(`${testService.url}/${dummyId}`); - request.flush(dummyEntity); - } - )); - - it('should rewrite request URL when called with config.rewrite', inject( - [TestService, HttpTestingController], - (testService: TestService, httpMock: HttpTestingController) => { - const dummyId = 1; - const dummyUrl = 'dummy-url'; - - testService - .delete(dummyId, { urlRewrite: dummyUrl }) - .subscribe(); - - const request = httpMock.expectOne(dummyUrl); - request.flush([]); - } - )); - - it('should add postfix to request URL when called with config.urlPostfix', inject( - [TestService, HttpTestingController], - (testService: TestService, httpMock: HttpTestingController) => { - const dummyId = 1; - const dummyPostfix = 'foo/0/bar/1'; - const expectedUrl = `${testService.url}/${dummyId}/${dummyPostfix}`; - - testService - .delete(dummyId, { - urlPostfix: dummyPostfix, - }) - .subscribe(); - - const request = httpMock.expectOne((req) => req.url === expectedUrl); - request.flush([]); - } - )); - - it(`should map request's response to desired result when called with config.mapResponseFn`, inject( - [TestService, HttpTestingController], - (testService: TestService, httpMock: HttpTestingController) => { - const dummyId = 1; - - const dummyResponse: { - succeeded: boolean; - message: string; - result: TestEntity; - } = { - succeeded: true, - message: 'OK', - result: { id: 1, foo: 'foo', bar: 999 }, - }; - - testService - .delete(dummyId, { - mapFn: (res) => - res.succeeded && res.result ? 'DELETED' : 'NOT_DELETED', - }) - .subscribe((result) => { - expect(result).toEqual('DELETED'); - }); - - const request = httpMock.expectOne(`${testService.url}/${dummyId}`); - request.flush(dummyResponse); - } - )); - - it('should add headers to request when called with config.headers', inject( - [TestService, HttpTestingController], - (testService: TestService, httpMock: HttpTestingController) => { - const dummyId = 1; - const headers = new HttpHeaders() - .set('x-foo', 'foo') - .set('x-bar', 'bar'); - testService.delete(dummyId, { headers }).subscribe(); - - const request = httpMock.expectOne(`${testService.url}/${dummyId}`); - expect(request.request.headers.get('x-foo')).toBe('foo'); - expect(request.request.headers.get('x-bar')).toBe('bar'); - request.flush([]); - } - )); - - it('should add params to request when called with config.params', inject( - [TestService, HttpTestingController], - (testService: TestService, httpMock: HttpTestingController) => { - const dummyId = 1; - const params = new HttpParams().set('foo', 'foo').set('bar', 'bar'); - testService.delete(dummyId, { params }).subscribe(); - - const request = httpMock.expectOne( - (req) => req.url === `${testService.url}/${dummyId}` - ); - expect(request.request.params.get('foo')).toEqual('foo'); - expect(request.request.params.get('bar')).toEqual('bar'); - request.flush([]); - } - )); - }); + describe('config', () => { + beforeEach(() => { + TestBed.configureTestingModule({ + providers: [TestService], + imports: [HttpClientTestingModule], + }); + }); + + it('should be created', inject([TestService], (testService: TestService) => { + expect(testService).toBeTruthy(); + })); + + it(`should return 'inline-base-url/inline-resource-name' when url accesor is called`, inject( + [TestService], + (testService: TestService) => { + const apiUrl = testService.url; + const expectedUrl = 'inline-base-url/inline-resource-name'; + expect(apiUrl).toBe(expectedUrl); + }, + )); + }); + + describe('utils', () => { + it('should extract HttpRequestOptions from any object', () => { + const mockObject = { + successMsg: 'Operation successful', + errorMsg: 'Operation failed', + urlPostfix: 'bar/foo', + headers: { 'x-foo': 'foo', 'x-bar': 'bar' }, + params: { foo: 'foo', bar: 'bar' }, + observe: 'body', + reportProgress: false, + responseType: 'json', + withCredentials: false, + }; + + const expectedRequestOptions = { + headers: { 'x-foo': 'foo', 'x-bar': 'bar' }, + params: { foo: 'foo', bar: 'bar' }, + observe: 'body', + reportProgress: false, + responseType: 'json', + withCredentials: false, + }; + + const requestOptions = extractRequestOptions(mockObject); + expect(requestOptions).toEqual(expectedRequestOptions); + }); + + it(`should return empty object if there's no common properties between HttpRequestOptions & object`, () => { + const mockObject = { + foo: 'foo', + bar: 'bar', + }; + + const expectedRequestOptions = {}; + + const requestOptions = extractRequestOptions(mockObject); + expect(requestOptions).toEqual(expectedRequestOptions); + }); + }); + + describe('list', () => { + beforeEach(() => { + TestBed.configureTestingModule({ + providers: [TestService], + imports: [HttpClientTestingModule], + }); + }); + + it('should return result from request', inject( + [TestService, HttpTestingController], + (testService: TestService, httpMock: HttpTestingController) => { + const dummyData: TestEntity[] = [ + { id: 1, foo: 'foo', bar: 1 }, + { id: 2, foo: 'bar', bar: 2 }, + ]; + + testService.list().subscribe((result) => { + expect(result).toEqual(dummyData); + }); + + const request = httpMock.expectOne(testService.url); + request.flush(dummyData); + }, + )); + + it('should rewrite request URL when called with config.rewrite', inject( + [TestService, HttpTestingController], + (testService: TestService, httpMock: HttpTestingController) => { + const dummyUrl = 'dummy-url'; + testService.list({ urlRewrite: dummyUrl }).subscribe(); + const request = httpMock.expectOne(dummyUrl); + request.flush([]); + }, + )); + + it('should add postfix to request URL when called with config.urlPostfix', inject( + [TestService, HttpTestingController], + (testService: TestService, httpMock: HttpTestingController) => { + const dummyPostfix = 'foo/0/bar/1'; + const expectedUrl = `${testService.url}/${dummyPostfix}`; + testService.list({ urlPostfix: dummyPostfix }).subscribe(); + const request = httpMock.expectOne((req) => req.url === expectedUrl); + request.flush([]); + }, + )); + + it(`should map request's response to desired result when called with config.mapResponseFn`, inject( + [TestService, HttpTestingController], + (testService: TestService, httpMock: HttpTestingController) => { + const dummyResponse: { data: TestEntity[]; count: number } = { + data: [ + { id: 1, foo: 'foo', bar: 1 }, + { id: 2, foo: 'bar', bar: 2 }, + ], + count: 2, + }; + + testService + .list({ + mapFn: (res) => res.data, + }) + .subscribe((result) => { + expect(result).toEqual(dummyResponse.data); + }); + + const request = httpMock.expectOne(testService.url); + request.flush(dummyResponse); + }, + )); + + it(`should transform request's result to desired result when called with config.mapResponseFn`, inject( + [TestService, HttpTestingController], + (testService: TestService, httpMock: HttpTestingController) => { + const dummyData: TestEntity[] = [ + { id: 1, foo: 'foo', bar: 1 }, + { id: 2, foo: 'bar', bar: 2 }, + ]; + + const expectedResult = [ + { name: 'foo', age: 18 }, + { name: 'bar', age: 18 }, + ]; + + testService + .list({ + mapFn: (res) => res.map((entity: TestEntity) => ({ name: entity.foo, age: 18 })), + }) + .subscribe((result) => { + expect(result).toEqual(expectedResult); + }); + + const request = httpMock.expectOne(testService.url); + request.flush(dummyData); + }, + )); + + it('should add headers to request when called with config.headers', inject( + [TestService, HttpTestingController], + (testService: TestService, httpMock: HttpTestingController) => { + const headers = new HttpHeaders().set('x-foo', 'foo').set('x-bar', 'bar'); + testService.list({ headers }).subscribe(); + + const request = httpMock.expectOne(testService.url); + expect(request.request.headers.get('x-foo')).toBe('foo'); + expect(request.request.headers.get('x-bar')).toBe('bar'); + request.flush([]); + }, + )); + + it('should add params to request when called with config.params', inject( + [TestService, HttpTestingController], + (testService: TestService, httpMock: HttpTestingController) => { + const params = new HttpParams().set('foo', 'foo').set('bar', 'bar'); + testService.list({ params }).subscribe(); + const request = httpMock.expectOne((req) => req.url === testService.url); + expect(request.request.params.get('foo')).toEqual('foo'); + expect(request.request.params.get('bar')).toEqual('bar'); + request.flush([]); + }, + )); + }); + + describe('single', () => { + beforeEach(() => { + TestBed.configureTestingModule({ + providers: [TestService], + imports: [HttpClientTestingModule], + }); + }); + + it('should return result from request', inject( + [TestService, HttpTestingController], + (testService: TestService, httpMock: HttpTestingController) => { + const dummyId = 1; + const dummyData: TestEntity = { id: dummyId, foo: 'foo', bar: 1 }; + + testService.single(dummyId).subscribe((result) => { + expect(result).toEqual(dummyData); + }); + + const request = httpMock.expectOne(`${testService.url}/${dummyId}`); + request.flush(dummyData); + }, + )); + + it('should rewrite request URL when called with config.rewrite', inject( + [TestService, HttpTestingController], + (testService: TestService, httpMock: HttpTestingController) => { + const dummyId = 1; + const dummyUrl = 'dummy-url'; + testService.single(dummyId, { urlRewrite: dummyUrl }).subscribe(); + const request = httpMock.expectOne(dummyUrl); + request.flush([]); + }, + )); + + it('should add postfix to request URL when called with config.urlPostfix', inject( + [TestService, HttpTestingController], + (testService: TestService, httpMock: HttpTestingController) => { + const dummyId = 1; + const dummyPostfix = 'foo/0/bar/1'; + const expectedUrl = `${testService.url}/${dummyId}/${dummyPostfix}`; + testService.single(dummyId, { urlPostfix: dummyPostfix }).subscribe(); + const request = httpMock.expectOne((req) => req.url === expectedUrl); + request.flush([]); + }, + )); + + it(`should map request's response to desired result when called with config.mapResponseFn`, inject( + [TestService, HttpTestingController], + (testService: TestService, httpMock: HttpTestingController) => { + const dummyId = 1; + const dummyResponse: { data: TestEntity[]; count: number } = { + data: [ + { id: 1, foo: 'foo', bar: 1 }, + { id: 2, foo: 'bar', bar: 2 }, + ], + count: 2, + }; + + testService + .single(dummyId, { + mapFn: (res) => res.data, + }) + .subscribe((result) => { + expect(result).toEqual(dummyResponse.data); + }); + + const request = httpMock.expectOne(`${testService.url}/${dummyId}`); + request.flush(dummyResponse); + }, + )); + + it(`should transform request's result to desired result when called with config.mapResponseFn`, inject( + [TestService, HttpTestingController], + (testService: TestService, httpMock: HttpTestingController) => { + const dummyId = 1; + const dummyData: TestEntity[] = [ + { id: 1, foo: 'foo', bar: 1 }, + { id: 2, foo: 'bar', bar: 2 }, + ]; + + const expectedResult = [ + { name: 'foo', age: 18 }, + { name: 'bar', age: 18 }, + ]; + + testService + .single(dummyId, { + mapFn: (res) => res.map((entity: TestEntity) => ({ name: entity.foo, age: 18 })), + }) + .subscribe((result) => { + expect(result).toEqual(expectedResult); + }); + + const request = httpMock.expectOne(`${testService.url}/${dummyId}`); + request.flush(dummyData); + }, + )); + + it('should add headers to request when called with config.headers', inject( + [TestService, HttpTestingController], + (testService: TestService, httpMock: HttpTestingController) => { + const dummyId = 1; + const headers = new HttpHeaders().set('x-foo', 'foo').set('x-bar', 'bar'); + testService.single(dummyId, { headers }).subscribe(); + + const request = httpMock.expectOne(`${testService.url}/${dummyId}`); + expect(request.request.headers.get('x-foo')).toBe('foo'); + expect(request.request.headers.get('x-bar')).toBe('bar'); + request.flush([]); + }, + )); + + it('should add params to request when called with config.params', inject( + [TestService, HttpTestingController], + (testService: TestService, httpMock: HttpTestingController) => { + const dummyId = 1; + const params = new HttpParams().set('foo', 'foo').set('bar', 'bar'); + testService.single(dummyId, { params }).subscribe(); + const request = httpMock.expectOne((req) => req.url === `${testService.url}/${dummyId}`); + expect(request.request.params.get('foo')).toEqual('foo'); + expect(request.request.params.get('bar')).toEqual('bar'); + request.flush([]); + }, + )); + }); + + describe('add', () => { + beforeEach(() => { + TestBed.configureTestingModule({ + providers: [TestService], + imports: [HttpClientTestingModule], + }); + }); + + it('should return result from request', inject( + [TestService, HttpTestingController], + (testService: TestService, httpMock: HttpTestingController) => { + const dummyEntity: TestEntity = { foo: 'foo', bar: 999 }; + testService.add(dummyEntity).subscribe((result) => { + expect(result).toEqual(dummyEntity); + }); + const request = httpMock.expectOne(testService.url); + request.flush(dummyEntity); + }, + )); + + it('should rewrite request URL when called with config.rewrite', inject( + [TestService, HttpTestingController], + (testService: TestService, httpMock: HttpTestingController) => { + const dummyEntity: TestEntity = { foo: 'foo', bar: 999 }; + const dummyUrl = 'dummy-url'; + testService.add(dummyEntity, { urlRewrite: dummyUrl }).subscribe(); + const request = httpMock.expectOne(dummyUrl); + request.flush([]); + }, + )); + + it('should add postfix to request URL when called with config.urlPostfix', inject( + [TestService, HttpTestingController], + (testService: TestService, httpMock: HttpTestingController) => { + const dummyEntity: TestEntity = { foo: 'foo', bar: 999 }; + const dummyPostfix = 'foo/0/bar/1'; + const expectedUrl = `${testService.url}/${dummyPostfix}`; + testService.add(dummyEntity, { urlPostfix: dummyPostfix }).subscribe(); + const request = httpMock.expectOne((req) => req.url === expectedUrl); + request.flush([]); + }, + )); + + it(`should map request's response to desired result when called with config.mapResponseFn`, inject( + [TestService, HttpTestingController], + (testService: TestService, httpMock: HttpTestingController) => { + const dummyEntity: TestEntity = { foo: 'foo', bar: 999 }; + + const dummyResponse: { + succeeded: boolean; + message: string; + result: TestEntity; + } = { + succeeded: true, + message: 'OK', + result: { id: 1, foo: 'foo', bar: 999 }, + }; + + testService + .add(dummyEntity, { + mapFn: (res) => res.result, + }) + .subscribe((result) => { + expect(result).toEqual(dummyResponse.result); + }); + + const request = httpMock.expectOne(testService.url); + request.flush(dummyResponse); + }, + )); + + it('should add headers to request when called with config.headers', inject( + [TestService, HttpTestingController], + (testService: TestService, httpMock: HttpTestingController) => { + const dummyEntity: TestEntity = { foo: 'foo', bar: 999 }; + const headers = new HttpHeaders().set('x-foo', 'foo').set('x-bar', 'bar'); + testService.add(dummyEntity, { headers }).subscribe(); + + const request = httpMock.expectOne(testService.url); + expect(request.request.headers.get('x-foo')).toBe('foo'); + expect(request.request.headers.get('x-bar')).toBe('bar'); + request.flush([]); + }, + )); + + it('should add params to request when called with config.params', inject( + [TestService, HttpTestingController], + (testService: TestService, httpMock: HttpTestingController) => { + const dummyEntity: TestEntity = { foo: 'foo', bar: 999 }; + const params = new HttpParams().set('foo', 'foo').set('bar', 'bar'); + testService.add(dummyEntity, { params }).subscribe(); + + const request = httpMock.expectOne((req) => req.url === testService.url); + expect(request.request.params.get('foo')).toEqual('foo'); + expect(request.request.params.get('bar')).toEqual('bar'); + request.flush([]); + }, + )); + }); + + describe('update', () => { + beforeEach(() => { + TestBed.configureTestingModule({ + providers: [TestService], + imports: [HttpClientTestingModule], + }); + }); + + it('should return result from request', inject( + [TestService, HttpTestingController], + (testService: TestService, httpMock: HttpTestingController) => { + const dummyId = 1; + const dummyEntity: TestEntity = { foo: 'foo', bar: 999 }; + const expectedResult = { id: dummyId, ...dummyEntity }; + + testService.update(dummyId, dummyEntity).subscribe((result) => { + expect(result).toEqual(expectedResult); + }); + + const request = httpMock.expectOne(`${testService.url}/${dummyId}`); + request.flush(expectedResult); + }, + )); + + it('should rewrite request URL when called with config.rewrite', inject( + [TestService, HttpTestingController], + (testService: TestService, httpMock: HttpTestingController) => { + const dummyId = 1; + const dummyEntity: TestEntity = { foo: 'foo', bar: 999 }; + const dummyUrl = 'dummy-url'; + + testService.update(dummyId, dummyEntity, { urlRewrite: dummyUrl }).subscribe(); + + const request = httpMock.expectOne(dummyUrl); + request.flush([]); + }, + )); + + it('should add postfix to request URL when called with config.urlPostfix', inject( + [TestService, HttpTestingController], + (testService: TestService, httpMock: HttpTestingController) => { + const dummyId = 1; + const dummyEntity: TestEntity = { foo: 'foo', bar: 999 }; + const dummyPostfix = 'foo/0/bar/1'; + const expectedUrl = `${testService.url}/${dummyId}/${dummyPostfix}`; + + testService + .update(dummyId, dummyEntity, { + urlPostfix: dummyPostfix, + }) + .subscribe(); + + const request = httpMock.expectOne((req) => req.url === expectedUrl); + request.flush([]); + }, + )); + + it(`should map request's response to desired result when called with config.mapResponseFn`, inject( + [TestService, HttpTestingController], + (testService: TestService, httpMock: HttpTestingController) => { + const dummyId = 1; + const dummyEntity: TestEntity = { foo: 'foo', bar: 999 }; + + const dummyResponse: { + succeeded: boolean; + message: string; + result: TestEntity; + } = { + succeeded: true, + message: 'OK', + result: { id: 1, foo: 'foo', bar: 999 }, + }; + + testService + .update(dummyId, dummyEntity, { + mapFn: (res) => res.result, + }) + .subscribe((result) => { + expect(result).toEqual(dummyResponse.result); + }); + + const request = httpMock.expectOne(`${testService.url}/${dummyId}`); + request.flush(dummyResponse); + }, + )); + + it('should add headers to request when called with config.headers', inject( + [TestService, HttpTestingController], + (testService: TestService, httpMock: HttpTestingController) => { + const dummyId = 1; + const dummyEntity: TestEntity = { foo: 'foo', bar: 999 }; + const headers = new HttpHeaders().set('x-foo', 'foo').set('x-bar', 'bar'); + testService.update(dummyId, dummyEntity, { headers }).subscribe(); + + const request = httpMock.expectOne(`${testService.url}/${dummyId}`); + expect(request.request.headers.get('x-foo')).toBe('foo'); + expect(request.request.headers.get('x-bar')).toBe('bar'); + request.flush([]); + }, + )); + + it('should add params to request when called with config.params', inject( + [TestService, HttpTestingController], + (testService: TestService, httpMock: HttpTestingController) => { + const dummyId = 1; + const dummyEntity: TestEntity = { foo: 'foo', bar: 999 }; + const params = new HttpParams().set('foo', 'foo').set('bar', 'bar'); + testService.update(dummyId, dummyEntity, { params }).subscribe(); + + const request = httpMock.expectOne((req) => req.url === `${testService.url}/${dummyId}`); + expect(request.request.params.get('foo')).toEqual('foo'); + expect(request.request.params.get('bar')).toEqual('bar'); + request.flush([]); + }, + )); + }); + + describe('delete', () => { + beforeEach(() => { + TestBed.configureTestingModule({ + providers: [TestService], + imports: [HttpClientTestingModule], + }); + }); + + it('should return result from request', inject( + [TestService, HttpTestingController], + (testService: TestService, httpMock: HttpTestingController) => { + const dummyId = 1; + const dummyEntity: TestEntity = { id: 1, foo: 'foo', bar: 999 }; + + testService.delete(dummyId).subscribe((result) => { + expect(result).toEqual(dummyEntity); + }); + + const request = httpMock.expectOne(`${testService.url}/${dummyId}`); + request.flush(dummyEntity); + }, + )); + + it('should rewrite request URL when called with config.rewrite', inject( + [TestService, HttpTestingController], + (testService: TestService, httpMock: HttpTestingController) => { + const dummyId = 1; + const dummyUrl = 'dummy-url'; + + testService.delete(dummyId, { urlRewrite: dummyUrl }).subscribe(); + + const request = httpMock.expectOne(dummyUrl); + request.flush([]); + }, + )); + + it('should add postfix to request URL when called with config.urlPostfix', inject( + [TestService, HttpTestingController], + (testService: TestService, httpMock: HttpTestingController) => { + const dummyId = 1; + const dummyPostfix = 'foo/0/bar/1'; + const expectedUrl = `${testService.url}/${dummyId}/${dummyPostfix}`; + + testService + .delete(dummyId, { + urlPostfix: dummyPostfix, + }) + .subscribe(); + + const request = httpMock.expectOne((req) => req.url === expectedUrl); + request.flush([]); + }, + )); + + it(`should map request's response to desired result when called with config.mapResponseFn`, inject( + [TestService, HttpTestingController], + (testService: TestService, httpMock: HttpTestingController) => { + const dummyId = 1; + + const dummyResponse: { + succeeded: boolean; + message: string; + result: TestEntity; + } = { + succeeded: true, + message: 'OK', + result: { id: 1, foo: 'foo', bar: 999 }, + }; + + testService + .delete(dummyId, { + mapFn: (res) => (res.succeeded && res.result ? 'DELETED' : 'NOT_DELETED'), + }) + .subscribe((result) => { + expect(result).toEqual('DELETED'); + }); + + const request = httpMock.expectOne(`${testService.url}/${dummyId}`); + request.flush(dummyResponse); + }, + )); + + it('should add headers to request when called with config.headers', inject( + [TestService, HttpTestingController], + (testService: TestService, httpMock: HttpTestingController) => { + const dummyId = 1; + const headers = new HttpHeaders().set('x-foo', 'foo').set('x-bar', 'bar'); + testService.delete(dummyId, { headers }).subscribe(); + + const request = httpMock.expectOne(`${testService.url}/${dummyId}`); + expect(request.request.headers.get('x-foo')).toBe('foo'); + expect(request.request.headers.get('x-bar')).toBe('bar'); + request.flush([]); + }, + )); + + it('should add params to request when called with config.params', inject( + [TestService, HttpTestingController], + (testService: TestService, httpMock: HttpTestingController) => { + const dummyId = 1; + const params = new HttpParams().set('foo', 'foo').set('bar', 'bar'); + testService.delete(dummyId, { params }).subscribe(); + + const request = httpMock.expectOne((req) => req.url === `${testService.url}/${dummyId}`); + expect(request.request.params.get('foo')).toEqual('foo'); + expect(request.request.params.get('bar')).toEqual('bar'); + request.flush([]); + }, + )); + }); }); diff --git a/packages/ngx-grs/src/lib/ngx-generic-rest.service.ts b/packages/ngx-grs/src/lib/ngx-generic-rest.service.ts index 5f4010c..5aa381c 100644 --- a/packages/ngx-grs/src/lib/ngx-generic-rest.service.ts +++ b/packages/ngx-grs/src/lib/ngx-generic-rest.service.ts @@ -3,123 +3,112 @@ import { inject } from '@angular/core'; import { type Observable, throwError } from 'rxjs'; import { catchError } from 'rxjs/operators'; import type { - HttpAddOptions, - HttpConfig, - HttpDeleteOptions, - HttpGetListOptions, - HttpGetSingleOptions, - HttpMethod, - HttpUpdateOptions, + HttpAddOptions, + HttpConfig, + HttpDeleteOptions, + HttpGetListOptions, + HttpGetSingleOptions, + HttpMethod, + HttpUpdateOptions, } from './ngx-generic-rest.types'; -import { - extractRequestOptions, - mapResponse, - resolveUrl, -} from './ngx-generic-rest.utils'; +import { extractRequestOptions, mapResponse, resolveUrl } from './ngx-generic-rest.utils'; export class NgxGenericRestService { - #httpClient = inject(HttpClient); + #httpClient = inject(HttpClient); - constructor(protected httpConfig: HttpConfig) { - this.httpConfig = httpConfig; - } + constructor(protected httpConfig: HttpConfig) { + this.httpConfig = httpConfig; + } - get url(): string { - const { baseUrl, resourceName } = this.httpConfig; - return `${baseUrl}/${resourceName}`; - } + get url(): string { + const { baseUrl, resourceName } = this.httpConfig; + return `${baseUrl}/${resourceName}`; + } - /** - * Exposes HTTP client service to allow custom HTTP requests - * @returns HTTP client service - */ - getHttpClient(): HttpClient { - return this.#httpClient; - } + /** + * Exposes HTTP client service to allow custom HTTP requests + * @returns HTTP client service + */ + getHttpClient(): HttpClient { + return this.#httpClient; + } - /** - * Performs a GET HTTP request - * @param options custom specific HTTP options for GET list requests - * @returns generic type | list of objects - */ - list(options?: HttpGetListOptions): Observable { - const method: HttpMethod = 'GET'; - const url = resolveUrl(this.url, options); - const requestOptions = extractRequestOptions(options); + /** + * Performs a GET HTTP request + * @param options custom specific HTTP options for GET list requests + * @returns generic type | list of objects + */ + list(options?: HttpGetListOptions): Observable { + const method: HttpMethod = 'GET'; + const url = resolveUrl(this.url, options); + const requestOptions = extractRequestOptions(options); - return this.#httpClient - .request(method, url, requestOptions) - .pipe(mapResponse(options), catchError(this.handleError)); - } + return this.#httpClient + .request(method, url, requestOptions) + .pipe(mapResponse(options), catchError(this.handleError)); + } - /** - * Performs a GET HTTP request - * @param options custom specific HTTP options for GET single requests - * @returns generic type | single object - */ - single( - id: string | number, - options?: HttpGetSingleOptions, - ): Observable { - const method: HttpMethod = 'GET'; - const url = resolveUrl(this.url, options, id.toString()); - const requestOptions = extractRequestOptions(options); + /** + * Performs a GET HTTP request + * @param options custom specific HTTP options for GET single requests + * @returns generic type | single object + */ + single(id: string | number, options?: HttpGetSingleOptions): Observable { + const method: HttpMethod = 'GET'; + const url = resolveUrl(this.url, options, id.toString()); + const requestOptions = extractRequestOptions(options); - return this.#httpClient - .request(method, url, requestOptions) - .pipe(mapResponse(options), catchError(this.handleError)); - } + return this.#httpClient + .request(method, url, requestOptions) + .pipe(mapResponse(options), catchError(this.handleError)); + } - /** - * Performs a POST HTTP request (flexible for bulk inserting) - * @param options custom specific HTTP options for Add requests - * @returns generic type | single object or list of objects - */ - add(body: T, options?: HttpAddOptions): Observable { - const method: HttpMethod = 'POST'; - const url = resolveUrl(this.url, options); - const requestOptions = { ...extractRequestOptions(options), body }; + /** + * Performs a POST HTTP request (flexible for bulk inserting) + * @param options custom specific HTTP options for Add requests + * @returns generic type | single object or list of objects + */ + add(body: T, options?: HttpAddOptions): Observable { + const method: HttpMethod = 'POST'; + const url = resolveUrl(this.url, options); + const requestOptions = { ...extractRequestOptions(options), body }; - return this.#httpClient - .request(method, url, requestOptions) - .pipe(mapResponse(options), catchError(this.handleError)); - } + return this.#httpClient + .request(method, url, requestOptions) + .pipe(mapResponse(options), catchError(this.handleError)); + } - /** - * Performs a PUT | PATCH HTTP request (flexible for bulk updating) - * @param options custom specific HTTP options for Update requests - * @returns generic type | single object or list of objects - */ - update( - id: string | number, - body: T, - options?: HttpUpdateOptions, - ): Observable { - const method: HttpMethod = options?.method || 'PUT'; - const url = resolveUrl(this.url, options, id.toString()); - const requestOptions = { ...extractRequestOptions(options), body }; + /** + * Performs a PUT | PATCH HTTP request (flexible for bulk updating) + * @param options custom specific HTTP options for Update requests + * @returns generic type | single object or list of objects + */ + update(id: string | number, body: T, options?: HttpUpdateOptions): Observable { + const method: HttpMethod = options?.method || 'PUT'; + const url = resolveUrl(this.url, options, id.toString()); + const requestOptions = { ...extractRequestOptions(options), body }; - return this.#httpClient - .request(method, url, requestOptions) - .pipe(mapResponse(options), catchError(this.handleError)); - } + return this.#httpClient + .request(method, url, requestOptions) + .pipe(mapResponse(options), catchError(this.handleError)); + } - /** - * Performs a DELETE HTTP request (flexible for bulk deleting) - * @param options custom specific HTTP options for Delete requests - * @returns generic type | single object or list of objects - */ - delete(id: string | number, options?: HttpDeleteOptions): Observable { - const method: HttpMethod = 'DELETE'; - const url = resolveUrl(this.url, options, id.toString()); - const requestOptions = extractRequestOptions(options); + /** + * Performs a DELETE HTTP request (flexible for bulk deleting) + * @param options custom specific HTTP options for Delete requests + * @returns generic type | single object or list of objects + */ + delete(id: string | number, options?: HttpDeleteOptions): Observable { + const method: HttpMethod = 'DELETE'; + const url = resolveUrl(this.url, options, id.toString()); + const requestOptions = extractRequestOptions(options); - return this.#httpClient - .request(method, url, requestOptions) - .pipe(mapResponse(options), catchError(this.handleError)); - } + return this.#httpClient + .request(method, url, requestOptions) + .pipe(mapResponse(options), catchError(this.handleError)); + } - protected handleError(error: any): Observable { - return throwError(error.message || error); - } + protected handleError(error: any): Observable { + return throwError(error.message || error); + } } diff --git a/packages/ngx-grs/src/lib/ngx-generic-rest.types.ts b/packages/ngx-grs/src/lib/ngx-generic-rest.types.ts index 1af3f0b..50d3dcc 100644 --- a/packages/ngx-grs/src/lib/ngx-generic-rest.types.ts +++ b/packages/ngx-grs/src/lib/ngx-generic-rest.types.ts @@ -1,19 +1,19 @@ import type { HttpHeaders, HttpParams } from '@angular/common/http'; export interface HttpConfig { - baseUrl: string; - resourceName: string; + baseUrl: string; + resourceName: string; } export type HttpMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE'; export type HttpRequestOptions = { - headers?: _httpHeaders; - params?: _httpParams; - observe?: _observe; - reportProgress?: boolean; - responseType?: _responseType; - withCredentials?: boolean; + headers?: _httpHeaders; + params?: _httpParams; + observe?: _observe; + reportProgress?: boolean; + responseType?: _responseType; + withCredentials?: boolean; }; type _httpHeaders = HttpHeaders | { [header: string]: string | string[] }; @@ -21,16 +21,16 @@ type _httpParams = HttpParams | { [param: string]: string | string[] }; type _observe = 'body' | 'events' | 'response'; type _responseType = 'arraybuffer' | 'blob' | 'json' | 'text'; -export type HttpOptions = HttpRequestOptions & { - urlRewrite?: string; - urlPostfix?: string; - mapFn?: (res: any) => T; +export type HttpOptions> = HttpRequestOptions & { + urlRewrite?: string; + urlPostfix?: string; + mapFn?: (res: any) => T; }; export type HttpGetListOptions = HttpOptions; export type HttpGetSingleOptions = HttpOptions; export type HttpAddOptions = HttpOptions; export type HttpUpdateOptions = HttpOptions & { - method?: 'PUT' | 'PATCH'; + method?: 'PUT' | 'PATCH'; }; export type HttpDeleteOptions = HttpOptions; diff --git a/packages/ngx-grs/src/lib/ngx-generic-rest.utils.ts b/packages/ngx-grs/src/lib/ngx-generic-rest.utils.ts index 02f0f0a..dcd4ea8 100644 --- a/packages/ngx-grs/src/lib/ngx-generic-rest.utils.ts +++ b/packages/ngx-grs/src/lib/ngx-generic-rest.utils.ts @@ -1,5 +1,5 @@ import { map } from 'rxjs/operators'; -import { HttpOptions } from './ngx-generic-rest.types'; +import type { HttpOptions } from './ngx-generic-rest.types'; /** * Dynamically resolves API URL @@ -8,28 +8,24 @@ import { HttpOptions } from './ngx-generic-rest.types'; * @param args extra arguments that are concatenated to URL before postfix. * @returns API endpoint */ -export const resolveUrl = ( - baseUrl: string, - options?: HttpOptions, - ...args: string[] -): string => { - const { urlRewrite, urlPostfix } = options || {}; +export const resolveUrl = (baseUrl: string, options?: HttpOptions, ...args: string[]): string => { + const { urlRewrite, urlPostfix } = options || {}; - if (urlRewrite) { - return urlRewrite; - } + if (urlRewrite) { + return urlRewrite; + } - let result = baseUrl; + let result = baseUrl; - if (args && args.length > 0) { - result += `/${args.join('/')}`; - } + if (args && args.length > 0) { + result += `/${args.join('/')}`; + } - if (urlPostfix) { - result += `/${urlPostfix}`; - } + if (urlPostfix) { + result += `/${urlPostfix}`; + } - return result; + return result; }; /** @@ -38,26 +34,22 @@ export const resolveUrl = ( * @returns object with 0 or n request parameters */ export const extractRequestOptions = (options?: any) => { - if (!options || typeof options !== 'object') { - return {}; - } - - return [ - 'headers', - 'params', - 'observe', - 'reportProgress', - 'responseType', - 'withCredentials', - ].reduce((requestOptions: any, key) => { - const value = options[key]; - - if (value !== undefined) { - requestOptions[key] = value; - } - - return requestOptions; - }, {}); + if (!options || typeof options !== 'object') { + return {}; + } + + return ['headers', 'params', 'observe', 'reportProgress', 'responseType', 'withCredentials'].reduce( + (requestOptions: any, key) => { + const value = options[key]; + + if (value !== undefined) { + requestOptions[key] = value; + } + + return requestOptions; + }, + {}, + ); }; /** @@ -65,5 +57,4 @@ export const extractRequestOptions = (options?: any) => { * @param options HTTP base config options * @returns any result that is specified */ -export const mapResponse = (options?: HttpOptions) => - map((res: T) => (options?.mapFn ? options.mapFn(res) : res)); +export const mapResponse = (options?: HttpOptions) => map((res: T) => (options?.mapFn ? options.mapFn(res) : res)); diff --git a/packages/ngx-grs/src/lib/test-setup.ts b/packages/ngx-grs/src/lib/test-setup.ts index f5424d6..a47880b 100644 --- a/packages/ngx-grs/src/lib/test-setup.ts +++ b/packages/ngx-grs/src/lib/test-setup.ts @@ -2,17 +2,17 @@ import { Injectable } from '@angular/core'; import { NgxGenericRestService } from './ngx-generic-rest.service'; export interface TestEntity { - id?: string | number; - foo?: string; - bar?: number; + id?: string | number; + foo?: string; + bar?: number; } @Injectable({ providedIn: 'root' }) export class TestService extends NgxGenericRestService { - constructor() { - super({ - baseUrl: 'inline-base-url', - resourceName: 'inline-resource-name', - }); - } + constructor() { + super({ + baseUrl: 'inline-base-url', + resourceName: 'inline-resource-name', + }); + } } diff --git a/packages/ngx-grs/tsconfig.lib.json b/packages/ngx-grs/tsconfig.lib.json index 543fd47..68dc5be 100644 --- a/packages/ngx-grs/tsconfig.lib.json +++ b/packages/ngx-grs/tsconfig.lib.json @@ -1,14 +1,11 @@ -/* To learn more about this file see: https://angular.io/config/tsconfig. */ { - "extends": "../../tsconfig.json", - "compilerOptions": { - "outDir": "../../out-tsc/lib", - "declaration": true, - "declarationMap": true, - "inlineSources": true, - "types": [] - }, - "exclude": [ - "**/*.spec.ts" - ] + "extends": "../../tsconfig.json", + "compilerOptions": { + "outDir": "../../out-tsc/lib", + "declaration": true, + "declarationMap": true, + "inlineSources": true, + "types": [] + }, + "exclude": ["**/*.spec.ts"] } diff --git a/packages/ngx-grs/tsconfig.lib.prod.json b/packages/ngx-grs/tsconfig.lib.prod.json index 06de549..7b29b93 100644 --- a/packages/ngx-grs/tsconfig.lib.prod.json +++ b/packages/ngx-grs/tsconfig.lib.prod.json @@ -1,10 +1,9 @@ -/* To learn more about this file see: https://angular.io/config/tsconfig. */ { - "extends": "./tsconfig.lib.json", - "compilerOptions": { - "declarationMap": false - }, - "angularCompilerOptions": { - "compilationMode": "partial" - } + "extends": "./tsconfig.lib.json", + "compilerOptions": { + "declarationMap": false + }, + "angularCompilerOptions": { + "compilationMode": "partial" + } } diff --git a/packages/ngx-grs/tsconfig.spec.json b/packages/ngx-grs/tsconfig.spec.json index ce7048b..72e004a 100644 --- a/packages/ngx-grs/tsconfig.spec.json +++ b/packages/ngx-grs/tsconfig.spec.json @@ -1,14 +1,8 @@ -/* To learn more about this file see: https://angular.io/config/tsconfig. */ { - "extends": "../../tsconfig.json", - "compilerOptions": { - "outDir": "../../out-tsc/spec", - "types": [ - "jasmine" - ] - }, - "include": [ - "**/*.spec.ts", - "**/*.d.ts" - ] + "extends": "../../tsconfig.json", + "compilerOptions": { + "outDir": "../../out-tsc/spec", + "types": ["jasmine"] + }, + "include": ["**/*.spec.ts", "**/*.d.ts"] } diff --git a/tsconfig.json b/tsconfig.json index 866a444..0c2f958 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,37 +1,32 @@ /* To learn more about this file see: https://angular.io/config/tsconfig. */ { - "compileOnSave": false, - "compilerOptions": { - "outDir": "./dist/out-tsc", - "strict": true, - "noImplicitOverride": true, - "noPropertyAccessFromIndexSignature": true, - "noImplicitReturns": true, - "noFallthroughCasesInSwitch": true, - "skipLibCheck": true, - "paths": { - "ngx-grs": [ - "./dist/ngx-grs" - ] - }, - "esModuleInterop": true, - "sourceMap": true, - "declaration": false, - "experimentalDecorators": true, - "moduleResolution": "node", - "importHelpers": true, - "target": "ES2022", - "module": "ES2022", - "useDefineForClassFields": false, - "lib": [ - "ES2022", - "dom" - ] - }, - "angularCompilerOptions": { - "enableI18nLegacyMessageIdFormat": false, - "strictInjectionParameters": true, - "strictInputAccessModifiers": true, - "strictTemplates": true - } + "compileOnSave": false, + "compilerOptions": { + "outDir": "./dist/out-tsc", + "strict": true, + "noImplicitOverride": true, + "noPropertyAccessFromIndexSignature": true, + "noImplicitReturns": true, + "noFallthroughCasesInSwitch": true, + "skipLibCheck": true, + "paths": { + "ngx-grs": ["./dist/ngx-grs"] + }, + "esModuleInterop": true, + "sourceMap": true, + "declaration": false, + "experimentalDecorators": true, + "moduleResolution": "node", + "importHelpers": true, + "target": "ES2022", + "module": "ES2022", + "useDefineForClassFields": false, + "lib": ["ES2022", "dom"] + }, + "angularCompilerOptions": { + "enableI18nLegacyMessageIdFormat": false, + "strictInjectionParameters": true, + "strictInputAccessModifiers": true, + "strictTemplates": true + } }