Compare commits
7 Commits
f00c1d1aef
...
fe10ed2850
Author | SHA1 | Date | |
---|---|---|---|
fe10ed2850 | |||
c8c4fc847d | |||
25a27e1998 | |||
57ae2191ae | |||
9eb1239842 | |||
13886502b6 | |||
58d7b3c89e |
Binary file not shown.
Before Width: | Height: | Size: 134 KiB |
Binary file not shown.
Before Width: | Height: | Size: 2.5 MiB |
@ -1,265 +0,0 @@
|
||||
name: Build, Lint & Test Lib
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
pull_request:
|
||||
types: [opened, synchronize, reopened, closed]
|
||||
branches:
|
||||
- main
|
||||
|
||||
jobs:
|
||||
build_job:
|
||||
if: github.event_name == 'push' || (github.event_name == 'pull_request' && github.event.action != 'closed')
|
||||
runs-on: ubuntu-latest
|
||||
name: Built, Lint and Test Library
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: true
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: 20
|
||||
|
||||
- name: Installing Dependencies
|
||||
run: npm ci
|
||||
|
||||
- name: Linting Library
|
||||
run: npm run lint-lib
|
||||
|
||||
- name: Testing Frontend
|
||||
run: npm run test-lib-ci
|
||||
|
||||
- name: Coveralls
|
||||
uses: coverallsapp/github-action@master
|
||||
with:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
path-to-lcov: './coverage/oidc-client-rx/lcov.info'
|
||||
|
||||
- name: Coveralls Finished
|
||||
uses: coverallsapp/github-action@master
|
||||
with:
|
||||
github-token: ${{ secrets.github_token }}
|
||||
parallel-finished: true
|
||||
|
||||
- name: Building Frontend
|
||||
run: npm run build-lib-prod
|
||||
|
||||
- name: Copying essential additional files
|
||||
run: npm run copy-files
|
||||
|
||||
- name: Show files
|
||||
run: ls
|
||||
|
||||
- name: Upload Artefact
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: angular_auth_oidc_client_artefact
|
||||
path: dist/oidc-client-rx
|
||||
|
||||
AngularLatestVersion:
|
||||
needs: build_job
|
||||
runs-on: ubuntu-latest
|
||||
name: Angular latest
|
||||
steps:
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: 20
|
||||
|
||||
- name: Download Artefact
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: angular_auth_oidc_client_artefact
|
||||
path: oidc-client-rx-artefact
|
||||
|
||||
- name: Install AngularCLI globally
|
||||
run: sudo npm install -g @angular/cli
|
||||
|
||||
- name: Show ng Version
|
||||
run: ng version
|
||||
|
||||
- name: Create Angular Project
|
||||
run: sudo ng new oidc-client-rx-test --skip-git
|
||||
|
||||
- name: Npm Install & Install Library from local artefact
|
||||
run: |
|
||||
sudo cp -R oidc-client-rx-artefact oidc-client-rx-test/
|
||||
cd oidc-client-rx-test
|
||||
sudo npm install --unsafe-perm=true
|
||||
sudo ng add ./oidc-client-rx-artefact --authority-url-or-tenant-id "my-authority-url" --flow-type "OIDC Code Flow PKCE using refresh tokens" --use-local-package=true --skip-confirmation
|
||||
|
||||
- name: Test Angular Application
|
||||
working-directory: ./oidc-client-rx-test
|
||||
run: npm test -- --watch=false --browsers=ChromeHeadless
|
||||
|
||||
- name: Build Angular Application
|
||||
working-directory: ./oidc-client-rx-test
|
||||
run: sudo npm run build
|
||||
|
||||
AngularLatestVersionWithSchematics:
|
||||
needs: build_job
|
||||
runs-on: ubuntu-latest
|
||||
name: Angular latest & Schematics Job
|
||||
steps:
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: 20
|
||||
|
||||
- name: Download Artefact
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: angular_auth_oidc_client_artefact
|
||||
path: oidc-client-rx-artefact
|
||||
|
||||
- name: Install AngularCLI globally
|
||||
run: sudo npm install -g @angular/cli
|
||||
|
||||
- name: Show ng Version
|
||||
run: ng version
|
||||
|
||||
- name: Create Angular Project
|
||||
run: sudo ng new oidc-client-rx-test --skip-git
|
||||
|
||||
- name: Npm Install & Install Library from local artefact
|
||||
run: |
|
||||
sudo cp -R oidc-client-rx-artefact oidc-client-rx-test/
|
||||
cd oidc-client-rx-test
|
||||
sudo npm install --unsafe-perm=true
|
||||
sudo ng add ./oidc-client-rx-artefact --authority-url-or-tenant-id "my-authority-url" --flow-type "Default config" --use-local-package=true --skip-confirmation
|
||||
|
||||
- name: Test Angular Application
|
||||
working-directory: ./oidc-client-rx-test
|
||||
run: npm test -- --watch=false --browsers=ChromeHeadless
|
||||
|
||||
- name: Build Angular Application
|
||||
working-directory: ./oidc-client-rx-test
|
||||
run: sudo npm run build
|
||||
|
||||
AngularLatestVersionWithNgModuleSchematics:
|
||||
needs: build_job
|
||||
runs-on: ubuntu-latest
|
||||
name: Angular latest Standalone & Schematics Job
|
||||
steps:
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: 20
|
||||
|
||||
- name: Download Artefact
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: angular_auth_oidc_client_artefact
|
||||
path: oidc-client-rx-artefact
|
||||
|
||||
- name: Install AngularCLI globally
|
||||
run: sudo npm install -g @angular/cli
|
||||
|
||||
- name: Show ng Version
|
||||
run: ng version
|
||||
|
||||
- name: Create Angular Project
|
||||
run: sudo ng new oidc-client-rx-test --skip-git --standalone=false
|
||||
|
||||
- name: Npm Install & Install Library from local artefact
|
||||
run: |
|
||||
sudo cp -R oidc-client-rx-artefact oidc-client-rx-test/
|
||||
cd oidc-client-rx-test
|
||||
sudo npm install --unsafe-perm=true
|
||||
sudo ng add ./oidc-client-rx-artefact --authority-url-or-tenant-id "my-authority-url" --flow-type "OIDC Code Flow PKCE using refresh tokens" --use-local-package=true --skip-confirmation
|
||||
|
||||
- name: Test Angular Application
|
||||
working-directory: ./oidc-client-rx-test
|
||||
run: npm test -- --watch=false --browsers=ChromeHeadless
|
||||
|
||||
- name: Build Angular Application
|
||||
working-directory: ./oidc-client-rx-test
|
||||
run: sudo npm run build
|
||||
|
||||
Angular16VersionWithRxJs6:
|
||||
needs: build_job
|
||||
runs-on: ubuntu-latest
|
||||
name: Angular 16 & RxJs 6
|
||||
steps:
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: 20
|
||||
|
||||
- name: Download Artefact
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: angular_auth_oidc_client_artefact
|
||||
path: oidc-client-rx-artefact
|
||||
|
||||
- name: Install AngularCLI globally
|
||||
run: sudo npm install -g @angular/cli@16
|
||||
|
||||
- name: Show ng Version
|
||||
run: ng version
|
||||
|
||||
- name: Create Angular Project
|
||||
run: sudo ng new oidc-client-rx-test --skip-git
|
||||
|
||||
- name: npm install RxJs 6
|
||||
working-directory: ./oidc-client-rx-test
|
||||
run: sudo npm install rxjs@6.5.3
|
||||
|
||||
- name: Npm Install & Install Library from local artefact
|
||||
run: |
|
||||
sudo cp -R oidc-client-rx-artefact oidc-client-rx-test/
|
||||
cd oidc-client-rx-test
|
||||
sudo npm install --unsafe-perm=true
|
||||
sudo ng add ./oidc-client-rx-artefact --authority-url-or-tenant-id "my-authority-url" --flow-type "OIDC Code Flow PKCE using refresh tokens" --use-local-package=true --skip-confirmation
|
||||
|
||||
- name: Test Angular Application
|
||||
working-directory: ./oidc-client-rx-test
|
||||
run: npm test -- --watch=false --browsers=ChromeHeadless
|
||||
|
||||
- name: Build Angular Application
|
||||
working-directory: ./oidc-client-rx-test
|
||||
run: sudo npm run build
|
||||
|
||||
LibWithAngularV16:
|
||||
needs: build_job
|
||||
runs-on: ubuntu-latest
|
||||
name: Angular V16
|
||||
steps:
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: 18
|
||||
|
||||
- name: Download Artefact
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: angular_auth_oidc_client_artefact
|
||||
path: oidc-client-rx-artefact
|
||||
|
||||
- name: Install AngularCLI globally
|
||||
run: sudo npm install -g @angular/cli@16
|
||||
|
||||
- name: Show ng Version
|
||||
run: ng version
|
||||
|
||||
- name: Create Angular Project
|
||||
run: sudo ng new oidc-client-rx-test --skip-git
|
||||
|
||||
- name: Npm Install & Install Library from local artefact
|
||||
run: |
|
||||
sudo cp -R oidc-client-rx-artefact oidc-client-rx-test/
|
||||
cd oidc-client-rx-test
|
||||
sudo npm install --unsafe-perm=true
|
||||
sudo ng add ./oidc-client-rx-artefact --authority-url-or-tenant-id "my-authority-url" --flow-type "OIDC Code Flow PKCE using refresh tokens" --use-local-package=true --skip-confirmation
|
||||
|
||||
- name: Test Angular Application
|
||||
working-directory: ./oidc-client-rx-test
|
||||
run: npm test -- --watch=false --browsers=ChromeHeadless
|
||||
|
||||
- name: Build Angular Application
|
||||
working-directory: ./oidc-client-rx-test
|
||||
run: sudo npm run build
|
@ -1,61 +0,0 @@
|
||||
name: Docs
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
pull_request:
|
||||
types: [opened, synchronize, reopened, closed]
|
||||
branches:
|
||||
- main
|
||||
|
||||
jobs:
|
||||
build_and_deploy_job:
|
||||
if: github.event_name == 'push' || (github.event_name == 'pull_request' && github.event.action != 'closed')
|
||||
runs-on: ubuntu-latest
|
||||
name: Build and Deploy Docs Job
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: true
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: 18
|
||||
|
||||
- name: Installing Dependencies
|
||||
run: sudo npm install
|
||||
|
||||
- name: Installing Dependencies for docs - in docs folder
|
||||
run: sudo npm install
|
||||
working-directory: docs/site/oidc-client-rx
|
||||
|
||||
- name: Building Documentation
|
||||
run: sudo npm run build
|
||||
working-directory: docs/site/oidc-client-rx
|
||||
|
||||
- name: Build And Deploy
|
||||
if: ${{ github.actor == 'damienbod' || github.actor == 'FabianGosebrink' }}
|
||||
id: builddeploy
|
||||
uses: Azure/static-web-apps-deploy@v1
|
||||
with:
|
||||
azure_static_web_apps_api_token: ${{ secrets.AZURE_STATIC_WEB_APPS_API_TOKEN }}
|
||||
repo_token: ${{ secrets.GITHUB_TOKEN }} # Used for Github integrations (i.e. PR comments)
|
||||
action: 'upload'
|
||||
###### Repository/Build Configurations - These values can be configured to match you app requirements. ######
|
||||
app_location: '/docs/site/oidc-client-rx' # App source code path
|
||||
app_artifact_location: 'build' # Built app content directory - optional
|
||||
###### End of Repository/Build Configurations ######
|
||||
|
||||
close_pull_request_job:
|
||||
if: github.event_name == 'pull_request' && github.event.action == 'closed'
|
||||
runs-on: ubuntu-latest
|
||||
name: Close Pull Request Job
|
||||
steps:
|
||||
- name: Close Pull Request
|
||||
id: closepullrequest
|
||||
uses: Azure/static-web-apps-deploy@v1
|
||||
with:
|
||||
azure_static_web_apps_api_token: ${{ secrets.AZURE_STATIC_WEB_APPS_API_TOKEN }}
|
||||
action: 'close'
|
@ -1,27 +0,0 @@
|
||||
name: Playwright Tests
|
||||
on:
|
||||
push:
|
||||
branches: [ main, master ]
|
||||
pull_request:
|
||||
branches: [ main, master ]
|
||||
jobs:
|
||||
test:
|
||||
timeout-minutes: 60
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: lts/*
|
||||
- name: Install dependencies
|
||||
run: npm install -g pnpm && pnpm install
|
||||
- name: Install Playwright Browsers
|
||||
run: pnpm exec playwright install --with-deps
|
||||
- name: Run Playwright tests
|
||||
run: pnpm exec playwright test
|
||||
- uses: actions/upload-artifact@v4
|
||||
if: ${{ !cancelled() }}
|
||||
with:
|
||||
name: playwright-report
|
||||
path: playwright-report/
|
||||
retention-days: 30
|
58
.github/workflows/build.yml
vendored
Normal file
58
.github/workflows/build.yml
vendored
Normal file
@ -0,0 +1,58 @@
|
||||
name: Build, Lint & Test Lib
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
pull_request:
|
||||
types: [opened, synchronize, reopened, closed]
|
||||
branches:
|
||||
- main
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
build_job:
|
||||
if: github.event_name == 'push' || github.event_name == 'workflow_dispatch' || (github.event_name == 'pull_request' && github.event.action != 'closed')
|
||||
runs-on: ubuntu-latest
|
||||
name: Build, Lint and Test Library
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Node and Install Dependencies
|
||||
uses: pnpm/action-setup@v4
|
||||
with:
|
||||
version: 10
|
||||
run_install: false
|
||||
|
||||
- name: Install Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 22
|
||||
cache: 'pnpm'
|
||||
|
||||
- name: Install dependencies
|
||||
run: pnpm install --frozen-lockfile
|
||||
|
||||
|
||||
- name: Linting Library
|
||||
run: npm run lint
|
||||
|
||||
- name: Testing Frontend
|
||||
run: npm run test-ci
|
||||
|
||||
- name: 'Report Coverage'
|
||||
if: (github.event_name == 'pull_request' && github.event.action != 'closed')
|
||||
uses: davelosert/vitest-coverage-report-action@v2
|
||||
|
||||
- name: Building Frontend
|
||||
run: npm run build
|
||||
|
||||
- name: Show files
|
||||
run: ls
|
||||
|
||||
- name: Upload Artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: oidc_client_rx_artifact
|
||||
path: dist
|
4
.gitignore
vendored
4
.gitignore
vendored
@ -2,6 +2,7 @@
|
||||
|
||||
# compiled output
|
||||
/dist
|
||||
**/dist
|
||||
/tmp
|
||||
/out-tsc
|
||||
# Only exists if Bazel was run
|
||||
@ -45,7 +46,6 @@ testem.log
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
|
||||
/.angulardoc.json
|
||||
debug.log
|
||||
|
||||
/.husky
|
||||
@ -55,3 +55,5 @@ debug.log
|
||||
/blob-report/
|
||||
/playwright/.cache/
|
||||
/.vitest
|
||||
/.rslib
|
||||
**/*.tsbuildinfo
|
||||
|
51
README.md
51
README.md
@ -2,6 +2,7 @@
|
||||
<img src="./assets/logo-512.png" height="150" alt="OUTPOSTS">
|
||||
<div style="color: #232848; font-weight: 700;">OIDC-CLIENT-RX</div>
|
||||
<div align="center">
|
||||
<img src="https://img.shields.io/github/actions/workflow/status/lonelyhentxi/oidc-client-rx/build.yml?branch=main" alt="build-status" />
|
||||
<img src="https://img.shields.io/badge/status-work--in--progress-blue" alt="status-badge" />
|
||||
</div>
|
||||
</h1>
|
||||
@ -10,7 +11,55 @@
|
||||
|
||||
## Quick Start
|
||||
|
||||
@TODO Coming Soon
|
||||
@TODO Add More Details
|
||||
|
||||
### Install
|
||||
|
||||
```sh
|
||||
pnpm add oidc-client-rx @outposts/injection-js @abraham/reflection
|
||||
# npm install oidc-client-rx @outposts/injection-js @abraham/reflection
|
||||
# yarn add oidc-client-rx @outposts/injection-js @abraham/reflection
|
||||
```
|
||||
|
||||
### Basic Usage
|
||||
|
||||
```typescript
|
||||
import '@abraham/reflection'; // or 'reflect-metadata' | 'core-js/es7/reflect'
|
||||
import { type Injector, ReflectiveInjector } from '@outposts/injection-js';
|
||||
import { LogLevel, OidcSecurityService, provideAuth, withDefaultFeatures } from 'oidc-client-rx';
|
||||
|
||||
const injector = ReflectiveInjector.resolveAndCreate(
|
||||
provideAuth(
|
||||
{
|
||||
config: {
|
||||
authority: '<your-authority>',
|
||||
redirectUrl: `${window.location.origin}/auth/callback`,
|
||||
postLogoutRedirectUri: window.location.origin,
|
||||
clientId: '<your-client-id>',
|
||||
scope: 'openid profile email offline_access',
|
||||
responseType: 'code',
|
||||
silentRenew: true,
|
||||
useRefreshToken: true,
|
||||
logLevel: LogLevel.Debug,
|
||||
...
|
||||
},
|
||||
},
|
||||
withDefaultFeatures()
|
||||
)
|
||||
) as Injector;
|
||||
|
||||
const oidcSecurityService = injector.get(OidcSecurityService);
|
||||
|
||||
oidcSecurityService.checkAuth().subscribe((result) => {
|
||||
console.debug('checkAuth result: ', result);
|
||||
});
|
||||
|
||||
const isAuthenticated$ = oidcSecurityService.isAuthenticated$;
|
||||
```
|
||||
|
||||
### More Examples
|
||||
|
||||
- [React + TanStack Router](https://github.com/lonelyhentxi/oidc-client-rx/tree/main/examples/react-tanstack-router)
|
||||
|
||||
## License
|
||||
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 47 KiB After Width: | Height: | Size: 54 KiB |
@ -6,7 +6,7 @@
|
||||
"style": {
|
||||
"noNonNullAssertion": "off",
|
||||
"noParameterAssign": "off",
|
||||
"useFilenamingConvention": "warn",
|
||||
"useFilenamingConvention": "off",
|
||||
"noParameterProperties": "off"
|
||||
},
|
||||
"suspicious": {
|
||||
|
13
examples/react-tanstack-router/.gitignore
vendored
Normal file
13
examples/react-tanstack-router/.gitignore
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
# Local
|
||||
.DS_Store
|
||||
*.local
|
||||
*.log*
|
||||
|
||||
# Dist
|
||||
node_modules
|
||||
dist/
|
||||
|
||||
# IDE
|
||||
.vscode/*
|
||||
!.vscode/extensions.json
|
||||
.idea
|
29
examples/react-tanstack-router/README.md
Normal file
29
examples/react-tanstack-router/README.md
Normal file
@ -0,0 +1,29 @@
|
||||
# Rsbuild project
|
||||
|
||||
## Setup
|
||||
|
||||
Install the dependencies:
|
||||
|
||||
```bash
|
||||
pnpm install
|
||||
```
|
||||
|
||||
## Get started
|
||||
|
||||
Start the dev server:
|
||||
|
||||
```bash
|
||||
pnpm dev
|
||||
```
|
||||
|
||||
Build the app for production:
|
||||
|
||||
```bash
|
||||
pnpm build
|
||||
```
|
||||
|
||||
Preview the production build locally:
|
||||
|
||||
```bash
|
||||
pnpm preview
|
||||
```
|
31
examples/react-tanstack-router/package.json
Normal file
31
examples/react-tanstack-router/package.json
Normal file
@ -0,0 +1,31 @@
|
||||
{
|
||||
"name": "react-tanstack-router",
|
||||
"private": true,
|
||||
"version": "1.0.0",
|
||||
"scripts": {
|
||||
"dev": "rsbuild dev",
|
||||
"build": "rsbuild build",
|
||||
"preview": "rsbuild preview"
|
||||
},
|
||||
"dependencies": {
|
||||
"@abraham/reflection": "^0.12.0",
|
||||
"@outposts/injection-js": "^2.5.1",
|
||||
"@tanstack/react-router": "^1.99.6",
|
||||
"@tanstack/router-devtools": "^1.99.6",
|
||||
"autoprefixer": "^10.4.20",
|
||||
"observable-hooks": "^4.2.4",
|
||||
"oidc-client-rx": "workspace:*",
|
||||
"react": "^19.0.0",
|
||||
"react-dom": "^19.0.0",
|
||||
"tailwindcss": "^3.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@rsbuild/core": "^1.2.3",
|
||||
"@rsbuild/plugin-react": "^1.1.0",
|
||||
"@tanstack/router-plugin": "^1.99.6",
|
||||
"@types/react": "^19.0.8",
|
||||
"@types/react-dom": "^19.0.3",
|
||||
"postcss": "^8.5.1",
|
||||
"typescript": "^5.7.3"
|
||||
}
|
||||
}
|
6
examples/react-tanstack-router/postcss.config.mjs
Normal file
6
examples/react-tanstack-router/postcss.config.mjs
Normal file
@ -0,0 +1,6 @@
|
||||
export default {
|
||||
plugins: {
|
||||
tailwindcss: {},
|
||||
autoprefixer: {},
|
||||
},
|
||||
};
|
0
examples/react-tanstack-router/public/.gitkeep
Normal file
0
examples/react-tanstack-router/public/.gitkeep
Normal file
12
examples/react-tanstack-router/rsbuild.config.ts
Normal file
12
examples/react-tanstack-router/rsbuild.config.ts
Normal file
@ -0,0 +1,12 @@
|
||||
import { defineConfig } from '@rsbuild/core';
|
||||
import { pluginReact } from '@rsbuild/plugin-react';
|
||||
import { TanStackRouterRspack } from '@tanstack/router-plugin/rspack';
|
||||
|
||||
export default defineConfig({
|
||||
plugins: [pluginReact()],
|
||||
tools: {
|
||||
rspack: {
|
||||
plugins: [TanStackRouterRspack()],
|
||||
},
|
||||
},
|
||||
});
|
1
examples/react-tanstack-router/src/env.d.ts
vendored
Normal file
1
examples/react-tanstack-router/src/env.d.ts
vendored
Normal file
@ -0,0 +1 @@
|
||||
/// <reference types="@rsbuild/core/types" />
|
87
examples/react-tanstack-router/src/index.tsx
Normal file
87
examples/react-tanstack-router/src/index.tsx
Normal file
@ -0,0 +1,87 @@
|
||||
import '@abraham/reflection'; // or 'reflect-metadata' | 'core-js/es7/reflect'
|
||||
import { type Injector, ReflectiveInjector } from '@outposts/injection-js';
|
||||
import { RouterProvider, createRouter } from '@tanstack/react-router';
|
||||
import {
|
||||
LogLevel,
|
||||
OidcSecurityService,
|
||||
provideAuth,
|
||||
withDefaultFeatures,
|
||||
} from 'oidc-client-rx';
|
||||
import {
|
||||
InjectorContextVoidInjector,
|
||||
InjectorProvider,
|
||||
} from 'oidc-client-rx/adapters/react';
|
||||
import { withTanstackRouter } from 'oidc-client-rx/adapters/tanstack-router';
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom/client';
|
||||
import { routeTree } from './routeTree.gen';
|
||||
|
||||
import './style.css';
|
||||
|
||||
// Set up a Router instance
|
||||
const router = createRouter({
|
||||
routeTree,
|
||||
defaultPreload: 'intent',
|
||||
scrollRestoration: true,
|
||||
context: {
|
||||
injector: InjectorContextVoidInjector,
|
||||
oidcSecurityService: {} as OidcSecurityService,
|
||||
},
|
||||
});
|
||||
|
||||
// Register things for typesafety
|
||||
declare module '@tanstack/react-router' {
|
||||
interface Register {
|
||||
router: typeof router;
|
||||
}
|
||||
}
|
||||
|
||||
const injector = ReflectiveInjector.resolveAndCreate(
|
||||
provideAuth(
|
||||
{
|
||||
config: {
|
||||
authority: 'https://k9bor3.logto.app/oidc',
|
||||
redirectUrl: `${window.location.origin}/auth/callback`,
|
||||
postLogoutRedirectUri: window.location.origin,
|
||||
clientId: 'zz5vo27wtvtjf36srwtbp',
|
||||
scope: 'openid offline_access',
|
||||
responseType: 'code',
|
||||
silentRenew: true,
|
||||
useRefreshToken: true,
|
||||
logLevel: LogLevel.Debug,
|
||||
autoUserInfo: true,
|
||||
renewUserInfoAfterTokenRenew: true,
|
||||
customParamsAuthRequest: {
|
||||
prompt: 'consent',
|
||||
},
|
||||
},
|
||||
},
|
||||
withDefaultFeatures(
|
||||
// the after feature will replace the before same type feature
|
||||
// so the following line can be ignored
|
||||
{ router: { enabled: false } }
|
||||
),
|
||||
withTanstackRouter(router)
|
||||
)
|
||||
) as Injector;
|
||||
|
||||
// if needed, check when init
|
||||
const oidcSecurityService = injector.get(OidcSecurityService);
|
||||
oidcSecurityService.checkAuth().subscribe();
|
||||
|
||||
const rootEl = document.getElementById('root');
|
||||
|
||||
if (rootEl) {
|
||||
const root = ReactDOM.createRoot(rootEl);
|
||||
|
||||
root.render(
|
||||
<React.StrictMode>
|
||||
<InjectorProvider injector={injector}>
|
||||
<RouterProvider
|
||||
router={router}
|
||||
context={{ injector, oidcSecurityService }}
|
||||
/>
|
||||
</InjectorProvider>
|
||||
</React.StrictMode>
|
||||
);
|
||||
}
|
111
examples/react-tanstack-router/src/routeTree.gen.ts
Normal file
111
examples/react-tanstack-router/src/routeTree.gen.ts
Normal file
@ -0,0 +1,111 @@
|
||||
/* eslint-disable */
|
||||
|
||||
// @ts-nocheck
|
||||
|
||||
// noinspection JSUnusedGlobalSymbols
|
||||
|
||||
// This file was automatically generated by TanStack Router.
|
||||
// You should NOT make any changes in this file as it will be overwritten.
|
||||
// Additionally, you should also exclude this file from your linter and/or formatter to prevent it from being checked or modified.
|
||||
|
||||
// Import Routes
|
||||
|
||||
import { Route as rootRoute } from './routes/__root';
|
||||
import { Route as AuthCallbackImport } from './routes/auth/callback';
|
||||
import { Route as IndexImport } from './routes/index';
|
||||
|
||||
// Create/Update Routes
|
||||
|
||||
const IndexRoute = IndexImport.update({
|
||||
id: '/',
|
||||
path: '/',
|
||||
getParentRoute: () => rootRoute,
|
||||
} as any);
|
||||
|
||||
const AuthCallbackRoute = AuthCallbackImport.update({
|
||||
id: '/auth/callback',
|
||||
path: '/auth/callback',
|
||||
getParentRoute: () => rootRoute,
|
||||
} as any);
|
||||
|
||||
// Populate the FileRoutesByPath interface
|
||||
|
||||
declare module '@tanstack/react-router' {
|
||||
interface FileRoutesByPath {
|
||||
'/': {
|
||||
id: '/';
|
||||
path: '/';
|
||||
fullPath: '/';
|
||||
preLoaderRoute: typeof IndexImport;
|
||||
parentRoute: typeof rootRoute;
|
||||
};
|
||||
'/auth/callback': {
|
||||
id: '/auth/callback';
|
||||
path: '/auth/callback';
|
||||
fullPath: '/auth/callback';
|
||||
preLoaderRoute: typeof AuthCallbackImport;
|
||||
parentRoute: typeof rootRoute;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// Create and export the route tree
|
||||
|
||||
export interface FileRoutesByFullPath {
|
||||
'/': typeof IndexRoute;
|
||||
'/auth/callback': typeof AuthCallbackRoute;
|
||||
}
|
||||
|
||||
export interface FileRoutesByTo {
|
||||
'/': typeof IndexRoute;
|
||||
'/auth/callback': typeof AuthCallbackRoute;
|
||||
}
|
||||
|
||||
export interface FileRoutesById {
|
||||
__root__: typeof rootRoute;
|
||||
'/': typeof IndexRoute;
|
||||
'/auth/callback': typeof AuthCallbackRoute;
|
||||
}
|
||||
|
||||
export interface FileRouteTypes {
|
||||
fileRoutesByFullPath: FileRoutesByFullPath;
|
||||
fullPaths: '/' | '/auth/callback';
|
||||
fileRoutesByTo: FileRoutesByTo;
|
||||
to: '/' | '/auth/callback';
|
||||
id: '__root__' | '/' | '/auth/callback';
|
||||
fileRoutesById: FileRoutesById;
|
||||
}
|
||||
|
||||
export interface RootRouteChildren {
|
||||
IndexRoute: typeof IndexRoute;
|
||||
AuthCallbackRoute: typeof AuthCallbackRoute;
|
||||
}
|
||||
|
||||
const rootRouteChildren: RootRouteChildren = {
|
||||
IndexRoute: IndexRoute,
|
||||
AuthCallbackRoute: AuthCallbackRoute,
|
||||
};
|
||||
|
||||
export const routeTree = rootRoute
|
||||
._addFileChildren(rootRouteChildren)
|
||||
._addFileTypes<FileRouteTypes>();
|
||||
|
||||
/* ROUTE_MANIFEST_START
|
||||
{
|
||||
"routes": {
|
||||
"__root__": {
|
||||
"filePath": "__root.tsx",
|
||||
"children": [
|
||||
"/",
|
||||
"/auth/callback"
|
||||
]
|
||||
},
|
||||
"/": {
|
||||
"filePath": "index.tsx"
|
||||
},
|
||||
"/auth/callback": {
|
||||
"filePath": "auth/callback.tsx"
|
||||
}
|
||||
}
|
||||
}
|
||||
ROUTE_MANIFEST_END */
|
38
examples/react-tanstack-router/src/routes/__root.tsx
Normal file
38
examples/react-tanstack-router/src/routes/__root.tsx
Normal file
@ -0,0 +1,38 @@
|
||||
import type { Injector } from '@outposts/injection-js';
|
||||
import {
|
||||
Link,
|
||||
Outlet,
|
||||
createRootRouteWithContext,
|
||||
} from '@tanstack/react-router';
|
||||
import { TanStackRouterDevtools } from '@tanstack/router-devtools';
|
||||
import type { OidcSecurityService } from 'oidc-client-rx';
|
||||
|
||||
export interface RouterContext {
|
||||
injector: Injector;
|
||||
oidcSecurityService: OidcSecurityService;
|
||||
}
|
||||
|
||||
export const Route = createRootRouteWithContext<RouterContext>()({
|
||||
component: RootComponent,
|
||||
});
|
||||
|
||||
function RootComponent() {
|
||||
return (
|
||||
<>
|
||||
<div className="flex gap-2 p-2 text-lg">
|
||||
<Link
|
||||
to="/"
|
||||
activeProps={{
|
||||
className: 'font-bold',
|
||||
}}
|
||||
activeOptions={{ exact: true }}
|
||||
>
|
||||
Home
|
||||
</Link>{' '}
|
||||
</div>
|
||||
<hr />
|
||||
<Outlet />
|
||||
<TanStackRouterDevtools position="bottom-right" />
|
||||
</>
|
||||
);
|
||||
}
|
13
examples/react-tanstack-router/src/routes/auth/callback.tsx
Normal file
13
examples/react-tanstack-router/src/routes/auth/callback.tsx
Normal file
@ -0,0 +1,13 @@
|
||||
import { createFileRoute } from '@tanstack/react-router';
|
||||
|
||||
export const Route = createFileRoute('/auth/callback')({
|
||||
component: AuthCallbackComponent,
|
||||
});
|
||||
|
||||
function AuthCallbackComponent() {
|
||||
return (
|
||||
<div className="p-2">
|
||||
<h3>Auth Callback: validating...</h3>
|
||||
</div>
|
||||
);
|
||||
}
|
40
examples/react-tanstack-router/src/routes/index.tsx
Normal file
40
examples/react-tanstack-router/src/routes/index.tsx
Normal file
@ -0,0 +1,40 @@
|
||||
import { createFileRoute } from '@tanstack/react-router';
|
||||
import { useObservableEagerState } from 'observable-hooks';
|
||||
import { useOidcClient } from 'oidc-client-rx/adapters/react';
|
||||
import { useCallback } from 'react';
|
||||
|
||||
export const Route = createFileRoute('/')({
|
||||
component: HomeComponent,
|
||||
});
|
||||
|
||||
function HomeComponent() {
|
||||
const { oidcSecurityService } = useOidcClient();
|
||||
|
||||
const { isAuthenticated } = useObservableEagerState(
|
||||
oidcSecurityService.isAuthenticated$
|
||||
);
|
||||
|
||||
const handleLogin = useCallback(() => {
|
||||
oidcSecurityService.authorize().subscribe();
|
||||
}, [oidcSecurityService]);
|
||||
|
||||
const handleLogout = useCallback(() => {
|
||||
oidcSecurityService.logoff().subscribe();
|
||||
}, [oidcSecurityService]);
|
||||
|
||||
return (
|
||||
<div className="p-2 text-center">
|
||||
<h1>Welcome OIDC-CLIENT-RX DEMO of react-tanstack-router</h1>
|
||||
<p>Is authenticated? {isAuthenticated ? 'True' : 'False'}</p>
|
||||
{isAuthenticated ? (
|
||||
<button onClick={handleLogout} type="button">
|
||||
Click to Logout
|
||||
</button>
|
||||
) : (
|
||||
<button onClick={handleLogin} type="button">
|
||||
Click to Login
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
13
examples/react-tanstack-router/src/style.css
Normal file
13
examples/react-tanstack-router/src/style.css
Normal file
@ -0,0 +1,13 @@
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
|
||||
html {
|
||||
color-scheme: light dark;
|
||||
}
|
||||
* {
|
||||
@apply border-gray-200 dark:border-gray-800;
|
||||
}
|
||||
body {
|
||||
@apply bg-gray-50 text-gray-950 dark:bg-gray-900 dark:text-gray-200;
|
||||
}
|
4
examples/react-tanstack-router/tailwind.config.mjs
Normal file
4
examples/react-tanstack-router/tailwind.config.mjs
Normal file
@ -0,0 +1,4 @@
|
||||
/** @type {import('tailwindcss').Config} */
|
||||
export default {
|
||||
content: ['./src/**/*.{js,jsx,ts,tsx}', './index.html'],
|
||||
};
|
18
examples/react-tanstack-router/tsconfig.json
Normal file
18
examples/react-tanstack-router/tsconfig.json
Normal file
@ -0,0 +1,18 @@
|
||||
{
|
||||
"extends": "../../tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"composite": true,
|
||||
"rootDir": ".",
|
||||
"lib": ["ES2021", "DOM", "DOM.Iterable"],
|
||||
"useDefineForClassFields": true,
|
||||
"resolveJsonModule": true,
|
||||
"emitDecoratorMetadata": true,
|
||||
"experimentalDecorators": true,
|
||||
"emitDeclarationOnly": true,
|
||||
"noEmit": true,
|
||||
"outDir": "./dist",
|
||||
"declarationDir": "./dist",
|
||||
"jsx": "preserve"
|
||||
},
|
||||
"include": ["src"]
|
||||
}
|
4
examples/react-tanstack-router/tsr.config.json
Normal file
4
examples/react-tanstack-router/tsr.config.json
Normal file
@ -0,0 +1,4 @@
|
||||
{
|
||||
"routesDirectory": "./src/routes",
|
||||
"generatedRouteTree": "./src/routeTree.gen.ts"
|
||||
}
|
41
lefthook.yml
41
lefthook.yml
@ -1,41 +0,0 @@
|
||||
# EXAMPLE USAGE
|
||||
# Refer for explanation to following link:
|
||||
# https://github.com/evilmartians/lefthook/blob/master/docs/full_guide.md
|
||||
#
|
||||
pre-push:
|
||||
commands:
|
||||
fix-prettier:
|
||||
tags: frontend security
|
||||
glob: '*.{js,ts}'
|
||||
run: npm run fix-prettier {staged_files}
|
||||
|
||||
pre-commit:
|
||||
parallel: true
|
||||
commands:
|
||||
check-blockwords:
|
||||
run: npm run check-blockwords
|
||||
|
||||
lint:
|
||||
run: npm run lint-lib
|
||||
#
|
||||
# pre-commit:
|
||||
# parallel: true
|
||||
# commands:
|
||||
# eslint:
|
||||
# glob: "*.{js,ts}"
|
||||
# run: yarn eslint {staged_files}
|
||||
# rubocop:
|
||||
# tags: backend style
|
||||
# glob: "*.rb"
|
||||
# exclude: "application.rb|routes.rb"
|
||||
# run: bundle exec rubocop --force-exclusion {all_files}
|
||||
# govet:
|
||||
# tags: backend style
|
||||
# files: git ls-files -m
|
||||
# glob: "*.go"
|
||||
# run: go vet {files}
|
||||
# scripts:
|
||||
# "hello.js":
|
||||
# runner: node
|
||||
# "any.go":
|
||||
# runner: go run
|
@ -1,4 +0,0 @@
|
||||
/**
|
||||
* @license oidc-client-rx
|
||||
* MIT license
|
||||
*/
|
3006
package-lock.json
generated
3006
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
49
package.json
49
package.json
@ -17,6 +17,16 @@
|
||||
"types": "./dist/index.d.ts",
|
||||
"import": "./dist/index.js",
|
||||
"require": "./dist/index.cjs"
|
||||
},
|
||||
"./adapters/react": {
|
||||
"types": "./dist/adapters/react/index.d.ts",
|
||||
"import": "./dist/adapters/react/index.js",
|
||||
"require": "./dist/adapters/react.cjs"
|
||||
},
|
||||
"./adapters/tanstack-router": {
|
||||
"types": "./dist/adapters/tanstack-router/index.d.ts",
|
||||
"import": "./dist/adapters/tanstack-router/index.js",
|
||||
"require": "./dist/adapters/tanstack-router.cjs"
|
||||
}
|
||||
},
|
||||
"main": "./dist/index.cjs",
|
||||
@ -30,31 +40,31 @@
|
||||
"test-ci": "vitest --watch=false --coverage",
|
||||
"pack": "npm run build && npm pack ./dist",
|
||||
"publish": "npm run build && npm publish ./dist",
|
||||
"coverage": "vitest run --coverage",
|
||||
"lint": "ultracite lint",
|
||||
"format": "ultracite format",
|
||||
"cli": "tsx scripts/cli.ts"
|
||||
},
|
||||
"dependencies": {
|
||||
"@ngify/http": "^2.0.4",
|
||||
"injection-js": "git+https://github.com/mgechev/injection-js.git#81a10e0",
|
||||
"reflect-metadata": "^0.2.2"
|
||||
"@outposts/injection-js": "^2.5.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@tanstack/react-router": "*",
|
||||
"react": ">=16.8.0",
|
||||
"rxjs": "^7.4.0||>=8.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@biomejs/biome": "1.9.4",
|
||||
"@biomejs/js-api": "0.7.1",
|
||||
"@biomejs/wasm-nodejs": "^1.9.4",
|
||||
"@evilmartians/lefthook": "^1.0.3",
|
||||
"@playwright/test": "^1.49.1",
|
||||
"@rslib/core": "^0.3.1",
|
||||
"@rslib/core": "^0.4.0",
|
||||
"@swc/core": "^1.10.12",
|
||||
"@tanstack/react-router": "^1.99.6",
|
||||
"@types/jsdom": "^21.1.7",
|
||||
"@types/lodash-es": "^4.17.12",
|
||||
"@types/node": "^22.12.0",
|
||||
"@vitest/browser": "^3.0.4",
|
||||
"@types/react": "^19.0.8",
|
||||
"@vitest/coverage-v8": "^3.0.4",
|
||||
"commander": "^13.1.0",
|
||||
"jsdom": "^26.0.0",
|
||||
@ -62,6 +72,8 @@
|
||||
"oxc-parser": "^0.48.1",
|
||||
"oxc-walker": "^0.2.2",
|
||||
"playwright": "^1.50.0",
|
||||
"react": "^19.0.0",
|
||||
"reflect-metadata": "^0.2.2",
|
||||
"rfc4648": "^1.5.0",
|
||||
"rxjs": "^7.4.0",
|
||||
"tsx": "^4.19.2",
|
||||
@ -71,6 +83,14 @@
|
||||
"vite-tsconfig-paths": "^5.1.4",
|
||||
"vitest": "^3.0.4"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"react": {
|
||||
"optional": true
|
||||
},
|
||||
"@tanstack/react-router": {
|
||||
"optional": true
|
||||
}
|
||||
},
|
||||
"keywords": [
|
||||
"rxjs",
|
||||
"oidc",
|
||||
@ -86,6 +106,19 @@
|
||||
"certified",
|
||||
"oauth",
|
||||
"authorization",
|
||||
"reactivex"
|
||||
]
|
||||
"reactivex",
|
||||
"injection-js",
|
||||
"injection"
|
||||
],
|
||||
"pnpm": {
|
||||
"onlyBuiltDependencies": [
|
||||
"@biomejs/biome",
|
||||
"@swc/core",
|
||||
"core-js",
|
||||
"edgedriver",
|
||||
"esbuild",
|
||||
"geckodriver",
|
||||
"msw"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
2012
pnpm-lock.yaml
generated
2012
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
2
pnpm-workspace.yaml
Normal file
2
pnpm-workspace.yaml
Normal file
@ -0,0 +1,2 @@
|
||||
packages:
|
||||
- 'examples/*'
|
@ -2,17 +2,31 @@ import { defineConfig } from '@rslib/core';
|
||||
|
||||
export default defineConfig({
|
||||
source: {
|
||||
tsconfigPath: './tsconfig.lib.json'
|
||||
tsconfigPath: './tsconfig.lib.json',
|
||||
},
|
||||
lib: [
|
||||
{
|
||||
format: 'esm',
|
||||
syntax: 'es2021',
|
||||
dts: true,
|
||||
bundle: false,
|
||||
dts: {
|
||||
bundle: false,
|
||||
build: true,
|
||||
distPath: './dist',
|
||||
},
|
||||
},
|
||||
{
|
||||
format: 'cjs',
|
||||
syntax: 'es2021',
|
||||
dts: false,
|
||||
bundle: true,
|
||||
source: {
|
||||
entry: {
|
||||
index: './src/index.ts',
|
||||
'adapters/react': './src/adapters/react/index.ts',
|
||||
'adapters/tanstack-router': './src/adapters/tanstack-router/index.ts',
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
output: {
|
||||
|
47
src/adapters/react/index.ts
Normal file
47
src/adapters/react/index.ts
Normal file
@ -0,0 +1,47 @@
|
||||
import type { InjectionToken, Injector, Type } from '@outposts/injection-js';
|
||||
import {
|
||||
type PropsWithChildren,
|
||||
createContext,
|
||||
createElement,
|
||||
useContext,
|
||||
useMemo,
|
||||
} from 'react';
|
||||
import { OidcSecurityService } from '../..';
|
||||
|
||||
export const InjectorContextVoidInjector: Injector = {
|
||||
get: <T>(_token: Type<T> | InjectionToken<T>, _notFoundValue?: T): T => {
|
||||
throw new Error('Please wrap with a InjectorContext.Provider first');
|
||||
},
|
||||
};
|
||||
|
||||
export const InjectorContext = createContext<Injector>(
|
||||
InjectorContextVoidInjector
|
||||
);
|
||||
|
||||
export function InjectorProvider({
|
||||
injector,
|
||||
...props
|
||||
}: PropsWithChildren<{ injector: Injector }>) {
|
||||
return createElement(InjectorContext, {
|
||||
...props,
|
||||
value: injector,
|
||||
});
|
||||
}
|
||||
|
||||
export function useInjector() {
|
||||
return useContext(InjectorContext);
|
||||
}
|
||||
|
||||
export function useOidcClient() {
|
||||
const injector = useInjector();
|
||||
|
||||
const oidcSecurityService = useMemo(
|
||||
() => injector.get(OidcSecurityService),
|
||||
[injector]
|
||||
);
|
||||
|
||||
return {
|
||||
injector,
|
||||
oidcSecurityService,
|
||||
};
|
||||
}
|
41
src/adapters/tanstack-router/index.ts
Normal file
41
src/adapters/tanstack-router/index.ts
Normal file
@ -0,0 +1,41 @@
|
||||
import { InjectionToken, inject } from '@outposts/injection-js';
|
||||
import type { Router } from '@tanstack/react-router';
|
||||
import type { AuthFeature } from '../../features';
|
||||
import { AbstractRouter } from '../../router';
|
||||
|
||||
export type TanStackRouter = Router<any, any, any, any, any, any>;
|
||||
|
||||
export const TANSTACK_ROUTER = new InjectionToken<TanStackRouter>(
|
||||
'TANSTACK_ROUTER'
|
||||
);
|
||||
|
||||
export class TanStackRouterAdapter implements AbstractRouter<string> {
|
||||
private router = inject(TANSTACK_ROUTER);
|
||||
|
||||
navigateByUrl(url: string): void {
|
||||
this.router.navigate({
|
||||
href: url,
|
||||
});
|
||||
}
|
||||
|
||||
getCurrentNavigation() {
|
||||
return {
|
||||
extractedUrl: this.router.state.location.href,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export function withTanstackRouter(router: TanStackRouter): AuthFeature {
|
||||
return {
|
||||
ɵproviders: [
|
||||
{
|
||||
provide: TANSTACK_ROUTER,
|
||||
useValue: router,
|
||||
},
|
||||
{
|
||||
provide: AbstractRouter,
|
||||
useClass: TanStackRouterAdapter,
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
@ -1,17 +1,17 @@
|
||||
import { TestBed } from '@/testing';
|
||||
import {
|
||||
type DefaultHttpTestingController,
|
||||
HTTP_CLIENT_TEST_CONTROLLER,
|
||||
provideHttpClientTesting,
|
||||
} from '@/testing/http';
|
||||
import { HttpHeaders } from '@ngify/http';
|
||||
import type { HttpTestingController } from '@ngify/http/testing';
|
||||
import { ReplaySubject, firstValueFrom, share } from 'rxjs';
|
||||
import { DataService } from './data.service';
|
||||
import { HttpBaseService } from './http-base.service';
|
||||
|
||||
describe('Data Service', () => {
|
||||
let dataService: DataService;
|
||||
let httpMock: HttpTestingController;
|
||||
let httpMock: DefaultHttpTestingController;
|
||||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { HttpHeaders } from '@ngify/http';
|
||||
import { Injectable, inject } from 'injection-js';
|
||||
import { Injectable, inject } from '@outposts/injection-js';
|
||||
import type { Observable } from 'rxjs';
|
||||
import type { OpenIdConfiguration } from '../config/openid-configuration';
|
||||
import { HttpParams } from '../http';
|
||||
|
@ -1,11 +1,10 @@
|
||||
import { HttpClient, type HttpHeaders } from '@ngify/http';
|
||||
import { Injectable, inject } from 'injection-js';
|
||||
import { Injectable, inject } from '@outposts/injection-js';
|
||||
import type { Observable } from 'rxjs';
|
||||
import type { HttpParams } from '../http';
|
||||
import { HTTP_CLIENT, type HttpHeaders, type HttpParams } from '../http';
|
||||
|
||||
@Injectable()
|
||||
export class HttpBaseService {
|
||||
private readonly http = inject(HttpClient);
|
||||
private readonly http = inject(HTTP_CLIENT);
|
||||
|
||||
get<T>(
|
||||
url: string,
|
||||
@ -13,7 +12,7 @@ export class HttpBaseService {
|
||||
): Observable<T> {
|
||||
return this.http.get<T>(url, {
|
||||
...options,
|
||||
params: options.params.toNgify(),
|
||||
params: options.params?.toNgify(),
|
||||
});
|
||||
}
|
||||
|
||||
@ -22,9 +21,9 @@ export class HttpBaseService {
|
||||
body: unknown,
|
||||
options: { headers?: HttpHeaders; params?: HttpParams } = {}
|
||||
): Observable<T> {
|
||||
return this.http.post<T>(url, body, {
|
||||
return this.http.post<T>(url, body as any, {
|
||||
...options,
|
||||
params: options.params.toNgify(),
|
||||
params: options.params?.toNgify(),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { InjectionToken, type Provider } from 'injection-js';
|
||||
import { InjectionToken, type Provider } from '@outposts/injection-js';
|
||||
import {
|
||||
type StsConfigLoader,
|
||||
StsConfigStaticLoader,
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { Injectable, inject } from 'injection-js';
|
||||
import { Injectable, inject } from '@outposts/injection-js';
|
||||
import { BehaviorSubject, type Observable, throwError } from 'rxjs';
|
||||
import { distinctUntilChanged } from 'rxjs/operators';
|
||||
import type { OpenIdConfiguration } from '../config/openid-configuration';
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { Injectable, inject } from 'injection-js';
|
||||
import { Injectable, inject } from '@outposts/injection-js';
|
||||
import { type Observable, forkJoin, of, throwError } from 'rxjs';
|
||||
import { catchError, map, switchMap, tap } from 'rxjs/operators';
|
||||
import { AutoLoginService } from '../auto-login/auto-login.service';
|
||||
|
@ -1,66 +0,0 @@
|
||||
import { TestBed } from '@/testing';
|
||||
import { of } from 'rxjs';
|
||||
import { PASSED_CONFIG } from './auth-config';
|
||||
import { AuthModule } from './auth.module';
|
||||
import { ConfigurationService } from './config/config.service';
|
||||
import {
|
||||
StsConfigHttpLoader,
|
||||
StsConfigLoader,
|
||||
StsConfigStaticLoader,
|
||||
} from './config/loader/config-loader';
|
||||
import { mockProvider } from './testing/mock';
|
||||
|
||||
describe('AuthModule', () => {
|
||||
describe('APP_CONFIG', () => {
|
||||
let authModule: AuthModule;
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [AuthModule.forRoot({ config: { authority: 'something' } })],
|
||||
providers: [mockProvider(ConfigurationService)],
|
||||
}).compileComponents();
|
||||
authModule = TestBed.getImportByType(AuthModule);
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(AuthModule).toBeDefined();
|
||||
expect(authModule).toBeDefined();
|
||||
});
|
||||
|
||||
it('should provide config', () => {
|
||||
const config = authModule.get(PASSED_CONFIG);
|
||||
|
||||
expect(config).toEqual({ config: { authority: 'something' } });
|
||||
});
|
||||
|
||||
it('should create StsConfigStaticLoader if config is passed', () => {
|
||||
const configLoader = authModule.get(StsConfigLoader);
|
||||
|
||||
expect(configLoader instanceof StsConfigStaticLoader).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('StsConfigHttpLoader', () => {
|
||||
let authModule: AuthModule;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [
|
||||
AuthModule.forRoot({
|
||||
loader: {
|
||||
provide: StsConfigLoader,
|
||||
useFactory: () => new StsConfigHttpLoader(of({})),
|
||||
},
|
||||
}),
|
||||
],
|
||||
providers: [mockProvider(ConfigurationService)],
|
||||
}).compileComponents();
|
||||
authModule = TestBed.getImportByType(AuthModule);
|
||||
});
|
||||
|
||||
it('should create StsConfigStaticLoader if config is passed', () => {
|
||||
const configLoader = authModule.get(StsConfigLoader);
|
||||
|
||||
expect(configLoader instanceof StsConfigHttpLoader).toBe(true);
|
||||
});
|
||||
});
|
||||
});
|
@ -1,41 +0,0 @@
|
||||
import {
|
||||
type InjectionToken,
|
||||
Injector,
|
||||
ReflectiveInjector,
|
||||
type Type,
|
||||
} from 'injection-js';
|
||||
import type { PassedInitialConfig } from './auth-config';
|
||||
import type { Module } from './injection';
|
||||
import { _provideAuth } from './provide-auth';
|
||||
|
||||
export interface AuthModuleOptions {
|
||||
passedConfig: PassedInitialConfig;
|
||||
parentInjector?: ReflectiveInjector;
|
||||
}
|
||||
|
||||
export class AuthModule extends Injector {
|
||||
passedConfig: PassedInitialConfig;
|
||||
injector: ReflectiveInjector;
|
||||
parentInjector?: Injector;
|
||||
|
||||
constructor(passedConfig?: PassedInitialConfig, parentInjector?: Injector) {
|
||||
super();
|
||||
this.passedConfig = passedConfig ?? {};
|
||||
this.parentInjector = parentInjector;
|
||||
this.injector = ReflectiveInjector.resolveAndCreate(
|
||||
[..._provideAuth(this.passedConfig)],
|
||||
this.parentInjector
|
||||
);
|
||||
}
|
||||
|
||||
static forRoot(passedConfig?: PassedInitialConfig): Module {
|
||||
return (parentInjector?: Injector) =>
|
||||
new AuthModule(passedConfig, parentInjector);
|
||||
}
|
||||
|
||||
get<T>(token: Type<T> | InjectionToken<T>, notFoundValue?: T): T;
|
||||
get(token: any, notFoundValue?: any);
|
||||
get(token: unknown, notFoundValue?: unknown): any {
|
||||
return this.injector.get(token, notFoundValue);
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
import { TestBed, mockRouterProvider } from '@/testing';
|
||||
import { type MockRouter, TestBed, mockRouterProvider } from '@/testing';
|
||||
import {
|
||||
AbstractRouter,
|
||||
type ActivatedRouteSnapshot,
|
||||
@ -43,7 +43,7 @@ describe('AutoLoginPartialRoutesGuard', () => {
|
||||
let storagePersistenceService: StoragePersistenceService;
|
||||
let configurationService: ConfigurationService;
|
||||
let autoLoginService: AutoLoginService;
|
||||
let router: AbstractRouter;
|
||||
let router: MockRouter;
|
||||
|
||||
beforeEach(() => {
|
||||
authStateService = TestBed.inject(AuthStateService);
|
||||
@ -293,11 +293,6 @@ describe('AutoLoginPartialRoutesGuard', () => {
|
||||
extractedUrl: router.parseUrl(
|
||||
'some-url12/with/some-param?queryParam=true'
|
||||
),
|
||||
extras: {},
|
||||
id: 1,
|
||||
initialUrl: router.parseUrl(''),
|
||||
previousNavigation: null,
|
||||
trigger: 'imperative',
|
||||
});
|
||||
|
||||
await firstValueFrom(guard.canLoad());
|
||||
@ -342,7 +337,7 @@ describe('AutoLoginPartialRoutesGuard', () => {
|
||||
let storagePersistenceService: StoragePersistenceService;
|
||||
let configurationService: ConfigurationService;
|
||||
let autoLoginService: AutoLoginService;
|
||||
let router: AbstractRouter;
|
||||
let router: MockRouter;
|
||||
|
||||
beforeEach(() => {
|
||||
authStateService = TestBed.inject(AuthStateService);
|
||||
@ -398,11 +393,6 @@ describe('AutoLoginPartialRoutesGuard', () => {
|
||||
extractedUrl: router.parseUrl(
|
||||
'some-url12/with/some-param?queryParam=true'
|
||||
),
|
||||
extras: {},
|
||||
id: 1,
|
||||
initialUrl: router.parseUrl(''),
|
||||
previousNavigation: null,
|
||||
trigger: 'imperative',
|
||||
});
|
||||
|
||||
vi.spyOn(authStateService, 'areAuthStorageTokensValid').mockReturnValue(
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { Injectable, inject } from 'injection-js';
|
||||
import { Injectable, inject } from '@outposts/injection-js';
|
||||
import type { Observable } from 'rxjs';
|
||||
import { map } from 'rxjs/operators';
|
||||
import type { AuthOptions } from '../auth-options';
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { Injectable, inject } from 'injection-js';
|
||||
import { Injectable, inject } from '@outposts/injection-js';
|
||||
import type { OpenIdConfiguration } from '../config/openid-configuration';
|
||||
import { injectAbstractType } from '../injection';
|
||||
import { AbstractRouter } from '../router';
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { Injectable, inject } from 'injection-js';
|
||||
import { Injectable, inject } from '@outposts/injection-js';
|
||||
import { Observable, Subject } from 'rxjs';
|
||||
import { tap } from 'rxjs/operators';
|
||||
import type { OpenIdConfiguration } from '../config/openid-configuration';
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { Injectable, inject } from 'injection-js';
|
||||
import { Injectable, inject } from '@outposts/injection-js';
|
||||
import { type Observable, throwError } from 'rxjs';
|
||||
import { catchError, tap } from 'rxjs/operators';
|
||||
import type { OpenIdConfiguration } from '../config/openid-configuration';
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { Injectable, inject } from 'injection-js';
|
||||
import { Injectable, inject } from '@outposts/injection-js';
|
||||
import { type Observable, throwError } from 'rxjs';
|
||||
import { catchError, tap } from 'rxjs/operators';
|
||||
import type { OpenIdConfiguration } from '../config/openid-configuration';
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { Injectable, inject } from 'injection-js';
|
||||
import { Injectable, inject } from '@outposts/injection-js';
|
||||
import { type Observable, type Subscription, interval } from 'rxjs';
|
||||
import { DOCUMENT } from '../dom';
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { Injectable, inject } from 'injection-js';
|
||||
import { Injectable, inject } from '@outposts/injection-js';
|
||||
import { type Observable, ReplaySubject, forkJoin, of, throwError } from 'rxjs';
|
||||
import { catchError, map, share, switchMap } from 'rxjs/operators';
|
||||
import { AuthStateService } from '../auth-state/auth-state.service';
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { Injectable, inject } from 'injection-js';
|
||||
import { Injectable, inject } from '@outposts/injection-js';
|
||||
import { type Observable, throwError } from 'rxjs';
|
||||
import { catchError, finalize } from 'rxjs/operators';
|
||||
import type { OpenIdConfiguration } from '../config/openid-configuration';
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { Injectable, inject } from 'injection-js';
|
||||
import { Injectable, inject } from '@outposts/injection-js';
|
||||
import {
|
||||
type Observable,
|
||||
TimeoutError,
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { inject, Injectable } from 'injection-js';
|
||||
import { Injectable, inject } from '@outposts/injection-js';
|
||||
import { type Observable, throwError } from 'rxjs';
|
||||
import { map, retry } from 'rxjs/operators';
|
||||
import { DataService } from '../../api/data.service';
|
||||
@ -42,7 +42,7 @@ export class AuthWellKnownDataService {
|
||||
introspectionEndpoint: wellKnownEndpoints.introspection_endpoint,
|
||||
parEndpoint:
|
||||
wellKnownEndpoints.pushed_authorization_request_endpoint,
|
||||
} as AuthWellKnownEndpoints)
|
||||
}) as AuthWellKnownEndpoints
|
||||
),
|
||||
map((mappedWellKnownEndpoints) => ({
|
||||
...mappedWellKnownEndpoints,
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { Injectable, inject } from 'injection-js';
|
||||
import { Injectable, inject } from '@outposts/injection-js';
|
||||
import { type Observable, throwError } from 'rxjs';
|
||||
import { catchError, tap } from 'rxjs/operators';
|
||||
import { EventTypes } from '../../public-events/event-types';
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { Injectable, inject } from 'injection-js';
|
||||
import { Injectable, inject } from '@outposts/injection-js';
|
||||
import { type Observable, forkJoin, of } from 'rxjs';
|
||||
import { concatMap, map } from 'rxjs/operators';
|
||||
import { injectAbstractType } from '../injection/inject';
|
||||
|
@ -1,4 +1,4 @@
|
||||
import type { Provider } from 'injection-js';
|
||||
import type { Provider } from '@outposts/injection-js';
|
||||
import { type Observable, forkJoin, of } from 'rxjs';
|
||||
import { map } from 'rxjs/operators';
|
||||
import type { OpenIdConfiguration } from '../openid-configuration';
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { TestBed, mockImplementationWhenArgsEqual } from '@/testing';
|
||||
import { TestBed } from '@/testing';
|
||||
import { mockImplementationWhenArgs, spyOnWithOrigin } from '@/testing/spy';
|
||||
import { vi } from 'vitest';
|
||||
import { LogLevel } from '../../logging/log-level';
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { Injectable, inject } from 'injection-js';
|
||||
import { Injectable, inject } from '@outposts/injection-js';
|
||||
import { LoggerService } from '../../logging/logger.service';
|
||||
import type { OpenIdConfiguration } from '../openid-configuration';
|
||||
import type { Level, RuleValidationResult } from './rule';
|
||||
|
@ -1,3 +1,3 @@
|
||||
import { InjectionToken } from "injection-js";
|
||||
import { InjectionToken } from '@outposts/injection-js';
|
||||
|
||||
export const DOCUMENT = new InjectionToken<Document>('document');
|
||||
export const DOCUMENT = new InjectionToken<Document>('document');
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { Injectable } from 'injection-js';
|
||||
import { Injectable } from '@outposts/injection-js';
|
||||
|
||||
@Injectable()
|
||||
export class JwkExtractor {
|
||||
|
131
src/features.ts
Normal file
131
src/features.ts
Normal file
@ -0,0 +1,131 @@
|
||||
import type { HttpFeature } from '@ngify/http';
|
||||
import type { Provider } from '@outposts/injection-js';
|
||||
import { DOCUMENT } from './dom';
|
||||
import { provideHttpClient } from './http';
|
||||
import {
|
||||
AbstractRouter,
|
||||
VanillaHistoryRouter,
|
||||
VanillaLocationRouter,
|
||||
} from './router';
|
||||
import { AbstractSecurityStorage } from './storage/abstract-security-storage';
|
||||
import { DefaultLocalStorageService } from './storage/default-localstorage.service';
|
||||
import { DefaultSessionStorageService } from './storage/default-sessionstorage.service';
|
||||
import { PLATFORM_ID } from './utils/platform-provider/platform.provider';
|
||||
|
||||
/**
|
||||
* A feature to be used with `provideAuth`.
|
||||
*/
|
||||
export interface AuthFeature {
|
||||
ɵproviders: Provider[];
|
||||
}
|
||||
|
||||
export interface BrowserPlatformFeatureOptions {
|
||||
enabled?: boolean;
|
||||
}
|
||||
|
||||
export function withBrowserPlatform({
|
||||
enabled = true,
|
||||
}: BrowserPlatformFeatureOptions = {}): AuthFeature {
|
||||
return {
|
||||
ɵproviders: enabled
|
||||
? [
|
||||
{
|
||||
provide: DOCUMENT,
|
||||
useFactory: () => document,
|
||||
},
|
||||
{
|
||||
provide: PLATFORM_ID,
|
||||
useValue: 'browser',
|
||||
},
|
||||
]
|
||||
: [],
|
||||
};
|
||||
}
|
||||
|
||||
export interface HttpClientFeatureOptions {
|
||||
enabled?: boolean;
|
||||
features?: HttpFeature[];
|
||||
}
|
||||
|
||||
export function withHttpClient({
|
||||
features,
|
||||
enabled = true,
|
||||
}: HttpClientFeatureOptions = {}): AuthFeature {
|
||||
return {
|
||||
ɵproviders: enabled ? provideHttpClient(features) : [],
|
||||
};
|
||||
}
|
||||
|
||||
export type SecurityStorageType = 'session-storage' | 'local-storage';
|
||||
|
||||
export interface SecurityStorageFeatureOptions {
|
||||
enabled?: boolean;
|
||||
type?: SecurityStorageType;
|
||||
}
|
||||
|
||||
export function withSecurityStorage({
|
||||
enabled = true,
|
||||
type = 'session-storage',
|
||||
}: SecurityStorageFeatureOptions = {}): AuthFeature {
|
||||
return {
|
||||
ɵproviders: enabled
|
||||
? [
|
||||
type === 'session-storage'
|
||||
? {
|
||||
provide: AbstractSecurityStorage,
|
||||
useClass: DefaultLocalStorageService,
|
||||
}
|
||||
: {
|
||||
provide: AbstractSecurityStorage,
|
||||
useClass: DefaultSessionStorageService,
|
||||
},
|
||||
]
|
||||
: [],
|
||||
};
|
||||
}
|
||||
|
||||
export type VanillaRouterType = 'location' | 'history';
|
||||
|
||||
export interface VanillaRouterFeatureOptions {
|
||||
enabled?: boolean;
|
||||
type?: VanillaRouterType;
|
||||
}
|
||||
|
||||
export function withVanillaRouter({
|
||||
enabled = true,
|
||||
type = 'history',
|
||||
}: VanillaRouterFeatureOptions = {}): AuthFeature {
|
||||
return {
|
||||
ɵproviders: enabled
|
||||
? [
|
||||
type === 'location'
|
||||
? {
|
||||
provide: AbstractRouter,
|
||||
useClass: VanillaLocationRouter,
|
||||
}
|
||||
: {
|
||||
provide: AbstractRouter,
|
||||
useClass: VanillaHistoryRouter,
|
||||
},
|
||||
]
|
||||
: [],
|
||||
};
|
||||
}
|
||||
|
||||
export interface DefaultFeaturesOptions {
|
||||
browserPlatform?: BrowserPlatformFeatureOptions;
|
||||
securityStorage?: SecurityStorageFeatureOptions;
|
||||
router?: VanillaRouterFeatureOptions;
|
||||
httpClient?: HttpClientFeatureOptions;
|
||||
}
|
||||
|
||||
export function withDefaultFeatures(
|
||||
options: DefaultFeaturesOptions = {}
|
||||
): AuthFeature[] {
|
||||
return [
|
||||
withBrowserPlatform(options.browserPlatform),
|
||||
withSecurityStorage(options.securityStorage),
|
||||
withHttpClient(options.httpClient),
|
||||
withVanillaRouter(options.router),
|
||||
].filter(Boolean) as AuthFeature[];
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
import { HttpHeaders } from '@ngify/http';
|
||||
import { Injectable, inject } from 'injection-js';
|
||||
import { Injectable, inject } from '@outposts/injection-js';
|
||||
import { type Observable, of, throwError, timer } from 'rxjs';
|
||||
import { catchError, mergeMap, retryWhen, switchMap } from 'rxjs/operators';
|
||||
import { DataService } from '../../api/data.service';
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { Injectable, inject } from 'injection-js';
|
||||
import { Injectable, inject } from '@outposts/injection-js';
|
||||
import { type Observable, of, throwError } from 'rxjs';
|
||||
import { catchError, switchMap, tap } from 'rxjs/operators';
|
||||
import { AuthStateService } from '../../auth-state/auth-state.service';
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { Injectable, inject } from 'injection-js';
|
||||
import { Injectable, inject } from '@outposts/injection-js';
|
||||
import { type Observable, of } from 'rxjs';
|
||||
import type { OpenIdConfiguration } from '../../config/openid-configuration';
|
||||
import { DOCUMENT } from '../../dom';
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { Injectable, inject } from 'injection-js';
|
||||
import { Injectable, inject } from '@outposts/injection-js';
|
||||
import { type Observable, of, throwError } from 'rxjs';
|
||||
import { AuthStateService } from '../../auth-state/auth-state.service';
|
||||
import type { OpenIdConfiguration } from '../../config/openid-configuration';
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { HttpHeaders } from '@ngify/http';
|
||||
import { inject, Injectable } from 'injection-js';
|
||||
import { Injectable, inject } from '@outposts/injection-js';
|
||||
import { type Observable, of, throwError, timer } from 'rxjs';
|
||||
import { catchError, mergeMap, retryWhen, switchMap } from 'rxjs/operators';
|
||||
import { DataService } from '../../api/data.service';
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { Injectable, inject } from 'injection-js';
|
||||
import { Injectable, inject } from '@outposts/injection-js';
|
||||
import type { Observable } from 'rxjs';
|
||||
import { map } from 'rxjs/operators';
|
||||
import { AuthStateService } from '../../auth-state/auth-state.service';
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { Injectable, inject } from 'injection-js';
|
||||
import { Injectable, inject } from '@outposts/injection-js';
|
||||
import { type Observable, of, throwError } from 'rxjs';
|
||||
import { catchError, switchMap } from 'rxjs/operators';
|
||||
import { AuthStateService } from '../../auth-state/auth-state.service';
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { Injectable, inject } from 'injection-js';
|
||||
import { Injectable, inject } from '@outposts/injection-js';
|
||||
import type { OpenIdConfiguration } from '../config/openid-configuration';
|
||||
import { LoggerService } from '../logging/logger.service';
|
||||
import { StoragePersistenceService } from '../storage/storage-persistence.service';
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { Injectable, inject } from 'injection-js';
|
||||
import { Injectable, inject } from '@outposts/injection-js';
|
||||
import type { Observable } from 'rxjs';
|
||||
import { concatMap } from 'rxjs/operators';
|
||||
import type { OpenIdConfiguration } from '../config/openid-configuration';
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { Injectable, inject } from 'injection-js';
|
||||
import { Injectable, inject } from '@outposts/injection-js';
|
||||
import type { OpenIdConfiguration } from '../../config/openid-configuration';
|
||||
import { LoggerService } from '../../logging/logger.service';
|
||||
import { CryptoService } from '../../utils/crypto/crypto.service';
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { Injectable, inject } from 'injection-js';
|
||||
import { Injectable, inject } from '@outposts/injection-js';
|
||||
import { AuthStateService } from '../auth-state/auth-state.service';
|
||||
import type { OpenIdConfiguration } from '../config/openid-configuration';
|
||||
import { LoggerService } from '../logging/logger.service';
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { HttpResponse } from '@ngify/http';
|
||||
import { inject, Injectable } from 'injection-js';
|
||||
import { Injectable, inject } from '@outposts/injection-js';
|
||||
import { type Observable, throwError } from 'rxjs';
|
||||
import { catchError, retry } from 'rxjs/operators';
|
||||
import { DataService } from '../api/data.service';
|
||||
|
@ -1,16 +1,29 @@
|
||||
import {
|
||||
// biome-ignore lint/nursery/noExportedImports: <explanation>
|
||||
HttpClient as DefaultHttpClient,
|
||||
type HttpBackend,
|
||||
HttpClient,
|
||||
type HttpFeature,
|
||||
HttpFeatureKind,
|
||||
// biome-ignore lint/nursery/noExportedImports: <explanation>
|
||||
HttpHeaders,
|
||||
type HttpInterceptor,
|
||||
type HttpInterceptorFn,
|
||||
type HttpRequest,
|
||||
type HttpParams as NgifyHttpParams,
|
||||
withInterceptors,
|
||||
withLegacyInterceptors,
|
||||
} from '@ngify/http';
|
||||
import { InjectionToken, Optional, type Provider } from 'injection-js';
|
||||
import {
|
||||
InjectionToken,
|
||||
Optional,
|
||||
type Provider,
|
||||
} from '@outposts/injection-js';
|
||||
import type { Observable } from 'rxjs';
|
||||
import type { ArrayOrNullableOne } from '../utils/types';
|
||||
export { HttpParams, HttpParamsOptions } from './params';
|
||||
// biome-ignore lint/nursery/noExportedImports: <explanation>
|
||||
import { HttpParams, type HttpParamsOptions } from './params';
|
||||
|
||||
export { HttpParams, HttpHeaders, type HttpParamsOptions, DefaultHttpClient };
|
||||
|
||||
export const HTTP_FEATURES = new InjectionToken<HttpFeature[]>('HTTP_FEATURES');
|
||||
|
||||
@ -108,14 +121,29 @@ export function provideHttpClient(features: HttpFeature[] = []): Provider[] {
|
||||
multi: true,
|
||||
},
|
||||
{
|
||||
provide: HttpClient,
|
||||
provide: HTTP_CLIENT,
|
||||
useFactory: (features: ArrayOrNullableOne<HttpFeature>[]) => {
|
||||
const normalizedFeatures = [features]
|
||||
.flat(Number.MAX_SAFE_INTEGER)
|
||||
.filter(Boolean) as HttpFeature[];
|
||||
return new HttpClient(...normalizedFeatures);
|
||||
return new DefaultHttpClient(...normalizedFeatures);
|
||||
},
|
||||
deps: [HTTP_FEATURES],
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
export type HttpClient = {
|
||||
get<T>(
|
||||
url: string,
|
||||
options?: { headers?: HttpHeaders; params?: NgifyHttpParams }
|
||||
): Observable<T>;
|
||||
|
||||
post<T>(
|
||||
url: string,
|
||||
body?: HttpRequest<any>['body'],
|
||||
options?: { headers?: HttpHeaders; params?: NgifyHttpParams }
|
||||
): Observable<T>;
|
||||
};
|
||||
|
||||
export const HTTP_CLIENT = new InjectionToken<HttpClient>('HTTP_CLIENT');
|
||||
|
@ -88,6 +88,7 @@ function paramParser(
|
||||
// The `window.location.search` can be used while creating an instance of the `HttpParams` class
|
||||
// (e.g. `new HttpParams({ fromString: window.location.search })`). The `window.location.search`
|
||||
// may start with the `?` char, so we strip it if it's present.
|
||||
// biome-ignore lint/performance/useTopLevelRegex: <explanation>
|
||||
const params: string[] = rawParams.replace(/^\?/, '').split('&');
|
||||
params.forEach((param: string) => {
|
||||
const eqIdx = param.indexOf('=');
|
||||
@ -304,7 +305,7 @@ export class HttpParams {
|
||||
toNgify(): NgifyHttpParams {
|
||||
this.init();
|
||||
return new NgifyHttpParams().appendAll(
|
||||
Object.fromEntries(this.map.entries())
|
||||
Object.fromEntries(this.map!.entries())
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { Injectable, inject } from 'injection-js';
|
||||
import { Injectable, inject } from '@outposts/injection-js';
|
||||
import { BehaviorSubject, Observable, of } from 'rxjs';
|
||||
import { take } from 'rxjs/operators';
|
||||
import type { OpenIdConfiguration } from '../config/openid-configuration';
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { Injectable, inject } from 'injection-js';
|
||||
import { Injectable, inject } from '@outposts/injection-js';
|
||||
import type { OpenIdConfiguration } from '../config/openid-configuration';
|
||||
import { DOCUMENT } from '../dom';
|
||||
import { LoggerService } from '../logging/logger.service';
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { Injectable, inject } from 'injection-js';
|
||||
import { Injectable, inject } from '@outposts/injection-js';
|
||||
import {
|
||||
Observable,
|
||||
ReplaySubject,
|
||||
@ -82,14 +82,14 @@ export class RefreshSessionIframeService {
|
||||
): void {
|
||||
const instanceId = Math.random();
|
||||
|
||||
const oidcSilentRenewInit$ = fromEventPattern(
|
||||
const oidcSilentRenewInit$ = fromEventPattern<CustomEvent>(
|
||||
(handler) =>
|
||||
this.document.defaultView.window.addEventListener(
|
||||
this.document.defaultView?.window?.addEventListener(
|
||||
'oidc-silent-renew-init',
|
||||
handler
|
||||
),
|
||||
(handler) =>
|
||||
this.document.defaultView.window.removeEventListener(
|
||||
this.document.defaultView?.window?.removeEventListener(
|
||||
'oidc-silent-renew-init',
|
||||
handler
|
||||
)
|
||||
@ -104,12 +104,12 @@ export class RefreshSessionIframeService {
|
||||
}
|
||||
this.silentRenewEventHandlerSubscription = fromEventPattern<CustomEvent>(
|
||||
(handler) =>
|
||||
this.document.defaultView.window.addEventListener(
|
||||
this.document.defaultView?.window?.addEventListener(
|
||||
'oidc-silent-renew-message',
|
||||
handler
|
||||
),
|
||||
(handler) =>
|
||||
this.document.defaultView.window.removeEventListener(
|
||||
this.document.defaultView?.window?.removeEventListener(
|
||||
'oidc-silent-renew-message',
|
||||
handler
|
||||
)
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { Injectable, inject } from 'injection-js';
|
||||
import { Injectable, inject } from '@outposts/injection-js';
|
||||
import { type Observable, Subject, of, throwError } from 'rxjs';
|
||||
import { catchError, map } from 'rxjs/operators';
|
||||
import { AuthStateService } from '../auth-state/auth-state.service';
|
||||
|
@ -4,7 +4,6 @@ export type { PassedInitialConfig } from './auth-config';
|
||||
export * from './auth-options';
|
||||
export * from './auth-state/auth-result';
|
||||
export * from './auth-state/auth-state';
|
||||
export * from './auth.module';
|
||||
export * from './auto-login/auto-login-partial-routes.guard';
|
||||
export * from './config/auth-well-known/auth-well-known-endpoints';
|
||||
export * from './config/config.service';
|
||||
@ -31,3 +30,4 @@ export * from './validation/validation-result';
|
||||
export * from './injection';
|
||||
export * from './router';
|
||||
export * from './http';
|
||||
export * from './features';
|
||||
|
@ -1,7 +0,0 @@
|
||||
import { InjectionToken } from 'injection-js';
|
||||
import type { Observable } from 'rxjs';
|
||||
|
||||
export const APP_INITIALIZER = new InjectionToken<
|
||||
// biome-ignore lint/suspicious/noConfusingVoidType: <explanation>
|
||||
readonly (() => void | Observable<unknown> | Promise<unknown>)[]
|
||||
>('APP_INITIALIZER');
|
@ -1,3 +1,2 @@
|
||||
export type { Module } from './module';
|
||||
export { APP_INITIALIZER } from './convention';
|
||||
export { injectAbstractType } from './inject';
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { inject } from 'injection-js';
|
||||
import { inject } from '@outposts/injection-js';
|
||||
|
||||
// biome-ignore lint/complexity/noBannedTypes: <explanation>
|
||||
export interface AbstractType<T> extends Function {
|
||||
|
@ -1,3 +1,3 @@
|
||||
import type { Injector } from 'injection-js';
|
||||
import type { Injector } from '@outposts/injection-js';
|
||||
|
||||
export type Module = (parentInjector: Injector) => Injector;
|
||||
|
@ -1,11 +1,15 @@
|
||||
import { TestBed } from '@/testing';
|
||||
import {
|
||||
type DefaultHttpTestingController,
|
||||
HTTP_CLIENT_TEST_CONTROLLER,
|
||||
TestBed,
|
||||
provideHttpClientTesting,
|
||||
} from '@/testing';
|
||||
import { HttpClient } from '@ngify/http';
|
||||
import type { HttpTestingController } from '@ngify/http/testing';
|
||||
import { HTTP_INTERCEPTOR_FNS, HTTP_LEGACY_INTERCEPTORS } from 'oidc-client-rx';
|
||||
import {
|
||||
type DefaultHttpClient,
|
||||
HTTP_CLIENT,
|
||||
HTTP_INTERCEPTOR_FNS,
|
||||
HTTP_LEGACY_INTERCEPTORS,
|
||||
} from 'oidc-client-rx';
|
||||
import { ReplaySubject, firstValueFrom, share } from 'rxjs';
|
||||
import { vi } from 'vitest';
|
||||
import { AuthStateService } from '../auth-state/auth-state.service';
|
||||
@ -16,9 +20,9 @@ import { AuthInterceptor, authInterceptor } from './auth.interceptor';
|
||||
import { ClosestMatchingRouteService } from './closest-matching-route.service';
|
||||
|
||||
describe('AuthHttpInterceptor', () => {
|
||||
let httpTestingController: HttpTestingController;
|
||||
let httpTestingController: DefaultHttpTestingController;
|
||||
let configurationService: ConfigurationService;
|
||||
let httpClient: HttpClient;
|
||||
let httpClient: DefaultHttpClient;
|
||||
let authStateService: AuthStateService;
|
||||
let closestMatchingRouteService: ClosestMatchingRouteService;
|
||||
|
||||
@ -40,7 +44,7 @@ describe('AuthHttpInterceptor', () => {
|
||||
],
|
||||
});
|
||||
|
||||
httpClient = TestBed.inject(HttpClient);
|
||||
httpClient = TestBed.inject(HTTP_CLIENT) as DefaultHttpClient;
|
||||
httpTestingController = TestBed.inject(HTTP_CLIENT_TEST_CONTROLLER);
|
||||
configurationService = TestBed.inject(ConfigurationService);
|
||||
authStateService = TestBed.inject(AuthStateService);
|
||||
@ -72,7 +76,7 @@ describe('AuthHttpInterceptor', () => {
|
||||
],
|
||||
});
|
||||
|
||||
httpClient = TestBed.inject(HttpClient);
|
||||
httpClient = TestBed.inject(HTTP_CLIENT) as DefaultHttpClient;
|
||||
httpTestingController = TestBed.inject(HTTP_CLIENT_TEST_CONTROLLER);
|
||||
configurationService = TestBed.inject(ConfigurationService);
|
||||
authStateService = TestBed.inject(AuthStateService);
|
||||
|
@ -6,7 +6,7 @@ import type {
|
||||
HttpInterceptorFn,
|
||||
HttpRequest,
|
||||
} from '@ngify/http';
|
||||
import { Injectable, inject } from 'injection-js';
|
||||
import { Injectable, inject } from '@outposts/injection-js';
|
||||
import type { Observable } from 'rxjs';
|
||||
import { AuthStateService } from '../auth-state/auth-state.service';
|
||||
import { ConfigurationService } from '../config/config.service';
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { Injectable } from 'injection-js';
|
||||
import { Injectable } from '@outposts/injection-js';
|
||||
import type { OpenIdConfiguration } from '../config/openid-configuration';
|
||||
|
||||
@Injectable()
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { Injectable } from 'injection-js';
|
||||
import { Injectable } from '@outposts/injection-js';
|
||||
|
||||
/**
|
||||
* Implement this class-interface to create a custom logger service.
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { Injectable } from 'injection-js';
|
||||
import { Injectable } from '@outposts/injection-js';
|
||||
import type { AbstractLoggerService } from './abstract-logger.service';
|
||||
|
||||
@Injectable()
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { Injectable } from 'injection-js';
|
||||
import { Injectable } from '@outposts/injection-js';
|
||||
import type { OpenIdConfiguration } from '../config/openid-configuration';
|
||||
import { injectAbstractType } from '../injection/inject';
|
||||
import { AbstractLoggerService } from './abstract-logger.service';
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { Injectable, inject } from 'injection-js';
|
||||
import { Injectable, inject } from '@outposts/injection-js';
|
||||
import { type Observable, of, throwError } from 'rxjs';
|
||||
import type { AuthOptions } from '../auth-options';
|
||||
import type { OpenIdConfiguration } from '../config/openid-configuration';
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { Injectable, inject } from 'injection-js';
|
||||
import { Injectable, inject } from '@outposts/injection-js';
|
||||
import { type Observable, of, throwError } from 'rxjs';
|
||||
import { map, switchMap, take } from 'rxjs/operators';
|
||||
import type { AuthOptions } from '../../auth-options';
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { HttpHeaders } from '@ngify/http';
|
||||
import { inject, Injectable } from 'injection-js';
|
||||
import { Injectable, inject } from '@outposts/injection-js';
|
||||
import { type Observable, throwError } from 'rxjs';
|
||||
import { catchError, map, retry, switchMap } from 'rxjs/operators';
|
||||
import { DataService } from '../../api/data.service';
|
||||
@ -74,7 +74,8 @@ export class ParService {
|
||||
};
|
||||
}),
|
||||
catchError((error) => {
|
||||
const errorMessage = 'There was an error on ParService postParRequest';
|
||||
const errorMessage =
|
||||
'There was an error on ParService postParRequest';
|
||||
|
||||
this.loggerService.logError(configuration, errorMessage, error);
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { Injectable, inject } from 'injection-js';
|
||||
import { Injectable, inject } from '@outposts/injection-js';
|
||||
import { type Observable, of, throwError } from 'rxjs';
|
||||
import { switchMap, take, tap } from 'rxjs/operators';
|
||||
import type { AuthOptions } from '../../auth-options';
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { DOCUMENT } from '../../dom';
|
||||
import { inject, Injectable } from 'injection-js';
|
||||
import { Injectable, inject } from '@outposts/injection-js';
|
||||
import { type Observable, Subject } from 'rxjs';
|
||||
import type { OpenIdConfiguration } from '../../config/openid-configuration';
|
||||
import { DOCUMENT } from '../../dom';
|
||||
import { LoggerService } from '../../logging/logger.service';
|
||||
import { StoragePersistenceService } from '../../storage/storage-persistence.service';
|
||||
import type { PopupOptions } from './popup-options';
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user