.eslintrc.json000066400000000000000000000020741516106664700136710ustar00rootroot00000000000000{ "root": true, "ignorePatterns": [ "projects/**/*" ], "overrides": [ { "files": [ "*.ts" ], "parserOptions": { "project": [ "tsconfig.json", "e2e/tsconfig.json" ], "createDefaultProgram": true }, "extends": [ "plugin:@angular-eslint/ng-cli-compat", "plugin:@angular-eslint/ng-cli-compat--formatting-add-on", "plugin:@angular-eslint/template/process-inline-templates" ], "rules": { "@angular-eslint/component-selector": [ "error", { "type": "element", "prefix": "p3x", "style": "kebab-case" } ], "@angular-eslint/directive-selector": [ "error", { "type": "attribute", "prefix": "p3x", "style": "camelCase" } ] } }, { "files": [ "*.html" ], "extends": [ "plugin:@angular-eslint/template/recommended" ], "rules": {} } ] } .github/000077500000000000000000000000001516106664700124325ustar00rootroot00000000000000.github/workflows/000077500000000000000000000000001516106664700144675ustar00rootroot00000000000000.github/workflows/build.yml000066400000000000000000000016761516106664700163230ustar00rootroot00000000000000# This workflow will do a clean install of node dependencies, build the source code and run tests across different versions of node # For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions name: build on: schedule: - cron: '0 0 1 * *' push: branches: [ master ] pull_request: branches: [ master ] jobs: build: runs-on: ubuntu-latest strategy: matrix: node-version: ['lts/*'] # See supported Node.js release schedule at https://nodejs.org/en/about/releases/ steps: - uses: actions/checkout@v2 - name: Use Node.js ${{ matrix.node-version }} uses: actions/setup-node@v2 with: node-version: ${{ matrix.node-version }} - run: npm i -g grunt-cli - run: npm install - run: grunt .gitignore000066400000000000000000000015571516106664700130720ustar00rootroot00000000000000/build /node_modules /*.log /*.iws .idea/workspace.xml .idea/tasks.xml .idea/profiles_settings.xml .idea/inspectionProfiles/Project_Default.xml .idea/inspectionProfiles/profiles_settings.xml node_modules/.yarn-integrity # See http://help.github.com/ignore-files/ for more about ignoring files. # compiled output /dist /release /tmp /out-tsc # Only exists if Bazel was run /bazel-out # dependencies /node_modules # profiling files chrome-profiler-events*.json speed-measure-plugin*.json # IDEs and editors /.idea .project .classpath .c9/ *.launch .settings/ *.sublime-workspace # IDE - VSCode .vscode/* !.vscode/settings.json !.vscode/tasks.json !.vscode/launch.json !.vscode/extensions.json .history/* # misc /.angular/cache /.sass-cache /connect.lock /coverage /libpeerconnection.log npm-debug.log yarn-error.log testem.log /typings # System Files .DS_Store Thumbs.db .ncurc.json000066400000000000000000000002711516106664700131550ustar00rootroot00000000000000{ "reject": [ "core-js", "reflect-metadata", "rxjs", "tslib", "zone.js", "typescript", "karma", "ng-packagr" ] } .npmignore000066400000000000000000000002711516106664700130710ustar00rootroot00000000000000/.idea /artifacts /build /Gemfile /_layouts /_site /_includes /test /node_modules /*.iml /*.ipr /*.iws /.travis.yml /.scrutinizer.yml /Gruntfile.js /corifeus-boot.json /.github /.vscode.vscode/000077500000000000000000000000001516106664700124335ustar00rootroot00000000000000.vscode/launch.json000066400000000000000000000012231516106664700145760ustar00rootroot00000000000000{ // Use IntelliSense to learn about possible attributes. // Hover to view descriptions of existing attributes. // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 "version": "0.2.0", "configurations": [ { "outputCapture": "std", "type": "node", "request": "launch", "name": "npm run start", "args": [ "run", "start" ], "skipFiles": [ "/**" ], "cwd": "${workspaceRoot}", "program": "/usr/bin/npm" } ] }Gruntfile.js000066400000000000000000000027541516106664700133770ustar00rootroot00000000000000const utils = require('corifeus-utils'); const path = require('path') const fs = require('fs').promises module.exports = (grunt) => { const builder = require(`corifeus-builder`); const loader = new builder.loader(grunt); loader.js({ replacer: { type: 'p3x', }, config: { htmlmin: { dist: { options: { // Target options removeComments: true, collapseWhitespace: true, minifyCSS: true, }, files: { './dist/workspace/index.html': './dist/workspace/index.html' } } }, } }); grunt.registerTask('publish', async function () { const done = this.async(); try { await builder.utils.spawn({ grunt: grunt, gruntThis: this, }, { cmd: 'npm', args: [ 'run', 'build-lib', ] }); done() } catch (e) { done(e) } }); grunt.registerTask('build', async function () { const done = this.async(); try { await builder.utils.spawn({ grunt: grunt, gruntThis: this, }, { cmd: 'npm', args: [ 'run', 'build-app', ] }); done() } catch (e) { done(e) } }); const defaultTask = builder.config.task.build.js.concat(['cory-angular-hook-lib', 'cory-raw-npm-angular', 'build', 'htmlmin:dist']) grunt.registerTask('default', defaultTask); } LICENSE000066400000000000000000000027051516106664700121030ustar00rootroot00000000000000 @license p3x-angular-http-cache-interceptor v2024.4.107 🔥 Cache every request in Angular, not only the GET, but all methods of this interceptor, and allows you to interact with the interceptor via specific headers and modify the request, and these specific headers will be not included in the final request https://corifeus.com/angular-http-cache-interceptor Copyright (c) 2024 Patrik Laszlo / P3X / Corifeus and contributors. MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. README.md000066400000000000000000000143551516106664700123610ustar00rootroot00000000000000[//]: #@corifeus-header [![Donate for Corifeus / P3X](https://img.shields.io/badge/Donate-Corifeus-003087.svg)](https://paypal.me/patrikx3) [![Contact Corifeus / P3X](https://img.shields.io/badge/Contact-P3X-ff9900.svg)](https://www.patrikx3.com/en/front/contact) [![Corifeus @ Facebook](https://img.shields.io/badge/Facebook-Corifeus-3b5998.svg)](https://www.facebook.com/corifeus.software) [![Uptime Robot ratio (30 days)](https://img.shields.io/uptimerobot/ratio/m780749701-41bcade28c1ea8154eda7cca.svg)](https://stats.uptimerobot.com/9ggnzcWrw) # 🔥 Cache every request in Angular, not only the GET, but all methods of this interceptor, and allows you to interact with the interceptor via specific headers and modify the request, and these specific headers will be not included in the final request v2024.4.107 **Bugs are evident™ - MATRIX️** ### NodeJS LTS is supported ### Built on NodeJs version ```txt v20.11.1 ``` # Built on Angular ```text 17.2.1 ``` # Description [//]: #@corifeus-header:end Usually, when you want to cache all requests, you do not cache all requests, but only the `GET` method. But, for some frontend applications, it is required to cache everything, otherwise the subsequent requests, without cache, would slow down the application flow. So, this micro-service caches all method/path/query variables/parameters/request body. The way, we can find out what we are caching it is not simple. Usually, you would cache by a key of the `httpRequest.urlWithParams` and only the `GET` HTTP method. To create this cache key, this package is using the `object-hash` package, with the following algorithm: ```ts import * as hash from 'object-hash' const hashOptions = { algorithm: 'md5', encoding: 'hex' } httpToKey(httpRequest: HttpRequest) { const key = httpRequest.method + '@' + httpRequest.urlWithParams + '@' + hash(httpRequest.params, hashOptions) + '@' + hash(httpRequest.body, hashOptions) return key } ``` There is room in the future, to restrict to specific methods and add more configurations and functions. If there is a need for this micro-service, it could be enhanced, but for now, it is caching everything, with the exception, when you include the `CachingHeaders.NoCache` header into your request, then this request will always hit the server. # Example web page that uses this package https://angular-http-cache-interceptor.corifeus.com # How to use it ```bash npm i p3x-angular-http-cache-interceptor object-hash ``` ## Include the caching interceptor into your Angular module ```ts import { NgModule } from '@angular/core'; import { P3XHttpCacheInterceptorModule } from 'p3x-angular-http-cache-interceptor'; @NgModule({ declarations: [ ], imports: [ P3XHttpCacheInterceptorModule, ], providers: [ ], bootstrap: [] }) export class SomeModule { } ``` ### Options ```ts import { P3XHttpCacheInterceptorModule, CachingHeaders, CachingStore } from 'p3x-angular-http-cache-interceptor'; P3XHttpCacheInterceptorModule.forRoot({ // default request is no cache behavior: CachingHeaders.NoCache, // if a request has CachingHeaders.Cache header it will cache globally store: CachingStore.Global, }) P3XHttpCacheInterceptorModule.forRoot({ // default request is cache behavior: CachingHeaders.Cache, // in this config, it will cache not globally, but per module store: CachingStore.PerModule, }) ``` ## Example invocation in a component With and without cache: ```ts import { Component } from '@angular/core'; import { HttpClient } from "@angular/common/http"; import {MatSnackBar} from "@angular/material/snack-bar"; import { CachingHeaders } from 'p3x-angular-http-cache-interceptor' @Component({ selector: 'p3x-root', templateUrl: './app.component.html', styleUrls: ['./app.component.scss'] }) export class AppComponent { constructor( private http: HttpClient, private snack: MatSnackBar, ) { } async loadCached() { try { const response : any = await this.http.get('https://server.patrikx3.com/api/core/util/random/32').toPromise() this.snack.open(`Will be always the same: ${response.random}`, 'OK') } catch(e) { this.snack.open(`Sorry, error happened, check the console for the error`, 'OK') console.error(e) } } async loadNonCached() { try { const response : any = await this.http.get('https://server.patrikx3.com/api/core/util/random/32', { headers: { [CachingHeaders.NoCache]: '1' } }).toPromise() this.snack.open(`Truly random data: ${response.random}`, 'OK') } catch(e) { this.snack.open(`Sorry, error happened, check the console for the error`, 'OK') console.error(e) } } } ``` [//]: #@corifeus-footer --- 🙏 This is an open-source project. Star this repository, if you like it, or even donate to maintain the servers and the development. Thank you so much! Possible, this server, rarely, is down, please, hang on for 15-30 minutes and the server will be back up. All my domains ([patrikx3.com](https://patrikx3.com) and [corifeus.com](https://corifeus.com)) could have minor errors, since I am developing in my free time. However, it is usually stable. **Note about versioning:** Versions are cut in Major.Minor.Patch schema. Major is always the current year. Minor is either 4 (January - June) or 10 (July - December). Patch is incremental by every build. If there is a breaking change, it should be noted in the readme. --- [**P3X-ANGULAR-HTTP-CACHE-INTERCEPTOR**](https://corifeus.com/angular-http-cache-interceptor) Build v2024.4.107 [![Donate for Corifeus / P3X](https://img.shields.io/badge/Donate-Corifeus-003087.svg)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=QZVM4V6HVZJW6) [![Contact Corifeus / P3X](https://img.shields.io/badge/Contact-P3X-ff9900.svg)](https://www.patrikx3.com/en/front/contact) [![Like Corifeus @ Facebook](https://img.shields.io/badge/LIKE-Corifeus-3b5998.svg)](https://www.facebook.com/corifeus.software) [//]: #@corifeus-footer:end README_Angular.md000066400000000000000000000052061516106664700140250ustar00rootroot00000000000000[//]: #@corifeus-header # 🔥 Cache every request in Angular, not only the GET, but all methods of this interceptor, and allows you to interact with the interceptor via specific headers and modify the request, and these specific headers will be not included in the final request [//]: #@corifeus-header:end # Workspace This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 9.1.1. ## Development server Run `ng serve` for a dev server. Navigate to `http://localhost:4200/`. The app will automatically reload if you change any of the source files. ## Code scaffolding Run `ng generate component component-name` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module`. ## Build Run `ng build` to build the project. The build artifacts will be stored in the `dist/` directory. Use the `--prod` flag for a production build. ## Running unit tests Run `ng test` to execute the unit tests via [Karma](https://karma-runner.github.io). ## Running end-to-end tests Run `ng e2e` to execute the end-to-end tests via [Protractor](http://www.protractortest.org/). ## Further help To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI README](https://github.com/angular/angular-cli/blob/master/README.md). [//]: #@corifeus-footer --- 🙏 This is an open-source project. Star this repository, if you like it, or even donate to maintain the servers and the development. Thank you so much! Possible, this server, rarely, is down, please, hang on for 15-30 minutes and the server will be back up. All my domains ([patrikx3.com](https://patrikx3.com) and [corifeus.com](https://corifeus.com)) could have minor errors, since I am developing in my free time. However, it is usually stable. **Note about versioning:** Versions are cut in Major.Minor.Patch schema. Major is always the current year. Minor is either 4 (January - June) or 10 (July - December). Patch is incremental by every build. If there is a breaking change, it should be noted in the readme. --- [**P3X-ANGULAR-HTTP-CACHE-INTERCEPTOR**](https://corifeus.com/angular-http-cache-interceptor) Build v2024.4.107 [![Donate for Corifeus / P3X](https://img.shields.io/badge/Donate-Corifeus-003087.svg)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=QZVM4V6HVZJW6) [![Contact Corifeus / P3X](https://img.shields.io/badge/Contact-P3X-ff9900.svg)](https://www.patrikx3.com/en/front/contact) [![Like Corifeus @ Facebook](https://img.shields.io/badge/LIKE-Corifeus-3b5998.svg)](https://www.facebook.com/corifeus.software) [//]: #@corifeus-footer:end angular.json000066400000000000000000000117031516106664700134200ustar00rootroot00000000000000{ "$schema": "./node_modules/@angular/cli/lib/config/schema.json", "version": 1, "newProjectRoot": "projects", "projects": { "workspace": { "projectType": "application", "schematics": { "@schematics/angular:component": { "style": "scss" } }, "root": "", "sourceRoot": "src", "prefix": "p3x", "architect": { "build": { "builder": "@angular-devkit/build-angular:browser", "options": { "outputPath": "dist/workspace", "index": "src/index.html", "main": "src/main.ts", "polyfills": "src/polyfills.ts", "tsConfig": "tsconfig.app.json", "assets": [ "src/favicon.ico", "src/assets" ], "styles": [ "src/styles.scss" ], "scripts": [], "vendorChunk": true, "extractLicenses": false, "buildOptimizer": false, "sourceMap": true, "optimization": false, "namedChunks": true }, "configurations": { "production": { "fileReplacements": [ { "replace": "src/environments/environment.ts", "with": "src/environments/environment.prod.ts" } ], "optimization": true, "outputHashing": "all", "sourceMap": false, "namedChunks": false, "extractLicenses": true, "vendorChunk": false, "buildOptimizer": true, "budgets": [ { "type": "initial", "maximumWarning": "2mb", "maximumError": "5mb" }, { "type": "anyComponentStyle", "maximumWarning": "6kb", "maximumError": "10kb" } ] } } }, "serve": { "builder": "@angular-devkit/build-angular:dev-server", "options": { "buildTarget": "workspace:build" }, "configurations": { "production": { "buildTarget": "workspace:build:production" } } }, "extract-i18n": { "builder": "@angular-devkit/build-angular:extract-i18n", "options": { "buildTarget": "workspace:build" } }, "test": { "builder": "@angular-devkit/build-angular:karma", "options": { "main": "src/test.ts", "polyfills": "src/polyfills.ts", "tsConfig": "tsconfig.spec.json", "karmaConfig": "karma.conf.js", "assets": [ "src/favicon.ico", "src/assets" ], "styles": [ "src/styles.scss" ], "scripts": [] } }, "lint": { "builder": "@angular-eslint/builder:lint", "options": { "lintFilePatterns": [ "src/**/*.ts", "src/**/*.html" ] } }, "e2e": { "builder": "@angular-devkit/build-angular:protractor", "options": { "protractorConfig": "e2e/protractor.conf.js", "devServerTarget": "workspace:serve" }, "configurations": { "production": { "devServerTarget": "workspace:serve:production" } } } } }, "angular-http-cache-interceptor": { "projectType": "library", "root": "projects/angular-http-cache-interceptor", "sourceRoot": "projects/angular-http-cache-interceptor/src", "prefix": "p3x", "architect": { "build": { "builder": "@angular-devkit/build-angular:ng-packagr", "options": { "tsConfig": "projects/angular-http-cache-interceptor/tsconfig.lib.json", "project": "projects/angular-http-cache-interceptor/ng-package.json" }, "configurations": { "production": { "tsConfig": "projects/angular-http-cache-interceptor/tsconfig.lib.prod.json" } } }, "test": { "builder": "@angular-devkit/build-angular:karma", "options": { "main": "projects/angular-http-cache-interceptor/src/test.ts", "tsConfig": "projects/angular-http-cache-interceptor/tsconfig.spec.json", "karmaConfig": "projects/angular-http-cache-interceptor/karma.conf.js" } }, "lint": { "builder": "@angular-eslint/builder:lint", "options": { "lintFilePatterns": [ "projects/angular-http-cache-interceptor/**/*.ts", "projects/angular-http-cache-interceptor/**/*.html" ] } } } } } } e2e/000077500000000000000000000000001516106664700115455ustar00rootroot00000000000000e2e/protractor.conf.js000066400000000000000000000014501516106664700152260ustar00rootroot00000000000000// @ts-check // Protractor configuration file, see link for more information // https://github.com/angular/protractor/blob/master/lib/config.ts const { SpecReporter } = require('jasmine-spec-reporter'); /** * @type { import("protractor").Config } */ exports.config = { allScriptsTimeout: 11000, specs: [ './src/**/*.e2e-spec.ts' ], capabilities: { browserName: 'chrome' }, directConnect: true, baseUrl: 'http://localhost:4200/', framework: 'jasmine', jasmineNodeOpts: { showColors: true, defaultTimeoutInterval: 30000, print: function() {} }, onPrepare() { require('ts-node').register({ project: require('path').join(__dirname, './tsconfig.json') }); jasmine.getEnv().addReporter(new SpecReporter({ spec: { displayStacktrace: true } })); } };e2e/src/000077500000000000000000000000001516106664700123345ustar00rootroot00000000000000e2e/src/app.e2e-spec.ts000066400000000000000000000012021516106664700150610ustar00rootroot00000000000000import { AppPage } from './app.po'; import { browser, logging } from 'protractor'; describe('workspace-project App', () => { let page: AppPage; beforeEach(() => { page = new AppPage(); }); it('should display welcome message', () => { page.navigateTo(); expect(page.getTitleText()).toEqual('workspace app is running!'); }); afterEach(async () => { // Assert that there are no errors emitted from the browser const logs = await browser.manage().logs().get(logging.Type.BROWSER); expect(logs).not.toContain(jasmine.objectContaining({ level: logging.Level.SEVERE, } as logging.Entry)); }); }); e2e/src/app.po.ts000066400000000000000000000004551516106664700141050ustar00rootroot00000000000000import { browser, by, element } from 'protractor'; export class AppPage { navigateTo(): Promise { return browser.get(browser.baseUrl) as Promise; } getTitleText(): Promise { return element(by.css('p3x-root .content span')).getText() as Promise; } } e2e/tsconfig.json000066400000000000000000000003311516106664700142510ustar00rootroot00000000000000{ "extends": "../tsconfig.json", "compilerOptions": { "outDir": "../out-tsc/e2e", "module": "commonjs", "target": "es2018", "types": [ "jasmine", "jasminewd2", "node" ] } } karma.conf.js000066400000000000000000000017751516106664700134610ustar00rootroot00000000000000// Karma configuration file, see link for more information // https://karma-runner.github.io/1.0/config/configuration-file.html module.exports = function (config) { config.set({ basePath: '', frameworks: ['jasmine', '@angular-devkit/build-angular'], plugins: [ require('karma-jasmine'), require('karma-chrome-launcher'), require('karma-jasmine-html-reporter'), require('karma-coverage-istanbul-reporter'), require('@angular-devkit/build-angular/plugins/karma') ], client: { clearContext: false // leave Jasmine Spec Runner output visible in browser }, coverageIstanbulReporter: { dir: require('path').join(__dirname, './coverage/workspace'), reports: ['html', 'lcovonly', 'text-summary'], fixWebpackSourcePaths: true }, reporters: ['progress', 'kjhtml'], port: 9876, colors: true, logLevel: config.LOG_INFO, autoWatch: true, browsers: ['Chrome'], singleRun: false, restartOnFileChange: true }); }; package.json000066400000000000000000000101051516106664700133550ustar00rootroot00000000000000{ "name": "p3x-angular-http-cache-interceptor", "version": "2024.4.107", "corifeus": { "icon": "fas fa-fire", "prefix": "p3x-", "publish": true, "type": "p3x", "code": "Breeze", "nodejs": "v20.11.1", "opencollective": false, "reponame": "angular-http-cache-interceptor", "build": true, "cdn": true, "publish-location": "./dist/angular-http-cache-interceptor", "angular": "17.2.1" }, "description": "🔥 Cache every request in Angular, not only the GET, but all methods of this interceptor, and allows you to interact with the interceptor via specific headers and modify the request, and these specific headers will be not included in the final request", "scripts": { "test": "grunt", "ng": "ng", "start": "ng serve --hmr", "build": "ng build", "test2": "ng test", "lint": "ng lint", "e2e": "ng e2e", "build-lib": "ng build --configuration=production --project angular-http-cache-interceptor && cp README.md ./dist/angular-http-cache-interceptor && cp LICENSE ./dist/angular-http-cache-interceptor && node node_modules/corifeus-builder/src/utils/angular/post-lib-build.js", "build-app": "ng build --source-map=false --output-hashing=all --configuration=production --base-href=/ --aot=true --build-optimizer=true --optimization=true && grunt htmlmin:dist", "stats": "ng build --stats-json && webpack-bundle-analyzer dist/workspace/stats.json" }, "repository": { "type": "git", "url": "git+https://github.com/patrikx3/angular-http-cache-interceptor.git" }, "keywords": [ "angular", "cache", "interceptor", "network", "http", "client", "http-client", "header", "headers", "interact", "configuration" ], "author": "Patrik Laszlo ", "license": "MIT", "bugs": { "url": "https://github.com/patrikx3/angular-http-cache-interceptor/issues" }, "homepage": "https://corifeus.com/angular-http-cache-interceptor", "dependencies": { "@angular/animations": "^17.2.1", "@angular/cdk": "^17.2.0", "@angular/common": "^17.2.1", "@angular/compiler": "^17.2.1", "@angular/core": "^17.2.1", "@angular/forms": "^17.2.1", "@angular/material": "^17.2.0", "@angular/platform-browser": "^17.2.1", "@angular/platform-browser-dynamic": "^17.2.1", "@angular/router": "^17.2.1", "@types/node": "^20.11.19", "hash": "^0.2.1", "highlight.js": "^11.9.0", "object": "^0.1.1", "object-hash": "^3.0.0", "postcss": "^8.4.35", "rxjs": "~6.6.3", "tslib": "^2.2.0", "zone.js": "~0.14.2" }, "dependencies-save": { "p3x-interceptor": "npm:p3x-angular-http-cache-interceptor@^2020.4.304" }, "devDependencies": { "@angular-devkit/build-angular": "^17.2.0", "@angular/cli": "^17.2.0", "@angular/compiler-cli": "^17.2.1", "@angular/language-service": "^17.2.1", "@types/highlight.js": "^9.12.4", "@types/jasmine": "~5.1.4", "@types/jasminewd2": "~2.0.13", "@typescript-eslint/eslint-plugin": "7.0.1", "@typescript-eslint/parser": "7.0.1", "codelyzer": "^6.0.2", "corifeus-builder": "^2024.4.106", "eslint": "^8.56.0", "eslint-plugin-import": "2.29.1", "eslint-plugin-jsdoc": "48.1.0", "eslint-plugin-prefer-arrow": "1.2.3", "jasmine-core": "~5.1.2", "jasmine-spec-reporter": "~7.0.0", "karma": "~6.3.2", "karma-chrome-launcher": "~3.2.0", "karma-coverage-istanbul-reporter": "~3.0.3", "karma-jasmine": "~5.1.0", "karma-jasmine-html-reporter": "^2.1.0", "ng-packagr": "^17.0.2", "protractor": "~7.0.0", "ts-node": "~10.9.2", "typescript": "~5.2.2", "webpack-bundle-analyzer": "^4.10.1" }, "engines": { "node": ">=12.13.0" } }projects/000077500000000000000000000000001516106664700127235ustar00rootroot00000000000000projects/angular-http-cache-interceptor/000077500000000000000000000000001516106664700207265ustar00rootroot00000000000000projects/angular-http-cache-interceptor/.eslintrc.json000066400000000000000000000015721516106664700235270ustar00rootroot00000000000000{ "extends": "../../.eslintrc.json", "ignorePatterns": [ "!**/*" ], "overrides": [ { "files": [ "*.ts" ], "parserOptions": { "project": [ "projects/angular-http-cache-interceptor/tsconfig.lib.json", "projects/angular-http-cache-interceptor/tsconfig.spec.json" ], "createDefaultProgram": true }, "rules": { "@angular-eslint/component-selector": [ "error", { "type": "element", "prefix": "p3x", "style": "kebab-case" } ], "@angular-eslint/directive-selector": [ "error", { "type": "attribute", "prefix": "p3x", "style": "camelCase" } ] } }, { "files": [ "*.html" ], "rules": {} } ] } projects/angular-http-cache-interceptor/.gitignore000066400000000000000000000015631516106664700227230ustar00rootroot00000000000000/build /node_modules /*.log /*.iws .idea/workspace.xml .idea/tasks.xml .idea/profiles_settings.xml .idea/inspectionProfiles/Project_Default.xml .idea/inspectionProfiles/profiles_settings.xml node_modules/.yarn-integrity # See http://help.github.com/ignore-files/ for more about ignoring files. # compiled output /dist /release /tmp /out-tsc # Only exists if Bazel was run /bazel-out # dependencies /node_modules # profiling files chrome-profiler-events*.json speed-measure-plugin*.json # IDEs and editors /.idea .project .classpath .c9/ *.launch .settings/ *.sublime-workspace # IDE - VSCode .vscode/* !.vscode/settings.json !.vscode/tasks.json !.vscode/launch.json !.vscode/extensions.json .history/* # misc /.sass-cache /connect.lock /coverage /libpeerconnection.log npm-debug.log yarn-error.log testem.log /typings # System Files .DS_Store Thumbs.db /package-lock.json projects/angular-http-cache-interceptor/README.md000066400000000000000000000022301516106664700222020ustar00rootroot00000000000000# AngularHttpCacheInterceptor This library was generated with [Angular CLI](https://github.com/angular/angular-cli) version 9.1.3. ## Code scaffolding Run `ng generate component component-name --project angular-http-cache-interceptor` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module --project angular-http-cache-interceptor`. > Note: Don't forget to add `--project angular-http-cache-interceptor` or else it will be added to the default project in your `angular.json` file. ## Build Run `ng build angular-http-cache-interceptor` to build the project. The build artifacts will be stored in the `dist/` directory. ## Publishing After building your library with `ng build angular-http-cache-interceptor`, go to the dist folder `cd dist/angular-http-cache-interceptor` and run `npm publish`. ## Running unit tests Run `ng test angular-http-cache-interceptor` to execute the unit tests via [Karma](https://karma-runner.github.io). ## Further help To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI README](https://github.com/angular/angular-cli/blob/master/README.md). projects/angular-http-cache-interceptor/karma.conf.js000066400000000000000000000020261516106664700233030ustar00rootroot00000000000000// Karma configuration file, see link for more information // https://karma-runner.github.io/1.0/config/configuration-file.html module.exports = function (config) { config.set({ basePath: '', frameworks: ['jasmine', '@angular-devkit/build-angular'], plugins: [ require('karma-jasmine'), require('karma-chrome-launcher'), require('karma-jasmine-html-reporter'), require('karma-coverage-istanbul-reporter'), require('@angular-devkit/build-angular/plugins/karma') ], client: { clearContext: false // leave Jasmine Spec Runner output visible in browser }, coverageIstanbulReporter: { dir: require('path').join(__dirname, '../../coverage/angular-http-cache-interceptor'), reports: ['html', 'lcovonly', 'text-summary'], fixWebpackSourcePaths: true }, reporters: ['progress', 'kjhtml'], port: 9876, colors: true, logLevel: config.LOG_INFO, autoWatch: true, browsers: ['Chrome'], singleRun: false, restartOnFileChange: true }); }; projects/angular-http-cache-interceptor/ng-package.json000066400000000000000000000002641516106664700236200ustar00rootroot00000000000000{ "$schema": "../../node_modules/ng-packagr/ng-package.schema.json", "dest": "../../dist/angular-http-cache-interceptor", "lib": { "entryFile": "src/public-api.ts" } } projects/angular-http-cache-interceptor/package.json000066400000000000000000000005621516106664700232170ustar00rootroot00000000000000{ "name": "p3x-angular-http-cache-interceptor", "peerDependencies": { "object-hash": "^2.1.1", "@angular/common": "^12.0.0", "@angular/core": "^12.0.0" }, "corifeus": { "install": false }, "devDependencies": { "corifeus-builder": "^2021.4.132" }, "dependencies": { "tslib": "^2.0.3" } }projects/angular-http-cache-interceptor/src/000077500000000000000000000000001516106664700215155ustar00rootroot00000000000000projects/angular-http-cache-interceptor/src/lib/000077500000000000000000000000001516106664700222635ustar00rootroot00000000000000projects/angular-http-cache-interceptor/src/lib/caching-headers.enum.ts000066400000000000000000000001771516106664700266100ustar00rootroot00000000000000// cache headers has to have a x- prefix export enum CachingHeaders { NoCache = "x-p3x-no-cache", Cache = "x-p3x-cache", } projects/angular-http-cache-interceptor/src/lib/caching-store.enum.ts000066400000000000000000000001341516106664700263220ustar00rootroot00000000000000// cache headers has to have a x- prefix export enum CachingStore { Global, PerModule } projects/angular-http-cache-interceptor/src/lib/http-cache-config.token.ts000066400000000000000000000002751516106664700272410ustar00rootroot00000000000000import { InjectionToken } from "@angular/core"; import { HttpCacheConfig } from "./http-cache-config"; export const P3X_HTTP_CACHE_CONFIG = new InjectionToken( 'P3X_HTTP_CACHE_CONFIG' ) projects/angular-http-cache-interceptor/src/lib/http-cache-config.ts000066400000000000000000000003061516106664700261150ustar00rootroot00000000000000import { CachingHeaders} from "./caching-headers.enum"; import { CachingStore } from "./caching-store.enum"; export interface HttpCacheConfig { behavior: CachingHeaders, store: CachingStore, } projects/angular-http-cache-interceptor/src/lib/http-cache-interceptor.interceptor.ts000066400000000000000000000102651516106664700315500ustar00rootroot00000000000000import {Inject, Injectable, Optional} from '@angular/core'; import {HttpEvent, HttpHandler, HttpInterceptor, HttpRequest, HttpResponse} from '@angular/common/http'; import {Observable, of} from 'rxjs'; import * as hash from 'object-hash' import {tap} from "rxjs/operators"; import {CachingHeaders} from "./caching-headers.enum"; import {CachingStore} from "./caching-store.enum"; import {P3X_HTTP_CACHE_CONFIG} from "./http-cache-config.token"; import {HttpCacheConfig} from "./http-cache-config"; const hashOptions = { algorithm: 'md5', encoding: 'hex' } const globalCache = new Map() @Injectable() export class HttpCacheInterceptorInterceptor implements HttpInterceptor { private cachedData = new Map() httpCacheConfig : HttpCacheConfig = { behavior: CachingHeaders.Cache, store: CachingStore.Global, } getCache(key: string) { if (this.httpCacheConfig.store === CachingStore.Global) { return globalCache.get(key) } else { return this.cachedData.get(key) } } setCache(key: string, value: any) { if (this.httpCacheConfig.store === CachingStore.Global) { globalCache.set(key, value) } else { this.cachedData.set(key, value) } } constructor(@Inject(P3X_HTTP_CACHE_CONFIG) @Optional() httpCacheConfigToken: HttpCacheConfig) { if (httpCacheConfigToken) { this.httpCacheConfig = httpCacheConfigToken } } httpToKey(httpRequest: HttpRequest) { const body = JSON.parse(JSON.stringify(httpRequest.body)) const key = httpRequest.method + '@' + httpRequest.urlWithParams + '@' + hash(httpRequest.params, hashOptions) + '@' + hash(body, hashOptions) return key } intercept(httpRequest: HttpRequest, next: HttpHandler): Observable> { //console.log(httpRequest) //console.log('has', httpRequest.headers.has(CachingHeaders.NoCache)) //console.log('value', httpRequest.headers.get(CachingHeaders.NoCache)) const forcedCache = httpRequest.headers.get(CachingHeaders.Cache) !== null const forcedNoneCache = httpRequest.headers.get(CachingHeaders.NoCache) !== null //console.log('forcedCache', forcedCache, 'forcedNoneCache', forcedNoneCache) let headers = httpRequest.headers.delete(CachingHeaders.NoCache) headers = headers.delete(CachingHeaders.Cache) httpRequest = httpRequest.clone({ headers: headers }) if (forcedCache && forcedNoneCache) { throw new Error('You cannot use cache and non-cache header at once!') } else if (forcedNoneCache || (this.httpCacheConfig.behavior === CachingHeaders.NoCache && !forcedCache)) { return next.handle(httpRequest); } else if (forcedCache || (this.httpCacheConfig.behavior === CachingHeaders.Cache && !forcedNoneCache)) { // Checked if there is cached data for this URI const key = this.httpToKey(httpRequest) const lastResponse = this.getCache(key); if (lastResponse) { // In case of parallel requests to same URI, // return the request already in progress // otherwise return the last cached data //console.info('http cache interceptor hit cache', key) return (lastResponse instanceof Observable) ? lastResponse : of(lastResponse.clone()); } //console.info('http cache interceptor', key) // If the request of going through for first time // then let the request proceed and cache the response const requestHandle = next.handle(httpRequest).pipe( tap((stateEvent: any) => { if (stateEvent instanceof HttpResponse) { this.setCache( key, stateEvent.clone() ); } }) ) // Meanwhile cache the request Observable to handle parallel request //this.cachedData.set(key, requestHandle); return requestHandle; } else { console.error(this.httpCacheConfig) console.error(httpRequest.headers) throw new Error('There is a configuration in your setup') } /* // Also leave scope of resetting already cached data for a URI if (httpRequest.headers.get("reset-cache")) { this.cachedData.delete(httpRequest.urlWithParams); } */ } } projects/angular-http-cache-interceptor/src/lib/http-cache-interceptor.module.ts000066400000000000000000000015561516106664700305020ustar00rootroot00000000000000import {ModuleWithProviders, NgModule} from '@angular/core'; import {HTTP_INTERCEPTORS} from "@angular/common/http"; import { HttpCacheInterceptorInterceptor } from './http-cache-interceptor.interceptor' import { P3X_HTTP_CACHE_CONFIG } from "./http-cache-config.token"; import { HttpCacheConfig } from "./http-cache-config"; @NgModule({ declarations: [], imports: [ ], providers: [ { provide: HTTP_INTERCEPTORS, useClass: HttpCacheInterceptorInterceptor, multi: true } ], exports: [] }) export class P3XHttpCacheInterceptorModule { static forRoot(httpCacheConfig: HttpCacheConfig): ModuleWithProviders { return { ngModule: P3XHttpCacheInterceptorModule, providers: [ { provide: P3X_HTTP_CACHE_CONFIG, useValue: httpCacheConfig } ] }; } } projects/angular-http-cache-interceptor/src/public-api.ts000066400000000000000000000004371516106664700241160ustar00rootroot00000000000000/* * Public API Surface of angular-http-cache-interceptor */ export * from './lib/http-cache-interceptor.module'; export * from './lib/caching-headers.enum' export * from './lib/http-cache-config' export * from './lib/http-cache-config.token' export * from './lib/caching-store.enum' projects/angular-http-cache-interceptor/src/test.ts000066400000000000000000000010131516106664700230370ustar00rootroot00000000000000// This file is required by karma.conf.js and loads recursively all the .spec and framework files import 'zone.js'; import 'zone.js/testing'; import { getTestBed } from '@angular/core/testing'; import { BrowserDynamicTestingModule, platformBrowserDynamicTesting } from '@angular/platform-browser-dynamic/testing'; // First, initialize the Angular testing environment. getTestBed().initTestEnvironment( BrowserDynamicTestingModule, platformBrowserDynamicTesting(), { teardown: { destroyAfterEach: false } } ); projects/angular-http-cache-interceptor/tsconfig.lib.json000066400000000000000000000006671516106664700242130ustar00rootroot00000000000000{ "extends": "../../tsconfig.json", "compilerOptions": { "outDir": "../../out-tsc/lib", "declarationMap": true, "declaration": true, "inlineSources": true, "types": [], "lib": [ "dom", "es2018" ] }, "angularCompilerOptions": { "skipTemplateCodegen": true, "strictMetadataEmit": true, "enableResourceInlining": true }, "exclude": [ "src/test.ts", "**/*.spec.ts" ] } projects/angular-http-cache-interceptor/tsconfig.lib.prod.json000066400000000000000000000002431516106664700251440ustar00rootroot00000000000000{ "extends": "./tsconfig.lib.json", "compilerOptions": { "declarationMap": false }, "angularCompilerOptions": { "compilationMode": "partial" } } projects/angular-http-cache-interceptor/tsconfig.spec.json000066400000000000000000000003661516106664700243730ustar00rootroot00000000000000{ "extends": "../../tsconfig.json", "compilerOptions": { "outDir": "../../out-tsc/spec", "types": [ "jasmine", "node" ] }, "files": [ "src/test.ts" ], "include": [ "**/*.spec.ts", "**/*.d.ts" ] } src/000077500000000000000000000000001516106664700116615ustar00rootroot00000000000000src/app/000077500000000000000000000000001516106664700124415ustar00rootroot00000000000000src/app/app-routing.module.ts000066400000000000000000000015301516106664700165410ustar00rootroot00000000000000import {NgModule} from '@angular/core' import {PreloadAllModules, RouterModule, Routes} from '@angular/router' const routes: Routes = [ { path: 'default', loadChildren: () => import('./default/default.module').then(m => m.DefaultModule) }, { path: 'cache', loadChildren: () => import('./cache/cache.module').then(m => m.CacheModule) }, { path: 'non-cache', loadChildren: () => import('./non-cache/non-cache.module').then(m => m.NonCacheModule) }, { path: '', redirectTo: `/default`, pathMatch: 'full' }, { path: '**', loadChildren: () => import('./not-found/not-found.module').then(m => m.NotFoundModule) } ] @NgModule({ imports: [ RouterModule.forRoot(routes, { preloadingStrategy: PreloadAllModules, }) ], exports: [RouterModule] }) export class AppRoutingModule { } src/app/app.component.html000066400000000000000000000026331516106664700161140ustar00rootroot00000000000000 P3X Angular HTTP Cache Interceptor v{{ version }} src/app/app.component.scss000066400000000000000000000004571516106664700161250ustar00rootroot00000000000000.list-item-fix { padding-left: 15px; } .ellipsis { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } .mat-mdc-button-wrapping.mat-button { white-space: normal !important; text-align: left; } .link-fix { display: block; $pos: 5px; padding: $pos; text-align: left; } src/app/app.component.spec.ts000066400000000000000000000007131516106664700165240ustar00rootroot00000000000000import { TestBed, waitForAsync } from '@angular/core/testing'; import { AppComponent } from './app.component'; describe('AppComponent', () => { beforeEach(waitForAsync(() => { TestBed.configureTestingModule({ imports: [AppComponent], }).compileComponents(); })); it('should create the app', () => { const fixture = TestBed.createComponent(AppComponent); const app = fixture.componentInstance; expect(app).toBeTruthy(); }); }); src/app/app.component.ts000066400000000000000000000027351516106664700156010ustar00rootroot00000000000000import {Component, OnInit} from '@angular/core'; import packageInfo from '../../package.json'; import { Router, RouterLinkActive, RouterLink, RouterOutlet } from "@angular/router"; import { MatDividerModule } from '@angular/material/divider'; import { MatButtonModule } from '@angular/material/button'; import { MatCardModule } from '@angular/material/card'; import { NgFor } from '@angular/common'; import { MatTabsModule } from '@angular/material/tabs'; import { MatToolbarModule } from '@angular/material/toolbar'; @Component({ selector: 'p3x-root', templateUrl: './app.component.html', styleUrls: ['./app.component.scss'], standalone: true, imports: [MatToolbarModule, MatTabsModule, NgFor, RouterLinkActive, RouterLink, MatCardModule, MatButtonModule, MatDividerModule, RouterOutlet] }) export class AppComponent implements OnInit { public version: string = packageInfo.version; navLinks: any[]; activeLinkIndex = -1; constructor(private router: Router) { this.navLinks = [ { label: 'Default', link: './default', index: 0 }, { label: 'Configured caching', link: './cache', index: 1 }, { label: 'Configured non-caching', link: './non-cache', index: 2 }, ]; } ngOnInit(): void { this.router.events.subscribe((res) => { this.activeLinkIndex = this.navLinks.indexOf(this.navLinks.find(tab => tab.link === '.' + this.router.url)); }); } } src/app/cache/000077500000000000000000000000001516106664700135045ustar00rootroot00000000000000src/app/cache/bootstrap/000077500000000000000000000000001516106664700155215ustar00rootroot00000000000000src/app/cache/bootstrap/bootstrap.component.html000066400000000000000000000007641516106664700224340ustar00rootroot00000000000000
This is configured to cache, so, it caches everything, unless you use the CachingHeaders.NoCache header in your request. Should you wish to use a per-module cache, in the interceptor configuration, you would use the CachingStore.PerModule store configuration.




src/app/cache/bootstrap/bootstrap.component.scss000066400000000000000000000000001516106664700224220ustar00rootroot00000000000000src/app/cache/bootstrap/bootstrap.component.spec.ts000066400000000000000000000012121516106664700230340ustar00rootroot00000000000000import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing'; import { BootstrapComponent } from './bootstrap.component'; describe('BootstrapComponent', () => { let component: BootstrapComponent; let fixture: ComponentFixture; beforeEach(waitForAsync(() => { TestBed.configureTestingModule({ imports: [BootstrapComponent] }) .compileComponents(); })); beforeEach(() => { fixture = TestBed.createComponent(BootstrapComponent); component = fixture.componentInstance; fixture.detectChanges(); }); it('should create', () => { expect(component).toBeTruthy(); }); }); src/app/cache/bootstrap/bootstrap.component.ts000066400000000000000000000021271516106664700221110ustar00rootroot00000000000000import { Component, OnInit } from '@angular/core'; import {HighlightService} from "../../common/highlight.service"; import { DefaultComponentComponent } from '../../common/default-component/default-component.component'; import { MatDividerModule } from '@angular/material/divider'; @Component({ selector: 'p3x-bootstrap-cache', templateUrl: './bootstrap.component.html', styleUrls: ['./bootstrap.component.scss'], standalone: true, imports: [MatDividerModule, DefaultComponentComponent] }) export class BootstrapComponent implements OnInit { defaultSettings: string constructor(private service: HighlightService) { } ngOnInit(): void { this.defaultSettings = this.service.hljs.highlight( `import { P3XHttpCacheInterceptorModule, CachingHeaders, CachingStore } from 'p3x-angular-http-cache-interceptor'; @NgModule({ declarations: [], imports: [ P3XHttpCacheInterceptorModule.forRoot({ behavior: CachingHeaders.Cache, store: CachingStore.Global, }), CommonModule ] }) export class NonCacheModule { }`, { language: 'typescript'}).value } } src/app/cache/cache-routing.module.ts000066400000000000000000000005611516106664700200720ustar00rootroot00000000000000import {NgModule} from '@angular/core' import {RouterModule, Routes} from '@angular/router' import {BootstrapComponent} from "./bootstrap/bootstrap.component"; const routes: Routes = [ { path: '**', component: BootstrapComponent }, ] @NgModule({ imports: [RouterModule.forChild(routes)], exports: [RouterModule] }) export class CacheRoutingModule { } src/app/cache/cache.module.ts000066400000000000000000000020301516106664700163760ustar00rootroot00000000000000import {NgModule} from '@angular/core'; import {CommonModule as AngularCommonModule} from '@angular/common'; import {BootstrapComponent} from './bootstrap/bootstrap.component'; import {CacheRoutingModule} from "./cache-routing.module"; import {CommonModule} from "../common/common.module"; import {P3XHttpCacheInterceptorModule} from '../../../projects/angular-http-cache-interceptor/src/lib/http-cache-interceptor.module'; import {CachingHeaders} from "../../../projects/angular-http-cache-interceptor/src/lib/caching-headers.enum"; import {CachingStore} from "../../../projects/angular-http-cache-interceptor/src/lib/caching-store.enum"; import { MatDividerModule } from "@angular/material/divider"; @NgModule({ imports: [ P3XHttpCacheInterceptorModule.forRoot({ behavior: CachingHeaders.Cache, store: CachingStore.Global, }), AngularCommonModule, CacheRoutingModule, CommonModule, MatDividerModule, BootstrapComponent, ], }) export class CacheModule { } src/app/common/000077500000000000000000000000001516106664700137315ustar00rootroot00000000000000src/app/common/common.module.ts000066400000000000000000000015101516106664700170520ustar00rootroot00000000000000import { NgModule } from '@angular/core'; import { CommonModule as AngularCommonModule } from '@angular/common'; import { DefaultComponentComponent } from './default-component/default-component.component'; import {MatSnackBarModule} from "@angular/material/snack-bar"; import {MatButtonModule} from "@angular/material/button"; import {MatDividerModule} from "@angular/material/divider"; import {HttpClientModule} from "@angular/common/http"; import { HighlightService } from "./highlight.service"; @NgModule({ imports: [ AngularCommonModule, MatSnackBarModule, MatButtonModule, MatDividerModule, HttpClientModule, DefaultComponentComponent, ], providers: [ HighlightService ], exports: [ DefaultComponentComponent, ] }) export class CommonModule { } src/app/common/default-component/000077500000000000000000000000001516106664700173555ustar00rootroot00000000000000src/app/common/default-component/default-component.component.html000066400000000000000000000022111516106664700256640ustar00rootroot00000000000000


Itt will try to load some random data, based on the default interceptor behavior without using headers.




Itt will try to load some random data with cached data. You can see in the browser inspector network tab, that there will be only one request. Here, we use the CachingHeaders.Cache header.




It will try to load some random data without cache. You can see in the browser inspector network tab, that every click will talk to a server and retrieve the new data. Here, we use the CachingHeaders.NoCache header.
src/app/common/default-component/default-component.component.scss000066400000000000000000000000001516106664700256650ustar00rootroot00000000000000src/app/common/default-component/default-component.component.spec.ts000066400000000000000000000012741516106664700263070ustar00rootroot00000000000000import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing'; import { DefaultComponentComponent } from './default-component.component'; describe('DefaultComponentComponent', () => { let component: DefaultComponentComponent; let fixture: ComponentFixture; beforeEach(waitForAsync(() => { TestBed.configureTestingModule({ imports: [DefaultComponentComponent] }) .compileComponents(); })); beforeEach(() => { fixture = TestBed.createComponent(DefaultComponentComponent); component = fixture.componentInstance; fixture.detectChanges(); }); it('should create', () => { expect(component).toBeTruthy(); }); }); src/app/common/default-component/default-component.component.ts000066400000000000000000000045121516106664700253540ustar00rootroot00000000000000import {Component, ViewEncapsulation} from '@angular/core'; import { HttpClient } from "@angular/common/http"; import {MatSnackBar, MatSnackBarConfig} from "@angular/material/snack-bar"; import { CachingHeaders} from "../../../../projects/angular-http-cache-interceptor/src/lib/caching-headers.enum"; import { MatDividerModule } from '@angular/material/divider'; import { MatButtonModule } from '@angular/material/button'; @Component({ selector: 'p3x-default-component', templateUrl: './default-component.component.html', styleUrls: ['./default-component.component.scss'], standalone: true, imports: [MatButtonModule, MatDividerModule], }) export class DefaultComponentComponent { defaultSnackbarSettings : MatSnackBarConfig = { horizontalPosition: "center", verticalPosition: "bottom" } constructor( private http: HttpClient, private snack: MatSnackBar, ) { } async loadDefault() { try { const response : any = await this.http.get('https://server.patrikx3.com/api/core/util/random/32').toPromise() this.snack.open(`The output is based on the default interceptor behavior: ${response.random}`, 'OK', this.defaultSnackbarSettings) } catch(e) { this.snack.open(`Sorry, error happened, check the console for the error`, 'OK', this.defaultSnackbarSettings) console.error(e) } } async loadCached() { try { const response : any = await this.http.get('https://server.patrikx3.com/api/core/util/random/32', { headers: { [CachingHeaders.Cache]: '1', } }).toPromise() this.snack.open(`Will be always the same output: ${response.random}`, 'OK', this.defaultSnackbarSettings) } catch(e) { this.snack.open(`Sorry, error happened, check the console for the error`, 'OK', this.defaultSnackbarSettings) console.error(e) } } async loadNonCached() { try { const response : any = await this.http.get('https://server.patrikx3.com/api/core/util/random/16', { headers: { [CachingHeaders.NoCache]: '1', } }).toPromise() this.snack.open(`Truly random data: ${response.random}`, 'OK', this.defaultSnackbarSettings) } catch(e) { this.snack.open(`Sorry, error happened, check the console for the error`, 'OK', this.defaultSnackbarSettings) console.error(e) } } } src/app/common/highlight.service.ts000066400000000000000000000005121516106664700177050ustar00rootroot00000000000000import { Injectable } from '@angular/core'; import hljs from 'highlight.js/lib/core'; import typescript from 'highlight.js/lib/languages/typescript'; hljs.registerLanguage('typescript', typescript); @Injectable({ providedIn: 'root' }) export class HighlightService { constructor() { } get hljs() { return hljs } } src/app/default/000077500000000000000000000000001516106664700140655ustar00rootroot00000000000000src/app/default/bootstrap/000077500000000000000000000000001516106664700161025ustar00rootroot00000000000000src/app/default/bootstrap/bootstrap.component.html000066400000000000000000000007351516106664700230130ustar00rootroot00000000000000
This is the default settings. By default, it caches everything, unless you use the CachingHeaders.NoCache header in your request. Besides, the cache is using a global store, unless you use the CachingStore.PerModule store configuration.




src/app/default/bootstrap/bootstrap.component.scss000066400000000000000000000000001516106664700230030ustar00rootroot00000000000000src/app/default/bootstrap/bootstrap.component.spec.ts000066400000000000000000000012121516106664700234150ustar00rootroot00000000000000import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing'; import { BootstrapComponent } from './bootstrap.component'; describe('BootstrapComponent', () => { let component: BootstrapComponent; let fixture: ComponentFixture; beforeEach(waitForAsync(() => { TestBed.configureTestingModule({ imports: [BootstrapComponent] }) .compileComponents(); })); beforeEach(() => { fixture = TestBed.createComponent(BootstrapComponent); component = fixture.componentInstance; fixture.detectChanges(); }); it('should create', () => { expect(component).toBeTruthy(); }); }); src/app/default/bootstrap/bootstrap.component.ts000066400000000000000000000017401516106664700224720ustar00rootroot00000000000000import { Component, OnInit } from '@angular/core'; import {HighlightService} from "../../common/highlight.service"; import { DefaultComponentComponent } from '../../common/default-component/default-component.component'; import { MatDividerModule } from '@angular/material/divider'; @Component({ selector: 'p3x-bootstrap-default', templateUrl: './bootstrap.component.html', styleUrls: ['./bootstrap.component.scss'], standalone: true, imports: [MatDividerModule, DefaultComponentComponent] }) export class BootstrapComponent implements OnInit { defaultSettings: string constructor(private service: HighlightService) { } ngOnInit(): void { this.defaultSettings = this.service.hljs.highlight( `import { P3XHttpCacheInterceptorModule } from 'p3x-angular-http-cache-interceptor'; @NgModule({ declarations: [], imports: [ P3XHttpCacheInterceptorModule, CommonModule, ] }) export class DefaultModule { }`, { language: 'typescript'}).value } } src/app/default/default-routing.module.ts000066400000000000000000000005631516106664700210360ustar00rootroot00000000000000import {NgModule} from '@angular/core' import {RouterModule, Routes} from '@angular/router' import {BootstrapComponent} from "./bootstrap/bootstrap.component"; const routes: Routes = [ { path: '**', component: BootstrapComponent }, ] @NgModule({ imports: [RouterModule.forChild(routes)], exports: [RouterModule] }) export class DefaultRoutingModule { } src/app/default/default.module.ts000066400000000000000000000016301516106664700173450ustar00rootroot00000000000000import { NgModule } from '@angular/core'; import { CommonModule as AngularCommonModule } from '@angular/common'; import { BootstrapComponent } from './bootstrap/bootstrap.component'; import {DefaultRoutingModule} from "./default-routing.module"; import {CommonModule} from "../common/common.module"; import {P3XHttpCacheInterceptorModule} from '../../../projects/angular-http-cache-interceptor/src/lib/http-cache-interceptor.module'; //import {CachingHeaders} from "../../../projects/angular-http-cache-interceptor/src/lib/caching-headers.enum"; //import { P3XHttpCacheInterceptorModule } from 'p3x-interceptor' import { MatDividerModule } from "@angular/material/divider"; @NgModule({ imports: [ P3XHttpCacheInterceptorModule, AngularCommonModule, DefaultRoutingModule, CommonModule, MatDividerModule, BootstrapComponent, ], }) export class DefaultModule { } src/app/non-cache/000077500000000000000000000000001516106664700142745ustar00rootroot00000000000000src/app/non-cache/bootstrap/000077500000000000000000000000001516106664700163115ustar00rootroot00000000000000src/app/non-cache/bootstrap/bootstrap.component.html000066400000000000000000000007341516106664700232210ustar00rootroot00000000000000
This is configured to not cache, unless you use the CachingHeaders.Cache header in your request. Should you wish to use a per-module cache, in the interceptor configuration, you would use the CachingStore.PerModule store configuration.




src/app/non-cache/bootstrap/bootstrap.component.scss000066400000000000000000000000001516106664700232120ustar00rootroot00000000000000src/app/non-cache/bootstrap/bootstrap.component.spec.ts000066400000000000000000000012121516106664700236240ustar00rootroot00000000000000import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing'; import { BootstrapComponent } from './bootstrap.component'; describe('BootstrapComponent', () => { let component: BootstrapComponent; let fixture: ComponentFixture; beforeEach(waitForAsync(() => { TestBed.configureTestingModule({ imports: [BootstrapComponent] }) .compileComponents(); })); beforeEach(() => { fixture = TestBed.createComponent(BootstrapComponent); component = fixture.componentInstance; fixture.detectChanges(); }); it('should create', () => { expect(component).toBeTruthy(); }); }); src/app/non-cache/bootstrap/bootstrap.component.ts000066400000000000000000000021361516106664700227010ustar00rootroot00000000000000import { Component, OnInit } from '@angular/core'; import {HighlightService} from "../../common/highlight.service"; import { DefaultComponentComponent } from '../../common/default-component/default-component.component'; import { MatDividerModule } from '@angular/material/divider'; @Component({ selector: 'p3x-bootstrap-non-cache', templateUrl: './bootstrap.component.html', styleUrls: ['./bootstrap.component.scss'], standalone: true, imports: [MatDividerModule, DefaultComponentComponent] }) export class BootstrapComponent implements OnInit { defaultSettings: string constructor(private service: HighlightService) { } ngOnInit(): void { this.defaultSettings = this.service.hljs.highlight( `import { P3XHttpCacheInterceptorModule, CachingHeaders, CachingStore } from 'p3x-angular-http-cache-interceptor'; @NgModule({ declarations: [], imports: [ P3XHttpCacheInterceptorModule.forRoot({ behavior: CachingHeaders.NoCache, store: CachingStore.Global, }), CommonModule ] }) export class NonCacheModule { }`, { language: 'typescript'}).value } } src/app/non-cache/non-cache-routing.module.ts000066400000000000000000000005641516106664700214550ustar00rootroot00000000000000import {NgModule} from '@angular/core' import {RouterModule, Routes} from '@angular/router' import {BootstrapComponent} from "./bootstrap/bootstrap.component"; const routes: Routes = [ { path: '**', component: BootstrapComponent }, ] @NgModule({ imports: [RouterModule.forChild(routes)], exports: [RouterModule] }) export class NonCacheRoutingModule { } src/app/non-cache/non-cache.module.ts000066400000000000000000000020561516106664700177660ustar00rootroot00000000000000import { NgModule } from '@angular/core'; import { CommonModule as AngularCommonModule } from '@angular/common'; import { BootstrapComponent } from './bootstrap/bootstrap.component'; import {NonCacheRoutingModule} from "./non-cache-routing.module"; import {CommonModule} from "../common/common.module"; import {P3XHttpCacheInterceptorModule} from '../../../projects/angular-http-cache-interceptor/src/lib/http-cache-interceptor.module'; import {CachingHeaders} from "../../../projects/angular-http-cache-interceptor/src/lib/caching-headers.enum"; import {CachingStore} from "../../../projects/angular-http-cache-interceptor/src/lib/caching-store.enum"; import { MatDividerModule } from "@angular/material/divider"; @NgModule({ imports: [ P3XHttpCacheInterceptorModule.forRoot({ behavior: CachingHeaders.NoCache, store: CachingStore.Global, }), NonCacheRoutingModule, AngularCommonModule, CommonModule, MatDividerModule, BootstrapComponent, ], }) export class NonCacheModule { } src/app/not-found/000077500000000000000000000000001516106664700143525ustar00rootroot00000000000000src/app/not-found/not-found-routing.module.ts000066400000000000000000000005571516106664700216130ustar00rootroot00000000000000import { NgModule } from '@angular/core'; import { Routes, RouterModule } from '@angular/router'; import {NotFoundComponent} from "./not-found.component"; const routes: Routes = [ { path: '**', component: NotFoundComponent }, ]; @NgModule({ imports: [RouterModule.forChild(routes)], exports: [RouterModule] }) export class NotFoundRoutingModule { } src/app/not-found/not-found.component.html000066400000000000000000000000511516106664700211460ustar00rootroot00000000000000

404 Not found

src/app/not-found/not-found.component.scss000066400000000000000000000000001516106664700211470ustar00rootroot00000000000000src/app/not-found/not-found.component.ts000066400000000000000000000004731516106664700206400ustar00rootroot00000000000000import { Component, OnInit } from '@angular/core'; @Component({ selector: 'p3x-not-found', templateUrl: './not-found.component.html', styleUrls: ['./not-found.component.scss'], standalone: true }) export class NotFoundComponent implements OnInit { constructor() { } ngOnInit(): void { } } src/app/not-found/not-found.module.ts000066400000000000000000000005571516106664700201260ustar00rootroot00000000000000import { NgModule } from '@angular/core'; import { CommonModule } from '@angular/common'; import { NotFoundRoutingModule } from './not-found-routing.module'; import { NotFoundComponent } from './not-found.component'; @NgModule({ imports: [ CommonModule, NotFoundRoutingModule, NotFoundComponent ] }) export class NotFoundModule { } src/assets/000077500000000000000000000000001516106664700131635ustar00rootroot00000000000000src/assets/.gitkeep000066400000000000000000000000001516106664700146020ustar00rootroot00000000000000src/environments/000077500000000000000000000000001516106664700144105ustar00rootroot00000000000000src/environments/environment.prod.ts000066400000000000000000000000631516106664700202660ustar00rootroot00000000000000export const environment = { production: true }; src/environments/environment.ts000066400000000000000000000012301516106664700173200ustar00rootroot00000000000000// This file can be replaced during build by using the `fileReplacements` array. // `ng build --prod` replaces `environment.ts` with `environment.prod.ts`. // The list of file replacements can be found in `angular.json`. export const environment = { production: false }; /* * For easier debugging in development mode, you can import the following file * to ignore zone related error stack frames such as `zone.run`, `zoneDelegate.invokeTask`. * * This import should be commented out in production mode because it will have a negative impact * on performance if an error is thrown. */ //import 'zone.js/plugins/zone-error'; // Included with Angular CLI. src/favicon.ico000066400000000000000000000764461516106664700140230ustar00rootroot00000000000000 hF 00 %V@@ (B:(  @]KI]KI;]KI\JI]KI]KIc]KI]KI]KIq]KI]KI]KI\JH]KI]KI]KI]KI7]KI]KI]KI-]KI]KI]KHM]KI]KI]KI]KI]KI]KIC]KI]KI]KI]KIi]KI]KI]KI]KI]KI]KI]KI]KI\KI]KI]KI]KH]KI]KI]KI]KI9]KI]KI]KI\KH\KHw\KI]KI]KI]KI\KI1]JI]KI]KI]KI]KH]KI]KI]KI \KI]KI]KI]KI5]KI'\KI]KI%]KI \KI]KI]KI+\KI]KI( @ ]KIC]KH]KI-]KI]KH]KI]KI]KI]KIQ]KI_]KI]KH]KI \JI]KI]KI]KI]JI]KI]KI]KI;]KI]KI]KI7]KI]KI]KI]KI]KI]KI]KI]KI ]KI ]KI]KI]KI]KI]KI{]KI]KH]KIc]KIc]KI]KI]KI]KI)]KI%]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]JI\JI]KI]KI]KI]KI]KI]KIk]KIM]KI]KI]KI]KI]KI]KI]KI9]KI7]KI]KI]KI]KI]KI]KI ]KI]KI]KI]KI]KI]KI]KI]KI]KH ]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KH]KI]KI]KI]KH]KIW]KI+]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]JH\JH]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KIW]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KH]KIE]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI ]KI]KI]KI]KI]KI]KI]KI]KI]KI\KI]]KI]KI]KI]KI]KI\KI]KI1]KI]KI]KI]KI]KI]KI]KI\KI]KI]KI]KI]KI]KI]KI]KI3]KH]KI]KI]KI]KI]KI]KI]KI\KI#]KI/]KI]KI]KI\KI]KI]KI]KI]KI]KI]KI]KI]KI\KI]JH]KI\KI\KIq]KI]KI]KI]KI]KI]KH]KI3]KI ]KI]KI]KI!]KI]KI]KI]KI]KI]JI=]KIo]KI]KI]KI]KIC\KI]KI_\JI(0` %\KHM]JI]KI]KI!\JH\JH]KI]]KI]KI]JH\JH]KIC]KIK]KI\KI]KI]KI]KI]KI\JH]KI]KH]KI]KI]KH]JH]KI-]KI)\KH]KI\KI\KI]KI]KI]KI\JH\JH\KHm]KIU]KI]KI]KI]JH]KI]KH]KI+]KI]KI\KH]JI\JH\JH]KH\JI\KI=\JH]JI]KI']KI]KI]KI\JH\JH]KI]KHU\KI ]JI]KI]KH]KI]KI]JH5\KH]KI]KI]KI]KI\KI]KIa]KI]KI]KI\JI]KIE]KH ]KI\JH]KI\JH\JH\JI]KI]KI]KI]KI]KI]KH\JH]KI]KI]KH]]JI\JH]KI]KI]KH]KIE]KI]KI]KI\KI]KI]KI\JH]KI]KHs\KI]KI]KI]KI\JH]KH]KI]KI\KH]KI;]KI]KH]KI]KI]KI]KI]KI]KI]KI%\KI]KI]KI]KI]KI]KI]KI]KI]KI]KI ]KI]KI]KH]KI]KI]KI]KI]JH]KI]KI\KI]KI1\KH]KI]KI]KI]KI]KI\KI3]KIc]JH]KH\JH\JH]KH]KI\KI\JH\JH\KH]JHE]KH ]KI\JH\JH]KH\JH\KI]KI]KI ]JI]JI]KI]KI]JI]KI]KI]KI]KI]KI]KI]KI]KI]KI \KI_]KI]JI]KI]KI]KI]KI]KIu]KI]KI]KH]KI]JH]KI]KI]KI]KI]KI]KI]KI]KI]KI\KI]KI]JH]KI]KI]KI\KI]KH%]KI?\JI\KH]KI]KI\JH]KI]KI]KI\KH]KI]KI\JH\JH\JH\JH\JH\JH]KI]KI\KH]KI]KI ]KI ]JI]KI]KI]KI]KI]KH]KI]KH]KI\JH]KI]KI]KI]KI]KI]KI]KI]KH]KI]KH]JI]KI_\KIo]KI]KI\JH]KH]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI%\KH]KI\KH\KH]KI\KH]KH\JH]KI]KI]KI]KI]KH\JH]KI\JH\KI]KI]KH\JH]KI\KI]JH]JI]KI\JI]JH]KI\JH]KI]KI]KI]KI]KH]JH]KI]JH]JH]KI]KI]KH]KI]KI]KI]KI]KH]KIQ]KIM]KI]KI]KI]KI\JH]JH]KI]KI]KI]KI]KH]KI]KI]KH\JH]KI]KH]KI]KI]KI]KI]KI]KI]KI]JI\KH\JH]KI\JH\JH]KI\JH]KI\KI]KI]KI[]KI#]KI]KI]KI]KI]KH]KI\JH]KI\KI]KI\KIw]KI]KI]KI]KH]KI]KI]KI]KI]KH]KI]KI\JI]JIg]KH\JH]KI]JI]KI]KI]KH\JH]KI?]KI+\JH\JI]KI\JH]KI]KI]JH\JH]KI\JH\JH]KIm]KH \KH\JH]KI\JH]KH]KI\JH]KH]KI ]KI]JI]KI]KI\KH\JH]KI]KI\JH]KI\JH]JH]KI\KH\KI9]KI]KH]KH]KH]JI]JH]KH}]KI\JI]KI\KH]KI]KI\JH]KI]JI]JI]KI]KI\KI\JI]KI]KI]KI]KI]JH]KI1]KIA]KH]KI]KI]KI]KI]KI]KI]KI]KI\KI]JH#]KI]KI\JH\KH]KI]KI]KI]KIC]KI]KI]KI]KI]KI\JH]KI\KI]JH]KIY]JI]KI\JI\KHi\JIE\KI\JH]KI]KI\JH]KI]JH]KH3\KI]JI]KI]KH]KI]KIE\KI]KI]KI\JH]KI]KI]KI-\KI]KH\JIE]KI]KI\JI]KI]KI?]KIC]KH]KI\JH]KI]JI=]KI]KI7(@ B\KIQ]JH]KIo]KI ]KI]KI]KI]KI]KI-]KI ]JH]KI]KI]KI]KI-]KIG]KI]KI]KI\KI]KI]KI]KI]KI]KI]KI]KIo]KH]KIm]KI]KI]KI]KI]KI']KI+\JI]KI]KI]KI]KI]KI]KI]JI]KI]KI\KI]KIY]JHC]KI]KI]KI]KI]KI]KI+]KI]KI]KI]KI]KI]KI]KI]JI]KI\KIg]KI]KI]KI]KI]KI]KIK\KI1]KI]KI]KI]KI]KI]KI]KI]KI ]KIE]KI3]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KIo]KI]KI]JII]KIC]KI]KI]KI]KI]KI]KI\KIA\KI5]KI]KI]KI\KI]KI!]KI]KI]KI]KI]KI]KI]KI]KI]KI\KI]KI]KI]KI]KI\KIu]KIy]KI]KI]KI]KI]KI]KI]KI{]KI]KIU]KH]KI]KI]KI]KI]KI\KI1\JH%]KI]KI]KI]KI]KI]KI]KI\KI%]KI]KI\JI]KI]KI]KI]KI]KI]KI]KI]KH ]KI]KI]KI]KI]KI]KI]KI\JH]KI ]KI}]KI]KI]KI]KI]KI]KI]KI]KI]KIU]JHW]KI]KI]KI]KI]KI]KI]KI]KIe]KI1]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI\KH]KI]KI]KI]KI]KI]KI]KI]KI\JH]KI)]JH ]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI\JI]KI\KH]KI]KI]KI]KI]KI]KI]KI]KI]KI\JIS]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI\KI]KI-]KI1]KI]KI]KI]KI]KI]KI]KI]KI]KIM]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI ]KI]KI]KI]KI]KI]KI]KI]KI]KH]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KH]KIa]KI]KI_]KI]KI]KI]KI]KI]KI]KI]KI\KH]KI]KI#]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KII]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]JI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]]JI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI\KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KH1]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]JI]KI]JI9]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KIk\JH ]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI_]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI%]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KH]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI[]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KH]KI}]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]JI]JI']KIG]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI ]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI\KHI]KI)]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KIE]KIa]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KIm]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI ]KI-]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI\KI]JHM]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI\KI]KI ]KII]KI]KI]KI]KI]KI]KI]KI]KI]KI]KHC]KI)]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]JI]KIg]KI ]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI ]KI-]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI#]KI]KI]KI]KI]KI]KI]KI]KHu]KIk]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]JIm]KIc]KI]KI]KI]KI]KI]KI]KI!]KI \KIk]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI]KI%]KI]KI]KI]KI]KI]KI]KI]KI ]KI]KIo\KI]KI]KI]KI]KI]KI]KI]KI]KI]KH]KI]KI]KI/]JI]KI]KI\JH]KHa]KH ]KIk]KI]KI]KI]KI]KI]KI]KI]KI]KH]KI5]KI]KI]KI]KI]KI]KI\JH]KIo]KI]KI]KI]KI]KI]KI]KI]KH]JH%]KI]KI]KI\JH]KIk\KI]KI]KI]KI]KI]KI]KI;]KI]KI]KI ]KH ]KIo]KI]KI]KI]KI]KI\KH]KI\KIk]KI]KI]KI]KIG]KI ]KIc\KI]KI\JI src/index.html000066400000000000000000000010311516106664700136510ustar00rootroot00000000000000 P3X Angular HTTP Cache Interceptor src/main.ts000066400000000000000000000023241516106664700131560ustar00rootroot00000000000000import { enableProdMode, importProvidersFrom } from '@angular/core'; import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; import { environment } from './environments/environment'; import { AppComponent } from './app/app.component'; import { MatCardModule } from '@angular/material/card'; import { MatTabsModule } from '@angular/material/tabs'; import { MatToolbarModule } from '@angular/material/toolbar'; import { MatDividerModule } from '@angular/material/divider'; import { MatButtonModule } from '@angular/material/button'; import { provideAnimations } from '@angular/platform-browser/animations'; import { BrowserModule, bootstrapApplication } from '@angular/platform-browser'; import { AppRoutingModule } from './app/app-routing.module'; window['corifeus'] = { core: { http: { status: 200, counter: 0, } } } if (environment.production) { enableProdMode(); } bootstrapApplication(AppComponent, { providers: [ importProvidersFrom(AppRoutingModule, BrowserModule, //MatProgressSpinnerModule, MatButtonModule, MatDividerModule, MatToolbarModule, MatTabsModule, MatCardModule), provideAnimations() ] }) .catch(err => console.error(err)); src/polyfills.ts000066400000000000000000000044441516106664700142540ustar00rootroot00000000000000/** * This file includes polyfills needed by Angular and is loaded before the app. * You can add your own extra polyfills to this file. * * This file is divided into 2 sections: * 1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers. * 2. Application imports. Files imported after ZoneJS that should be loaded before your main * file. * * The current setup is for so-called "evergreen" browsers; the last versions of browsers that * automatically update themselves. This includes Safari >= 10, Chrome >= 55 (including Opera), * Edge >= 13 on the desktop, and iOS 10 and Chrome on mobile. * * Learn more in https://angular.io/guide/browser-support */ /*************************************************************************************************** * BROWSER POLYFILLS */ /** * By default, zone.js will patch all possible macroTask and DomEvents * user can disable parts of macroTask/DomEvents patch by setting following flags * because those flags need to be set before `zone.js` being loaded, and webpack * will put import in the top of bundle, so user need to create a separate file * in this directory (for example: zone-flags.ts), and put the following flags * into that file, and then add the following code before importing zone.js. * import './zone-flags'; * * The flags allowed in zone-flags.ts are listed here. * * The following flags will work for all browsers. * * (window as any).__Zone_disable_requestAnimationFrame = true; // disable patch requestAnimationFrame * (window as any).__Zone_disable_on_property = true; // disable patch onProperty such as onclick * (window as any).__zone_symbol__UNPATCHED_EVENTS = ['scroll', 'mousemove']; // disable patch specified eventNames * * in IE/Edge developer tools, the addEventListener will also be wrapped by zone.js * with the following flag, it will bypass `zone.js` patch for IE/Edge * * (window as any).__Zone_enable_cross_context_check = true; * */ /*************************************************************************************************** * Zone JS is required by default for Angular itself. */ import 'zone.js'; // Included with Angular CLI. /*************************************************************************************************** * APPLICATION IMPORTS */ src/styles.scss000066400000000000000000000132701516106664700141040ustar00rootroot00000000000000@use '@angular/material' as mat; @import './node_modules/highlight.js/scss/idea'; // Custom Theming for Angular Material // For more information: https://material.angular.io/guide/theming // Plus imports for other components in your app. // Include the common styles for Angular Material. We include this here so that you only // have to load a single css file for Angular Material in your app. // Be sure that you only ever include this mixin once! // TODO(v15): As of v15 mat.legacy-core no longer includes default typography styles. // The following line adds: // 1. Default typography styles for all components // 2. Styles for typography hierarchy classes (e.g. .mat-headline-1) // If you specify typography styles for the components you use elsewhere, you should delete this line. // If you don't need the default component typographies but still want the hierarchy styles, // you can delete this line and instead use: // `@include mat.legacy-typography-hierarchy(mat.define-typography-config());` @include mat.all-component-typographies(); @include mat.core(); // The following mixins include base theme styles that are only needed once per application. These // theme styles do not depend on the color, typography, or density settings in your theme. However, // these styles may differ depending on the theme's design system. Currently all themes use the // Material 2 design system, but in the future it may be possible to create theme based on other // design systems, such as Material 3. // // Please note: you do not need to include the 'base' mixins, if you include the corresponding // 'theme' mixin elsewhere in your Sass. The full 'theme' mixins already include the base styles. // // To learn more about "base" theme styles visit our theming guide: // https://material.angular.io/guide/theming#theming-dimensions // // TODO(v17): Please move these @include statements to the preferred place in your Sass, and pass // your theme to them. This will ensure the correct values for your app are included. //@include mat.all-component-bases(/* TODO(v17): pass $your-theme here */); // Define the palettes for your theme using the Material Design palettes available in palette.scss // (imported above). For each palette, you can optionally specify a default, lighter, and darker // hue. Available color palettes: https://material.io/design/color/ $workspace-primary: mat.define-palette(mat.$green-palette); $workspace-accent: mat.define-palette(mat.$purple-palette, A200, A100, A400); // The warn palette is optional (defaults to red). $workspace-warn: mat.define-palette(mat.$red-palette); // Create the theme object (a Sass map containing all of the palettes). $workspace-theme: mat.define-light-theme( ( color: ( primary: $workspace-primary, accent: $workspace-accent, warn: $workspace-warn ), typography: mat.define-typography-config(), density: 0, ) ); // Include theme styles for core and each component used in your app. // Alternatively, you can import and @include the theme mixins for each component // that you are using. //@include mat.all-component-themes($workspace-theme); @include mat.core-theme($workspace-theme); @include mat.divider-theme($workspace-theme); //@include mat.progress-spinner-theme($workspace-theme); @include mat.toolbar-theme(mat.define-light-theme( ( color: ( primary: mat.define-palette(mat.$blue-gray-palette, 600), accent: mat.define-palette(mat.$deep-orange-palette), warn: mat.define-palette(mat.$green-palette) ), typography: mat.define-typography-config(), density: 0, ) )); @include mat.snack-bar-theme(mat.define-light-theme( ( color: ( primary: mat.define-palette(mat.$blue-grey-palette), accent: mat.define-palette(mat.$blue-grey-palette), warn: mat.define-palette(mat.$green-palette) ), typography: mat.define-typography-config(), density: 0, ) )); @include mat.button-theme(mat.define-light-theme( ( color: ( primary: mat.define-palette(mat.$blue-palette, 800), accent: mat.define-palette(mat.$orange-palette, 900), warn: mat.define-palette(mat.$green-palette) ), typography: mat.define-typography-config(), density: 0, ) )); @include mat.fab-theme( mat.define-light-theme( ( color: ( primary: mat.define-palette(mat.$blue-palette, 800), accent: mat.define-palette(mat.$orange-palette, 900), warn: mat.define-palette(mat.$green-palette) ), typography: mat.define-typography-config(), density: 0, ) )); @include mat.icon-button-theme( mat.define-light-theme( ( color: ( primary: mat.define-palette(mat.$blue-palette, 800), accent: mat.define-palette(mat.$orange-palette, 900), warn: mat.define-palette(mat.$green-palette) ), typography: mat.define-typography-config(), density: 0, ) )); @include mat.card-theme($workspace-theme); @include mat.tabs-theme(mat.define-light-theme( ( color: ( primary: mat.define-palette(mat.$blue-grey-palette, 100), accent: mat.define-palette(mat.$blue-grey-palette, 900), warn: mat.define-palette(mat.$green-palette) ), typography: mat.define-typography-config(), density: 0, ) )); /* You can add global styles to this file, and also import other style files */ html, body { height: 100%; } body { margin: 0px; overflow-x: hidden; font-family: Roboto, "Helvetica Neue", sans-serif; background-color: mat.get-color-from-palette(mat.$gray-palette, 200); } .p3x-ng-http-pre { overflow: auto; } src/test.ts000066400000000000000000000007711516106664700132150ustar00rootroot00000000000000// This file is required by karma.conf.js and loads recursively all the .spec and framework files import 'zone.js/testing'; import { getTestBed } from '@angular/core/testing'; import { BrowserDynamicTestingModule, platformBrowserDynamicTesting } from '@angular/platform-browser-dynamic/testing'; // First, initialize the Angular testing environment. getTestBed().initTestEnvironment( BrowserDynamicTestingModule, platformBrowserDynamicTesting(), { teardown: { destroyAfterEach: false } } ); tsconfig.app.json000066400000000000000000000003221516106664700143550ustar00rootroot00000000000000{ "extends": "./tsconfig.json", "compilerOptions": { "outDir": "./out-tsc/app", "types": [] }, "files": [ "src/main.ts", "src/polyfills.ts" ], "include": [ "src/**/*.d.ts" ] } tsconfig.json000066400000000000000000000014341516106664700136030ustar00rootroot00000000000000{ "compileOnSave": false, "compilerOptions": { "allowSyntheticDefaultImports": true, "resolveJsonModule": true, "baseUrl": "./", "outDir": "./dist/out-tsc", "sourceMap": true, "declaration": false, "downlevelIteration": true, "experimentalDecorators": true, "module": "es2022", "moduleResolution": "node", "importHelpers": true, "target": "ES2022", "lib": [ "es2022", "dom" ], "paths": { "angular-http-cache-interceptor": [ "dist/angular-http-cache-interceptor/angular-http-cache-interceptor", "dist/angular-http-cache-interceptor" ] }, "useDefineForClassFields": false }, "angularCompilerOptions": { "fullTemplateTypeCheck": true, "strictInjectionParameters": true } } tsconfig.spec.json000066400000000000000000000004161516106664700145330ustar00rootroot00000000000000{ "extends": "./tsconfig.json", "compilerOptions": { "outDir": "./out-tsc/spec", "types": [ "jasmine", "node" ] }, "files": [ "src/test.ts", "src/polyfills.ts" ], "include": [ "src/**/*.spec.ts", "src/**/*.d.ts" ] }