root: Replace (npm + Corepack) with pnpm (#22830)

* Replace npm + Corepack with pnpm

Migrate package management from npm + Corepack to pnpm across the root,
web, and website workspaces:

- Swap npm/Corepack tooling for pnpm: drop package-lock.json files and the
  bespoke Corepack bootstrap scripts (setup-corepack.mjs, utils/corepack.mjs,
  lint-lockfile.mjs); add pnpm-lock.yaml + pnpm-workspace.yaml per workspace.
- CI uses the official pnpm/action-setup + actions/setup-node; pin the pnpm
  store dir via PNPM_HOME so setup-node's `cache: pnpm` post-step succeeds.
- Docker sources pnpm from the official ghcr.io/pnpm/pnpm image via a
  ${BUILDPLATFORM}-pinned stage; the website docs build does a hoisted root
  install so @goauthentik/docusaurus-config resolves its own deps.
- Gate the web install on the `node` dep so runtime-only jobs don't invoke
  pnpm; scope the from-stable env setup so the new tooling doesn't run against
  the stable checkout's npm packageManager field.
- Resolve @goauthentik/api (client-ts) from its TypeScript source instead of a
  tsc-built dist, so it no longer depends on an install-time prepare having run
  (the storybook build's environment never built it); sfe's rollup gains .ts
  resolution to match.
- Netlify builds with pnpm; encode pnpm's supply-chain controls
  (onlyBuiltDependencies/allowBuilds, minimumReleaseAge) in the workspace.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

Remove custom node action.

* Format.
This commit is contained in:
Teffen Ellis
2026-07-01 21:24:19 +02:00
committed by GitHub
parent dedf977eea
commit 928eefe098
66 changed files with 49464 additions and 99817 deletions

View File

@@ -1,77 +0,0 @@
name: "Setup Node.js and NPM"
description: "Sets up Node.js with a specific NPM version via Corepack"
inputs:
working-directory:
description: "Path to the working directory containing the package.json file"
required: false
default: "."
dependencies:
required: false
description: "List of dependencies to setup"
default: "monorepo,working-directory"
node-version-file:
description: "Path to file containing the Node.js version"
required: false
default: "package.json"
cache-dependency-path:
description: "Path to dependency lock file for caching"
required: false
default: "package-lock.json"
cache:
description: "Package manager to cache"
default: "npm"
registry-url:
description: "npm registry URL"
default: "https://registry.npmjs.org"
runs:
using: "composite"
steps:
- name: Setup Node.js (Corepack bootstrap)
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v4
with:
node-version-file: ${{ inputs.node-version-file }}
registry-url: ${{ inputs.registry-url }}
cache: ${{ inputs.cache }}
cache-dependency-path: |
${{ inputs.cache-dependency-path }}
${{ inputs.working-directory }}/${{ inputs.cache-dependency-path }}
- name: Install Corepack
working-directory: ${{ github.workspace}}
shell: bash
run: | #shell
node ./scripts/node/setup-corepack.mjs --force
corepack enable
- name: Lint Node.js and NPM versions
shell: bash
run: node ./scripts/node/lint-runtime.mjs
- name: Setup Node.js (Monorepo Root)
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v4
with:
node-version-file: ${{ inputs.node-version-file }}
registry-url: ${{ inputs.registry-url }}
- name: Install monorepo dependencies
if: ${{ contains(inputs.dependencies, 'monorepo') }}
shell: bash
run: | #shell
node ./scripts/node/lint-lockfile.mjs
corepack npm ci
- name: Setup Node.js (Working Directory)
if: ${{ contains(inputs.dependencies, 'working-directory') }}
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v4
with:
node-version-file: ${{ inputs.working-directory }}/${{ inputs.node-version-file }}
registry-url: ${{ inputs.registry-url }}
- name: Install working directory dependencies
if: ${{ contains(inputs.dependencies, 'working-directory') }}
shell: bash
run: | # shell
corepack install
echo "node version: $(node --version)"
echo "npm version: $(corepack npm --version)"
node ./scripts/node/lint-lockfile.mjs ${{ inputs.working-directory }}
corepack npm ci --prefix ${{ inputs.working-directory }}

View File

@@ -67,11 +67,30 @@ runs:
uses: taiki-e/install-action@bffeee26d4db9be238a4ea78d8826604ebcb594d # v2 uses: taiki-e/install-action@bffeee26d4db9be238a4ea78d8826604ebcb594d # v2
with: with:
tool: cargo-deny cargo-machete cargo-llvm-cov nextest tool: cargo-deny cargo-machete cargo-llvm-cov nextest
- name: Setup pnpm
if: ${{ contains(inputs.dependencies, 'node') }}
uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0
- name: Pin pnpm store directory
if: ${{ contains(inputs.dependencies, 'node') }}
shell: bash
run: |
echo "PNPM_HOME=${RUNNER_TEMP}/pnpm-home" >> "$GITHUB_ENV"
echo "npm_config_store_dir=${RUNNER_TEMP}/pnpm-home/store" >> "$GITHUB_ENV"
- name: Setup node (root, web) - name: Setup node (root, web)
if: ${{ contains(inputs.dependencies, 'node') }} if: ${{ contains(inputs.dependencies, 'node') }}
uses: ./.github/actions/setup-node uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v4
with: with:
working-directory: web node-version-file: package.json
cache: pnpm
cache-dependency-path: |
pnpm-lock.yaml
web/pnpm-lock.yaml
- name: Install node dependencies (root, web)
if: ${{ contains(inputs.dependencies, 'node') }}
shell: bash
run: |
pnpm install --frozen-lockfile
pnpm --dir web install --frozen-lockfile
- name: Setup go - name: Setup go
if: ${{ contains(inputs.dependencies, 'go') }} if: ${{ contains(inputs.dependencies, 'go') }}
uses: actions/setup-go@924ae3a1cded613372ab5595356fb5720e22ba16 # v5 uses: actions/setup-go@924ae3a1cded613372ab5595356fb5720e22ba16 # v5
@@ -89,7 +108,15 @@ runs:
run: | run: |
export PSQL_TAG=${{ inputs.postgresql_version }} export PSQL_TAG=${{ inputs.postgresql_version }}
docker compose -f .github/actions/setup/compose.yml up -d --wait docker compose -f .github/actions/setup/compose.yml up -d --wait
corepack npm ci --prefix web - name: Install web dependencies
# Only when node is also requested: pnpm is provided by the node setup
# above, and the web workspace needs a pnpm lockfile to install from. This
# keeps runtime-only jobs (e.g. rust, pending-migrations) and the legacy
# stable checkout — which predates the pnpm migration — from invoking pnpm.
if: ${{ contains(inputs.dependencies, 'runtime') && contains(inputs.dependencies, 'node') }}
shell: bash
working-directory: ${{ inputs.working-directory }}
run: pnpm --dir web install --frozen-lockfile
- name: Generate config - name: Generate config
if: ${{ contains(inputs.dependencies, 'python') }} if: ${{ contains(inputs.dependencies, 'python') }}
shell: uv run python {0} shell: uv run python {0}

View File

@@ -67,10 +67,20 @@ jobs:
registry: ghcr.io registry: ghcr.io
username: ${{ github.repository_owner }} username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }} password: ${{ secrets.GITHUB_TOKEN }}
- uses: ./.github/actions/setup-node - uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0
- name: Pin pnpm store directory
run: |
echo "PNPM_HOME=${RUNNER_TEMP}/pnpm-home" >> "$GITHUB_ENV"
echo "npm_config_store_dir=${RUNNER_TEMP}/pnpm-home/store" >> "$GITHUB_ENV"
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v4
with: with:
working-directory: web node-version-file: package.json
dependencies: "monorepo" cache: pnpm
cache-dependency-path: |
pnpm-lock.yaml
web/pnpm-lock.yaml
- name: Install monorepo dependencies
run: pnpm install --frozen-lockfile
- uses: actions/setup-go@924ae3a1cded613372ab5595356fb5720e22ba16 # v6 - uses: actions/setup-go@924ae3a1cded613372ab5595356fb5720e22ba16 # v6
with: with:
go-version-file: "go.mod" go-version-file: "go.mod"

View File

@@ -22,33 +22,59 @@ jobs:
- prettier-check - prettier-check
steps: steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v5 - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v5
- uses: ./.github/actions/setup-node - uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0
- name: Pin pnpm store directory
run: |
echo "PNPM_HOME=${RUNNER_TEMP}/pnpm-home" >> "$GITHUB_ENV"
echo "npm_config_store_dir=${RUNNER_TEMP}/pnpm-home/store" >> "$GITHUB_ENV"
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v4
with: with:
working-directory: website node-version-file: package.json
cache: pnpm
cache-dependency-path: |
pnpm-lock.yaml
website/pnpm-lock.yaml
- name: Install dependencies
run: |
pnpm install --frozen-lockfile
pnpm --dir website install --frozen-lockfile
- name: Lint - name: Lint
run: corepack npm run ${{ matrix.command }} --prefix website run: pnpm --dir website run ${{ matrix.command }}
build: build:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v5 - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v5
- uses: ./.github/actions/setup-node - uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0
- name: Pin pnpm store directory
run: |
echo "PNPM_HOME=${RUNNER_TEMP}/pnpm-home" >> "$GITHUB_ENV"
echo "npm_config_store_dir=${RUNNER_TEMP}/pnpm-home/store" >> "$GITHUB_ENV"
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v4
with: with:
working-directory: website node-version-file: package.json
cache: pnpm
cache-dependency-path: |
pnpm-lock.yaml
website/pnpm-lock.yaml
- name: Install dependencies
run: |
pnpm install --frozen-lockfile
pnpm --dir website install --frozen-lockfile
- uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v4 - uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v4
with: with:
path: | path: |
${{ github.workspace }}/website/api/.docusaurus ${{ github.workspace }}/website/api/.docusaurus
${{ github.workspace }}/website/api/**/.cache ${{ github.workspace }}/website/api/**/.cache
key: | key: |
${{ runner.os }}-docusaurus-${{ hashFiles('**/package-lock.json') }}-${{ hashFiles('**.[jt]s', '**.[jt]sx') }} ${{ runner.os }}-docusaurus-${{ hashFiles('**/pnpm-lock.yaml') }}-${{ hashFiles('**.[jt]s', '**.[jt]sx') }}
restore-keys: | restore-keys: |
${{ runner.os }}-docusaurus-${{ hashFiles('**/package-lock.json') }} ${{ runner.os }}-docusaurus-${{ hashFiles('**/pnpm-lock.yaml') }}
- name: Build API Docs via Docusaurus - name: Build API Docs via Docusaurus
working-directory: website working-directory: website
env: env:
NODE_ENV: production NODE_ENV: production
run: corepack npm run build -w api run: pnpm run build:api
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v4 - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v4
with: with:
name: api-docs name: api-docs
@@ -65,9 +91,22 @@ jobs:
with: with:
name: api-docs name: api-docs
path: website/api/build path: website/api/build
- uses: ./.github/actions/setup-node - uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0
- name: Pin pnpm store directory
run: |
echo "PNPM_HOME=${RUNNER_TEMP}/pnpm-home" >> "$GITHUB_ENV"
echo "npm_config_store_dir=${RUNNER_TEMP}/pnpm-home/store" >> "$GITHUB_ENV"
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v4
with: with:
working-directory: website node-version-file: package.json
cache: pnpm
cache-dependency-path: |
pnpm-lock.yaml
website/pnpm-lock.yaml
- name: Install dependencies
run: |
pnpm install --frozen-lockfile
pnpm --dir website install --frozen-lockfile
- name: Deploy Netlify (Production) - name: Deploy Netlify (Production)
working-directory: website/api working-directory: website/api
if: github.event_name == 'push' && github.ref == 'refs/heads/main' if: github.event_name == 'push' && github.ref == 'refs/heads/main'

View File

@@ -24,9 +24,18 @@ jobs:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v5 - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v5
- name: Setup authentik env - name: Setup authentik env
uses: ./.github/actions/setup uses: ./.github/actions/setup
- uses: ./.github/actions/setup-node - uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0
- name: Pin pnpm store directory
run: |
echo "PNPM_HOME=${RUNNER_TEMP}/pnpm-home" >> "$GITHUB_ENV"
echo "npm_config_store_dir=${RUNNER_TEMP}/pnpm-home/store" >> "$GITHUB_ENV"
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v4
with: with:
working-directory: lifecycle/aws node-version-file: package.json
cache: pnpm
cache-dependency-path: pnpm-lock.yaml
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Check changes have been applied - name: Check changes have been applied
run: | run: |
uv run make aws-cfn uv run make aws-cfn

View File

@@ -27,6 +27,4 @@ jobs:
env: env:
NETLIFY_SITE_ID: eb246b7b-1d83-4f69-89f7-01a936b4ca59 NETLIFY_SITE_ID: eb246b7b-1d83-4f69-89f7-01a936b4ca59
NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }} NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }}
run: | run: pnpm dlx netlify-cli deploy --dir=source_docs --prod
npm install -g netlify-cli
netlify deploy --dir=source_docs --prod

View File

@@ -24,34 +24,73 @@ jobs:
- prettier-check - prettier-check
steps: steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v5 - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v5
- uses: ./.github/actions/setup-node - uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0
- name: Pin pnpm store directory
run: |
echo "PNPM_HOME=${RUNNER_TEMP}/pnpm-home" >> "$GITHUB_ENV"
echo "npm_config_store_dir=${RUNNER_TEMP}/pnpm-home/store" >> "$GITHUB_ENV"
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v4
with: with:
working-directory: website node-version-file: package.json
cache: pnpm
cache-dependency-path: |
pnpm-lock.yaml
website/pnpm-lock.yaml
- name: Install dependencies
run: |
pnpm install --frozen-lockfile
pnpm --dir website install --frozen-lockfile
- name: Lint - name: Lint
run: corepack npm run ${{ matrix.command }} --prefix website run: pnpm --dir website run ${{ matrix.command }}
build-docs: build-docs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
env: env:
NODE_ENV: production NODE_ENV: production
steps: steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v5 - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v5
- uses: ./.github/actions/setup-node - uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0
- name: Pin pnpm store directory
run: |
echo "PNPM_HOME=${RUNNER_TEMP}/pnpm-home" >> "$GITHUB_ENV"
echo "npm_config_store_dir=${RUNNER_TEMP}/pnpm-home/store" >> "$GITHUB_ENV"
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v4
name: Setup Node.js name: Setup Node.js
with: with:
working-directory: website node-version-file: package.json
cache: pnpm
cache-dependency-path: |
pnpm-lock.yaml
website/pnpm-lock.yaml
- name: Install dependencies
run: |
pnpm install --frozen-lockfile
pnpm --dir website install --frozen-lockfile
- name: Build Documentation via Docusaurus - name: Build Documentation via Docusaurus
run: corepack npm run build --prefix website run: pnpm --dir website run build
build-integrations: build-integrations:
runs-on: ubuntu-latest runs-on: ubuntu-latest
env: env:
NODE_ENV: production NODE_ENV: production
steps: steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v5 - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v5
- uses: ./.github/actions/setup-node - uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0
- name: Pin pnpm store directory
run: |
echo "PNPM_HOME=${RUNNER_TEMP}/pnpm-home" >> "$GITHUB_ENV"
echo "npm_config_store_dir=${RUNNER_TEMP}/pnpm-home/store" >> "$GITHUB_ENV"
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v4
with: with:
working-directory: website node-version-file: package.json
cache: pnpm
cache-dependency-path: |
pnpm-lock.yaml
website/pnpm-lock.yaml
- name: Install dependencies
run: |
pnpm install --frozen-lockfile
pnpm --dir website install --frozen-lockfile
- name: Build Integrations via Docusaurus - name: Build Integrations via Docusaurus
run: corepack npm run build -w integrations --prefix website run: pnpm --dir website run build:integrations
build-container: build-container:
runs-on: ubuntu-latest runs-on: ubuntu-latest
permissions: permissions:

View File

@@ -134,6 +134,11 @@ jobs:
uses: ./.github/actions/setup uses: ./.github/actions/setup
with: with:
postgresql_version: ${{ matrix.psql }} postgresql_version: ${{ matrix.psql }}
# The stable checkout predates the pnpm migration, so its
# package.json still pins npm as the package manager. Skip node here
# (migrating to stable only needs Python + the database); pnpm/node is
# set up again for the current checkout below.
dependencies: "system,python,runtime"
- name: run migrations to stable - name: run migrations to stable
run: | run: |
docker ps docker ps
@@ -260,22 +265,33 @@ jobs:
COMPOSE_PROFILES: ${{ matrix.job.profiles }} COMPOSE_PROFILES: ${{ matrix.job.profiles }}
run: | run: |
docker compose -f tests/e2e/compose.yml up -d --quiet-pull docker compose -f tests/e2e/compose.yml up -d --quiet-pull
- uses: ./.github/actions/setup-node - uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0
- name: Pin pnpm store directory
run: |
echo "PNPM_HOME=${RUNNER_TEMP}/pnpm-home" >> "$GITHUB_ENV"
echo "npm_config_store_dir=${RUNNER_TEMP}/pnpm-home/store" >> "$GITHUB_ENV"
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v4
with:
node-version-file: package.json
cache: pnpm
cache-dependency-path: pnpm-lock.yaml
- name: Install dependencies
run: pnpm install --frozen-lockfile
- id: cache-web - id: cache-web
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v4 uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v4
if: contains(matrix.job.profiles, 'selenium') if: contains(matrix.job.profiles, 'selenium')
with: with:
path: web/dist path: web/dist
key: ${{ runner.os }}-web-${{ hashFiles('web/package-lock.json', 'package-lock.json', 'web/src/**', 'web/packages/sfe/src/**') }}-b key: ${{ runner.os }}-web-${{ hashFiles('web/pnpm-lock.yaml', 'pnpm-lock.yaml', 'web/src/**', 'web/packages/sfe/src/**') }}-b
- name: prepare web ui - name: prepare web ui
if: steps.cache-web.outputs.cache-hit != 'true' && contains(matrix.job.profiles, 'selenium') if: steps.cache-web.outputs.cache-hit != 'true' && contains(matrix.job.profiles, 'selenium')
working-directory: web working-directory: web
env: env:
NODE_ENV: "production" NODE_ENV: "production"
run: | run: |
corepack npm ci pnpm install --frozen-lockfile
corepack npm run build pnpm run build
corepack npm run build:sfe pnpm run build:sfe
- name: run e2e - name: run e2e
run: | run: |
uv run coverage run manage.py test ${{ matrix.job.glob }} uv run coverage run manage.py test ${{ matrix.job.glob }}
@@ -321,15 +337,15 @@ jobs:
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v4 uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v4
with: with:
path: web/dist path: web/dist
key: ${{ runner.os }}-web-${{ hashFiles('web/package-lock.json', 'web/src/**', 'web/packages/sfe/src/**') }}-b key: ${{ runner.os }}-web-${{ hashFiles('web/pnpm-lock.yaml', 'web/src/**', 'web/packages/sfe/src/**') }}-b
- name: prepare web ui - name: prepare web ui
if: steps.cache-web.outputs.cache-hit != 'true' if: steps.cache-web.outputs.cache-hit != 'true'
env: env:
NODE_ENV: "production" NODE_ENV: "production"
run: | run: |
corepack npm ci --prefix web pnpm --dir web install --frozen-lockfile
corepack npm run build --prefix web pnpm --dir web run build
corepack npm run build:sfe --prefix web pnpm --dir web run build:sfe
- name: run conformance - name: run conformance
run: | run: |
uv run coverage run manage.py test ${{ matrix.job.glob }} uv run coverage run manage.py test ${{ matrix.job.glob }}

View File

@@ -145,11 +145,24 @@ jobs:
- uses: actions/setup-go@924ae3a1cded613372ab5595356fb5720e22ba16 # v6 - uses: actions/setup-go@924ae3a1cded613372ab5595356fb5720e22ba16 # v6
with: with:
go-version-file: "go.mod" go-version-file: "go.mod"
- uses: ./.github/actions/setup-node - uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0
- name: Pin pnpm store directory
run: |
echo "PNPM_HOME=${RUNNER_TEMP}/pnpm-home" >> "$GITHUB_ENV"
echo "npm_config_store_dir=${RUNNER_TEMP}/pnpm-home/store" >> "$GITHUB_ENV"
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v4
with: with:
working-directory: web node-version-file: package.json
cache: pnpm
cache-dependency-path: |
pnpm-lock.yaml
web/pnpm-lock.yaml
- name: Install dependencies
run: |
pnpm install --frozen-lockfile
pnpm --dir web install --frozen-lockfile
- name: Build web - name: Build web
run: corepack npm run build-proxy --prefix web run: pnpm --dir web run build-proxy
- name: Build outpost - name: Build outpost
run: | run: |
set -x set -x

View File

@@ -18,31 +18,57 @@ jobs:
timeout-minutes: 15 timeout-minutes: 15
steps: steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v5 - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v5
- uses: ./.github/actions/setup-node - uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0
- name: Pin pnpm store directory
run: |
echo "PNPM_HOME=${RUNNER_TEMP}/pnpm-home" >> "$GITHUB_ENV"
echo "npm_config_store_dir=${RUNNER_TEMP}/pnpm-home/store" >> "$GITHUB_ENV"
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v4
with: with:
working-directory: web node-version-file: package.json
cache: pnpm
cache-dependency-path: |
pnpm-lock.yaml
web/pnpm-lock.yaml
- name: Install dependencies
run: |
pnpm install --frozen-lockfile
pnpm --dir web install --frozen-lockfile
- name: Lint - name: Lint
run: corepack npm run lint-check --prefix web run: pnpm --dir web run lint-check
- name: Check types - name: Check types
run: corepack npm run tsc --prefix web run: pnpm --dir web run tsc
- name: Check formatting - name: Check formatting
run: corepack npm run prettier-check --prefix web run: pnpm --dir web run prettier-check
- name: Lit analyse - name: Lit analyse
run: corepack npm run lit-analyse --prefix web run: pnpm --dir web run lit-analyse
build: build:
runs-on: ubuntu-latest runs-on: ubuntu-latest
timeout-minutes: 15 timeout-minutes: 15
steps: steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v5 - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v5
- uses: ./.github/actions/setup-node - uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0
- name: Pin pnpm store directory
run: |
echo "PNPM_HOME=${RUNNER_TEMP}/pnpm-home" >> "$GITHUB_ENV"
echo "npm_config_store_dir=${RUNNER_TEMP}/pnpm-home/store" >> "$GITHUB_ENV"
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v4
with: with:
working-directory: web node-version-file: package.json
cache: pnpm
cache-dependency-path: |
pnpm-lock.yaml
web/pnpm-lock.yaml
- name: Install dependencies
run: |
pnpm install --frozen-lockfile
pnpm --dir web install --frozen-lockfile
- name: build - name: build
env: env:
NODE_ENV: "production" NODE_ENV: "production"
working-directory: web/ working-directory: web/
run: corepack npm run build run: pnpm run build
ci-web-mark: ci-web-mark:
if: always() if: always()
needs: needs:
@@ -60,9 +86,22 @@ jobs:
timeout-minutes: 30 timeout-minutes: 30
steps: steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v5 - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v5
- uses: ./.github/actions/setup-node - uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0
- name: Pin pnpm store directory
run: |
echo "PNPM_HOME=${RUNNER_TEMP}/pnpm-home" >> "$GITHUB_ENV"
echo "npm_config_store_dir=${RUNNER_TEMP}/pnpm-home/store" >> "$GITHUB_ENV"
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v4
with: with:
working-directory: web node-version-file: package.json
cache: pnpm
cache-dependency-path: |
pnpm-lock.yaml
web/pnpm-lock.yaml
- name: Install dependencies
run: |
pnpm install --frozen-lockfile
pnpm --dir web install --frozen-lockfile
- name: test - name: test
working-directory: web/ working-directory: web/
run: corepack npm run test || exit 0 run: pnpm run test || exit 0

View File

@@ -35,9 +35,19 @@ jobs:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v5 - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v5
with: with:
fetch-depth: 2 fetch-depth: 2
- uses: ./.github/actions/setup-node - uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0
- name: Pin pnpm store directory
run: |
echo "PNPM_HOME=${RUNNER_TEMP}/pnpm-home" >> "$GITHUB_ENV"
echo "npm_config_store_dir=${RUNNER_TEMP}/pnpm-home/store" >> "$GITHUB_ENV"
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v4
with: with:
working-directory: ${{ matrix.package }} node-version-file: package.json
registry-url: https://registry.npmjs.org
cache: pnpm
cache-dependency-path: pnpm-lock.yaml
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Get changed files - name: Get changed files
id: changed-files id: changed-files
uses: tj-actions/changed-files@9426d40962ed5378910ee2e21d5f8c6fcbf2dd96 # 24d32ffd492484c1d75e0c0b894501ddb9d30d62 uses: tj-actions/changed-files@9426d40962ed5378910ee2e21d5f8c6fcbf2dd96 # 24d32ffd492484c1d75e0c0b894501ddb9d30d62
@@ -48,6 +58,5 @@ jobs:
if: steps.changed-files.outputs.any_changed == 'true' if: steps.changed-files.outputs.any_changed == 'true'
working-directory: ${{ matrix.package }} working-directory: ${{ matrix.package }}
run: | run: |
corepack npm ci pnpm run build
corepack npm run build pnpm publish --no-git-checks
corepack npm publish

View File

@@ -87,9 +87,22 @@ jobs:
- uses: actions/setup-go@924ae3a1cded613372ab5595356fb5720e22ba16 # v6 - uses: actions/setup-go@924ae3a1cded613372ab5595356fb5720e22ba16 # v6
with: with:
go-version-file: "go.mod" go-version-file: "go.mod"
- uses: ./.github/actions/setup-node - uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0
- name: Pin pnpm store directory
run: |
echo "PNPM_HOME=${RUNNER_TEMP}/pnpm-home" >> "$GITHUB_ENV"
echo "npm_config_store_dir=${RUNNER_TEMP}/pnpm-home/store" >> "$GITHUB_ENV"
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v4
with: with:
working-directory: web node-version-file: package.json
cache: pnpm
cache-dependency-path: |
pnpm-lock.yaml
web/pnpm-lock.yaml
- name: Install dependencies
run: |
pnpm install --frozen-lockfile
pnpm --dir web install --frozen-lockfile
- name: Set up QEMU - name: Set up QEMU
uses: docker/setup-qemu-action@06116385d9baf250c9f4dcb4858b16962ea869c3 # v4.1.0 uses: docker/setup-qemu-action@06116385d9baf250c9f4dcb4858b16962ea869c3 # v4.1.0
- name: Set up Docker Buildx - name: Set up Docker Buildx
@@ -149,13 +162,26 @@ jobs:
- uses: actions/setup-go@924ae3a1cded613372ab5595356fb5720e22ba16 # v6 - uses: actions/setup-go@924ae3a1cded613372ab5595356fb5720e22ba16 # v6
with: with:
go-version-file: "go.mod" go-version-file: "go.mod"
- uses: ./.github/actions/setup-node - uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0
- name: Pin pnpm store directory
run: |
echo "PNPM_HOME=${RUNNER_TEMP}/pnpm-home" >> "$GITHUB_ENV"
echo "npm_config_store_dir=${RUNNER_TEMP}/pnpm-home/store" >> "$GITHUB_ENV"
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v4
with: with:
working-directory: web node-version-file: package.json
cache: pnpm
cache-dependency-path: |
pnpm-lock.yaml
web/pnpm-lock.yaml
- name: Install dependencies
run: |
pnpm install --frozen-lockfile
pnpm --dir web install --frozen-lockfile
- name: Build web - name: Build web
working-directory: web/ working-directory: web/
run: | run: |
npm run build-proxy pnpm run build-proxy
- name: Build outpost - name: Build outpost
run: | run: |
set -x set -x

2
.gitignore vendored
View File

@@ -14,8 +14,6 @@ media
# Node # Node
node_modules node_modules
corepack.tgz
.corepack
.cspellcache .cspellcache
cspell-report.* cspell-report.*

21
.npmrc
View File

@@ -1,20 +1,13 @@
# Block lifecycle scripts (preinstall/install/postinstall/prepare) from dependencies. # Fail fast if the active Node/pnpm doesn't match the "engines" field.
# This neutralizes the dominant npm supply-chain attack vector.
#
# Packages that legitimately need a build step (e.g. esbuild, chromedriver, tree-sitter)
# must be rebuilt explicitly:
#
# npm rebuild --foreground-scripts esbuild chromedriver tree-sitter tree-sitter-json
ignore-scripts=true
# Fail fast if the active Node/npm doesn't match the "engines" field.
engine-strict=true engine-strict=true
# Pin exact versions so `npm install <pkg>` writes "1.2.3" not "^1.2.3". # Pin exact versions so `pnpm add <pkg>` writes "1.2.3" not "^1.2.3".
save-exact=true save-exact=true
# Surface CVE warnings during install; doesn't block.
audit=true
# Suppress funding banners. # Suppress funding banners.
fund=false fund=false
# Lifecycle scripts are blocked by default in pnpm 10+. Per-project
# allow-lists live in the `pnpm.onlyBuiltDependencies` field of each
# `package.json` (replaces the prior `npm rebuild --foreground-scripts`
# dance keyed off `.npmrc`'s `ignore-scripts`).

View File

@@ -23,6 +23,10 @@ website/api/reference
## Yarn ## Yarn
.yarn/**/* .yarn/**/*
# PNPM
pnpm-workspace.yaml
pnpm-lock.yaml
## Node ## Node
node_modules node_modules
coverage coverage
@@ -50,4 +54,3 @@ src/locales/
# Storybook # Storybook
storybook-static/ storybook-static/
.storybook/css-import-maps* .storybook/css-import-maps*

View File

@@ -107,8 +107,8 @@ migrate: ## Run the Authentik Django server's migrations
i18n-extract: core-i18n-extract web-i18n-extract ## Extract strings that require translation into files to send to a translation service i18n-extract: core-i18n-extract web-i18n-extract ## Extract strings that require translation into files to send to a translation service
aws-cfn: node-install aws-cfn: node-install
corepack npm install --prefix lifecycle/aws pnpm --dir lifecycle/aws install
$(UV) run corepack npm run aws-cfn --prefix lifecycle/aws $(UV) run pnpm --dir lifecycle/aws run aws-cfn
run: ## Run the main authentik server and worker processes run: ## Run the main authentik server and worker processes
$(UV) run ak allinone $(UV) run ak allinone
@@ -163,7 +163,7 @@ endif
$(SED_INPLACE) 's/^VERSION = ".*"/VERSION = "$(version)"/' ${PWD}/authentik/__init__.py $(SED_INPLACE) 's/^VERSION = ".*"/VERSION = "$(version)"/' ${PWD}/authentik/__init__.py
$(SED_INPLACE) "s/version = \"${current_version}\"/version = \"$(version)\"/" ${PWD}/Cargo.toml ${PWD}/Cargo.lock $(SED_INPLACE) "s/version = \"${current_version}\"/version = \"$(version)\"/" ${PWD}/Cargo.toml ${PWD}/Cargo.lock
$(MAKE) gen-build gen-compose aws-cfn $(MAKE) gen-build gen-compose aws-cfn
$(SED_INPLACE) "s/\"${current_version}\"/\"$(version)\"/" ${PWD}/package.json ${PWD}/package-lock.json ${PWD}/web/package.json ${PWD}/web/package-lock.json $(SED_INPLACE) "s/\"${current_version}\"/\"$(version)\"/" ${PWD}/package.json ${PWD}/web/package.json
echo -n $(version) > ${PWD}/internal/constants/VERSION echo -n $(version) > ${PWD}/internal/constants/VERSION
######################### #########################
@@ -214,7 +214,7 @@ gen-client-rust: ## Build and install the authentik API for Rust
gen-client-ts: ## Build and install the authentik API for Typescript into the authentik UI Application gen-client-ts: ## Build and install the authentik API for Typescript into the authentik UI Application
make -C "${PWD}/packages/client-ts" build make -C "${PWD}/packages/client-ts" build
npm --prefix web install pnpm --dir web install
_gen-clients: gen-client-go gen-client-rust gen-client-ts _gen-clients: gen-client-go gen-client-rust gen-client-ts
gen-clients: ## Build and install API clients used by authentik gen-clients: ## Build and install API clients used by authentik
@@ -229,55 +229,48 @@ gen-dev-config: ## Generate a local development config file
## Node.js ## Node.js
######################### #########################
# Packages whose install/postinstall scripts are required for correct # Lifecycle scripts are blocked by default in pnpm 10+ via
# operation (binary downloads, native bindings). The root .npmrc sets # `pnpm-workspace.yaml#onlyBuiltDependencies`. Adding a package to that list
# `ignore-scripts=true` to block dependency lifecycle scripts by default; # grants it arbitrary code execution at install — audit at review time.
# this list is rebuilt explicitly with scripts re-enabled. Audit any
# additions: each entry runs arbitrary code at install time.
TRUSTED_INSTALL_SCRIPTS := esbuild chromedriver tree-sitter tree-sitter-json
node-preinstall: ## Install corepack and lint the runtime to ensure the correct Node.js version is being used before installing dependencies. node-preinstall: ## Verify the active Node.js and pnpm versions match what's in package.json.
node ./scripts/node/setup-corepack.mjs
node ./scripts/node/lint-runtime.mjs node ./scripts/node/lint-runtime.mjs
node-install: node-preinstall ## Install the necessary libraries to build Node.js packages node-install: node-preinstall ## Install the necessary libraries to build Node.js packages
corepack npm ci pnpm install --frozen-lockfile
######################### #########################
## Web ## Web
######################### #########################
web-install: ## Install the necessary libraries to build the Authentik UI web-install: ## Install the necessary libraries to build the Authentik UI
corepack npm ci --prefix web pnpm --dir web install --frozen-lockfile
web-postinstall: ## Trigger postinstall scripts for packages with native bindings or binary downloads, which are blocked by default for security reasons.
corepack npm rebuild --prefix web --ignore-scripts=false --foreground-scripts $(TRUSTED_INSTALL_SCRIPTS)
web-build: node-install ## Build the Authentik UI web-build: node-install ## Build the Authentik UI
corepack npm run --prefix web build pnpm --dir web run build
web: web-lint-fix web-lint web-check-compile ## Automatically fix formatting issues in the Authentik UI source code, lint the code, and compile it web: web-lint-fix web-lint web-check-compile ## Automatically fix formatting issues in the Authentik UI source code, lint the code, and compile it
web-test: ## Run tests for the Authentik UI web-test: ## Run tests for the Authentik UI
corepack npm run --prefix web test pnpm --dir web run test
web-watch: ## Build and watch the Authentik UI for changes, updating automatically web-watch: ## Build and watch the Authentik UI for changes, updating automatically
corepack npm run --prefix web watch pnpm --dir web run watch
web-storybook-watch: ## Build and run the storybook documentation server web-storybook-watch: ## Build and run the storybook documentation server
corepack npm run --prefix web storybook pnpm --dir web run storybook
web-lint-fix: web-lint-fix:
corepack npm run --prefix web prettier pnpm --dir web run prettier
web-lint: web-lint:
corepack npm run --prefix web lint pnpm --dir web run lint
corepack npm run --prefix web lit-analyse pnpm --dir web run lit-analyse
web-check-compile: web-check-compile:
corepack npm run --prefix web tsc pnpm --dir web run tsc
web-i18n-extract: web-i18n-extract:
corepack npm run --prefix web extract-locales pnpm --dir web run extract-locales
######################### #########################
## Docs ## Docs
@@ -286,35 +279,35 @@ web-i18n-extract:
docs: docs-lint-fix docs-build ## Automatically fix formatting issues in the Authentik docs source code, lint the code, and compile it docs: docs-lint-fix docs-build ## Automatically fix formatting issues in the Authentik docs source code, lint the code, and compile it
docs-install: node-install ## Install the necessary libraries to build the Authentik documentation docs-install: node-install ## Install the necessary libraries to build the Authentik documentation
corepack npm ci --prefix website pnpm --dir website install --frozen-lockfile
docs-lint-fix: lint-spellcheck docs-lint-fix: lint-spellcheck
corepack npm run --prefix website prettier pnpm --dir website run prettier
docs-build: docs-build:
node ./scripts/node/lint-runtime.mjs website node ./scripts/node/lint-runtime.mjs website
corepack npm run --prefix website build pnpm --dir website run build
docs-watch: ## Build and watch the topics documentation docs-watch: ## Build and watch the topics documentation
corepack npm run --prefix website start pnpm --dir website run start
integrations: docs-lint-fix integrations-build ## Fix formatting issues in the integrations source code, lint the code, and compile it integrations: docs-lint-fix integrations-build ## Fix formatting issues in the integrations source code, lint the code, and compile it
integrations-build: integrations-build:
corepack npm run --prefix website -w integrations build pnpm --dir website run build:integrations
integrations-watch: ## Build and watch the Integrations documentation integrations-watch: ## Build and watch the Integrations documentation
corepack npm run --prefix website -w integrations start pnpm --filter "./website/integrations" run start
docs-api-build: docs-api-build:
corepack npm run --prefix website -w api build pnpm --dir website run build:api
docs-api-watch: ## Build and watch the API documentation docs-api-watch: ## Build and watch the API documentation
corepack npm run --prefix website -w api generate pnpm --filter "./website/api" run generate
corepack npm run --prefix website -w api start pnpm --filter "./website/api" run start
docs-api-clean: ## Clean generated API documentation docs-api-clean: ## Clean generated API documentation
corepack npm run --prefix website -w api build:api:clean pnpm --filter "./website/api" run clean
######################### #########################
## Docker ## Docker

View File

@@ -301,7 +301,8 @@
"LICENSE", // License file "LICENSE", // License file
".gitignore", // Git ignore file ".gitignore", // Git ignore file
".gitattributes", // Git attributes file ".gitattributes", // Git attributes file
"*-lock.{json,yaml}", // Lock files (NPM, Yarn, Pip, Cargo) "*-lock.{json,yaml}", // Lock files (NPM, Yarn, Pnpm, Pip, Cargo)
"pnpm-workspace.yaml", // PNPM workspace + override config
"CHANGELOG*.md", // Changelog files "CHANGELOG*.md", // Changelog files
".vscode/**", // VSCode configuration ".vscode/**", // VSCode configuration
"out", // TypeScript type-checking output "out", // TypeScript type-checking output

View File

@@ -1,130 +0,0 @@
{
"name": "@goauthentik/lifecycle-aws",
"version": "0.0.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "@goauthentik/lifecycle-aws",
"version": "0.0.0",
"license": "MIT",
"devDependencies": {
"aws-cdk": "^2.1128.1",
"cross-env": "^10.1.0"
},
"engines": {
"node": ">=24",
"npm": ">=11.14.1"
}
},
"node_modules/@epic-web/invariant": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/@epic-web/invariant/-/invariant-1.0.0.tgz",
"integrity": "sha512-lrTPqgvfFQtR/eY/qkIzp98OGdNJu0m5ji3q/nJI8v3SXkRKEnWiOxMmbvcSoAIzv/cGiuvRy57k4suKQSAdwA==",
"dev": true,
"license": "MIT"
},
"node_modules/aws-cdk": {
"version": "2.1128.1",
"resolved": "https://registry.npmjs.org/aws-cdk/-/aws-cdk-2.1128.1.tgz",
"integrity": "sha512-y9OHn5/BOcIiq409vPvpypMIr7/8M1ScFe8IkFMSCN1/GI/5c73fQ4pfzNq+VDkj86T5zxs7BQ1qU2lQQytdXA==",
"dev": true,
"license": "Apache-2.0",
"bin": {
"cdk": "bin/cdk"
},
"engines": {
"node": ">= 18.0.0"
}
},
"node_modules/cross-env": {
"version": "10.1.0",
"resolved": "https://registry.npmjs.org/cross-env/-/cross-env-10.1.0.tgz",
"integrity": "sha512-GsYosgnACZTADcmEyJctkJIoqAhHjttw7RsFrVoJNXbsWWqaq6Ym+7kZjq6mS45O0jij6vtiReppKQEtqWy6Dw==",
"dev": true,
"license": "MIT",
"dependencies": {
"@epic-web/invariant": "^1.0.0",
"cross-spawn": "^7.0.6"
},
"bin": {
"cross-env": "dist/bin/cross-env.js",
"cross-env-shell": "dist/bin/cross-env-shell.js"
},
"engines": {
"node": ">=20"
}
},
"node_modules/cross-spawn": {
"version": "7.0.6",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
"integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
"dev": true,
"license": "MIT",
"dependencies": {
"path-key": "^3.1.0",
"shebang-command": "^2.0.0",
"which": "^2.0.1"
},
"engines": {
"node": ">= 8"
}
},
"node_modules/isexe": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
"integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
"dev": true,
"license": "ISC"
},
"node_modules/path-key": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
"integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=8"
}
},
"node_modules/shebang-command": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
"integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
"dev": true,
"license": "MIT",
"dependencies": {
"shebang-regex": "^3.0.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/shebang-regex": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
"integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=8"
}
},
"node_modules/which": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
"integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
"dev": true,
"license": "ISC",
"dependencies": {
"isexe": "^2.0.0"
},
"bin": {
"node-which": "bin/node-which"
},
"engines": {
"node": ">= 8"
}
}
}
}

View File

@@ -12,19 +12,14 @@
}, },
"engines": { "engines": {
"node": ">=24", "node": ">=24",
"npm": ">=11.14.1" "pnpm": ">=11.5.1"
}, },
"devEngines": { "devEngines": {
"runtime": { "runtime": {
"name": "node", "name": "node",
"onFail": "warn", "onFail": "warn",
"version": ">=24" "version": ">=24"
},
"packageManager": {
"name": "npm",
"version": ">=11.14.1",
"onFail": "warn"
} }
}, },
"packageManager": "npm@11.14.1+sha512.6a8a4d67478497a2dbc6815cad72e64c43f33413717e242756047d466241ab39bee61e691683a64658e94496ec5f1a1c05e4a5ec62dcc773280dfd949443a367" "packageManager": "pnpm@11.5.1+sha512.93f7b57422ea7068257235b4c16eb60762eb68e1dc23723199cc739043ea9be2c4143274a399d8c6defa2b1176226d9ca1c4b63482d6200c1a8fbaa78c1d1485"
} }

View File

@@ -1,5 +1,9 @@
# syntax=docker/dockerfile:1 # syntax=docker/dockerfile:1
# Tag must track the root package.json `packageManager` version. ${BUILDPLATFORM}
# keeps the binary's arch aligned with the builder stage on cross-arch builds.
FROM --platform=${BUILDPLATFORM} ghcr.io/pnpm/pnpm:11.5.1@sha256:3cbdefab0d887dee497ddc8dfe6d871257317d69520fe30f9ccec0a84bde6e89 AS pnpm
# Stage: Build webui # Stage: Build webui
FROM --platform=${BUILDPLATFORM} docker.io/library/node:26-trixie-slim@sha256:a1d9d671994fc2d26e297ac56b4b1522a8bc7fa71c43b14cd1b1fe6c5116f7dc AS node-builder FROM --platform=${BUILDPLATFORM} docker.io/library/node:26-trixie-slim@sha256:a1d9d671994fc2d26e297ac56b4b1522a8bc7fa71c43b14cd1b1fe6c5116f7dc AS node-builder
@@ -9,36 +13,38 @@ ENV NODE_ENV=production
WORKDIR /work WORKDIR /work
COPY --from=pnpm /opt/pnpm /opt/pnpm
ENV PATH="/opt/pnpm:${PATH}"
RUN --mount=type=bind,target=/work/package.json,src=./package.json \ RUN --mount=type=bind,target=/work/package.json,src=./package.json \
--mount=type=bind,target=/work/package-lock.json,src=./package-lock.json \
--mount=type=bind,target=/work/web/package.json,src=./web/package.json \ --mount=type=bind,target=/work/web/package.json,src=./web/package.json \
--mount=type=bind,target=/work/web/package-lock.json,src=./web/package-lock.json \ --mount=type=bind,target=/work/web/pnpm-lock.yaml,src=./web/pnpm-lock.yaml \
--mount=type=bind,target=/work/scripts/node/,src=./scripts/node/ \ --mount=type=bind,target=/work/scripts/node/,src=./scripts/node/ \
--mount=type=bind,target=/work/packages/logger-js/,src=./packages/logger-js/ \ --mount=type=bind,target=/work/packages/logger-js/,src=./packages/logger-js/ \
node ./scripts/node/setup-corepack.mjs --force && \
node ./scripts/node/lint-runtime.mjs ./web node ./scripts/node/lint-runtime.mjs ./web
WORKDIR /work/web WORKDIR /work/web
# These files need to be copied and cannot be mounted as `npm ci` will build the client's typescript # These files need to be copied and cannot be mounted as `pnpm install` will build the client's typescript
COPY ./packages /work/packages COPY ./packages /work/packages
COPY ./web/packages /work/web/packages COPY ./web/packages /work/web/packages
RUN --mount=type=bind,target=/work/.npmrc,src=./.npmrc \ RUN --mount=type=bind,target=/work/.npmrc,src=./.npmrc \
--mount=type=bind,target=/work/web/package.json,src=./web/package.json \ --mount=type=bind,target=/work/web/package.json,src=./web/package.json \
--mount=type=bind,target=/work/web/package-lock.json,src=./web/package-lock.json \ --mount=type=bind,target=/work/web/pnpm-lock.yaml,src=./web/pnpm-lock.yaml \
--mount=type=bind,target=/work/web/pnpm-workspace.yaml,src=./web/pnpm-workspace.yaml \
--mount=type=bind,target=/work/web/packages/sfe/package.json,src=./web/packages/sfe/package.json \ --mount=type=bind,target=/work/web/packages/sfe/package.json,src=./web/packages/sfe/package.json \
--mount=type=bind,target=/work/web/scripts,src=./web/scripts \ --mount=type=bind,target=/work/web/scripts,src=./web/scripts \
--mount=type=cache,id=npm-ak,sharing=shared,target=/root/.npm \ --mount=type=cache,id=pnpm-ak,sharing=shared,target=/root/.local/share/pnpm/store \
corepack npm ci pnpm install --frozen-lockfile
COPY ./package.json /work COPY ./package.json /work
COPY ./web /work/web/ COPY ./web /work/web/
# TODO: Update this after moving website to docs # TODO: Update this after moving website to docs
COPY ./website /work/website/ COPY ./website /work/website/
RUN npm run build && \ RUN pnpm run build && \
npm run build:sfe pnpm run build:sfe
# Stage: Build go proxy # Stage: Build go proxy
FROM --platform=${BUILDPLATFORM} docker.io/library/golang:1.26.4-trixie@sha256:68b7145ec43d1820b9a56704554b53d1520aa2a15cb5233e374188a31b2a1bce AS go-builder FROM --platform=${BUILDPLATFORM} docker.io/library/golang:1.26.4-trixie@sha256:68b7145ec43d1820b9a56704554b53d1520aa2a15cb5233e374188a31b2a1bce AS go-builder

View File

@@ -1,35 +1,41 @@
# syntax=docker/dockerfile:1 # syntax=docker/dockerfile:1
# Tag must track the root package.json `packageManager` version. ${BUILDPLATFORM}
# keeps the binary's arch aligned with the builder stage on cross-arch builds.
FROM --platform=${BUILDPLATFORM} ghcr.io/pnpm/pnpm:11.5.1@sha256:3cbdefab0d887dee497ddc8dfe6d871257317d69520fe30f9ccec0a84bde6e89 AS pnpm
# Stage 1: Build web # Stage 1: Build web
FROM --platform=${BUILDPLATFORM} docker.io/library/node:26 AS web-builder FROM --platform=${BUILDPLATFORM} docker.io/library/node:26 AS web-builder
ENV NODE_ENV=production ENV NODE_ENV=production
WORKDIR /static WORKDIR /static
# These files need to be copied and cannot be mounted as `npm ci` will build the client's typescript # These files need to be copied and cannot be mounted as `pnpm install` will build the client's typescript
COPY ./packages /packages COPY ./packages /packages
COPY ./web/packages /static/packages COPY ./web/packages /static/packages
COPY --from=pnpm /opt/pnpm /opt/pnpm
ENV PATH="/opt/pnpm:${PATH}"
RUN --mount=type=bind,target=/static/package.json,src=./package.json \ RUN --mount=type=bind,target=/static/package.json,src=./package.json \
--mount=type=bind,target=/static/package-lock.json,src=./package-lock.json \
--mount=type=bind,target=/static/web/package.json,src=./web/package.json \ --mount=type=bind,target=/static/web/package.json,src=./web/package.json \
--mount=type=bind,target=/static/web/package-lock.json,src=./web/package-lock.json \ --mount=type=bind,target=/static/web/pnpm-lock.yaml,src=./web/pnpm-lock.yaml \
--mount=type=bind,target=/static/scripts/node/,src=./scripts/node/ \ --mount=type=bind,target=/static/scripts/node/,src=./scripts/node/ \
--mount=type=bind,target=/static/packages/logger-js/,src=./packages/logger-js/ \ --mount=type=bind,target=/static/packages/logger-js/,src=./packages/logger-js/ \
node ./scripts/node/setup-corepack.mjs --force && \
node ./scripts/node/lint-runtime.mjs ./web node ./scripts/node/lint-runtime.mjs ./web
COPY package.json / COPY package.json /
RUN --mount=type=bind,target=/static/.npmrc,src=./.npmrc \ RUN --mount=type=bind,target=/static/.npmrc,src=./.npmrc \
--mount=type=bind,target=/static/package.json,src=./web/package.json \ --mount=type=bind,target=/static/package.json,src=./web/package.json \
--mount=type=bind,target=/static/package-lock.json,src=./web/package-lock.json \ --mount=type=bind,target=/static/pnpm-lock.yaml,src=./web/pnpm-lock.yaml \
--mount=type=bind,target=/static/pnpm-workspace.yaml,src=./web/pnpm-workspace.yaml \
--mount=type=bind,target=/static/scripts,src=./web/scripts \ --mount=type=bind,target=/static/scripts,src=./web/scripts \
--mount=type=cache,target=/root/.npm \ --mount=type=cache,target=/root/.local/share/pnpm/store \
corepack npm ci pnpm install --frozen-lockfile
COPY web . COPY web .
RUN npm run build-proxy RUN pnpm run build-proxy
# Stage 2: Build # Stage 2: Build
FROM --platform=${BUILDPLATFORM} docker.io/library/golang:1.26.4-trixie@sha256:68b7145ec43d1820b9a56704554b53d1520aa2a15cb5233e374188a31b2a1bce AS builder FROM --platform=${BUILDPLATFORM} docker.io/library/golang:1.26.4-trixie@sha256:68b7145ec43d1820b9a56704554b53d1520aa2a15cb5233e374188a31b2a1bce AS builder

24481
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -3,8 +3,7 @@
"version": "2026.8.0-rc1", "version": "2026.8.0-rc1",
"private": true, "private": true,
"scripts": { "scripts": {
"lint": "run-s lint:runtime lint:spellcheck lint:lockfile", "lint": "run-s lint:runtime lint:spellcheck",
"lint:lockfile": "node ./scripts/node/lint-lockfile.mjs",
"lint:runtime": "node ./scripts/node/lint-runtime.mjs", "lint:runtime": "node ./scripts/node/lint-runtime.mjs",
"lint:spellcheck": "cspell . --config cspell.config.jsonc" "lint:spellcheck": "cspell . --config cspell.config.jsonc"
}, },
@@ -14,11 +13,11 @@
}, },
"dependencies": { "dependencies": {
"@eslint/js": "^9.39.3", "@eslint/js": "^9.39.3",
"@goauthentik/docusaurus-config": "./packages/docusaurus-config", "@goauthentik/docusaurus-config": "workspace:*",
"@goauthentik/eslint-config": "./packages/eslint-config", "@goauthentik/eslint-config": "workspace:*",
"@goauthentik/logger-js": "./packages/logger-js", "@goauthentik/logger-js": "workspace:*",
"@goauthentik/prettier-config": "./packages/prettier-config", "@goauthentik/prettier-config": "workspace:*",
"@goauthentik/tsconfig": "./packages/tsconfig", "@goauthentik/tsconfig": "workspace:*",
"cspell": "^10.0.1", "cspell": "^10.0.1",
"eslint": "^9.39.3", "eslint": "^9.39.3",
"npm-run-all": "^4.1.5", "npm-run-all": "^4.1.5",
@@ -29,37 +28,17 @@
"typescript": "^6.0.3", "typescript": "^6.0.3",
"typescript-eslint": "^8.59.3" "typescript-eslint": "^8.59.3"
}, },
"workspaces": [],
"engines": { "engines": {
"node": ">=24", "node": ">=24",
"npm": ">=11.14.1" "pnpm": ">=11.5.1"
}, },
"devEngines": { "devEngines": {
"runtime": { "runtime": {
"name": "node", "name": "node",
"onFail": "warn", "onFail": "warn",
"version": ">=24" "version": ">=24"
},
"packageManager": {
"name": "npm",
"version": ">=11.14.1",
"onFail": "warn"
} }
}, },
"packageManager": "npm@11.14.1+sha512.6a8a4d67478497a2dbc6815cad72e64c43f33413717e242756047d466241ab39bee61e691683a64658e94496ec5f1a1c05e4a5ec62dcc773280dfd949443a367", "packageManager": "pnpm@11.5.1+sha512.93f7b57422ea7068257235b4c16eb60762eb68e1dc23723199cc739043ea9be2c4143274a399d8c6defa2b1176226d9ca1c4b63482d6200c1a8fbaa78c1d1485",
"prettier": "@goauthentik/prettier-config", "prettier": "@goauthentik/prettier-config"
"overrides": {
"@typescript-eslint/eslint-plugin": {
"typescript": "$typescript"
},
"@typescript-eslint/parser": {
"typescript": "$typescript"
},
"format-imports": {
"eslint": "$eslint"
},
"typescript-eslint": {
"typescript": "$typescript"
}
}
} }

View File

@@ -8,18 +8,19 @@
"url": "https://github.com/goauthentik/authentik.git" "url": "https://github.com/goauthentik/authentik.git"
}, },
"scripts": { "scripts": {
"build": "npm run clean && tsc -b tsconfig.json tsconfig.esm.json", "build": "pnpm run clean && tsc -b tsconfig.json tsconfig.esm.json",
"clean": "tsc -b --clean tsconfig.json tsconfig.esm.json", "clean": "tsc -b --clean tsconfig.json tsconfig.esm.json",
"prepare": "npm run build" "prepare": "pnpm run build"
}, },
"main": "./dist/index.js", "main": "./src/index.ts",
"types": "./dist/index.d.ts", "types": "./src/index.ts",
"devDependencies": { "devDependencies": {
"@goauthentik/prettier-config": "^3.5.0", "@goauthentik/prettier-config": "^3.5.0",
"prettier": "^3.8.1", "prettier": "^3.8.1",
"typescript": "^4.0 || ^5.0" "typescript": "^4.0 || ^5.0"
}, },
"packageManager": "pnpm@11.5.1+sha512.93f7b57422ea7068257235b4c16eb60762eb68e1dc23723199cc739043ea9be2c4143274a399d8c6defa2b1176226d9ca1c4b63482d6200c1a8fbaa78c1d1485",
"prettier": "@goauthentik/prettier-config", "prettier": "@goauthentik/prettier-config",
"sideEffects": false, "sideEffects": false,
"module": "./dist/esm/index.js" "module": "./src/index.ts"
} }

File diff suppressed because it is too large Load Diff

View File

@@ -34,9 +34,9 @@
"@docusaurus/theme-search-algolia": "^3.10.0", "@docusaurus/theme-search-algolia": "^3.10.0",
"@docusaurus/types": "^3.10.0", "@docusaurus/types": "^3.10.0",
"@eslint/js": "^9.39.3", "@eslint/js": "^9.39.3",
"@goauthentik/eslint-config": "../eslint-config", "@goauthentik/eslint-config": "link:../eslint-config",
"@goauthentik/prettier-config": "../prettier-config", "@goauthentik/prettier-config": "link:../prettier-config",
"@goauthentik/tsconfig": "../tsconfig", "@goauthentik/tsconfig": "link:../tsconfig",
"@types/node": "^25.7.0", "@types/node": "^25.7.0",
"@types/react": "^19.2.14", "@types/react": "^19.2.14",
"@types/react-dom": "^19.2.3", "@types/react-dom": "^19.2.3",
@@ -65,8 +65,7 @@
"out/**/*" "out/**/*"
], ],
"engines": { "engines": {
"node": ">=24", "node": ">=24"
"npm": ">=11.14.1"
}, },
"devEngines": { "devEngines": {
"runtime": { "runtime": {
@@ -75,23 +74,12 @@
"version": ">=24" "version": ">=24"
}, },
"packageManager": { "packageManager": {
"name": "npm", "name": "pnpm",
"version": ">=11.14.1", "version": ">=11.5.1",
"onFail": "warn" "onFail": "warn"
} }
}, },
"prettier": "@goauthentik/prettier-config", "prettier": "@goauthentik/prettier-config",
"overrides": {
"@typescript-eslint/eslint-plugin": {
"typescript": "$typescript"
},
"@typescript-eslint/parser": {
"typescript": "$typescript"
},
"typescript-eslint": {
"typescript": "$typescript"
}
},
"peerDependenciesMeta": { "peerDependenciesMeta": {
"@docusaurus/theme-search-algolia": { "@docusaurus/theme-search-algolia": {
"optional": true "optional": true

File diff suppressed because it is too large Load Diff

View File

@@ -45,10 +45,10 @@
}, },
"devDependencies": { "devDependencies": {
"@eslint/js": "^9.39.3", "@eslint/js": "^9.39.3",
"@goauthentik/eslint-config": "../eslint-config", "@goauthentik/eslint-config": "link:../eslint-config",
"@goauthentik/logger-js": "../logger-js", "@goauthentik/logger-js": "link:../logger-js",
"@goauthentik/prettier-config": "../prettier-config", "@goauthentik/prettier-config": "link:../prettier-config",
"@goauthentik/tsconfig": "../tsconfig", "@goauthentik/tsconfig": "link:../tsconfig",
"@types/node": "^25.7.0", "@types/node": "^25.7.0",
"esbuild": "^0.27.4", "esbuild": "^0.27.4",
"eslint": "^9.39.3", "eslint": "^9.39.3",
@@ -72,8 +72,7 @@
"out/**/*" "out/**/*"
], ],
"engines": { "engines": {
"node": ">=24", "node": ">=24"
"npm": ">=11.14.1"
}, },
"devEngines": { "devEngines": {
"runtime": { "runtime": {
@@ -82,8 +81,8 @@
"version": ">=24" "version": ">=24"
}, },
"packageManager": { "packageManager": {
"name": "npm", "name": "pnpm",
"version": ">=11.14.1", "version": ">=11.5.1",
"onFail": "warn" "onFail": "warn"
} }
}, },
@@ -96,20 +95,6 @@
"reload", "reload",
"authentik" "authentik"
], ],
"overrides": {
"@typescript-eslint/eslint-plugin": {
"typescript": "$typescript"
},
"@typescript-eslint/parser": {
"typescript": "$typescript"
},
"format-imports": {
"eslint": "$eslint"
},
"typescript-eslint": {
"typescript": "$typescript"
}
},
"peerDependenciesMeta": { "peerDependenciesMeta": {
"@goauthentik/logger-js": { "@goauthentik/logger-js": {
"optional": true "optional": true

File diff suppressed because it is too large Load Diff

View File

@@ -45,8 +45,8 @@
"eslint-plugin-wc": "^3.1.0" "eslint-plugin-wc": "^3.1.0"
}, },
"devDependencies": { "devDependencies": {
"@goauthentik/prettier-config": "../prettier-config", "@goauthentik/prettier-config": "link:../prettier-config",
"@goauthentik/tsconfig": "../tsconfig", "@goauthentik/tsconfig": "link:../tsconfig",
"@types/eslint": "^9.6.1", "@types/eslint": "^9.6.1",
"@types/node": "^25.7.0", "@types/node": "^25.7.0",
"typescript": "^6.0.3", "typescript": "^6.0.3",
@@ -64,8 +64,7 @@
"out/**/*" "out/**/*"
], ],
"engines": { "engines": {
"node": ">=24", "node": ">=24"
"npm": ">=11.14.1"
}, },
"devEngines": { "devEngines": {
"runtime": { "runtime": {
@@ -74,26 +73,12 @@
"onFail": "warn" "onFail": "warn"
}, },
"packageManager": { "packageManager": {
"name": "npm", "name": "pnpm",
"version": ">=11.14.1", "version": ">=11.5.1",
"onFail": "warn" "onFail": "warn"
} }
}, },
"prettier": "@goauthentik/prettier-config", "prettier": "@goauthentik/prettier-config",
"overrides": {
"@typescript-eslint/eslint-plugin": {
"typescript": "$typescript"
},
"@typescript-eslint/parser": {
"typescript": "$typescript"
},
"format-imports": {
"eslint": "$eslint"
},
"typescript-eslint": {
"typescript": "$typescript"
}
},
"peerDependenciesMeta": { "peerDependenciesMeta": {
"react": { "react": {
"optional": true "optional": true

File diff suppressed because it is too large Load Diff

View File

@@ -29,8 +29,8 @@
}, },
"devDependencies": { "devDependencies": {
"@eslint/js": "^9.39.3", "@eslint/js": "^9.39.3",
"@goauthentik/prettier-config": "../prettier-config", "@goauthentik/prettier-config": "link:../prettier-config",
"@goauthentik/tsconfig": "../tsconfig", "@goauthentik/tsconfig": "link:../tsconfig",
"@types/node": "^25.7.0", "@types/node": "^25.7.0",
"eslint": "^9.39.3", "eslint": "^9.39.3",
"pino": "^10.3.1", "pino": "^10.3.1",
@@ -50,8 +50,7 @@
"out/**/*" "out/**/*"
], ],
"engines": { "engines": {
"node": ">=24", "node": ">=24"
"npm": ">=11.14.1"
}, },
"devEngines": { "devEngines": {
"runtime": { "runtime": {
@@ -60,26 +59,12 @@
"onFail": "ignore" "onFail": "ignore"
}, },
"packageManager": { "packageManager": {
"name": "npm", "name": "pnpm",
"version": ">=11.14.1", "version": ">=11.5.1",
"onFail": "ignore" "onFail": "ignore"
} }
}, },
"prettier": "@goauthentik/prettier-config", "prettier": "@goauthentik/prettier-config",
"overrides": {
"@typescript-eslint/eslint-plugin": {
"typescript": "$typescript"
},
"@typescript-eslint/parser": {
"typescript": "$typescript"
},
"format-imports": {
"eslint": "$eslint"
},
"typescript-eslint": {
"typescript": "$typescript"
}
},
"peerDependenciesMeta": { "peerDependenciesMeta": {
"pino": { "pino": {
"optional": true "optional": true

File diff suppressed because it is too large Load Diff

View File

@@ -37,8 +37,8 @@
}, },
"devDependencies": { "devDependencies": {
"@eslint/js": "^9.39.3", "@eslint/js": "^9.39.3",
"@goauthentik/eslint-config": "../eslint-config", "@goauthentik/eslint-config": "link:../eslint-config",
"@goauthentik/tsconfig": "../tsconfig", "@goauthentik/tsconfig": "link:../tsconfig",
"@types/node": "^25.7.0", "@types/node": "^25.7.0",
"eslint": "^9.39.3", "eslint": "^9.39.3",
"prettier": "^3.8.3", "prettier": "^3.8.3",
@@ -56,8 +56,7 @@
"out/**/*" "out/**/*"
], ],
"engines": { "engines": {
"node": ">=24", "node": ">=24"
"npm": ">=11.14.1"
}, },
"devEngines": { "devEngines": {
"runtime": { "runtime": {
@@ -66,26 +65,12 @@
"onFail": "warn" "onFail": "warn"
}, },
"packageManager": { "packageManager": {
"name": "npm", "name": "pnpm",
"version": ">=11.14.1", "version": ">=11.5.1",
"onFail": "warn" "onFail": "warn"
} }
}, },
"prettier": "./index.js", "prettier": "./index.js",
"overrides": {
"@typescript-eslint/eslint-plugin": {
"typescript": "$typescript"
},
"@typescript-eslint/parser": {
"typescript": "$typescript"
},
"format-imports": {
"eslint": "$eslint"
},
"typescript-eslint": {
"typescript": "$typescript"
}
},
"publishConfig": { "publishConfig": {
"access": "public" "access": "public"
} }

View File

@@ -1,17 +0,0 @@
{
"name": "@goauthentik/tsconfig",
"version": "2.0.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "@goauthentik/tsconfig",
"version": "2.0.0",
"license": "MIT",
"engines": {
"node": ">=24",
"npm": ">=11.14.1"
}
}
}
}

View File

@@ -14,8 +14,7 @@
"main": "tsconfig.json", "main": "tsconfig.json",
"type": "module", "type": "module",
"engines": { "engines": {
"node": ">=24", "node": ">=24"
"npm": ">=11.14.1"
}, },
"devEngines": { "devEngines": {
"runtime": { "runtime": {
@@ -24,8 +23,8 @@
"onFail": "warn" "onFail": "warn"
}, },
"packageManager": { "packageManager": {
"name": "npm", "name": "pnpm",
"version": ">=11.14.1", "version": ">=11.5.1",
"onFail": "warn" "onFail": "warn"
} }
}, },

14849
pnpm-lock.yaml generated Normal file

File diff suppressed because it is too large Load Diff

29
pnpm-workspace.yaml Normal file
View File

@@ -0,0 +1,29 @@
packages:
- "packages/docusaurus-config"
- "packages/esbuild-plugin-live-reload"
- "packages/eslint-config"
- "packages/logger-js"
- "packages/prettier-config"
- "packages/tsconfig"
- "lifecycle/aws"
overrides:
"@typescript-eslint/eslint-plugin>typescript": "$typescript"
"@typescript-eslint/parser>typescript": "$typescript"
"format-imports>eslint": "$eslint"
"typescript-eslint>typescript": "$typescript"
# Allow-list of dependencies whose install/postinstall scripts may run.
# Everything else is blocked, replacing the prior `ignore-scripts=true` +
# `npm rebuild --foreground-scripts <pkg>` pattern from #20400. Each entry is
# audited at review time — adding a package here grants it arbitrary code
# execution at install.
onlyBuiltDependencies:
- esbuild
# Explicit approval map for pnpm 11+. `true` = allowed (mirror onlyBuiltDependencies);
# `false` = explicitly declined (silences the "pending approval" prompt
# without running the script).
allowBuilds:
core-js: false
esbuild: true

View File

@@ -1,280 +0,0 @@
#!/usr/bin/env node
/**
* @file Lints the package-lock.json file to ensure it is in sync with package.json.
*
* Usage:
* lint-lockfile [options] [directory]
*
* Options:
* --warn Report issues as warnings instead of failing. The lockfile is
* still regenerated on disk, but the process exits 0.
*
* Exit codes:
* 0 Lockfile is in sync (or --warn was passed)
* 1 Unexpected error
* 2 Lockfile drift detected
*/
/// <reference lib="esnext" />
import * as assert from "node:assert/strict";
import { findPackageJSON } from "node:module";
import { dirname } from "node:path";
import { isDeepStrictEqual, parseArgs } from "node:util";
import { ConsoleLogger } from "../../packages/logger-js/lib/node.js";
import { parseCWD, reportAndExit } from "./utils/commands.mjs";
import { corepack } from "./utils/corepack.mjs";
import { gitStatus } from "./utils/git.mjs";
import { findNPMPackage, loadJSON, npm, pluckDependencyFields } from "./utils/node.mjs";
//#region Constants
const logger = ConsoleLogger.prefix("lint:lockfile");
const { values: options, positionals } = parseArgs({
options: {
"warn": {
type: "boolean",
default: false,
description: "Report issues as warnings instead of failing",
},
"skip-git": {
type: "boolean",
default: !!process.env.CI,
description:
"Skip checking for uncommitted changes (use with --warn to ignore drift without reporting)",
},
},
allowPositionals: true,
});
const cwd = parseCWD(positionals);
const ignoredProperties = new Set([
// ---
"peer",
"engines",
"optional",
]);
//#region Utilities
/**
* @param {Record<string, unknown>} actual
* @param {Record<string, unknown>} expected
* @param {string[]} [prefix]
* @returns {Set<string>[]}
*/
function extractDiffedProperties(actual, expected, prefix = []) {
const a = actual ?? {};
const b = expected ?? {};
const keys = new Set([...Object.keys(a), ...Object.keys(b)]);
/** @type {Set<string>[]} */
const diffs = [];
for (const key of keys) {
const path = [...prefix, key];
const valA = a[key];
const valB = b[key];
if (
valA !== null &&
valB !== null &&
typeof valA === "object" &&
typeof valB === "object" &&
!Array.isArray(valA) &&
!Array.isArray(valB)
) {
// @ts-ignore
diffs.push(...extractDiffedProperties(valA, valB, path));
} else if (!isDeepStrictEqual(valA, valB)) {
diffs.push(new Set(path));
}
}
return diffs;
}
//#endregion
/**
* Exit code when lockfile drift is detected (distinct from general errors)
*/
const EXIT_DRIFT = 2;
/**
* @returns {Promise<string[]>} The list of issues detected.
*/
async function run() {
/** @type {string[]} */
const issues = [];
/**
* Records an issue. In strict mode, throws immediately.
* In warn mode, collects the message for later reporting.
*
* @param {boolean} ok
* @param {string} message
*/
const check = (ok, message) => {
if (ok) return;
if (options.warn) {
issues.push(message);
return;
}
assert.fail(message);
};
/**
* Checks deep equality of two values. In strict mode, throws if they are not equal.
* In warn mode, records an issue instead.
*
* @param {unknown} actual
* @param {unknown} expected
* @param {string} message
*/
const checkDeep = (actual, expected, message) => {
if (options.warn) {
if (!isDeepStrictEqual(actual, expected)) {
issues.push(message);
}
return;
}
assert.deepStrictEqual(actual, expected, message);
};
logger.info(`Linting lockfile integrity in: ${cwd}`);
// MARK: Locate files
const resolvedPath = import.meta.resolve(cwd);
const packageJSONPath = findPackageJSON(resolvedPath);
assert.ok(
packageJSONPath,
"Could not find package.json in the current directory or any parent directories",
);
const packageDir = dirname(packageJSONPath);
const { packageLockPath } = await findNPMPackage(packageDir);
const lockfileDir = dirname(packageLockPath);
const isWorkspace = lockfileDir !== packageDir;
const corepackVersion = await corepack`--version`().catch(() => null);
const useCorepack = !!corepackVersion;
logger.info(`corepack: ${corepackVersion || "disabled"}`);
const expected = {
lockfile: await loadJSON(packageLockPath),
package: await loadJSON(packageJSONPath).then(pluckDependencyFields),
};
logger.info(`package.json: ${packageJSONPath} (${expected.package.name})`);
logger.info(`package-lock.json: ${packageLockPath}${isWorkspace ? " (workspace root)" : ""}`);
// MARK: Uncommitted changes
if (options["skip-git"]) {
logger.warn("Skipping git status check");
} else {
const packageStatus = await gitStatus(packageJSONPath);
const lockfileStatus = await gitStatus(packageLockPath);
if (!packageStatus.available || !lockfileStatus.available) {
logger.warn("Git is not available; skipping uncommitted change detection.");
} else {
check(packageStatus.clean, `package.json has uncommitted changes: ${packageJSONPath}`);
check(
lockfileStatus.clean,
`package-lock.json has uncommitted changes: ${packageLockPath}`,
);
}
}
// MARK: Regenerate
const npmVersion = await npm`--version`({ useCorepack });
logger.info(`Detected npm version: ${npmVersion}`);
await npm`install --package-lock-only`({
cwd: lockfileDir,
useCorepack,
});
logger.info("npm install complete.");
const actual = {
lockfile: await loadJSON(packageLockPath),
package: await loadJSON(packageJSONPath).then(pluckDependencyFields),
};
// MARK: Compare
assert.deepStrictEqual(
actual.package,
expected.package,
`package.json was unexpectedly modified during lockfile check: ${packageJSONPath}`,
);
try {
checkDeep(
actual.lockfile,
expected.lockfile,
`package-lock.json is out of sync with package.json`,
);
} catch (error) {
if (!(error instanceof assert.AssertionError)) {
throw error;
}
// NPM versions <=11.10 has issues with deterministic lockfile generation,
// especially around optional peer dependencies.
const diffedProperties = extractDiffedProperties(actual.lockfile, expected.lockfile).filter(
(segments) => segments.isDisjointFrom(ignoredProperties),
);
if (diffedProperties.length) {
const formatted = diffedProperties
.map((segments) => Array.from(segments).join("."))
.join("\n");
throw new Error(`Lockfile drift detected:\n${formatted}`, { cause: error });
}
logger.warn(
"Permissible dependency differences detected. Run `npm install` to update the lockfile.",
);
}
return issues;
}
run()
.then((issues) => {
if (issues.length) {
logger.warn(`⚠️ ${issues.length} issue(s) detected:`);
for (const issue of issues) {
logger.warn(` - ${issue}`);
}
if (options.warn) {
logger.warn(
"The lockfile on disk has been regenerated. Review and commit the changes.",
);
process.exit(EXIT_DRIFT);
}
} else {
logger.info("✅ Lockfile is in sync.");
}
process.exit(0);
})
.catch((error) => reportAndExit(error, logger));

View File

@@ -1,9 +1,9 @@
#!/usr/bin/env node #!/usr/bin/env node
/** /**
* @file Lints the installed Node.js and npm versions against the requirements specified in package.json. * @file Lints the installed Node.js and pnpm versions against the requirements specified in package.json.
* *
* Usage: * Usage:
* lint-node [options] [directory] * lint-runtime [options] [directory]
* *
* Exit codes: * Exit codes:
* 0 Versions are in sync * 0 Versions are in sync
@@ -14,10 +14,9 @@ import * as assert from "node:assert/strict";
import { parseArgs } from "node:util"; import { parseArgs } from "node:util";
import { ConsoleLogger } from "../../packages/logger-js/lib/node.js"; import { ConsoleLogger } from "../../packages/logger-js/lib/node.js";
import { CommandError, parseCWD, reportAndExit } from "./utils/commands.mjs"; import { parseCWD, reportAndExit } from "./utils/commands.mjs";
import { corepack } from "./utils/corepack.mjs";
import { resolveRepoRoot } from "./utils/git.mjs"; import { resolveRepoRoot } from "./utils/git.mjs";
import { compareVersions, findNPMPackage, loadJSON, node, npm, parseRange } from "./utils/node.mjs"; import { compareVersions, findNPMPackage, loadJSON, node, pnpm, parseRange } from "./utils/node.mjs";
const logger = ConsoleLogger.prefix("lint-runtime"); const logger = ConsoleLogger.prefix("lint-runtime");
@@ -33,10 +32,10 @@ async function readRequirements(start) {
const nodeVersion = await node`--version`().then((output) => output.replace(/^v/, "")); const nodeVersion = await node`--version`().then((output) => output.replace(/^v/, ""));
const requiredNpmVersion = packageJSONData.engines?.npm; const requiredPnpmVersion = packageJSONData.engines?.pnpm;
const requiredNodeVersion = packageJSONData.engines?.node; const requiredNodeVersion = packageJSONData.engines?.node;
return { nodeVersion, requiredNpmVersion, requiredNodeVersion }; return { nodeVersion, requiredPnpmVersion, requiredNodeVersion };
} }
async function main() { async function main() {
@@ -50,47 +49,28 @@ async function main() {
logger.info(`cwd ${cwd}`); logger.info(`cwd ${cwd}`);
logger.info(`repository ${repoRoot || "not found"}`); logger.info(`repository ${repoRoot || "not found"}`);
const corepackVersion = await corepack`--version`().catch(() => null); const pnpmVersion = await pnpm`--version`({ cwd }).catch((error) => {
const useCorepack = !!corepackVersion; logger.warn(`Failed to read pnpm version: ${error.message}`);
logger.info(`corepack ${corepackVersion || "disabled"}`); return null;
const npmVersion = await npm`--version`({ cwd, useCorepack })
.then((version) => {
logger.info(`npm${corepackVersion ? " (via Corepack)" : ""} ${version}`);
return version;
})
.catch((error) => {
if (error instanceof CommandError && corepackVersion) {
logger.warn(`Failed to read npm version via Corepack ${error.message}`);
logger.info(`Attempting to read npm version directly without Corepack...`);
// Corepack might be misconfigured or outdated.
// Attempting a second read without Corepack can help us distinguish
// between a general npm issue and a Corepack-specific one.
return npm`--version`({ cwd }).then((version) => {
logger.info(`npm (direct) ${version}`);
return version;
}); });
if (pnpmVersion) {
logger.info(`pnpm ${pnpmVersion}`);
} }
throw error; const { nodeVersion, requiredPnpmVersion, requiredNodeVersion } = await readRequirements(cwd);
});
const { nodeVersion, requiredNpmVersion, requiredNodeVersion } = await readRequirements(cwd);
logger.info(`node ${nodeVersion}`); logger.info(`node ${nodeVersion}`);
if (requiredNpmVersion) { if (requiredPnpmVersion && pnpmVersion) {
logger.info(`package.json npm ${requiredNpmVersion}`); logger.info(`package.json pnpm ${requiredPnpmVersion}`);
const { operator, version: required } = parseRange(requiredNpmVersion); const { operator, version: required } = parseRange(requiredPnpmVersion);
const result = compareVersions(npmVersion, required); const result = compareVersions(pnpmVersion, required);
assert.ok( assert.ok(
operator === ">=" ? result >= 0 : result === 0, operator === ">=" ? result >= 0 : result === 0,
`npm version ${npmVersion} does not satisfy required version ${requiredNpmVersion}`, `pnpm version ${pnpmVersion} does not satisfy required version ${requiredPnpmVersion}`,
); );
} }
@@ -109,7 +89,7 @@ async function main() {
main() main()
.then(() => { .then(() => {
logger.info("✅ Node.js and npm versions are in sync."); logger.info("✅ Node.js and pnpm versions are in sync.");
process.exit(0); process.exit(0);
}) })
.catch((error) => reportAndExit(error, logger)); .catch((error) => reportAndExit(error, logger));

View File

@@ -1,113 +0,0 @@
#!/usr/bin/env node
/**
* @file Downloads the latest corepack tarball from the npm registry.
*/
import * as fs from "node:fs/promises";
import { parseArgs } from "node:util";
import { ConsoleLogger } from "../../packages/logger-js/lib/node.js";
import { $, parseCWD, reportAndExit } from "./utils/commands.mjs";
import { corepack, pullLatestCorepack, verifyPackageManagerIntegrity } from "./utils/corepack.mjs";
import { resolveRepoRoot } from "./utils/git.mjs";
import { findNPMPackage, loadJSON, npm } from "./utils/node.mjs";
/**
* @deprecated Remove after Corepack is merged into the monorepo and we can rely on the version specified in package.json.
*/
const FALLBACK_PACKAGE_MANAGER =
"npm@11.14.1+sha512.6a8a4d67478497a2dbc6815cad72e64c43f33413717e242756047d466241ab39bee61e691683a64658e94496ec5f1a1c05e4a5ec62dcc773280dfd949443a367";
const logger = ConsoleLogger.prefix("setup-corepack");
async function main() {
const parsedArgs = parseArgs({
options: {
force: {
type: "boolean",
default: false,
description: "Force re-download of corepack even if a version is already installed",
},
},
allowPositionals: true,
});
const cwdArg = parseCWD(parsedArgs.positionals);
const repoRoot = await resolveRepoRoot(cwdArg).catch(() => null);
const cwd = repoRoot || cwdArg;
const npmVersion = await npm`--version`({ cwd });
logger.info(`npm ${npmVersion}`);
const corepackVersion = await corepack`--version`({ cwd }).catch(() => null);
logger.info(`corepack ${corepackVersion || "not found"}`);
if (corepackVersion && !parsedArgs.values.force) {
logger.info("Corepack is already installed, skipping download (use --force to override)");
return;
}
await pullLatestCorepack(cwd);
await npm`install --force -g corepack@latest`({ cwd });
logger.info("Corepack installed successfully");
const { packageJSONPath } = await findNPMPackage(cwd);
logger.info(`Checking versions in ${packageJSONPath}`);
const packageJSONData = await loadJSON(packageJSONPath);
const packageManagerSpec = packageJSONData.packageManager || FALLBACK_PACKAGE_MANAGER;
const plusIndex = packageManagerSpec.indexOf("+");
const packageManager =
plusIndex === -1 ? packageManagerSpec : packageManagerSpec.slice(0, plusIndex);
const checksum = plusIndex === -1 ? "" : packageManagerSpec.slice(plusIndex + 1);
if (!checksum) {
throw new Error(
`Invalid packageManager field in package.json. Expected format "name@version+checksum". Got "${packageJSONData.packageManager}".`,
);
}
await verifyPackageManagerIntegrity(packageManager, checksum);
await $`corepack install -g ${packageManager}`({ cwd });
logger.info(`Setting up Corepack to use ${packageManager}...`);
const writablePackageJSON = await fs.access(packageJSONPath, fs.constants.W_OK).then(
() => true,
() => false,
);
/**
* @type {string}
*/
let subcommand;
if (!writablePackageJSON) {
if (!packageJSONData.packageManager) {
throw new Error(
`package.json is not writable and does not specify a packageManager field. Was the package.json file mounted via Docker?`,
);
}
subcommand = "install -g";
} else {
logger.info("package.json is writable");
subcommand = "use";
}
return $`corepack ${subcommand} ${packageManager}`({ cwd });
}
main()
.then(() => {
logger.info("Corepack setup completed successfully");
process.exit(0);
})
.catch((error) => reportAndExit(error, logger));

View File

@@ -1,165 +0,0 @@
import * as crypto from "node:crypto";
import * as fs from "node:fs/promises";
import { join, relative } from "node:path";
import { ConsoleLogger } from "../../../packages/logger-js/lib/node.js";
import { $ } from "./commands.mjs";
const REGISTRY_BASE_URL = "https://registry.npmjs.org";
const REGISTRY_URL = `${REGISTRY_BASE_URL}/corepack`;
const OUTPUT_DIR = join(".corepack", "releases");
const OUTPUT_FILENAME = "latest.tgz";
export const corepack = $.bind("corepack");
/**
* Reads the installed Corepack version.
*
* @param {string} [cwd] The directory to run the command in.
* @returns {Promise<string | null>} The installed Corepack version
*/
export function readCorepackVersion(cwd = process.cwd()) {
return $`corepack --version`({ cwd });
}
const logger = ConsoleLogger.prefix("setup-corepack");
/**
* @param {string} baseDirectory
*/
export async function pullLatestCorepack(baseDirectory = process.cwd()) {
logger.info("Fetching corepack metadata from registry...");
const outputDir = join(baseDirectory, OUTPUT_DIR);
const outputPath = join(outputDir, OUTPUT_FILENAME);
const res = await fetch(REGISTRY_URL, { signal: AbortSignal.timeout(1000 * 60) });
if (!res.ok) {
throw new Error(`Failed to fetch registry metadata: ${res.status} ${res.statusText}`);
}
const metadata = await res.json();
const latestVersion = metadata["dist-tags"].latest;
const versionData = metadata.versions[latestVersion];
const tarballUrl = versionData.dist.tarball;
const expectedIntegrity = versionData.dist.integrity;
logger.info(`Latest corepack version: ${latestVersion}`);
logger.info(`Tarball URL: ${tarballUrl}`);
logger.info(`Expected integrity: ${expectedIntegrity}`);
logger.info({ url: tarballUrl }, "Downloading tarball...");
const tarballRes = await fetch(tarballUrl, {
signal: AbortSignal.timeout(1000 * 60),
});
if (!tarballRes.ok) {
throw new Error(
`Failed to download tarball: ${tarballRes.status} ${tarballRes.statusText}`,
);
}
const tarballBuffer = Buffer.from(await tarballRes.arrayBuffer());
logger.info("Verifying integrity...");
const [algorithm, expectedHash] = expectedIntegrity.split("-");
const actualHash = crypto.createHash(algorithm).update(tarballBuffer).digest("base64");
if (actualHash !== expectedHash) {
throw new Error(
`Integrity mismatch!\n Expected: ${expectedHash}\n Actual: ${actualHash}`,
);
}
logger.info("Integrity verified.");
await fs.mkdir(outputDir, { recursive: true });
await fs.writeFile(outputPath, tarballBuffer);
logger.info(`Saved to ${relative(baseDirectory, outputPath)}`);
logger.info(`corepack@${latestVersion} (${expectedIntegrity})`);
}
/**
* Downloads the tarball for a package manager spec from the npm registry and
* verifies it matches the expected Corepack-style checksum (`<algorithm>.<hex>`).
*
* Corepack's CLI does not enforce the `+integrity` suffix on the `packageManager`
* field when invoked via `corepack install -g`, so we verify the bytes ourselves
* before handing control back to Corepack.
*
* @param {string} packageManager E.g. `npm@11.14.1`.
* @param {string} expectedChecksum E.g. `sha512.6a8a4d67...`.
* @returns {Promise<void>}
*/
export async function verifyPackageManagerIntegrity(packageManager, expectedChecksum) {
const atIndex = packageManager.lastIndexOf("@");
if (atIndex <= 0) {
throw new Error(
`Invalid packageManager spec "${packageManager}". Expected "name@version".`,
);
}
const name = packageManager.slice(0, atIndex);
const version = packageManager.slice(atIndex + 1);
const separatorIndex = expectedChecksum.indexOf(".");
if (separatorIndex <= 0) {
throw new Error(
`Invalid checksum format "${expectedChecksum}". Expected "<algorithm>.<hex>".`,
);
}
const algorithm = expectedChecksum.slice(0, separatorIndex);
const expectedHex = expectedChecksum.slice(separatorIndex + 1).toLowerCase();
logger.info(`Verifying ${name}@${version} against ${algorithm} checksum...`);
const metadataUrl = `${REGISTRY_BASE_URL}/${encodeURIComponent(name)}/${encodeURIComponent(version)}`;
const metadataRes = await fetch(metadataUrl, {
signal: AbortSignal.timeout(1000 * 60),
});
if (!metadataRes.ok) {
throw new Error(
`Failed to fetch registry metadata for ${name}@${version}: ${metadataRes.status} ${metadataRes.statusText}`,
);
}
const versionData = await metadataRes.json();
const tarballUrl = versionData?.dist?.tarball;
if (!tarballUrl) {
throw new Error(`Registry response missing dist.tarball for ${name}@${version}.`);
}
logger.info({ url: tarballUrl }, "Downloading tarball...");
const tarballRes = await fetch(tarballUrl, {
signal: AbortSignal.timeout(1000 * 60),
});
if (!tarballRes.ok) {
throw new Error(
`Failed to download tarball: ${tarballRes.status} ${tarballRes.statusText}`,
);
}
const tarballBuffer = Buffer.from(await tarballRes.arrayBuffer());
const actualHex = crypto.createHash(algorithm).update(tarballBuffer).digest("hex");
if (actualHex !== expectedHex) {
throw new Error(
`Integrity mismatch for ${name}@${version}!\n Expected: ${algorithm}.${expectedHex}\n Actual: ${algorithm}.${actualHex}`,
);
}
logger.info(`Integrity verified for ${name}@${version}.`);
}

View File

@@ -10,19 +10,19 @@ import { dirname, join } from "node:path";
import { $ } from "./commands.mjs"; import { $ } from "./commands.mjs";
/** /**
* Find the nearest directory containing both package.json and package-lock.json, * Find the nearest directory containing both package.json and pnpm-lock.yaml,
* starting from the given directory and walking upward. * starting from the given directory and walking upward.
* *
* @param {string} start The directory to start searching from. * @param {string} start The directory to start searching from.
* @returns {Promise<{ packageJSONPath: string, packageLockPath: string }>} * @returns {Promise<{ packageJSONPath: string, packageLockPath: string }>}
* @throws {Error} If no co-located package.json and package-lock.json are found. * @throws {Error} If no co-located package.json and pnpm-lock.yaml are found.
*/ */
export async function findNPMPackage(start) { export async function findNPMPackage(start) {
let currentDir = start; let currentDir = start;
while (currentDir !== dirname(currentDir)) { while (currentDir !== dirname(currentDir)) {
const packageJSONPath = join(currentDir, "package.json"); const packageJSONPath = join(currentDir, "package.json");
const packageLockPath = join(currentDir, "package-lock.json"); const packageLockPath = join(currentDir, "pnpm-lock.yaml");
try { try {
await Promise.all([fs.access(packageJSONPath), fs.access(packageLockPath)]); await Promise.all([fs.access(packageJSONPath), fs.access(packageLockPath)]);
@@ -37,7 +37,7 @@ export async function findNPMPackage(start) {
currentDir = dirname(currentDir); currentDir = dirname(currentDir);
} }
throw new Error(`No co-located package.json and package-lock.json found above ${start}`); throw new Error(`No co-located package.json and pnpm-lock.yaml found above ${start}`);
} }
/** /**
@@ -130,29 +130,13 @@ export function compareVersions(a, b) {
export const node = $.bind("node"); export const node = $.bind("node");
/** /**
* @typedef {object} NPMCommandOptions * Runs a pnpm command and returns its stdout output as a string.
* @property {boolean} [useCorepack] Whether to prefix the command with "corepack " to use Corepack's shims.
* @returns {Promise<string>}
*/
/**
* Runs an npm command and returns its stdout output as a string.
* *
* @param {TemplateStringsArray} strings * @param {TemplateStringsArray} strings
* @param {...unknown} expressions * @param {...unknown} expressions
* @returns {(options?: ExecOptions & NPMCommandOptions) => Promise<string>} * @returns {(options?: ExecOptions) => Promise<string>}
*/ */
export function npm(strings, ...expressions) { export const pnpm = $.bind("pnpm");
const subcommand = String.raw(strings, ...expressions);
return ({ useCorepack, ...options } = {}) => {
const command = [useCorepack ? "corepack" : "", "npm", subcommand]
.filter(Boolean)
.join(" ");
return $`${command}`(options);
};
}
/** /**
* Parses a version range string, stripping any leading >= and normalizing to three parts. * Parses a version range string, stripping any leading >= and normalizing to three parts.

View File

@@ -3,6 +3,10 @@
## Node ## Node
node_modules node_modules
# PNPM
pnpm-workspace.yaml
pnpm-lock.yaml
## Static Files ## Static Files
**/LICENSE **/LICENSE

21189
web/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -5,7 +5,7 @@
"private": true, "private": true,
"scripts": { "scripts": {
"build": "wireit", "build": "wireit",
"build:sfe": "npm run build -w @goauthentik/web-sfe", "build:sfe": "pnpm --filter @goauthentik/web-sfe run build",
"build-locales": "node scripts/build-locales.mjs", "build-locales": "node scripts/build-locales.mjs",
"build-proxy": "wireit", "build-proxy": "wireit",
"bundler:watch": "node scripts/build-web.mjs --watch", "bundler:watch": "node scripts/build-web.mjs --watch",
@@ -94,18 +94,18 @@
"@codemirror/lang-xml": "^6.1.0", "@codemirror/lang-xml": "^6.1.0",
"@codemirror/legacy-modes": "^6.5.3", "@codemirror/legacy-modes": "^6.5.3",
"@codemirror/theme-one-dark": "^6.1.3", "@codemirror/theme-one-dark": "^6.1.3",
"@eslint/js": "^9.39.3", "@eslint/js": "^9.39.4",
"@floating-ui/dom": "^1.7.6", "@floating-ui/dom": "^1.7.6",
"@formatjs/intl-listformat": "^8.3.8", "@formatjs/intl-listformat": "^8.3.9",
"@fortawesome/fontawesome-free": "^7.2.0", "@fortawesome/fontawesome-free": "^7.2.0",
"@goauthentik/api": "0.0.0", "@goauthentik/api": "link:packages/client-ts",
"@goauthentik/brand-assets": "^2.0.0", "@goauthentik/brand-assets": "^2.0.0",
"@goauthentik/core": "^1.0.0", "@goauthentik/core": "workspace:*",
"@goauthentik/esbuild-plugin-live-reload": "^2.0.1", "@goauthentik/esbuild-plugin-live-reload": "^2.0.1",
"@goauthentik/eslint-config": "^1.3.0", "@goauthentik/eslint-config": "^1.3.0",
"@goauthentik/prettier-config": "^3.5.0", "@goauthentik/prettier-config": "^3.5.0",
"@goauthentik/tsconfig": "^1.0.9", "@goauthentik/tsconfig": "^1.0.9",
"@hcaptcha/types": "^1.1.0", "@hcaptcha/types": "^1.2.0",
"@lit/context": "^1.1.6", "@lit/context": "^1.1.6",
"@lit/localize": "^0.12.2", "@lit/localize": "^0.12.2",
"@lit/localize-tools": "^0.8.2", "@lit/localize-tools": "^0.8.2",
@@ -118,7 +118,7 @@
"@openlayers-elements/core": "^0.4.0", "@openlayers-elements/core": "^0.4.0",
"@openlayers-elements/maps": "^0.4.0", "@openlayers-elements/maps": "^0.4.0",
"@patternfly/elements": "^4.4.0", "@patternfly/elements": "^4.4.0",
"@patternfly/patternfly": "^4.224.2", "@patternfly/patternfly": "^4.224.5",
"@playwright/test": "^1.61.0", "@playwright/test": "^1.61.0",
"@sentry/browser": "^10.60.0", "@sentry/browser": "^10.60.0",
"@storybook/addon-docs": "^10.4.6", "@storybook/addon-docs": "^10.4.6",
@@ -128,15 +128,15 @@
"@types/codemirror": "^5.60.17", "@types/codemirror": "^5.60.17",
"@types/grecaptcha": "^3.0.9", "@types/grecaptcha": "^3.0.9",
"@types/guacamole-common-js": "^1.5.5", "@types/guacamole-common-js": "^1.5.5",
"@types/node": "^25.7.0", "@types/node": "^25.9.1",
"@types/react": "^19.2.17", "@types/react": "^19.2.17",
"@types/react-dom": "^19.2.3", "@types/react-dom": "^19.2.3",
"@typescript-eslint/eslint-plugin": "^8.62.0", "@typescript-eslint/eslint-plugin": "^8.62.0",
"@typescript-eslint/parser": "^8.61.1", "@typescript-eslint/parser": "^8.61.1",
"@typescript-eslint/utils": "^8.60.0", "@typescript-eslint/utils": "^8.60.1",
"@typescript/native-preview": "^7.0.0-dev.20260510.1", "@typescript/native-preview": "7.0.0-dev.20260602.1",
"@vitest/browser": "^4.1.9", "@vitest/browser": "^4.1.9",
"@vitest/browser-playwright": "^4.1.6", "@vitest/browser-playwright": "^4.1.8",
"@webcomponents/webcomponentsjs": "^2.8.0", "@webcomponents/webcomponentsjs": "^2.8.0",
"base64-js": "^1.5.1", "base64-js": "^1.5.1",
"change-case": "^5.4.4", "change-case": "^5.4.4",
@@ -149,25 +149,25 @@
"deepmerge-ts": "^7.1.5", "deepmerge-ts": "^7.1.5",
"dompurify": "^3.4.11", "dompurify": "^3.4.11",
"esbuild": "^0.28.1", "esbuild": "^0.28.1",
"eslint": "^9.39.3", "eslint": "^9.39.4",
"eslint-plugin-lit": "^2.3.1", "eslint-plugin-lit": "^2.3.1",
"eslint-plugin-wc": "^3.1.0", "eslint-plugin-wc": "^3.1.0",
"fuse.js": "^7.4.2", "fuse.js": "^7.4.2",
"globals": "^17.6.0", "globals": "^17.6.0",
"guacamole-common-js": "^1.5.0", "guacamole-common-js": "^1.5.0",
"hastscript": "^9.0.1", "hastscript": "^9.0.1",
"knip": "^6.14.1", "knip": "^6.15.0",
"lex": "^2025.11.0", "lex": "workspace:*",
"lit": "^3.3.3", "lit": "^3.3.3",
"lit-analyzer": "^2.0.3", "lit-analyzer": "^2.0.3",
"lit-element": "^4.2.2", "lit-element": "^4.2.2",
"lit-html": "^3.3.2", "lit-html": "^3.3.3",
"md-front-matter": "^1.0.4", "md-front-matter": "^1.0.4",
"mermaid": "^11.15.0", "mermaid": "^11.15.0",
"node-domexception": "^2025.11.0", "node-domexception": "workspace:*",
"npm-run-all": "^4.1.5", "npm-run-all": "^4.1.5",
"pino": "^10.3.1", "pino": "^10.3.1",
"pino-pretty": "^13.1.2", "pino-pretty": "^13.1.3",
"playwright": "^1.61.0", "playwright": "^1.61.0",
"prettier": "^3.8.3", "prettier": "^3.8.3",
"prettier-plugin-packagejson": "^3.0.2", "prettier-plugin-packagejson": "^3.0.2",
@@ -183,18 +183,18 @@
"remark-frontmatter": "^5.0.0", "remark-frontmatter": "^5.0.0",
"remark-gfm": "^4.0.1", "remark-gfm": "^4.0.1",
"remark-mdx-frontmatter": "^5.2.0", "remark-mdx-frontmatter": "^5.2.0",
"storybook": "^10.2.1", "storybook": "^10.4.2",
"style-mod": "^4.1.3", "style-mod": "^4.1.3",
"stylelint": "^17.11.1", "stylelint": "^17.12.0",
"trusted-types": "^2.0.0", "trusted-types": "^2.0.0",
"ts-pattern": "^5.9.0", "ts-pattern": "^5.9.0",
"turnstile-types": "^1.2.3", "turnstile-types": "^1.2.3",
"type-fest": "^5.7.0", "type-fest": "^5.7.0",
"typescript": "^6.0.3", "typescript": "^6.0.3",
"typescript-eslint": "^8.59.3", "typescript-eslint": "^8.60.1",
"unist-util-visit": "^5.1.0", "unist-util-visit": "^5.1.0",
"vite": "^8.0.16", "vite": "^8.0.16",
"vitest": "^4.1.6", "vitest": "^4.1.8",
"webcomponent-qr-code": "^1.3.0", "webcomponent-qr-code": "^1.3.0",
"wireit": "^0.14.12", "wireit": "^0.14.12",
"yaml": "^2.9.0" "yaml": "^2.9.0"
@@ -203,14 +203,11 @@
"@esbuild/darwin-arm64": "^0.28.0", "@esbuild/darwin-arm64": "^0.28.0",
"@esbuild/linux-arm64": "^0.28.0", "@esbuild/linux-arm64": "^0.28.0",
"@esbuild/linux-x64": "^0.28.0", "@esbuild/linux-x64": "^0.28.0",
"@goauthentik/prettier-config-dev": "../packages/prettier-config", "@goauthentik/prettier-config-dev": "link:../packages/prettier-config",
"@rollup/rollup-darwin-arm64": "^4.61.1", "@rollup/rollup-darwin-arm64": "^4.61.1",
"@rollup/rollup-linux-arm64-gnu": "^4.61.1", "@rollup/rollup-linux-arm64-gnu": "^4.61.1",
"@rollup/rollup-linux-x64-gnu": "^4.61.1" "@rollup/rollup-linux-x64-gnu": "^4.61.1"
}, },
"workspaces": [
"./packages/*"
],
"wireit": { "wireit": {
"build": { "build": {
"command": "${NODE_RUNNER} scripts/build-web.mjs", "command": "${NODE_RUNNER} scripts/build-web.mjs",
@@ -237,10 +234,10 @@
"./dist/styles/**" "./dist/styles/**"
], ],
"#comment": [ "#comment": [
"`npm run build` and `npm run watch` are the most common ", "`pnpm run build` and `pnpm run watch` are the most common ",
"commands you should be using when working on the front end", "commands you should be using when working on the front end",
"The files and output spec here expect you to use `npm run build --watch` ", "The files and output spec here expect you to use `pnpm run build --watch` ",
"instead of `npm run watch`. The former is more comprehensive, but ", "instead of `pnpm run watch`. The former is more comprehensive, but ",
"the latter is faster." "the latter is faster."
], ],
"env": { "env": {
@@ -294,66 +291,15 @@
}, },
"engines": { "engines": {
"node": ">=24", "node": ">=24",
"npm": ">=11.14.1" "pnpm": ">=11.5.1"
}, },
"devEngines": { "devEngines": {
"runtime": { "runtime": {
"name": "node", "name": "node",
"onFail": "warn", "onFail": "warn",
"version": ">=24" "version": ">=24"
},
"packageManager": {
"name": "npm",
"version": ">=11.14.1",
"onFail": "warn"
} }
}, },
"packageManager": "npm@11.14.1+sha512.6a8a4d67478497a2dbc6815cad72e64c43f33413717e242756047d466241ab39bee61e691683a64658e94496ec5f1a1c05e4a5ec62dcc773280dfd949443a367", "packageManager": "pnpm@11.5.1+sha512.93f7b57422ea7068257235b4c16eb60762eb68e1dc23723199cc739043ea9be2c4143274a399d8c6defa2b1176226d9ca1c4b63482d6200c1a8fbaa78c1d1485",
"prettier": "./prettier.config.mjs", "prettier": "./prettier.config.mjs"
"overrides": {
"@goauthentik/esbuild-plugin-live-reload": {
"esbuild": "$esbuild",
"typescript": "$typescript"
},
"@goauthentik/eslint-config": {
"typescript": "$typescript"
},
"@goauthentik/prettier-config": {
"prettier": "$prettier",
"prettier-plugin-packagejson": "$prettier-plugin-packagejson",
"typescript": "$typescript"
},
"@mrmarble/djangoql-completion": {
"lex": "$lex",
"lodash": "^4.18.1"
},
"@typescript-eslint/eslint-plugin": {
"typescript": "$typescript"
},
"@typescript-eslint/parser": {
"typescript": "$typescript"
},
"@typescript-eslint/typescript-estree": {
"typescript": "$typescript"
},
"@typescript-eslint/utils": {
"typescript": "$typescript"
},
"format-imports": {
"eslint": "$eslint"
},
"node-fetch-commonjs": {
"node-domexception": "$node-domexception"
},
"rapidoc": {
"@apitools/openapi-parser": "0.0.37"
},
"tree-sitter": false,
"typescript-eslint": {
"typescript": "$typescript"
},
"wireit": {
"brace-expansion": "^1.1.14"
}
}
} }

View File

@@ -45,13 +45,12 @@
}, },
"dependencies": { "dependencies": {
"@goauthentik/tsconfig": "^2.0.0", "@goauthentik/tsconfig": "^2.0.0",
"@types/node": "^25.7.0", "@types/node": "^25.9.1",
"@types/semver": "^7.7.1", "@types/semver": "^7.7.1",
"semver": "^7.7.4", "semver": "^7.8.1",
"typescript": "^6.0.3" "typescript": "^6.0.3"
}, },
"engines": { "engines": {
"node": ">=24", "node": ">=24"
"npm": ">=11.14.1"
} }
} }

View File

@@ -14,8 +14,8 @@
"./package.json": "./package.json" "./package.json": "./package.json"
}, },
"dependencies": { "dependencies": {
"@goauthentik/api": "0.0.0", "@goauthentik/api": "link:../client-ts",
"@goauthentik/core": "^1.0.0", "@goauthentik/core": "workspace:*",
"@rollup/plugin-commonjs": "^29.0.3", "@rollup/plugin-commonjs": "^29.0.3",
"@rollup/plugin-node-resolve": "^16.0.3", "@rollup/plugin-node-resolve": "^16.0.3",
"@rollup/plugin-swc": "^0.4.1", "@rollup/plugin-swc": "^0.4.1",
@@ -24,7 +24,7 @@
"@webcomponents/template": "^1.5.1", "@webcomponents/template": "^1.5.1",
"base64-js": "^1.5.1", "base64-js": "^1.5.1",
"core-js": "^3.49.0", "core-js": "^3.49.0",
"formdata-polyfill": "^2025.11.0", "formdata-polyfill": "workspace:*",
"globby": "16.2.0", "globby": "16.2.0",
"jquery": "^3.7.1", "jquery": "^3.7.1",
"lit-html": "^1.4.1", "lit-html": "^1.4.1",
@@ -32,15 +32,15 @@
"weakmap-polyfill": "^2.0.4" "weakmap-polyfill": "^2.0.4"
}, },
"optionalDependencies": { "optionalDependencies": {
"@swc/core-darwin-arm64": "^1.15.3", "@swc/core-darwin-arm64": "^1.15.40",
"@swc/core-darwin-x64": "^1.15.3", "@swc/core-darwin-x64": "^1.15.40",
"@swc/core-linux-arm-gnueabihf": "^1.15.3", "@swc/core-linux-arm-gnueabihf": "^1.15.40",
"@swc/core-linux-arm64-gnu": "^1.15.3", "@swc/core-linux-arm64-gnu": "^1.15.40",
"@swc/core-linux-arm64-musl": "^1.15.3", "@swc/core-linux-arm64-musl": "^1.15.40",
"@swc/core-linux-x64-gnu": "^1.15.3", "@swc/core-linux-x64-gnu": "^1.15.40",
"@swc/core-linux-x64-musl": "^1.15.3", "@swc/core-linux-x64-musl": "^1.15.40",
"@swc/core-win32-arm64-msvc": "^1.15.3", "@swc/core-win32-arm64-msvc": "^1.15.40",
"@swc/core-win32-ia32-msvc": "^1.15.3", "@swc/core-win32-ia32-msvc": "^1.15.40",
"@swc/core-win32-x64-msvc": "^1.15.3" "@swc/core-win32-x64-msvc": "^1.15.40"
} }
} }

View File

@@ -45,7 +45,12 @@ export async function createConfig() {
context: "window", context: "window",
plugins: [ plugins: [
copyPlugin, copyPlugin,
resolve({ browser: true }), // `.ts`/`.tsx` so the linked `@goauthentik/api` source (resolved from
// its package `main`) and its relative imports resolve; swc transpiles them.
resolve({
browser: true,
extensions: [".mjs", ".js", ".json", ".node", ".ts", ".tsx"],
}),
commonjs(), commonjs(),
swc({ swc({
swc: { swc: {

13937
web/pnpm-lock.yaml generated Normal file

File diff suppressed because it is too large Load Diff

60
web/pnpm-workspace.yaml Normal file
View File

@@ -0,0 +1,60 @@
packages:
- "packages/*"
# client-ts is a symlink to the repo-root packages/client-ts; consuming it as
# a workspace member makes pnpm treat an out-of-root path as an importer, which
# it cannot represent in this lockfile. Link it as an external local package
# instead (see web + sfe package.json).
- "!packages/client-ts"
# pnpm's default isolated linker exposes packages strictly — only declared
# dependencies are visible. The web bundle relies on a handful of phantom
# deps that were hoisted by npm at the root of `node_modules` (lit-html
# internals, ol, mdast-util-to-string, etc.). Until each is added as an
# explicit dependency, fall back to the flat hoisted layout that mirrors
# npm's behavior.
nodeLinker: hoisted
overrides:
"@goauthentik/esbuild-plugin-live-reload>esbuild": "$esbuild"
"@goauthentik/esbuild-plugin-live-reload>typescript": "$typescript"
"@goauthentik/eslint-config>typescript": "$typescript"
"@goauthentik/prettier-config>prettier": "$prettier"
"@goauthentik/prettier-config>prettier-plugin-packagejson": "$prettier-plugin-packagejson"
"@goauthentik/prettier-config>typescript": "$typescript"
"@mrmarble/djangoql-completion>lex": "$lex"
"@mrmarble/djangoql-completion>lodash": "^4.18.1"
"@typescript-eslint/eslint-plugin>typescript": "$typescript"
"@typescript-eslint/parser>typescript": "$typescript"
"@typescript-eslint/typescript-estree>typescript": "$typescript"
"@typescript-eslint/utils>typescript": "$typescript"
"format-imports>eslint": "$eslint"
"node-fetch-commonjs>node-domexception": "$node-domexception"
"rapidoc>@apitools/openapi-parser": "0.0.37"
"typescript-eslint>typescript": "$typescript"
"wireit>brace-expansion": "^1.1.14"
# Allow-list of dependencies whose install/postinstall scripts may run.
# Everything else is blocked, replacing the prior `ignore-scripts=true` +
# `npm rebuild --foreground-scripts <pkg>` pattern from #20400. Each entry
# is audited at review time — adding a package here grants it arbitrary code
# execution at install.
onlyBuiltDependencies:
- chromedriver
- esbuild
- tree-sitter
- tree-sitter-json
- "@tree-sitter-grammars/tree-sitter-yaml"
# Explicit approval map for pnpm 11+. `true` = allowed (mirror
# onlyBuiltDependencies); `false` = explicitly declined to silence the
# "pending approval" prompt without running the install script.
allowBuilds:
"@scarf/scarf": false
"@swc/core": false
"@tree-sitter-grammars/tree-sitter-yaml": true
chromedriver: true
core-js: false
core-js-pure: false
esbuild: true
tree-sitter: true
tree-sitter-json: true

View File

@@ -3,7 +3,13 @@ build
out out
coverage coverage
.docusaurus .docusaurus
node_modules
help help
static static
scripts/docsmg/target/ scripts/docsmg/target/
## Node
node_modules
# PNPM
pnpm-workspace.yaml
pnpm-lock.yaml

View File

@@ -1,41 +1,53 @@
# Tag must track the root package.json `packageManager` version. ${BUILDPLATFORM}
# keeps the binary's arch aligned with the builder stage on cross-arch builds.
FROM --platform=${BUILDPLATFORM} ghcr.io/pnpm/pnpm:11.5.1@sha256:3cbdefab0d887dee497ddc8dfe6d871257317d69520fe30f9ccec0a84bde6e89 AS pnpm
FROM --platform=${BUILDPLATFORM} docker.io/library/node:26.4.0-trixie@sha256:b46a10d964ad15136ebdf9012142131481caa0697d7a4d4eafe4bbabd818f876 AS docs-builder FROM --platform=${BUILDPLATFORM} docker.io/library/node:26.4.0-trixie@sha256:b46a10d964ad15136ebdf9012142131481caa0697d7a4d4eafe4bbabd818f876 AS docs-builder
ENV NODE_ENV=production ENV NODE_ENV=production
WORKDIR /work WORKDIR /work
COPY --from=pnpm /opt/pnpm /opt/pnpm
ENV PATH="/opt/pnpm:${PATH}"
RUN --mount=type=bind,target=/work/package.json,src=./package.json \ RUN --mount=type=bind,target=/work/package.json,src=./package.json \
--mount=type=bind,target=/work/package-lock.json,src=./package-lock.json \
--mount=type=bind,target=/work/scripts/node/,src=./scripts/node/ \ --mount=type=bind,target=/work/scripts/node/,src=./scripts/node/ \
--mount=type=bind,target=/work/packages/logger-js/,src=./packages/logger-js/ \ --mount=type=bind,target=/work/packages/logger-js/,src=./packages/logger-js/ \
--mount=type=bind,target=/work/packages/tsconfig/,src=./packages/tsconfig/ \
--mount=type=bind,target=/work/packages/eslint-config/,src=./packages/eslint-config/ \
--mount=type=bind,target=/work/packages/prettier-config/,src=./packages/prettier-config/ \
--mount=type=bind,target=/work/packages/docusaurus-config/,src=./packages/docusaurus-config/ \
--mount=type=bind,target=/work/website/package.json,src=./website/package.json \ --mount=type=bind,target=/work/website/package.json,src=./website/package.json \
--mount=type=bind,target=/work/website/package-lock.json,src=./website/package-lock.json \ --mount=type=bind,target=/work/website/pnpm-lock.yaml,src=./website/pnpm-lock.yaml \
node ./scripts/node/setup-corepack.mjs --force && \
node ./scripts/node/lint-runtime.mjs ./website node ./scripts/node/lint-runtime.mjs ./website
# Hoisted root install so `@goauthentik/docusaurus-config` resolves its own deps
# (e.g. `deepmerge-ts`) from /work/node_modules during the docs build; its source
# is bind-mounted read-only, so a per-package node_modules can't be written.
RUN --mount=type=bind,target=/work/.npmrc,src=./.npmrc \ RUN --mount=type=bind,target=/work/.npmrc,src=./.npmrc \
--mount=type=bind,target=/work/package.json,src=./package.json \ --mount=type=bind,target=/work/package.json,src=./package.json \
--mount=type=bind,target=/work/package-lock.json,src=./package-lock.json \ --mount=type=bind,target=/work/pnpm-lock.yaml,src=./pnpm-lock.yaml \
--mount=type=bind,target=/work/scripts/node/,src=./scripts/node/ \ --mount=type=bind,target=/work/pnpm-workspace.yaml,src=./pnpm-workspace.yaml \
--mount=type=bind,target=/work/packages/logger-js/,src=./packages/logger-js/ \ --mount=type=bind,target=/work/packages/docusaurus-config/package.json,src=./packages/docusaurus-config/package.json \
--mount=type=bind,target=/work/packages/tsconfig/,src=./packages/tsconfig/ \ --mount=type=bind,target=/work/packages/esbuild-plugin-live-reload/package.json,src=./packages/esbuild-plugin-live-reload/package.json \
--mount=type=bind,target=/work/packages/eslint-config/,src=./packages/eslint-config/ \ --mount=type=bind,target=/work/packages/eslint-config/package.json,src=./packages/eslint-config/package.json \
--mount=type=bind,target=/work/packages/prettier-config/,src=./packages/prettier-config/ \ --mount=type=bind,target=/work/packages/logger-js/package.json,src=./packages/logger-js/package.json \
--mount=type=bind,target=/work/packages/prettier-config/package.json,src=./packages/prettier-config/package.json \
--mount=type=bind,target=/work/packages/tsconfig/package.json,src=./packages/tsconfig/package.json \
--mount=type=bind,target=/work/lifecycle/aws/package.json,src=./lifecycle/aws/package.json \
--mount=type=cache,id=pnpm-root,sharing=shared,target=/root/.local/share/pnpm/store \
pnpm install --frozen-lockfile --config.node-linker=hoisted \
--filter "@goauthentik/docusaurus-config"
RUN --mount=type=bind,target=/work/.npmrc,src=./.npmrc \
--mount=type=bind,target=/work/packages/docusaurus-config/,src=./packages/docusaurus-config/ \ --mount=type=bind,target=/work/packages/docusaurus-config/,src=./packages/docusaurus-config/ \
--mount=type=bind,target=/work/website/package.json,src=./website/package.json \ --mount=type=bind,target=/work/website/package.json,src=./website/package.json \
--mount=type=bind,target=/work/website/package-lock.json,src=./website/package-lock.json \ --mount=type=bind,target=/work/website/pnpm-lock.yaml,src=./website/pnpm-lock.yaml \
--mount=type=bind,target=/work/website/pnpm-workspace.yaml,src=./website/pnpm-workspace.yaml \
--mount=type=bind,target=/work/website/vendored/detect-package-manager,src=./website/vendored/detect-package-manager \ --mount=type=bind,target=/work/website/vendored/detect-package-manager,src=./website/vendored/detect-package-manager \
--mount=type=bind,target=/work/website/docusaurus-theme/package.json,src=./website/docusaurus-theme/package.json \ --mount=type=bind,target=/work/website/docusaurus-theme/package.json,src=./website/docusaurus-theme/package.json \
--mount=type=bind,target=/work/website/api/package.json,src=./website/api/package.json \ --mount=type=bind,target=/work/website/api/package.json,src=./website/api/package.json \
--mount=type=bind,target=/work/website/integrations/package.json,src=./website/integrations/package.json \ --mount=type=bind,target=/work/website/integrations/package.json,src=./website/integrations/package.json \
--mount=type=bind,target=/work/website/docs/package.json,src=./website/docs/package.json \ --mount=type=bind,target=/work/website/docs/package.json,src=./website/docs/package.json \
--mount=type=cache,id=npm-website,sharing=shared,target=/root/.npm \ --mount=type=cache,id=pnpm-website,sharing=shared,target=/root/.local/share/pnpm/store \
corepack npm ci && \ pnpm --dir website install --frozen-lockfile
corepack npm ci --workspaces --include-workspace-root --prefix ./website
WORKDIR /work/website WORKDIR /work/website
@@ -46,7 +58,7 @@ COPY ./lifecycle/container/compose.yml /work/lifecycle/container/
COPY ./SECURITY.md /work/ COPY ./SECURITY.md /work/
RUN --mount=type=bind,target=/work/packages/docusaurus-config/,src=./packages/docusaurus-config/ \ RUN --mount=type=bind,target=/work/packages/docusaurus-config/,src=./packages/docusaurus-config/ \
corepack npm run build -w docs pnpm run build
FROM docker.io/library/nginx:1.31.2-trixie@sha256:ec4ed8b5299e5e90694af7750eb6dffd2627317d30544d056b0371f8082f7bce FROM docker.io/library/nginx:1.31.2-trixie@sha256:ec4ed8b5299e5e90694af7750eb6dffd2627317d30544d056b0371f8082f7bce
LABEL org.opencontainers.image.authors="Authentik Security Inc." \ LABEL org.opencontainers.image.authors="Authentik Security Inc." \

View File

@@ -10,11 +10,11 @@
[build] [build]
base = "website" base = "website"
package = "api" package = "api"
command = "npm ci --prefix ../packages/docusaurus-config && npm run build -w api" command = "pnpm --dir .. install --frozen-lockfile && pnpm install --frozen-lockfile && pnpm run build:api"
publish = "build" publish = "build"
[dev] [dev]
command = "npm start" command = "pnpm start"
targetPort = 3000 targetPort = 3000
[context.production.environment] [context.production.environment]

View File

@@ -5,7 +5,7 @@
"license": "MIT", "license": "MIT",
"private": true, "private": true,
"scripts": { "scripts": {
"build": "run-s generate build:docusaurus", "build": "docusaurus gen-api-docs all && docusaurus build",
"build:docusaurus": "docusaurus build", "build:docusaurus": "docusaurus build",
"clean": "run-s generate:clean docusaurus:clean", "clean": "run-s generate:clean docusaurus:clean",
"docusaurus": "docusaurus", "docusaurus": "docusaurus",
@@ -29,12 +29,12 @@
"@docusaurus/theme-common": "^3.10.1", "@docusaurus/theme-common": "^3.10.1",
"@docusaurus/tsconfig": "^3.10.1", "@docusaurus/tsconfig": "^3.10.1",
"@docusaurus/types": "^3.10.1", "@docusaurus/types": "^3.10.1",
"@goauthentik/docusaurus-config": "../../packages/docusaurus-config", "@goauthentik/docusaurus-config": "link:../../packages/docusaurus-config",
"@goauthentik/docusaurus-theme": "*", "@goauthentik/docusaurus-theme": "workspace:*",
"@goauthentik/tsconfig": "^2.0.0", "@goauthentik/tsconfig": "^2.0.0",
"@mdx-js/react": "^3.1.1", "@mdx-js/react": "^3.1.1",
"@types/postman-collection": "^3.5.11", "@types/postman-collection": "^3.5.11",
"@types/react": "^19.2.14", "@types/react": "^19.2.16",
"@types/react-dom": "^19.2.3", "@types/react-dom": "^19.2.3",
"docusaurus-plugin-openapi-docs": "^5.0.2", "docusaurus-plugin-openapi-docs": "^5.0.2",
"docusaurus-theme-openapi-docs": "^5.0.2", "docusaurus-theme-openapi-docs": "^5.0.2",
@@ -43,8 +43,8 @@
"postman-code-generators": "^2.1.1", "postman-code-generators": "^2.1.1",
"postman-collection": "^5.3.0", "postman-collection": "^5.3.0",
"prism-react-renderer": "^2.4.1", "prism-react-renderer": "^2.4.1",
"react": "^19.2.6", "react": "^19.2.7",
"react-dom": "^19.2.6", "react-dom": "^19.2.7",
"typescript": "^6.0.3" "typescript": "^6.0.3"
}, },
"optionalDependencies": { "optionalDependencies": {

View File

@@ -10,11 +10,11 @@
[build] [build]
base = "website" base = "website"
package = "docs" package = "docs"
command = "npm ci --prefix ../packages/docusaurus-config && npm run build -w docs" command = "pnpm --dir .. install --frozen-lockfile && pnpm install --frozen-lockfile && pnpm run build"
publish = "docs/build" publish = "docs/build"
[dev] [dev]
command = "npm start" command = "pnpm start"
targetPort = 3000 targetPort = 3000
[context.production.environment] [context.production.environment]

View File

@@ -4,7 +4,7 @@
"license": "MIT", "license": "MIT",
"private": true, "private": true,
"scripts": { "scripts": {
"build": "run-s build:docusaurus build:copy", "build": "docusaurus build && cp -r ./build/ ../build/",
"build:copy": "cp -r ./build/ ../build/", "build:copy": "cp -r ./build/ ../build/",
"build:docusaurus": "docusaurus build", "build:docusaurus": "docusaurus build",
"check-types": "tsc -b .", "check-types": "tsc -b .",
@@ -20,24 +20,23 @@
"@docusaurus/theme-mermaid": "^3.10.1", "@docusaurus/theme-mermaid": "^3.10.1",
"@docusaurus/tsconfig": "^3.10.1", "@docusaurus/tsconfig": "^3.10.1",
"@docusaurus/types": "^3.10.1", "@docusaurus/types": "^3.10.1",
"@goauthentik/docusaurus-config": "../../packages/docusaurus-config", "@goauthentik/docusaurus-config": "link:../../packages/docusaurus-config",
"@goauthentik/docusaurus-theme": "*", "@goauthentik/docusaurus-theme": "workspace:*",
"@iconify-json/fa7-regular": "^1.2.2", "@iconify-json/fa7-regular": "^1.2.3",
"@iconify-json/fa7-solid": "^1.2.5", "@iconify-json/fa7-solid": "^1.2.5",
"@iconify-json/fluent-mdl2": "^1.2.1", "@iconify-json/fluent-mdl2": "^1.2.1",
"@iconify-json/mdi": "^1.2.3", "@iconify-json/mdi": "^1.2.3",
"@mdx-js/react": "^3.1.1", "@mdx-js/react": "^3.1.1",
"@types/react": "^19.2.14", "@types/react": "^19.2.16",
"@types/react-dom": "^19.2.3", "@types/react-dom": "^19.2.3",
"prism-react-renderer": "^2.4.1", "prism-react-renderer": "^2.4.1",
"react": "^19.2.6", "react": "^19.2.7",
"react-before-after-slider-component": "^1.1.8", "react-before-after-slider-component": "^1.1.8",
"react-dom": "^19.2.6", "react-dom": "^19.2.7",
"typescript": "^6.0.3", "typescript": "^6.0.3",
"unist-util-visit": "^5.0.0" "unist-util-visit": "^5.1.0"
}, },
"engines": { "engines": {
"node": ">=24", "node": ">=24"
"npm": ">=11.14.1"
} }
} }

View File

@@ -60,7 +60,8 @@ export function useHostname() {
export function useCachedVersionPluginData(): AKReleasesPluginData | null { export function useCachedVersionPluginData(): AKReleasesPluginData | null {
const pluginData = usePluginData("ak-releases-plugin", undefined) as const pluginData = usePluginData("ak-releases-plugin", undefined) as
AKReleasesPluginData | undefined; | AKReleasesPluginData
| undefined;
return pluginData ?? null; return pluginData ?? null;
} }

View File

@@ -32,7 +32,7 @@
"dependencies": { "dependencies": {
"@docusaurus/preset-classic": "^3.10.1", "@docusaurus/preset-classic": "^3.10.1",
"@docusaurus/utils": "^3.10.1", "@docusaurus/utils": "^3.10.1",
"@goauthentik/docusaurus-config": "../../packages/docusaurus-config", "@goauthentik/docusaurus-config": "link:../../packages/docusaurus-config",
"@types/semver": "^7.7.1", "@types/semver": "^7.7.1",
"clsx": "^2.1.1", "clsx": "^2.1.1",
"fast-glob": "^3.3.3", "fast-glob": "^3.3.3",
@@ -45,6 +45,6 @@
"semver": "^7.8.5", "semver": "^7.8.5",
"typescript": "^6.0.3", "typescript": "^6.0.3",
"unified": "^11.0.5", "unified": "^11.0.5",
"unist-util-visit": "^5.0.0" "unist-util-visit": "^5.1.0"
} }
} }

View File

@@ -8,7 +8,8 @@ import { usePluginData } from "@docusaurus/useGlobalData";
*/ */
export function useRedirectEntries(): RedirectEntry[] | null { export function useRedirectEntries(): RedirectEntry[] | null {
const pluginData = usePluginData("ak-redirects-plugin", undefined) as const pluginData = usePluginData("ak-redirects-plugin", undefined) as
AKRedirectsPluginData | undefined; | AKRedirectsPluginData
| undefined;
if (!pluginData || !pluginData.redirects) { if (!pluginData || !pluginData.redirects) {
return null; return null;

View File

@@ -10,11 +10,11 @@
[build] [build]
base = "website" base = "website"
package = "integrations" package = "integrations"
command = "npm ci --prefix ../packages/docusaurus-config && npm run build -w integrations" command = "pnpm --dir .. install --frozen-lockfile && pnpm install --frozen-lockfile && pnpm run build:integrations"
publish = "integrations/build" publish = "integrations/build"
[dev] [dev]
command = "npm start" command = "pnpm start"
targetPort = 3000 targetPort = 3000
[context.production.environment] [context.production.environment]

View File

@@ -4,7 +4,7 @@
"license": "MIT", "license": "MIT",
"private": true, "private": true,
"scripts": { "scripts": {
"build": "run-s build:docusaurus", "build": "docusaurus build",
"build:docusaurus": "docusaurus build", "build:docusaurus": "docusaurus build",
"clear": "docusaurus clear", "clear": "docusaurus clear",
"docusaurus": "docusaurus", "docusaurus": "docusaurus",
@@ -19,18 +19,17 @@
"@docusaurus/theme-mermaid": "^3.10.1", "@docusaurus/theme-mermaid": "^3.10.1",
"@docusaurus/tsconfig": "^3.10.1", "@docusaurus/tsconfig": "^3.10.1",
"@docusaurus/types": "^3.10.1", "@docusaurus/types": "^3.10.1",
"@goauthentik/docusaurus-config": "../../packages/docusaurus-config", "@goauthentik/docusaurus-config": "link:../../packages/docusaurus-config",
"@goauthentik/docusaurus-theme": "*", "@goauthentik/docusaurus-theme": "workspace:*",
"@mdx-js/react": "^3.1.1", "@mdx-js/react": "^3.1.1",
"@types/react": "^19.2.14", "@types/react": "^19.2.16",
"@types/react-dom": "^19.2.3", "@types/react-dom": "^19.2.3",
"prism-react-renderer": "^2.4.1", "prism-react-renderer": "^2.4.1",
"react": "^19.2.6", "react": "^19.2.7",
"react-dom": "^19.2.6", "react-dom": "^19.2.7",
"typescript": "^6.0.3" "typescript": "^6.0.3"
}, },
"engines": { "engines": {
"node": ">=24", "node": ">=24"
"npm": ">=11.14.1"
} }
} }

21662
website/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -4,29 +4,28 @@
"license": "MIT", "license": "MIT",
"private": true, "private": true,
"scripts": { "scripts": {
"build": "npm run build -w docs", "build": "pnpm --filter \"./docs\" run build",
"build:api": "npm run build -w api", "build:api": "pnpm --filter \"./api\" run build",
"build:integrations": "npm run build -w integrations", "build:integrations": "pnpm --filter \"./integrations\" run build",
"check-types": "tsc -b", "check-types": "tsc -b",
"docusaurus": "docusaurus", "docusaurus": "docusaurus",
"lint": "eslint --fix .", "lint": "eslint --fix .",
"lint-check": "eslint --max-warnings 0 .", "lint-check": "eslint --max-warnings 0 .",
"prettier": "prettier --write .", "prettier": "prettier --write .",
"prettier-check": "npm run prettier-prepare && prettier --check .", "prettier-check": "prettier --check .",
"prettier-prepare": "npm ci --prefix ../packages/prettier-config", "start": "pnpm --filter \"./docs\" run start",
"start": "npm start -w docs",
"test": "node --test" "test": "node --test"
}, },
"dependencies": { "dependencies": {
"@eslint/js": "^9.39.3", "@eslint/js": "^9.39.4",
"@goauthentik/brand-assets": "^2.0.0", "@goauthentik/brand-assets": "^2.0.0",
"@goauthentik/eslint-config": "../packages/eslint-config", "@goauthentik/eslint-config": "link:../packages/eslint-config",
"@goauthentik/prettier-config": "../packages/prettier-config", "@goauthentik/prettier-config": "link:../packages/prettier-config",
"@goauthentik/tsconfig": "../packages/tsconfig", "@goauthentik/tsconfig": "link:../packages/tsconfig",
"@types/node": "^26.1.0", "@types/node": "^26.1.0",
"deepmerge-ts": "^7.1.5", "deepmerge-ts": "^7.1.5",
"escape-string-regexp": "^5.0.0", "escape-string-regexp": "^5.0.0",
"eslint": "^9.39.3", "eslint": "^9.39.4",
"netlify-plugin-cache": "^1.0.3", "netlify-plugin-cache": "^1.0.3",
"netlify-redirect-parser": "^14.4.0", "netlify-redirect-parser": "^14.4.0",
"npm-run-all": "^4.1.5", "npm-run-all": "^4.1.5",
@@ -34,7 +33,7 @@
"prettier": "^3.8.3", "prettier": "^3.8.3",
"prettier-plugin-packagejson": "^3.0.2", "prettier-plugin-packagejson": "^3.0.2",
"typescript": "^6.0.3", "typescript": "^6.0.3",
"typescript-eslint": "^8.59.3" "typescript-eslint": "^8.60.1"
}, },
"optionalDependencies": { "optionalDependencies": {
"@rspack/binding-darwin-arm64": "2.0.8", "@rspack/binding-darwin-arm64": "2.0.8",
@@ -50,69 +49,17 @@
"lightningcss-linux-arm64-gnu": "1.32.0", "lightningcss-linux-arm64-gnu": "1.32.0",
"lightningcss-linux-x64-gnu": "1.32.0" "lightningcss-linux-x64-gnu": "1.32.0"
}, },
"workspaces": [
"vendored/*",
"docusaurus-theme",
"api",
"integrations",
"docs"
],
"engines": { "engines": {
"node": ">=24", "node": ">=24",
"npm": ">=11.14.1" "pnpm": ">=11.5.1"
}, },
"devEngines": { "devEngines": {
"runtime": { "runtime": {
"name": "node", "name": "node",
"onFail": "error", "onFail": "error",
"version": ">=24" "version": ">=24"
},
"packageManager": {
"name": "npm",
"version": ">=11.6.2",
"onFail": "warn"
} }
}, },
"packageManager": "npm@11.14.1+sha512.6a8a4d67478497a2dbc6815cad72e64c43f33413717e242756047d466241ab39bee61e691683a64658e94496ec5f1a1c05e4a5ec62dcc773280dfd949443a367", "packageManager": "pnpm@11.5.1+sha512.93f7b57422ea7068257235b4c16eb60762eb68e1dc23723199cc739043ea9be2c4143274a399d8c6defa2b1176226d9ca1c4b63482d6200c1a8fbaa78c1d1485",
"prettier": "@goauthentik/prettier-config", "prettier": "@goauthentik/prettier-config"
"overrides": {
"@goauthentik/docusaurus-config": {
"react": "$react",
"react-dom": "$react-dom",
"@docusaurus/theme-common": "$@docusaurus/theme-common"
},
"@goauthentik/eslint-config": {
"typescript": "$typescript"
},
"@goauthentik/prettier-config": {
"prettier": "$prettier",
"prettier-plugin-packagejson": "$prettier-plugin-packagejson"
},
"@typescript-eslint/parser": {
"typescript": "$typescript"
},
"@typescript-eslint/utils": {
"typescript": "$typescript"
},
"docusaurus-theme-openapi-docs": {
"postman-code-generators": {
".": "^2.1.1",
"detect-package-manager": "file:./vendored/detect-package-manager",
"shelljs": "0.10.0"
}
},
"format-imports": {
"eslint": "$eslint"
},
"lodash": "^4.18.1",
"postman-code-generators": {
"detect-package-manager": "file:./vendored/detect-package-manager",
"shelljs": "0.10.0"
},
"postman-collection": "^5.3.0",
"typescript-eslint": {
"typescript": "$typescript"
},
"uuid": "^14.0.0"
}
} }

19953
website/pnpm-lock.yaml generated Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,57 @@
packages:
- "vendored/*"
- "docusaurus-theme"
- "api"
- "integrations"
- "docs"
# Docusaurus and several first-party plugins rely on phantom deps
# (notably `@docusaurus/utils`) that npm hoisted. Until each is added as an
# explicit dependency, fall back to the flat hoisted layout that mirrors
# npm's behavior.
nodeLinker: hoisted
overrides:
"@goauthentik/docusaurus-config>react": "^19.2.6"
"@goauthentik/docusaurus-config>react-dom": "^19.2.6"
"@goauthentik/docusaurus-config>@docusaurus/theme-common": "^3.10.1"
"@goauthentik/eslint-config>typescript": "$typescript"
"@goauthentik/prettier-config>prettier": "$prettier"
"@goauthentik/prettier-config>prettier-plugin-packagejson": "$prettier-plugin-packagejson"
"@typescript-eslint/parser>typescript": "$typescript"
"@typescript-eslint/utils>typescript": "$typescript"
"docusaurus-theme-openapi-docs>postman-code-generators": "^2.1.1"
"docusaurus-theme-openapi-docs>detect-package-manager": "workspace:*"
"docusaurus-theme-openapi-docs>shelljs": "0.10.0"
"format-imports>eslint": "$eslint"
"lodash": "^4.18.1"
"postman-code-generators>detect-package-manager": "workspace:*"
"postman-code-generators>shelljs": "0.10.0"
"postman-collection": "^5.3.0"
"typescript-eslint>typescript": "$typescript"
"uuid": "^14.0.0"
# Allow-list of dependencies whose install/postinstall scripts may run.
# Everything else is blocked, replacing the prior `ignore-scripts=true` +
# `npm rebuild --foreground-scripts <pkg>` pattern from #20400. Each entry
# is audited at review time — adding a package here grants it arbitrary code
# execution at install.
onlyBuiltDependencies:
- "@parcel/watcher"
- "@swc/core"
# Explicit approval map for pnpm 11+. `true` = allowed (mirror
# onlyBuiltDependencies); `false` = explicitly declined to silence the
# "pending approval" prompt without running the install script.
allowBuilds:
"@parcel/watcher": true
"@swc/core": true
core-js: false
postman-code-generators: false
minimumReleaseAgeExclude:
- js-yaml@4.1.1
- serialize-javascript@7.0.3
- yaml@1.10.3
- serialize-javascript@7.0.5
- '@types/node@26.1.0'