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
|
# compiled output
|
||||||
/dist
|
/dist
|
||||||
|
**/dist
|
||||||
/tmp
|
/tmp
|
||||||
/out-tsc
|
/out-tsc
|
||||||
# Only exists if Bazel was run
|
# Only exists if Bazel was run
|
||||||
@ -45,7 +46,6 @@ testem.log
|
|||||||
.DS_Store
|
.DS_Store
|
||||||
Thumbs.db
|
Thumbs.db
|
||||||
|
|
||||||
/.angulardoc.json
|
|
||||||
debug.log
|
debug.log
|
||||||
|
|
||||||
/.husky
|
/.husky
|
||||||
@ -55,3 +55,5 @@ debug.log
|
|||||||
/blob-report/
|
/blob-report/
|
||||||
/playwright/.cache/
|
/playwright/.cache/
|
||||||
/.vitest
|
/.vitest
|
||||||
|
/.rslib
|
||||||
|
**/*.tsbuildinfo
|
||||||
|
51
README.md
51
README.md
@ -2,6 +2,7 @@
|
|||||||
<img src="./assets/logo-512.png" height="150" alt="OUTPOSTS">
|
<img src="./assets/logo-512.png" height="150" alt="OUTPOSTS">
|
||||||
<div style="color: #232848; font-weight: 700;">OIDC-CLIENT-RX</div>
|
<div style="color: #232848; font-weight: 700;">OIDC-CLIENT-RX</div>
|
||||||
<div align="center">
|
<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" />
|
<img src="https://img.shields.io/badge/status-work--in--progress-blue" alt="status-badge" />
|
||||||
</div>
|
</div>
|
||||||
</h1>
|
</h1>
|
||||||
@ -10,7 +11,55 @@
|
|||||||
|
|
||||||
## Quick Start
|
## 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
|
## License
|
||||||
|
|
||||||
|
Binary file not shown.
Before Width: | Height: | Size: 47 KiB After Width: | Height: | Size: 54 KiB |
@ -6,7 +6,7 @@
|
|||||||
"style": {
|
"style": {
|
||||||
"noNonNullAssertion": "off",
|
"noNonNullAssertion": "off",
|
||||||
"noParameterAssign": "off",
|
"noParameterAssign": "off",
|
||||||
"useFilenamingConvention": "warn",
|
"useFilenamingConvention": "off",
|
||||||
"noParameterProperties": "off"
|
"noParameterProperties": "off"
|
||||||
},
|
},
|
||||||
"suspicious": {
|
"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
47
package.json
47
package.json
@ -17,6 +17,16 @@
|
|||||||
"types": "./dist/index.d.ts",
|
"types": "./dist/index.d.ts",
|
||||||
"import": "./dist/index.js",
|
"import": "./dist/index.js",
|
||||||
"require": "./dist/index.cjs"
|
"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",
|
"main": "./dist/index.cjs",
|
||||||
@ -30,31 +40,31 @@
|
|||||||
"test-ci": "vitest --watch=false --coverage",
|
"test-ci": "vitest --watch=false --coverage",
|
||||||
"pack": "npm run build && npm pack ./dist",
|
"pack": "npm run build && npm pack ./dist",
|
||||||
"publish": "npm run build && npm publish ./dist",
|
"publish": "npm run build && npm publish ./dist",
|
||||||
"coverage": "vitest run --coverage",
|
|
||||||
"lint": "ultracite lint",
|
"lint": "ultracite lint",
|
||||||
"format": "ultracite format",
|
"format": "ultracite format",
|
||||||
"cli": "tsx scripts/cli.ts"
|
"cli": "tsx scripts/cli.ts"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@ngify/http": "^2.0.4",
|
"@ngify/http": "^2.0.4",
|
||||||
"injection-js": "git+https://github.com/mgechev/injection-js.git#81a10e0",
|
"@outposts/injection-js": "^2.5.1"
|
||||||
"reflect-metadata": "^0.2.2"
|
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
|
"@tanstack/react-router": "*",
|
||||||
|
"react": ">=16.8.0",
|
||||||
"rxjs": "^7.4.0||>=8.0.0"
|
"rxjs": "^7.4.0||>=8.0.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@biomejs/biome": "1.9.4",
|
"@biomejs/biome": "1.9.4",
|
||||||
"@biomejs/js-api": "0.7.1",
|
"@biomejs/js-api": "0.7.1",
|
||||||
"@biomejs/wasm-nodejs": "^1.9.4",
|
"@biomejs/wasm-nodejs": "^1.9.4",
|
||||||
"@evilmartians/lefthook": "^1.0.3",
|
|
||||||
"@playwright/test": "^1.49.1",
|
"@playwright/test": "^1.49.1",
|
||||||
"@rslib/core": "^0.3.1",
|
"@rslib/core": "^0.4.0",
|
||||||
"@swc/core": "^1.10.12",
|
"@swc/core": "^1.10.12",
|
||||||
|
"@tanstack/react-router": "^1.99.6",
|
||||||
"@types/jsdom": "^21.1.7",
|
"@types/jsdom": "^21.1.7",
|
||||||
"@types/lodash-es": "^4.17.12",
|
"@types/lodash-es": "^4.17.12",
|
||||||
"@types/node": "^22.12.0",
|
"@types/node": "^22.12.0",
|
||||||
"@vitest/browser": "^3.0.4",
|
"@types/react": "^19.0.8",
|
||||||
"@vitest/coverage-v8": "^3.0.4",
|
"@vitest/coverage-v8": "^3.0.4",
|
||||||
"commander": "^13.1.0",
|
"commander": "^13.1.0",
|
||||||
"jsdom": "^26.0.0",
|
"jsdom": "^26.0.0",
|
||||||
@ -62,6 +72,8 @@
|
|||||||
"oxc-parser": "^0.48.1",
|
"oxc-parser": "^0.48.1",
|
||||||
"oxc-walker": "^0.2.2",
|
"oxc-walker": "^0.2.2",
|
||||||
"playwright": "^1.50.0",
|
"playwright": "^1.50.0",
|
||||||
|
"react": "^19.0.0",
|
||||||
|
"reflect-metadata": "^0.2.2",
|
||||||
"rfc4648": "^1.5.0",
|
"rfc4648": "^1.5.0",
|
||||||
"rxjs": "^7.4.0",
|
"rxjs": "^7.4.0",
|
||||||
"tsx": "^4.19.2",
|
"tsx": "^4.19.2",
|
||||||
@ -71,6 +83,14 @@
|
|||||||
"vite-tsconfig-paths": "^5.1.4",
|
"vite-tsconfig-paths": "^5.1.4",
|
||||||
"vitest": "^3.0.4"
|
"vitest": "^3.0.4"
|
||||||
},
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"react": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"@tanstack/react-router": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
},
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"rxjs",
|
"rxjs",
|
||||||
"oidc",
|
"oidc",
|
||||||
@ -86,6 +106,19 @@
|
|||||||
"certified",
|
"certified",
|
||||||
"oauth",
|
"oauth",
|
||||||
"authorization",
|
"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({
|
export default defineConfig({
|
||||||
source: {
|
source: {
|
||||||
tsconfigPath: './tsconfig.lib.json'
|
tsconfigPath: './tsconfig.lib.json',
|
||||||
},
|
},
|
||||||
lib: [
|
lib: [
|
||||||
{
|
{
|
||||||
format: 'esm',
|
format: 'esm',
|
||||||
syntax: 'es2021',
|
syntax: 'es2021',
|
||||||
dts: true,
|
bundle: false,
|
||||||
|
dts: {
|
||||||
|
bundle: false,
|
||||||
|
build: true,
|
||||||
|
distPath: './dist',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
format: 'cjs',
|
format: 'cjs',
|
||||||
syntax: 'es2021',
|
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: {
|
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 { TestBed } from '@/testing';
|
||||||
import {
|
import {
|
||||||
|
type DefaultHttpTestingController,
|
||||||
HTTP_CLIENT_TEST_CONTROLLER,
|
HTTP_CLIENT_TEST_CONTROLLER,
|
||||||
provideHttpClientTesting,
|
provideHttpClientTesting,
|
||||||
} from '@/testing/http';
|
} from '@/testing/http';
|
||||||
import { HttpHeaders } from '@ngify/http';
|
import { HttpHeaders } from '@ngify/http';
|
||||||
import type { HttpTestingController } from '@ngify/http/testing';
|
|
||||||
import { ReplaySubject, firstValueFrom, share } from 'rxjs';
|
import { ReplaySubject, firstValueFrom, share } from 'rxjs';
|
||||||
import { DataService } from './data.service';
|
import { DataService } from './data.service';
|
||||||
import { HttpBaseService } from './http-base.service';
|
import { HttpBaseService } from './http-base.service';
|
||||||
|
|
||||||
describe('Data Service', () => {
|
describe('Data Service', () => {
|
||||||
let dataService: DataService;
|
let dataService: DataService;
|
||||||
let httpMock: HttpTestingController;
|
let httpMock: DefaultHttpTestingController;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { HttpHeaders } from '@ngify/http';
|
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 { Observable } from 'rxjs';
|
||||||
import type { OpenIdConfiguration } from '../config/openid-configuration';
|
import type { OpenIdConfiguration } from '../config/openid-configuration';
|
||||||
import { HttpParams } from '../http';
|
import { HttpParams } from '../http';
|
||||||
|
@ -1,11 +1,10 @@
|
|||||||
import { HttpClient, type HttpHeaders } from '@ngify/http';
|
import { Injectable, inject } from '@outposts/injection-js';
|
||||||
import { Injectable, inject } from 'injection-js';
|
|
||||||
import type { Observable } from 'rxjs';
|
import type { Observable } from 'rxjs';
|
||||||
import type { HttpParams } from '../http';
|
import { HTTP_CLIENT, type HttpHeaders, type HttpParams } from '../http';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class HttpBaseService {
|
export class HttpBaseService {
|
||||||
private readonly http = inject(HttpClient);
|
private readonly http = inject(HTTP_CLIENT);
|
||||||
|
|
||||||
get<T>(
|
get<T>(
|
||||||
url: string,
|
url: string,
|
||||||
@ -13,7 +12,7 @@ export class HttpBaseService {
|
|||||||
): Observable<T> {
|
): Observable<T> {
|
||||||
return this.http.get<T>(url, {
|
return this.http.get<T>(url, {
|
||||||
...options,
|
...options,
|
||||||
params: options.params.toNgify(),
|
params: options.params?.toNgify(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -22,9 +21,9 @@ export class HttpBaseService {
|
|||||||
body: unknown,
|
body: unknown,
|
||||||
options: { headers?: HttpHeaders; params?: HttpParams } = {}
|
options: { headers?: HttpHeaders; params?: HttpParams } = {}
|
||||||
): Observable<T> {
|
): Observable<T> {
|
||||||
return this.http.post<T>(url, body, {
|
return this.http.post<T>(url, body as any, {
|
||||||
...options,
|
...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 {
|
import {
|
||||||
type StsConfigLoader,
|
type StsConfigLoader,
|
||||||
StsConfigStaticLoader,
|
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 { BehaviorSubject, type Observable, throwError } from 'rxjs';
|
||||||
import { distinctUntilChanged } from 'rxjs/operators';
|
import { distinctUntilChanged } from 'rxjs/operators';
|
||||||
import type { OpenIdConfiguration } from '../config/openid-configuration';
|
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 { type Observable, forkJoin, of, throwError } from 'rxjs';
|
||||||
import { catchError, map, switchMap, tap } from 'rxjs/operators';
|
import { catchError, map, switchMap, tap } from 'rxjs/operators';
|
||||||
import { AutoLoginService } from '../auto-login/auto-login.service';
|
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 {
|
import {
|
||||||
AbstractRouter,
|
AbstractRouter,
|
||||||
type ActivatedRouteSnapshot,
|
type ActivatedRouteSnapshot,
|
||||||
@ -43,7 +43,7 @@ describe('AutoLoginPartialRoutesGuard', () => {
|
|||||||
let storagePersistenceService: StoragePersistenceService;
|
let storagePersistenceService: StoragePersistenceService;
|
||||||
let configurationService: ConfigurationService;
|
let configurationService: ConfigurationService;
|
||||||
let autoLoginService: AutoLoginService;
|
let autoLoginService: AutoLoginService;
|
||||||
let router: AbstractRouter;
|
let router: MockRouter;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
authStateService = TestBed.inject(AuthStateService);
|
authStateService = TestBed.inject(AuthStateService);
|
||||||
@ -293,11 +293,6 @@ describe('AutoLoginPartialRoutesGuard', () => {
|
|||||||
extractedUrl: router.parseUrl(
|
extractedUrl: router.parseUrl(
|
||||||
'some-url12/with/some-param?queryParam=true'
|
'some-url12/with/some-param?queryParam=true'
|
||||||
),
|
),
|
||||||
extras: {},
|
|
||||||
id: 1,
|
|
||||||
initialUrl: router.parseUrl(''),
|
|
||||||
previousNavigation: null,
|
|
||||||
trigger: 'imperative',
|
|
||||||
});
|
});
|
||||||
|
|
||||||
await firstValueFrom(guard.canLoad());
|
await firstValueFrom(guard.canLoad());
|
||||||
@ -342,7 +337,7 @@ describe('AutoLoginPartialRoutesGuard', () => {
|
|||||||
let storagePersistenceService: StoragePersistenceService;
|
let storagePersistenceService: StoragePersistenceService;
|
||||||
let configurationService: ConfigurationService;
|
let configurationService: ConfigurationService;
|
||||||
let autoLoginService: AutoLoginService;
|
let autoLoginService: AutoLoginService;
|
||||||
let router: AbstractRouter;
|
let router: MockRouter;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
authStateService = TestBed.inject(AuthStateService);
|
authStateService = TestBed.inject(AuthStateService);
|
||||||
@ -398,11 +393,6 @@ describe('AutoLoginPartialRoutesGuard', () => {
|
|||||||
extractedUrl: router.parseUrl(
|
extractedUrl: router.parseUrl(
|
||||||
'some-url12/with/some-param?queryParam=true'
|
'some-url12/with/some-param?queryParam=true'
|
||||||
),
|
),
|
||||||
extras: {},
|
|
||||||
id: 1,
|
|
||||||
initialUrl: router.parseUrl(''),
|
|
||||||
previousNavigation: null,
|
|
||||||
trigger: 'imperative',
|
|
||||||
});
|
});
|
||||||
|
|
||||||
vi.spyOn(authStateService, 'areAuthStorageTokensValid').mockReturnValue(
|
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 type { Observable } from 'rxjs';
|
||||||
import { map } from 'rxjs/operators';
|
import { map } from 'rxjs/operators';
|
||||||
import type { AuthOptions } from '../auth-options';
|
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 type { OpenIdConfiguration } from '../config/openid-configuration';
|
||||||
import { injectAbstractType } from '../injection';
|
import { injectAbstractType } from '../injection';
|
||||||
import { AbstractRouter } from '../router';
|
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 { Observable, Subject } from 'rxjs';
|
||||||
import { tap } from 'rxjs/operators';
|
import { tap } from 'rxjs/operators';
|
||||||
import type { OpenIdConfiguration } from '../config/openid-configuration';
|
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 { type Observable, throwError } from 'rxjs';
|
||||||
import { catchError, tap } from 'rxjs/operators';
|
import { catchError, tap } from 'rxjs/operators';
|
||||||
import type { OpenIdConfiguration } from '../config/openid-configuration';
|
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 { type Observable, throwError } from 'rxjs';
|
||||||
import { catchError, tap } from 'rxjs/operators';
|
import { catchError, tap } from 'rxjs/operators';
|
||||||
import type { OpenIdConfiguration } from '../config/openid-configuration';
|
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 { type Observable, type Subscription, interval } from 'rxjs';
|
||||||
import { DOCUMENT } from '../dom';
|
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 { type Observable, ReplaySubject, forkJoin, of, throwError } from 'rxjs';
|
||||||
import { catchError, map, share, switchMap } from 'rxjs/operators';
|
import { catchError, map, share, switchMap } from 'rxjs/operators';
|
||||||
import { AuthStateService } from '../auth-state/auth-state.service';
|
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 { type Observable, throwError } from 'rxjs';
|
||||||
import { catchError, finalize } from 'rxjs/operators';
|
import { catchError, finalize } from 'rxjs/operators';
|
||||||
import type { OpenIdConfiguration } from '../config/openid-configuration';
|
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 {
|
import {
|
||||||
type Observable,
|
type Observable,
|
||||||
TimeoutError,
|
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 { type Observable, throwError } from 'rxjs';
|
||||||
import { map, retry } from 'rxjs/operators';
|
import { map, retry } from 'rxjs/operators';
|
||||||
import { DataService } from '../../api/data.service';
|
import { DataService } from '../../api/data.service';
|
||||||
@ -42,7 +42,7 @@ export class AuthWellKnownDataService {
|
|||||||
introspectionEndpoint: wellKnownEndpoints.introspection_endpoint,
|
introspectionEndpoint: wellKnownEndpoints.introspection_endpoint,
|
||||||
parEndpoint:
|
parEndpoint:
|
||||||
wellKnownEndpoints.pushed_authorization_request_endpoint,
|
wellKnownEndpoints.pushed_authorization_request_endpoint,
|
||||||
} as AuthWellKnownEndpoints)
|
}) as AuthWellKnownEndpoints
|
||||||
),
|
),
|
||||||
map((mappedWellKnownEndpoints) => ({
|
map((mappedWellKnownEndpoints) => ({
|
||||||
...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 { type Observable, throwError } from 'rxjs';
|
||||||
import { catchError, tap } from 'rxjs/operators';
|
import { catchError, tap } from 'rxjs/operators';
|
||||||
import { EventTypes } from '../../public-events/event-types';
|
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 { type Observable, forkJoin, of } from 'rxjs';
|
||||||
import { concatMap, map } from 'rxjs/operators';
|
import { concatMap, map } from 'rxjs/operators';
|
||||||
import { injectAbstractType } from '../injection/inject';
|
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 { type Observable, forkJoin, of } from 'rxjs';
|
||||||
import { map } from 'rxjs/operators';
|
import { map } from 'rxjs/operators';
|
||||||
import type { OpenIdConfiguration } from '../openid-configuration';
|
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 { mockImplementationWhenArgs, spyOnWithOrigin } from '@/testing/spy';
|
||||||
import { vi } from 'vitest';
|
import { vi } from 'vitest';
|
||||||
import { LogLevel } from '../../logging/log-level';
|
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 { LoggerService } from '../../logging/logger.service';
|
||||||
import type { OpenIdConfiguration } from '../openid-configuration';
|
import type { OpenIdConfiguration } from '../openid-configuration';
|
||||||
import type { Level, RuleValidationResult } from './rule';
|
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()
|
@Injectable()
|
||||||
export class JwkExtractor {
|
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 { 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 { type Observable, of, throwError, timer } from 'rxjs';
|
||||||
import { catchError, mergeMap, retryWhen, switchMap } from 'rxjs/operators';
|
import { catchError, mergeMap, retryWhen, switchMap } from 'rxjs/operators';
|
||||||
import { DataService } from '../../api/data.service';
|
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 { type Observable, of, throwError } from 'rxjs';
|
||||||
import { catchError, switchMap, tap } from 'rxjs/operators';
|
import { catchError, switchMap, tap } from 'rxjs/operators';
|
||||||
import { AuthStateService } from '../../auth-state/auth-state.service';
|
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 Observable, of } from 'rxjs';
|
||||||
import type { OpenIdConfiguration } from '../../config/openid-configuration';
|
import type { OpenIdConfiguration } from '../../config/openid-configuration';
|
||||||
import { DOCUMENT } from '../../dom';
|
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 { type Observable, of, throwError } from 'rxjs';
|
||||||
import { AuthStateService } from '../../auth-state/auth-state.service';
|
import { AuthStateService } from '../../auth-state/auth-state.service';
|
||||||
import type { OpenIdConfiguration } from '../../config/openid-configuration';
|
import type { OpenIdConfiguration } from '../../config/openid-configuration';
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { HttpHeaders } from '@ngify/http';
|
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 { type Observable, of, throwError, timer } from 'rxjs';
|
||||||
import { catchError, mergeMap, retryWhen, switchMap } from 'rxjs/operators';
|
import { catchError, mergeMap, retryWhen, switchMap } from 'rxjs/operators';
|
||||||
import { DataService } from '../../api/data.service';
|
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 type { Observable } from 'rxjs';
|
||||||
import { map } from 'rxjs/operators';
|
import { map } from 'rxjs/operators';
|
||||||
import { AuthStateService } from '../../auth-state/auth-state.service';
|
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 { type Observable, of, throwError } from 'rxjs';
|
||||||
import { catchError, switchMap } from 'rxjs/operators';
|
import { catchError, switchMap } from 'rxjs/operators';
|
||||||
import { AuthStateService } from '../../auth-state/auth-state.service';
|
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 type { OpenIdConfiguration } from '../config/openid-configuration';
|
||||||
import { LoggerService } from '../logging/logger.service';
|
import { LoggerService } from '../logging/logger.service';
|
||||||
import { StoragePersistenceService } from '../storage/storage-persistence.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 type { Observable } from 'rxjs';
|
||||||
import { concatMap } from 'rxjs/operators';
|
import { concatMap } from 'rxjs/operators';
|
||||||
import type { OpenIdConfiguration } from '../config/openid-configuration';
|
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 type { OpenIdConfiguration } from '../../config/openid-configuration';
|
||||||
import { LoggerService } from '../../logging/logger.service';
|
import { LoggerService } from '../../logging/logger.service';
|
||||||
import { CryptoService } from '../../utils/crypto/crypto.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 { AuthStateService } from '../auth-state/auth-state.service';
|
||||||
import type { OpenIdConfiguration } from '../config/openid-configuration';
|
import type { OpenIdConfiguration } from '../config/openid-configuration';
|
||||||
import { LoggerService } from '../logging/logger.service';
|
import { LoggerService } from '../logging/logger.service';
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { HttpResponse } from '@ngify/http';
|
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 { type Observable, throwError } from 'rxjs';
|
||||||
import { catchError, retry } from 'rxjs/operators';
|
import { catchError, retry } from 'rxjs/operators';
|
||||||
import { DataService } from '../api/data.service';
|
import { DataService } from '../api/data.service';
|
||||||
|
@ -1,16 +1,29 @@
|
|||||||
import {
|
import {
|
||||||
|
// biome-ignore lint/nursery/noExportedImports: <explanation>
|
||||||
|
HttpClient as DefaultHttpClient,
|
||||||
type HttpBackend,
|
type HttpBackend,
|
||||||
HttpClient,
|
|
||||||
type HttpFeature,
|
type HttpFeature,
|
||||||
HttpFeatureKind,
|
HttpFeatureKind,
|
||||||
|
// biome-ignore lint/nursery/noExportedImports: <explanation>
|
||||||
|
HttpHeaders,
|
||||||
type HttpInterceptor,
|
type HttpInterceptor,
|
||||||
type HttpInterceptorFn,
|
type HttpInterceptorFn,
|
||||||
|
type HttpRequest,
|
||||||
|
type HttpParams as NgifyHttpParams,
|
||||||
withInterceptors,
|
withInterceptors,
|
||||||
withLegacyInterceptors,
|
withLegacyInterceptors,
|
||||||
} from '@ngify/http';
|
} 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';
|
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');
|
export const HTTP_FEATURES = new InjectionToken<HttpFeature[]>('HTTP_FEATURES');
|
||||||
|
|
||||||
@ -108,14 +121,29 @@ export function provideHttpClient(features: HttpFeature[] = []): Provider[] {
|
|||||||
multi: true,
|
multi: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
provide: HttpClient,
|
provide: HTTP_CLIENT,
|
||||||
useFactory: (features: ArrayOrNullableOne<HttpFeature>[]) => {
|
useFactory: (features: ArrayOrNullableOne<HttpFeature>[]) => {
|
||||||
const normalizedFeatures = [features]
|
const normalizedFeatures = [features]
|
||||||
.flat(Number.MAX_SAFE_INTEGER)
|
.flat(Number.MAX_SAFE_INTEGER)
|
||||||
.filter(Boolean) as HttpFeature[];
|
.filter(Boolean) as HttpFeature[];
|
||||||
return new HttpClient(...normalizedFeatures);
|
return new DefaultHttpClient(...normalizedFeatures);
|
||||||
},
|
},
|
||||||
deps: [HTTP_FEATURES],
|
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
|
// 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`
|
// (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.
|
// 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('&');
|
const params: string[] = rawParams.replace(/^\?/, '').split('&');
|
||||||
params.forEach((param: string) => {
|
params.forEach((param: string) => {
|
||||||
const eqIdx = param.indexOf('=');
|
const eqIdx = param.indexOf('=');
|
||||||
@ -304,7 +305,7 @@ export class HttpParams {
|
|||||||
toNgify(): NgifyHttpParams {
|
toNgify(): NgifyHttpParams {
|
||||||
this.init();
|
this.init();
|
||||||
return new NgifyHttpParams().appendAll(
|
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 { BehaviorSubject, Observable, of } from 'rxjs';
|
||||||
import { take } from 'rxjs/operators';
|
import { take } from 'rxjs/operators';
|
||||||
import type { OpenIdConfiguration } from '../config/openid-configuration';
|
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 type { OpenIdConfiguration } from '../config/openid-configuration';
|
||||||
import { DOCUMENT } from '../dom';
|
import { DOCUMENT } from '../dom';
|
||||||
import { LoggerService } from '../logging/logger.service';
|
import { LoggerService } from '../logging/logger.service';
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { Injectable, inject } from 'injection-js';
|
import { Injectable, inject } from '@outposts/injection-js';
|
||||||
import {
|
import {
|
||||||
Observable,
|
Observable,
|
||||||
ReplaySubject,
|
ReplaySubject,
|
||||||
@ -82,14 +82,14 @@ export class RefreshSessionIframeService {
|
|||||||
): void {
|
): void {
|
||||||
const instanceId = Math.random();
|
const instanceId = Math.random();
|
||||||
|
|
||||||
const oidcSilentRenewInit$ = fromEventPattern(
|
const oidcSilentRenewInit$ = fromEventPattern<CustomEvent>(
|
||||||
(handler) =>
|
(handler) =>
|
||||||
this.document.defaultView.window.addEventListener(
|
this.document.defaultView?.window?.addEventListener(
|
||||||
'oidc-silent-renew-init',
|
'oidc-silent-renew-init',
|
||||||
handler
|
handler
|
||||||
),
|
),
|
||||||
(handler) =>
|
(handler) =>
|
||||||
this.document.defaultView.window.removeEventListener(
|
this.document.defaultView?.window?.removeEventListener(
|
||||||
'oidc-silent-renew-init',
|
'oidc-silent-renew-init',
|
||||||
handler
|
handler
|
||||||
)
|
)
|
||||||
@ -104,12 +104,12 @@ export class RefreshSessionIframeService {
|
|||||||
}
|
}
|
||||||
this.silentRenewEventHandlerSubscription = fromEventPattern<CustomEvent>(
|
this.silentRenewEventHandlerSubscription = fromEventPattern<CustomEvent>(
|
||||||
(handler) =>
|
(handler) =>
|
||||||
this.document.defaultView.window.addEventListener(
|
this.document.defaultView?.window?.addEventListener(
|
||||||
'oidc-silent-renew-message',
|
'oidc-silent-renew-message',
|
||||||
handler
|
handler
|
||||||
),
|
),
|
||||||
(handler) =>
|
(handler) =>
|
||||||
this.document.defaultView.window.removeEventListener(
|
this.document.defaultView?.window?.removeEventListener(
|
||||||
'oidc-silent-renew-message',
|
'oidc-silent-renew-message',
|
||||||
handler
|
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 { type Observable, Subject, of, throwError } from 'rxjs';
|
||||||
import { catchError, map } from 'rxjs/operators';
|
import { catchError, map } from 'rxjs/operators';
|
||||||
import { AuthStateService } from '../auth-state/auth-state.service';
|
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-options';
|
||||||
export * from './auth-state/auth-result';
|
export * from './auth-state/auth-result';
|
||||||
export * from './auth-state/auth-state';
|
export * from './auth-state/auth-state';
|
||||||
export * from './auth.module';
|
|
||||||
export * from './auto-login/auto-login-partial-routes.guard';
|
export * from './auto-login/auto-login-partial-routes.guard';
|
||||||
export * from './config/auth-well-known/auth-well-known-endpoints';
|
export * from './config/auth-well-known/auth-well-known-endpoints';
|
||||||
export * from './config/config.service';
|
export * from './config/config.service';
|
||||||
@ -31,3 +30,4 @@ export * from './validation/validation-result';
|
|||||||
export * from './injection';
|
export * from './injection';
|
||||||
export * from './router';
|
export * from './router';
|
||||||
export * from './http';
|
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 type { Module } from './module';
|
||||||
export { APP_INITIALIZER } from './convention';
|
|
||||||
export { injectAbstractType } from './inject';
|
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>
|
// biome-ignore lint/complexity/noBannedTypes: <explanation>
|
||||||
export interface AbstractType<T> extends Function {
|
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;
|
export type Module = (parentInjector: Injector) => Injector;
|
||||||
|
@ -1,11 +1,15 @@
|
|||||||
import { TestBed } from '@/testing';
|
|
||||||
import {
|
import {
|
||||||
|
type DefaultHttpTestingController,
|
||||||
HTTP_CLIENT_TEST_CONTROLLER,
|
HTTP_CLIENT_TEST_CONTROLLER,
|
||||||
|
TestBed,
|
||||||
provideHttpClientTesting,
|
provideHttpClientTesting,
|
||||||
} from '@/testing';
|
} from '@/testing';
|
||||||
import { HttpClient } from '@ngify/http';
|
import {
|
||||||
import type { HttpTestingController } from '@ngify/http/testing';
|
type DefaultHttpClient,
|
||||||
import { HTTP_INTERCEPTOR_FNS, HTTP_LEGACY_INTERCEPTORS } from 'oidc-client-rx';
|
HTTP_CLIENT,
|
||||||
|
HTTP_INTERCEPTOR_FNS,
|
||||||
|
HTTP_LEGACY_INTERCEPTORS,
|
||||||
|
} from 'oidc-client-rx';
|
||||||
import { ReplaySubject, firstValueFrom, share } from 'rxjs';
|
import { ReplaySubject, firstValueFrom, share } from 'rxjs';
|
||||||
import { vi } from 'vitest';
|
import { vi } from 'vitest';
|
||||||
import { AuthStateService } from '../auth-state/auth-state.service';
|
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';
|
import { ClosestMatchingRouteService } from './closest-matching-route.service';
|
||||||
|
|
||||||
describe('AuthHttpInterceptor', () => {
|
describe('AuthHttpInterceptor', () => {
|
||||||
let httpTestingController: HttpTestingController;
|
let httpTestingController: DefaultHttpTestingController;
|
||||||
let configurationService: ConfigurationService;
|
let configurationService: ConfigurationService;
|
||||||
let httpClient: HttpClient;
|
let httpClient: DefaultHttpClient;
|
||||||
let authStateService: AuthStateService;
|
let authStateService: AuthStateService;
|
||||||
let closestMatchingRouteService: ClosestMatchingRouteService;
|
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);
|
httpTestingController = TestBed.inject(HTTP_CLIENT_TEST_CONTROLLER);
|
||||||
configurationService = TestBed.inject(ConfigurationService);
|
configurationService = TestBed.inject(ConfigurationService);
|
||||||
authStateService = TestBed.inject(AuthStateService);
|
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);
|
httpTestingController = TestBed.inject(HTTP_CLIENT_TEST_CONTROLLER);
|
||||||
configurationService = TestBed.inject(ConfigurationService);
|
configurationService = TestBed.inject(ConfigurationService);
|
||||||
authStateService = TestBed.inject(AuthStateService);
|
authStateService = TestBed.inject(AuthStateService);
|
||||||
|
@ -6,7 +6,7 @@ import type {
|
|||||||
HttpInterceptorFn,
|
HttpInterceptorFn,
|
||||||
HttpRequest,
|
HttpRequest,
|
||||||
} from '@ngify/http';
|
} from '@ngify/http';
|
||||||
import { Injectable, inject } from 'injection-js';
|
import { Injectable, inject } from '@outposts/injection-js';
|
||||||
import type { Observable } from 'rxjs';
|
import type { Observable } from 'rxjs';
|
||||||
import { AuthStateService } from '../auth-state/auth-state.service';
|
import { AuthStateService } from '../auth-state/auth-state.service';
|
||||||
import { ConfigurationService } from '../config/config.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';
|
import type { OpenIdConfiguration } from '../config/openid-configuration';
|
||||||
|
|
||||||
@Injectable()
|
@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.
|
* 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';
|
import type { AbstractLoggerService } from './abstract-logger.service';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { Injectable } from 'injection-js';
|
import { Injectable } from '@outposts/injection-js';
|
||||||
import type { OpenIdConfiguration } from '../config/openid-configuration';
|
import type { OpenIdConfiguration } from '../config/openid-configuration';
|
||||||
import { injectAbstractType } from '../injection/inject';
|
import { injectAbstractType } from '../injection/inject';
|
||||||
import { AbstractLoggerService } from './abstract-logger.service';
|
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 Observable, of, throwError } from 'rxjs';
|
||||||
import type { AuthOptions } from '../auth-options';
|
import type { AuthOptions } from '../auth-options';
|
||||||
import type { OpenIdConfiguration } from '../config/openid-configuration';
|
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 { type Observable, of, throwError } from 'rxjs';
|
||||||
import { map, switchMap, take } from 'rxjs/operators';
|
import { map, switchMap, take } from 'rxjs/operators';
|
||||||
import type { AuthOptions } from '../../auth-options';
|
import type { AuthOptions } from '../../auth-options';
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { HttpHeaders } from '@ngify/http';
|
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 { type Observable, throwError } from 'rxjs';
|
||||||
import { catchError, map, retry, switchMap } from 'rxjs/operators';
|
import { catchError, map, retry, switchMap } from 'rxjs/operators';
|
||||||
import { DataService } from '../../api/data.service';
|
import { DataService } from '../../api/data.service';
|
||||||
@ -74,7 +74,8 @@ export class ParService {
|
|||||||
};
|
};
|
||||||
}),
|
}),
|
||||||
catchError((error) => {
|
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);
|
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 { type Observable, of, throwError } from 'rxjs';
|
||||||
import { switchMap, take, tap } from 'rxjs/operators';
|
import { switchMap, take, tap } from 'rxjs/operators';
|
||||||
import type { AuthOptions } from '../../auth-options';
|
import type { AuthOptions } from '../../auth-options';
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { DOCUMENT } from '../../dom';
|
import { Injectable, inject } from '@outposts/injection-js';
|
||||||
import { inject, Injectable } from 'injection-js';
|
|
||||||
import { type Observable, Subject } from 'rxjs';
|
import { type Observable, Subject } from 'rxjs';
|
||||||
import type { OpenIdConfiguration } from '../../config/openid-configuration';
|
import type { OpenIdConfiguration } from '../../config/openid-configuration';
|
||||||
|
import { DOCUMENT } from '../../dom';
|
||||||
import { LoggerService } from '../../logging/logger.service';
|
import { LoggerService } from '../../logging/logger.service';
|
||||||
import { StoragePersistenceService } from '../../storage/storage-persistence.service';
|
import { StoragePersistenceService } from '../../storage/storage-persistence.service';
|
||||||
import type { PopupOptions } from './popup-options';
|
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