Skip to content
Merged

V2 #43

Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 24 additions & 9 deletions .github/workflows/release.yml → .github/workflows/main.yml
Original file line number Diff line number Diff line change
@@ -1,28 +1,42 @@
# This workflow will run tests using node and then publish a package to GitHub Packages when a release is created
# For more information see: https://docs.github.com/en/actions/publishing-packages/publishing-nodejs-packages
name: Main

name: Release
on:
push:
branches:
- release
branches: [main]
pull_request:
branches: [main]

jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v3
- uses: actions/setup-node@v4
with:
node-version: 24
cache: npm
- run: npm ci
- run: npx nuxt-module-build prepare

test:
if: github.event_name == 'push'
needs: build
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 24
cache: npm
- run: npm ci
- run: npm run lint
- run: npx nuxt-module-build prepare
- run: npm run prepack
- run: npm test

release:
needs: build
if: github.event_name == 'push'
needs: test
runs-on: ubuntu-latest
permissions:
contents: write
Expand All @@ -32,9 +46,10 @@ jobs:
id-token: write
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v3
- uses: actions/setup-node@v4
with:
node-version: 21
node-version: 24
cache: npm
- run: npm ci
- run: npx nuxt-module-build prepare
- run: npm run prepack
Expand Down
59 changes: 59 additions & 0 deletions .github/workflows/versioned.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
name: Versioned

on:
push:
branches: ['v*']
pull_request:
branches: ['v*']

jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 24
cache: npm
- run: npm ci
- run: npx nuxt-module-build prepare

test:
if: github.event_name == 'push'
needs: build
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 24
cache: npm
- run: npm ci
- run: npm run lint
- run: npx nuxt-module-build prepare
- run: npm run prepack
- run: npm test

release:
if: github.event_name == 'push' && github.ref_name != vars.LATEST_VERSION_BRANCH
needs: test
runs-on: ubuntu-latest
permissions:
contents: write
issues: write
pull-requests: write
packages: write
id-token: write
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 24
cache: npm
- run: npm ci
- run: npx nuxt-module-build prepare
- run: npm run prepack
- run: npx semantic-release
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
61 changes: 61 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# AGENTS.md

Nuxt module package (`@workmate/nuxt-auth`). Published artifact is `dist/module.mjs` built by `@nuxt/module-builder`. There is no host app — `playground/` is the dev harness and `test/fixtures/basic/` is the test harness.

## Layout that matters

- `src/module.ts` — module entry. Registers plugins, server handlers (`/api/auth/*`), route middlewares, and the schema-generation templates. Adding a new server route or middleware requires editing here, not just dropping a file.
- `src/schema-utils.ts` — build-time only. Collects per-provider Zod schemas from user config, converts each to JSON Schema, strips schemas from the options written to `runtimeConfig`, and renders `auth-schemas.gen.mjs` + `auth-schemas.gen.d.ts` via `addTemplate`. Both Nuxt and Nitro aliases for `#auth-schemas` point at the generated runtime file (see the alias setup in `src/module.ts`).
- `src/runtime/` — code shipped to the host app. Composables, plugins, middleware, providers, server handlers wired by `module.ts`.
- `src/runtime/providers/` — `AuthProvider` is the base class; `Local`, `Github`, `Google` extend it. There are no Facebook/LinkedIn provider files.
- Github/Google server callback handlers (`/api/auth/callback/{provider}`) are only registered when that provider is present in user config — check the `providers.github` / `providers.google` conditionals in `src/module.ts`.
- `playground/nuxt.config.ts` and `test/fixtures/basic/nuxt.config.ts` import the module from `../src/module` (not the published package).
- `test/basic.test.ts` is the only test today. It boots Nuxt via `@nuxt/test-utils/e2e` — full SSR, not unit tests. `PLAN.md` describes a larger intended test suite but it is not built yet.

## Schema pipeline (non-obvious, easy to break)

- Providers accept `schemas: { login?, user? }` (Zod). These cannot survive `runtimeConfig` — Nuxt 4 runs Nitro in a separate worker and Zod instances aren't JSON-serializable.
- `collectSchemas` converts them to JSON Schema at build time; `stripSchemasFromProviders` removes them before defu-merge into `runtimeConfig.auth`. At runtime the generated `#auth-schemas` module rebuilds Zod via `z.fromJSONSchema()`.
- Providers and `src/runtime/composables/useAuthLogin.ts` read `loginSchemas[name]` / `userSchemas[name]` from `#auth-schemas` for validation. Never read schemas from `runtimeConfig` — they won't be there.
- Generated type file exports `LoginData` and `UserDataByProvider` (keyed by `local | github | google`). `useAuthLogin().local()` is typed off `LoginData["local"]`, which is derived from the user's Zod schema in `nuxt.config.ts` — so changing that schema changes public types.
- This depends on **Zod 4** (`zod@4.x`). `z.toJSONSchema` / `z.fromJSONSchema` do not exist on Zod 3. Do not downgrade.
- After changing schemas in `playground/nuxt.config.ts`, the generated files in `.nuxt/` need a regen — re-run `dev` / `dev:prepare`.

## Commands

First-time / after `node_modules` reset:

```bash
npm run dev:prepare # nuxt-module-build build --stub && nuxt-module-build prepare && nuxi prepare playground
```

Daily:

```bash
npm run dev # runs playground at :3000
npm run lint # eslint .
npm test # vitest run (boots Nuxt; slow, not unit-level)
npm run test:watch
npm run prepack # nuxt-module-build build → dist/
```

No `typecheck` script. Types are validated indirectly by `nuxt-module-build prepare` (which writes `.nuxt/tsconfig.json` that the root `tsconfig.json` extends) and by `npm test`.

Do **not** run `npm run release` locally — it publishes to npm and pushes tags. Releases happen on CI when commits land on the `release` branch (`.github/workflows/release.yml` runs `lint → nuxt-module-build prepare → prepack → test → semantic-release`).

## Conventions that bite

- **Conventional Commits required.** `semantic-release` derives the version from commit messages on the `release` branch. A non-conforming commit gets ignored or breaks the release.
- ESLint config (`eslint.config.js`) intentionally disables `no-explicit-any`, `no-empty-object-type`, `no-invalid-void-type`, `vue/multi-word-component-names`, `no-console`, stylistic rules, and more. Don't reintroduce these as "fixes" — the relaxations are deliberate.
- `ban-ts-comment` is configured to **allow** `@ts-expect-error`. Prefer it over `@ts-ignore`.
- `.editorconfig` enforces 2-space, LF, final newline. Source files use **double quotes** and trailing semicolons; match the existing style (ESLint stylistic is off so it won't catch you).
- Module options are merged into `runtimeConfig.auth` (private, full options minus Zod schemas) and a subset into `runtimeConfig.public.auth` (`redirects`, `global`, `apiClient` only). When adding options, decide which side they belong on — see the defu merges near the bottom of `src/module.ts`'s `setup`.
- `nuxt-module-build prepare` writes types into `.nuxt/` that `tsconfig.json` extends. Type errors after pulling new code usually mean re-running `npm run dev:prepare`.

## Things not to assume

- `README.md` and `CHANGELOG.md` are partly stale — `PLAN.md` (Stage 3) explicitly tracks doc updates for the schema-pipeline API still owed. Treat `PLAN.md` + source as truth; treat README config examples (`principal`/`password`, `defineAuthEndpointSchemas`) as outdated.
- There is no separate unit-test layer. Every test currently spins up Nuxt — adding cheap unit tests is fine but pick a non-`@nuxt/test-utils` import.
- No formatter (no Prettier). ESLint with stylistic off is the only lint pass.
- No husky / lint-staged / pre-commit hooks.
- Node 24 in the CI build step, Node 21 in the release step (`.github/workflows/release.yml`). Prefer Node ≥21 locally.
21 changes: 21 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,5 +46,26 @@

# Changelog

## v2.0.0

### Breaking changes

- `body: { principal, password }` removed from `local` provider `signIn` config — use `schemas.login` instead
- Zod 4 required (`zod@^4.0.0`) — `z.toJSONSchema` / `z.fromJSONSchema` are Zod 4 only

### Features

- Open login body for local provider — any object is forwarded to the `signIn` endpoint; field names are no longer constrained to `principal`/`password`
- Per-provider Zod schema pipeline: define `schemas.login` and `schemas.user` in `nuxt.config.ts` per provider
- Build-time JSON Schema conversion via `src/schema-utils.ts`; runtime `#auth-schemas` virtual module reconstructs Zod schemas for both Nuxt and Nitro
- `useAuthLogin` composable — `localLogin`, `googleLogin`, `githubLogin` typed from your schemas
- `useAuthUser` composable — `{ user, isLoggedIn, refreshUser }`
- `useAuthToken` composable — `{ token, refreshToken, tokenType, provider, tokenNames, refreshTokens }`
- Server-side login body validation via `schemas.login` — invalid requests return HTTP 400 with field errors
- Server-side user response validation via `schemas.user` — mismatches throw with field-level detail

---

## v1.0.0

Initial release. See [migration guide](README.md#migration-v1--v2) for upgrading to v2.
Loading
Loading