Compare commits

...

37 Commits

Author SHA1 Message Date
GitHub Actions
a3cc9cb5f8 chore(release): bump package version(s) [skip ci] 2022-12-24 03:15:11 +00:00
Balázs Orbán
0ad4be2809 fix(core): add header to README 2022-12-24 04:04:56 +01:00
Balázs Orbán
aea4aaf25f fix(sveltekit): add header to README 2022-12-24 04:04:49 +01:00
Balázs Orbán
9bd7bc8a47 chore: fix docs building 2022-12-24 03:43:32 +01:00
Balázs Orbán
bf8fc9ca94 chore: fix docs scripts 2022-12-24 03:39:57 +01:00
Balázs Orbán
7116248e87 chore: mark @auth/* as prereleases 2022-12-24 03:30:53 +01:00
Balázs Orbán
ef8f353d94 Merge branch 'main' of github.com:nextauthjs/next-auth 2022-12-24 03:26:10 +01:00
Balázs Orbán
01620f9b7c chore: drop older node.js versions, update pnpm 2022-12-24 03:26:07 +01:00
Balázs Orbán
87d41aff94 chore: re-add LICENSE as it seems to not be picked up 2022-12-24 02:22:29 +00:00
Balázs Orbán
2d21f5ea5e chore: remove LICENSE file in favor of .github
See: https://github.com/nextauthjs/.github
2022-12-24 02:21:52 +00:00
Balázs Orbán
adf7cae7a0 chore: gitignore eslintcache 2022-12-24 03:17:50 +01:00
Balázs Orbán
f9b75e0a39 chore: remove extra tsconfigs 2022-12-24 03:16:50 +01:00
Balázs Orbán
9d6f54539d chore: simplify eslint linting 2022-12-24 03:10:03 +01:00
Balázs Orbán
0e51c66e11 chore: remove package-level lint and format 2022-12-24 01:49:31 +01:00
Balázs Orbán
e47c3c81f1 chore: format 2022-12-24 01:47:46 +01:00
Balázs Orbán
d69edb8501 chore: tweak prettierignore 2022-12-24 01:46:17 +01:00
Balázs Orbán
e5c0e3513b chore: upgrade monorepo-release package 2022-12-24 01:33:50 +01:00
Balázs Orbán
ca208ce732 chore: remove husky 2022-12-24 01:33:20 +01:00
Balázs Orbán
dcb601987b Merge branch 'main' of github.com:nextauthjs/next-auth 2022-12-23 15:00:20 +01:00
Balázs Orbán
7fd799a9ac chore: only lint with prettier 2022-12-23 15:00:13 +01:00
Balázs Orbán
fdd5e2390d chore: format 2022-12-23 14:42:37 +01:00
Balázs Orbán
fdecbb59c4 chore: move all lint/format to top 2022-12-23 14:41:53 +01:00
Nico Domino
677d8a346f chore(docs): fix aloglia docusaurus.config.js settings (#6159)
* chore: fix docusaurus algolia config

* chore: add empty 03-core dir
2022-12-23 12:41:43 +01:00
GitHub Actions
aad0b8db0e chore(release): bump package version(s) [skip ci] 2022-12-23 06:16:36 +00:00
Balázs Orbán
137bbb8d84 fix(core): improve AuthConfig docs 2022-12-23 07:02:50 +01:00
Balázs Orbán
d7fbd05eba chore: update monorepo-release package 2022-12-23 06:52:57 +01:00
Balázs Orbán
532aa24495 chore: use classic PAT for now 2022-12-23 05:10:27 +01:00
github-actions
f5da5a5f33 chore(release): bump package version(s) [skip ci] 2022-12-23 04:31:30 +01:00
Balázs Orbán
3b85f46c21 Update release.yml 2022-12-23 04:11:44 +01:00
Balázs Orbán
6aa1af2ffb Update release.yml 2022-12-23 04:11:00 +01:00
Balázs Orbán
9364625681 Update release.yml 2022-12-23 04:09:30 +01:00
Balázs Orbán
1bf2e1d468 Merge branch 'main' of github.com:nextauthjs/next-auth 2022-12-23 03:58:39 +01:00
Balázs Orbán
ac304f17da docs: fix link to sveltekit 2022-12-23 03:58:35 +01:00
Balázs Orbán
3a685b28f8 Update release.yml 2022-12-23 02:56:15 +00:00
Balázs Orbán
5b34b95c58 Update release.yml 2022-12-23 02:42:21 +00:00
Balázs Orbán
a706105205 chore: skip dynamodb as it times out 2022-12-23 03:28:07 +01:00
Balázs Orbán
39c78f27b5 fix(sveltekit): update to latest @auth/core, autogenerate API reference (#6153)
* docs(sveltekit): autogenerate API reference

* feat(sveltekit): update to use latest `@auth/core`

* chore: format

* chore: add auth packages as docs dependency

* chore: format

* chore: more formatting

* chore: don't run build before tests
2022-12-23 02:17:24 +00:00
106 changed files with 1683 additions and 1896 deletions

70
.eslintignore Normal file
View File

@@ -0,0 +1,70 @@
.eslintrc.js
.cache-loader
.DS_Store
.pnpm-debug.log
.turbo
.vscode/generated*
/_work
/actions-runner
node_modules
patches
pnpm-lock.yaml
.github/actions/issue-validator/index.mjs
*.cjs
*.js
*.d.ts
*.d.ts.map
.svelte-kit
.next
.nuxt
# --------------- Docs ---------------
.docusaurus
build
docs/docs/reference/03-core
docs/docs/reference/04-sveltekit
static
# --------------- Packages ---------------
coverage
dist
# @auth/core
packages/core/src/providers/oauth-types.ts
packages/core/src/lib/pages/styles.ts
# @auth/sveltekit
packages/frameworks-sveltekit/package
packages/frameworks-sveltekit/vite.config.{js,ts}.timestamp-*
# next-auth
packages/next-auth/src/providers/oauth-types.ts
packages/next-auth/css/index.css
# Adapters
.branches
db.sqlite
dev.db
dynamodblocal-bin
firebase-debug.log
firestore-debug.log
migrations
test.schema.gql
# --------------- Apps ---------------
# Examples should have their own Prettier config since they are templates too
apps/example-sveltekit
# Development app
apps
# --------------- Tests ---------------
# TODO: these should be linted
packages/**/*test*

View File

@@ -1,31 +1,37 @@
// @ts-check // @ts-check
const path = require("path")
/** @type {import("eslint").ESLint.ConfigData} */ /** @type {import("eslint").ESLint.ConfigData} */
module.exports = { module.exports = {
root: true, env: { browser: true, es2022: true, node: true },
parser: "@typescript-eslint/parser", extends: ["eslint:recommended", "prettier"],
extends: ["standard-with-typescript", "prettier/prettier"],
rules: {
camelcase: "off",
"@typescript-eslint/naming-convention": "off",
"@typescript-eslint/strict-boolean-expressions": "off",
"@typescript-eslint/explicit-function-return-type": "off",
"@typescript-eslint/restrict-template-expressions": "off",
},
overrides: [ overrides: [
{ {
files: ["*.ts", "*.tsx"], files: ["*.ts", "*.tsx"],
parser: "@typescript-eslint/parser",
parserOptions: { parserOptions: {
project: [ project: ["./packages/**/tsconfig.json", "./apps/**/tsconfig.json"],
path.resolve(__dirname, "./packages/**/tsconfig.eslint.json"), },
path.resolve(__dirname, "./packages/frameworks/**/tsconfig.json"), settings: { react: { version: "18" } },
path.resolve(__dirname, "./apps/**/tsconfig.json"), extends: [
"plugin:react/recommended",
"plugin:react/jsx-runtime",
"standard-with-typescript",
"prettier",
], ],
rules: {
"@typescript-eslint/explicit-function-return-type": "off",
"@typescript-eslint/method-signature-style": "off",
"@typescript-eslint/naming-convention": "off",
"@typescript-eslint/no-non-null-assertion": "off",
"@typescript-eslint/restrict-template-expressions": "off",
"@typescript-eslint/strict-boolean-expressions": "off",
"react/prop-types": "off",
"react/no-unescaped-entities": "off",
}, },
}, },
{ {
files: ["*.test.ts", "*.test.js"], files: ["*.test.ts", "*.test.js"],
extends: ["plugin:jest/recommended"],
env: { jest: true }, env: { jest: true },
}, },
{ {
@@ -34,7 +40,8 @@ module.exports = {
extends: ["plugin:@docusaurus/recommended"], extends: ["plugin:@docusaurus/recommended"],
}, },
{ {
files: ["packages/core/src/**/*"], // TODO: Expand to all packages
files: ["packages/{core,sveltekit}/*.ts"],
plugins: ["jsdoc"], plugins: ["jsdoc"],
extends: ["plugin:jsdoc/recommended"], extends: ["plugin:jsdoc/recommended"],
rules: { rules: {
@@ -49,19 +56,20 @@ module.exports = {
}, },
}, },
{ {
files: ["packages/core/src/adapters.ts"], files: ["packages/frameworks-sveltekit"],
rules: { plugins: ["svelte3"],
"@typescript-eslint/method-signature-style": "off", overrides: [{ files: ["*.svelte"], processor: "svelte3/svelte3" }],
settings: {
"svelte3/typescript": () => require("typescript"),
}, },
parserOptions: { sourceType: "module", ecmaVersion: 2020 },
env: { browser: true, es2017: true, node: true },
}, },
], ],
plugins: ["jest"], parserOptions: {
ignorePatterns: [ sourceType: "module",
"**/dist/**", ecmaVersion: "latest",
"**/node_modules/**", ecmaFeatures: { jsx: true },
".eslintrc.js", },
"**/.turbo/**", root: true,
"**/coverage/**",
"**/build/**",
],
} }

View File

@@ -35,4 +35,3 @@ Upvoting issues to show your interest will help us prioritize and address them a
- [How to create a Minimal, Complete, and Verifiable example](https://stackoverflow.com/help/mcve) - [How to create a Minimal, Complete, and Verifiable example](https://stackoverflow.com/help/mcve)
- [Reporting a NextAuth.js bug](https://github.com/nextauthjs/next-auth/blob/main/.github/ISSUE_TEMPLATE/1_bug_framework.yml) - [Reporting a NextAuth.js bug](https://github.com/nextauthjs/next-auth/blob/main/.github/ISSUE_TEMPLATE/1_bug_framework.yml)
- [How to Contribute to Open Source (Next.js)](https://www.youtube.com/watch?v=cuoNzXFLitc) - [How to Contribute to Open Source (Next.js)](https://www.youtube.com/watch?v=cuoNzXFLitc)

View File

@@ -20,8 +20,6 @@ jobs:
fetch-depth: 2 fetch-depth: 2
- name: Install pnpm - name: Install pnpm
uses: pnpm/action-setup@v2.2.4 uses: pnpm/action-setup@v2.2.4
with:
version: 7.5.1
- name: Setup Node - name: Setup Node
uses: actions/setup-node@v3 uses: actions/setup-node@v3
with: with:
@@ -29,8 +27,6 @@ jobs:
cache: "pnpm" cache: "pnpm"
- name: Install dependencies - name: Install dependencies
run: pnpm install run: pnpm install
- name: Build
run: pnpm build
- name: Run tests - name: Run tests
run: pnpm test run: pnpm test
env: env:
@@ -52,10 +48,9 @@ jobs:
uses: actions/checkout@v3 uses: actions/checkout@v3
with: with:
fetch-depth: 0 fetch-depth: 0
token: ${{ secrets.GH_PAT_CLASSIC }}
- name: Install pnpm - name: Install pnpm
uses: pnpm/action-setup@v2.2.4 uses: pnpm/action-setup@v2.2.4
with:
version: 7.5.1
- name: Setup Node - name: Setup Node
uses: actions/setup-node@v3 uses: actions/setup-node@v3
with: with:
@@ -66,10 +61,10 @@ jobs:
- name: Publish to npm and GitHub - name: Publish to npm and GitHub
run: pnpm release run: pnpm release
env: env:
GITHUB_TOKEN: ${{ secrets.GH_PAT }} # Use GH_PAT when this is fixed:
# https://github.com/github/roadmap/issues/622
GITHUB_TOKEN: ${{ secrets.GH_PAT_CLASSIC }}
NPM_TOKEN: ${{ secrets.NPM_TOKEN }} NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
NO_VERFIY: 1
DRY_RUN: 1
release-pr: release-pr:
name: Publish PR name: Publish PR
runs-on: ubuntu-latest runs-on: ubuntu-latest
@@ -81,8 +76,6 @@ jobs:
uses: actions/checkout@v3 uses: actions/checkout@v3
- name: Install pnpm - name: Install pnpm
uses: pnpm/action-setup@v2.2.4 uses: pnpm/action-setup@v2.2.4
with:
version: 7.5.1
- name: Setup Node - name: Setup Node
uses: actions/setup-node@v3 uses: actions/setup-node@v3
with: with:
@@ -113,4 +106,3 @@ jobs:
env: env:
VERSION: ${{ steps.determine-version.outputs.version }} VERSION: ${{ steps.determine-version.outputs.version }}
GITHUB_TOKEN: ${{ secrets.GH_PAT }} GITHUB_TOKEN: ${{ secrets.GH_PAT }}

3
.gitignore vendored
View File

@@ -1,7 +1,7 @@
# Misc # Misc
.DS_Store .DS_Store
.npmrc .npmrc
.eslintcache
.env .env
.env.local .env.local
.env.development.local .env.development.local
@@ -87,6 +87,7 @@ packages/core/*.d.ts.map
packages/core/lib packages/core/lib
packages/core/providers packages/core/providers
docs/docs/reference/03-core docs/docs/reference/03-core
docs/docs/reference/04-sveltekit
# SvelteKit # SvelteKit

1
.husky/.gitignore vendored
View File

@@ -1 +0,0 @@
_

View File

@@ -1,4 +0,0 @@
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"
# npx pretty-quick --staged

66
.prettierignore Normal file
View File

@@ -0,0 +1,66 @@
.cache-loader
.DS_Store
.pnpm-debug.log
.turbo
.vscode/generated*
/_work
/actions-runner
node_modules
patches
pnpm-lock.yaml
.github/actions/issue-validator/index.mjs
*.d.ts
*.d.ts.map
.svelte-kit
.next
.nuxt
# --------------- Docs ---------------
.docusaurus
build
docs/docs/reference/03-core
docs/docs/reference/04-sveltekit
static
# --------------- Packages ---------------
coverage
dist
packages/**/*.cjs
packages/**/*.js
# @auth/core
packages/core/src/providers/oauth-types.ts
packages/core/src/lib/pages/styles.ts
# @auth/sveltekit
packages/frameworks-sveltekit/package
packages/frameworks-sveltekit/vite.config.{js,ts}.timestamp-*
# next-auth
packages/next-auth/src/providers/oauth-types.ts
packages/next-auth/css/index.css
# Adapters
.branches
db.sqlite
dev.db
dynamodblocal-bin
firebase-debug.log
firestore-debug.log
migrations
test.schema.gql
# --------------- Apps ---------------
# Examples should have their own Prettier config since they are templates too
apps/example-sveltekit
# Development app
apps/dev/prisma
apps/dev/migrations
apps/dev/typeorm

View File

@@ -6,10 +6,11 @@ module.exports = {
singleQuote: false, singleQuote: false,
overrides: [ overrides: [
{ {
files: "apps/dev/pages/api/auth/[...nextauth].ts", files: [
options: { "apps/dev/pages/api/auth/[...nextauth].ts",
printWidth: 150, "docs/{sidebars,docusaurus.config}.js",
}, ],
options: { printWidth: 150 },
}, },
], ],
} }

View File

@@ -4,5 +4,5 @@
"packages/next-auth/{client,core,css,jwt,next,providers,react,utils,*.js,*.d.ts}": true "packages/next-auth/{client,core,css,jwt,next,providers,react,utils,*.js,*.d.ts}": true
}, },
"typescript.tsdk": "node_modules/typescript/lib", "typescript.tsdk": "node_modules/typescript/lib",
"openInGitHub.remote.branch": "main", "openInGitHub.remote.branch": "main"
} }

View File

@@ -3,16 +3,12 @@
"description": "Markdown link to OAuth 2 specification", "description": "Markdown link to OAuth 2 specification",
"scope": "typescript", "scope": "typescript",
"prefix": "oauth2", "prefix": "oauth2",
"body": [ "body": ["[OAuth 2](https://datatracker.ietf.org/doc/html/rfc6749)"]
"[OAuth 2](https://datatracker.ietf.org/doc/html/rfc6749)"
]
}, },
"oidc-spec": { "oidc-spec": {
"description": "Markdown link to OpenID Connect specification", "description": "Markdown link to OpenID Connect specification",
"scope": "typescript", "scope": "typescript",
"prefix": "oidc", "prefix": "oidc",
"body": [ "body": ["[OIDC](https://openid.net/specs/openid-connect-core-1_0.html)"]
"[OIDC](https://openid.net/specs/openid-connect-core-1_0.html)" }
]
},
} }

View File

@@ -11,10 +11,10 @@
top: 0; top: 0;
opacity: 1; opacity: 1;
overflow: hidden; overflow: hidden;
border-radius: 0 0 .6rem .6rem; border-radius: 0 0 0.6rem 0.6rem;
padding: .6rem 1rem; padding: 0.6rem 1rem;
margin: 0; margin: 0;
background-color: rgba(0,0,0,.05); background-color: rgba(0, 0, 0, 0.05);
transition: all 0.2s ease-in; transition: all 0.2s ease-in;
} }
@@ -26,7 +26,7 @@
.signedInText, .signedInText,
.notSignedInText { .notSignedInText {
position: absolute; position: absolute;
padding-top: .8rem; padding-top: 0.8rem;
left: 1rem; left: 1rem;
right: 6.5rem; right: 6.5rem;
white-space: nowrap; white-space: nowrap;
@@ -55,13 +55,13 @@
.button, .button,
.buttonPrimary { .buttonPrimary {
float: right; float: right;
margin-right: -.4rem; margin-right: -0.4rem;
font-weight: 500; font-weight: 500;
border-radius: .3rem; border-radius: 0.3rem;
cursor: pointer; cursor: pointer;
font-size: 1rem; font-size: 1rem;
line-height: 1.4rem; line-height: 1.4rem;
padding: .7rem .8rem; padding: 0.7rem 0.8rem;
position: relative; position: relative;
z-index: 10; z-index: 10;
background-color: transparent; background-color: transparent;
@@ -73,11 +73,11 @@
border-color: #346df1; border-color: #346df1;
color: #fff; color: #fff;
text-decoration: none; text-decoration: none;
padding: .7rem 1.4rem; padding: 0.7rem 1.4rem;
} }
.buttonPrimary:hover { .buttonPrimary:hover {
box-shadow: inset 0 0 5rem rgba(0,0,0,0.2) box-shadow: inset 0 0 5rem rgba(0, 0, 0, 0.2);
} }
.navItems { .navItems {

View File

@@ -1,13 +1,11 @@
import Header from 'components/header' import Header from "components/header"
import Footer from 'components/footer' import Footer from "components/footer"
export default function Layout({ children }) { export default function Layout({ children }) {
return ( return (
<> <>
<Header /> <Header />
<main> <main>{children}</main>
{children}
</main>
<Footer /> <Footer />
</> </>
) )

View File

@@ -1,17 +1,19 @@
import Layout from '../components/layout' import Layout from "../components/layout"
export default function Page() { export default function Page() {
return ( return (
<Layout> <Layout>
<h1>API Example</h1> <h1>API Example</h1>
<p>The examples below show responses from the example API endpoints.</p> <p>The examples below show responses from the example API endpoints.</p>
<p><em>You must be signed in to see responses.</em></p> <p>
<em>You must be signed in to see responses.</em>
</p>
<h2>Session</h2> <h2>Session</h2>
<p>/api/examples/session</p> <p>/api/examples/session</p>
<iframe src='/api/examples/session' /> <iframe src="/api/examples/session" />
<h2>JSON Web Token</h2> <h2>JSON Web Token</h2>
<p>/api/examples/jwt</p> <p>/api/examples/jwt</p>
<iframe src='/api/examples/jwt' /> <iframe src="/api/examples/jwt" />
</Layout> </Layout>
) )
} }

View File

@@ -1,21 +1,26 @@
import Layout from '../components/layout' import Layout from "../components/layout"
export default function Page() { export default function Page() {
return ( return (
<Layout> <Layout>
<h1>Client Side Rendering</h1> <h1>Client Side Rendering</h1>
<p> <p>
This page uses the <strong>useSession()</strong> React Hook in the <strong>&lt;/Header&gt;</strong> component. This page uses the <strong>useSession()</strong> React Hook in the{" "}
<strong>&lt;/Header&gt;</strong> component.
</p> </p>
<p> <p>
The <strong>useSession()</strong> React Hook easy to use and allows pages to render very quickly. The <strong>useSession()</strong> React Hook easy to use and allows
pages to render very quickly.
</p> </p>
<p> <p>
The advantage of this approach is that session state is shared between pages by using the <strong>Provider</strong> in <strong>_app.js</strong> so The advantage of this approach is that session state is shared between
that navigation between pages using <strong>useSession()</strong> is very fast. pages by using the <strong>Provider</strong> in <strong>_app.js</strong>{" "}
so that navigation between pages using <strong>useSession()</strong> is
very fast.
</p> </p>
<p> <p>
The disadvantage of <strong>useSession()</strong> is that it requires client side JavaScript. The disadvantage of <strong>useSession()</strong> is that it requires
client side JavaScript.
</p> </p>
</Layout> </Layout>
) )

View File

@@ -1,11 +1,11 @@
import Layout from 'components/layout' import Layout from "components/layout"
export default function Page() { export default function Page() {
return ( return (
<Layout> <Layout>
<h1>NextAuth.js Example</h1> <h1>NextAuth.js Example</h1>
<p> <p>
This is an example site to demonstrate how to use{' '} This is an example site to demonstrate how to use{" "}
<a href="https://authjs.dev">NextAuth.js</a> for authentication. <a href="https://authjs.dev">NextAuth.js</a> for authentication.
</p> </p>
</Layout> </Layout>

View File

@@ -1,6 +1,6 @@
import { unstable_getServerSession } from "next-auth/next" import { unstable_getServerSession } from "next-auth/next"
import Layout from "../components/layout" import Layout from "../components/layout"
import { authOptions } from './api/auth/[...nextauth]'; import { authOptions } from "./api/auth/[...nextauth]"
export default function Page() { export default function Page() {
// As this page uses Server Side Rendering, the `session` will be already // As this page uses Server Side Rendering, the `session` will be already

View File

@@ -27,6 +27,6 @@ iframe {
border: 1px solid #ccc; border: 1px solid #ccc;
height: 10rem; height: 10rem;
width: 100%; width: 100%;
border-radius: .5rem; border-radius: 0.5rem;
filter: invert(1); filter: invert(1);
} }

View File

@@ -1,11 +1,7 @@
{ {
"compilerOptions": { "compilerOptions": {
"target": "esnext", "target": "esnext",
"lib": [ "lib": ["dom", "dom.iterable", "esnext"],
"dom",
"dom.iterable",
"esnext"
],
"allowJs": true, "allowJs": true,
"skipLibCheck": true, "skipLibCheck": true,
"strict": false, "strict": false,
@@ -25,14 +21,6 @@
} }
] ]
}, },
"include": [ "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
"next-env.d.ts", "exclude": ["node_modules", "jest.config.js"]
"**/*.ts",
"**/*.tsx",
".next/types/**/*.ts"
],
"exclude": [
"node_modules",
"jest.config.js"
]
} }

View File

@@ -37,7 +37,7 @@ NextAuth.js is an easy to implement, full-stack (client/server) open source auth
Go to [next-auth.js.org](https://next-auth.js.org) for more information and documentation. Go to [next-auth.js.org](https://next-auth.js.org) for more information and documentation.
> *NextAuth.js is not officially associated with Vercel or Next.js.* > _NextAuth.js is not officially associated with Vercel or Next.js._
## Getting Started ## Getting Started
@@ -67,7 +67,7 @@ You **can** skip configuring a database and come back to it later if you want.
For more information about setting up a database, please check out the following links: For more information about setting up a database, please check out the following links:
* Docs: [next-auth.js.org/adapters/overview](https://next-auth.js.org/adapters/overview) - Docs: [next-auth.js.org/adapters/overview](https://next-auth.js.org/adapters/overview)
### 3. Configure Authentication Providers ### 3. Configure Authentication Providers
@@ -110,4 +110,3 @@ Follow the [Deployment documentation](https://next-auth.js.org/deployment)
## License ## License
ISC ISC

View File

@@ -19,7 +19,6 @@ export default function ProtectedPage() {
fetchData() fetchData()
}, [session]) }, [session])
// If no session exists, display access denied message // If no session exists, display access denied message
if (!session) { if (!session) {
return ( return (

View File

@@ -1,11 +1,7 @@
{ {
"compilerOptions": { "compilerOptions": {
"target": "es5", "target": "es5",
"lib": [ "lib": ["dom", "dom.iterable", "esnext"],
"dom",
"dom.iterable",
"esnext"
],
"allowJs": true, "allowJs": true,
"skipLibCheck": true, "skipLibCheck": true,
"strict": true, "strict": true,
@@ -19,6 +15,12 @@
"jsx": "preserve", "jsx": "preserve",
"incremental": true "incremental": true
}, },
"include": ["process.d.ts", "next-env.d.ts", "next-auth.d.ts", "**/*.ts", "**/*.tsx"], "include": [
"process.d.ts",
"next-env.d.ts",
"next-auth.d.ts",
"**/*.ts",
"**/*.tsx"
],
"exclude": ["node_modules"] "exclude": ["node_modules"]
} }

View File

@@ -34,7 +34,7 @@ Auth.js is an easy to implement, full-stack (client/server) open source authenti
Go to [authjs.dev](https://authjs.dev) for more information and documentation. Go to [authjs.dev](https://authjs.dev) for more information and documentation.
> Auth.js is not officially associated with Vercel or Next.js._ > Auth.js is not officially associated with Vercel or Next.js.\_
## Getting Started ## Getting Started

View File

@@ -1,7 +1,7 @@
module.exports = { module.exports = {
root: true, root: true,
extends: ['@nuxt/eslint-config'], extends: ["@nuxt/eslint-config"],
rules: { rules: {
'vue/multi-word-component-names': 'off' "vue/multi-word-component-names": "off",
} },
} }

View File

@@ -28,9 +28,9 @@ Here's an example of what it looks like:
```ts ```ts
// server/api/auth/[...].ts // server/api/auth/[...].ts
import { NuxtAuthHandler } from '@/lib/auth/server' import { NuxtAuthHandler } from "@/lib/auth/server"
import GithubProvider from '@auth/core/providers/github' import GithubProvider from "@auth/core/providers/github"
import type { AuthOptions } from '@auth/core' import type { AuthOptions } from "@auth/core"
const runtimeConfig = useRuntimeConfig() const runtimeConfig = useRuntimeConfig()
@@ -39,9 +39,9 @@ export const authOptions: AuthOptions = {
providers: [ providers: [
GithubProvider({ GithubProvider({
clientId: runtimeConfig.github.clientId, clientId: runtimeConfig.github.clientId,
clientSecret: runtimeConfig.github.clientSecret clientSecret: runtimeConfig.github.clientSecret,
}) }),
] ],
} }
export default NuxtAuthHandler(authOptions) export default NuxtAuthHandler(authOptions)

View File

@@ -7,7 +7,9 @@
<style> <style>
body { body {
font-family: -apple-system, Segoe UI, Roboto, Ubuntu, Cantarell, Noto Sans, sans-serif, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-family: -apple-system, Segoe UI, Roboto, Ubuntu, Cantarell, Noto Sans,
sans-serif, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif,
"Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
padding: 0 1rem 1rem 1rem; padding: 0 1rem 1rem 1rem;
max-width: 680px; max-width: 680px;
margin: 0 auto; margin: 0 auto;

View File

@@ -1,5 +1,5 @@
<script setup lang="ts"> <script setup lang="ts">
import { signIn, signOut } from '@/lib/auth/client' import { signIn, signOut } from "@/lib/auth/client"
const session = useSession() const session = useSession()
</script> </script>
@@ -9,30 +9,37 @@ const session = useSession()
<div class="signedInStatus"> <div class="signedInStatus">
<p :class="['nojs-show', 'loaded']"> <p :class="['nojs-show', 'loaded']">
<template v-if="session"> <template v-if="session">
<span v-if="session.user?.image" :style="{ backgroundImage: `url(${session.user.image})` }" class="avatar" /> <span
v-if="session.user?.image"
:style="{ backgroundImage: `url(${session.user.image})` }"
class="avatar"
/>
<span class="signedInText"> <span class="signedInText">
<small>Signed in as</small><br> <small>Signed in as</small><br />
<strong>{{ session.user?.email || session.user?.name }}</strong> <strong>{{ session.user?.email || session.user?.name }}</strong>
</span> </span>
<a href="/api/auth/signout" class="button" @click.prevent="signOut">Sign out</a> <a href="/api/auth/signout" class="button" @click.prevent="signOut"
>Sign out</a
>
</template> </template>
<template v-else> <template v-else>
<span class="notSignedInText">You are not signed in</span> <span class="notSignedInText">You are not signed in</span>
<a href="/api/auth/signin" class="buttonPrimary" @click.prevent="signIn">Sign in</a> <a
href="/api/auth/signin"
class="buttonPrimary"
@click.prevent="signIn"
>Sign in</a
>
</template> </template>
</p> </p>
</div> </div>
<nav> <nav>
<ul class="navItems"> <ul class="navItems">
<li class="navItem"> <li class="navItem">
<NuxtLink to="/"> <NuxtLink to="/"> Home </NuxtLink>
Home
</NuxtLink>
</li> </li>
<li class="navItem"> <li class="navItem">
<NuxtLink to="/protected"> <NuxtLink to="/protected"> Protected </NuxtLink>
Protected
</NuxtLink>
</li> </li>
</ul> </ul>
</nav> </nav>
@@ -57,10 +64,10 @@ const session = useSession()
top: 0; top: 0;
opacity: 1; opacity: 1;
overflow: hidden; overflow: hidden;
border-radius: 0 0 .6rem .6rem; border-radius: 0 0 0.6rem 0.6rem;
padding: .6rem 1rem; padding: 0.6rem 1rem;
margin: 0; margin: 0;
background-color: rgba(0,0,0,.05); background-color: rgba(0, 0, 0, 0.05);
transition: all 0.2s ease-in; transition: all 0.2s ease-in;
} }
@@ -72,7 +79,7 @@ const session = useSession()
.signedInText, .signedInText,
.notSignedInText { .notSignedInText {
position: absolute; position: absolute;
padding-top: .8rem; padding-top: 0.8rem;
left: 1rem; left: 1rem;
right: 6.5rem; right: 6.5rem;
white-space: nowrap; white-space: nowrap;
@@ -101,13 +108,13 @@ const session = useSession()
.button, .button,
.buttonPrimary { .buttonPrimary {
float: right; float: right;
margin-right: -.4rem; margin-right: -0.4rem;
font-weight: 500; font-weight: 500;
border-radius: .3rem; border-radius: 0.3rem;
cursor: pointer; cursor: pointer;
font-size: 1rem; font-size: 1rem;
line-height: 1.4rem; line-height: 1.4rem;
padding: .7rem .8rem; padding: 0.7rem 0.8rem;
position: relative; position: relative;
z-index: 10; z-index: 10;
background-color: transparent; background-color: transparent;
@@ -119,11 +126,11 @@ const session = useSession()
border-color: #346df1; border-color: #346df1;
color: #fff; color: #fff;
text-decoration: none; text-decoration: none;
padding: .7rem 1.4rem; padding: 0.7rem 1.4rem;
} }
.buttonPrimary:hover { .buttonPrimary:hover {
box-shadow: inset 0 0 5rem rgba(0,0,0,0.2) box-shadow: inset 0 0 5rem rgba(0, 0, 0, 0.2);
} }
.navItems { .navItems {

View File

@@ -1,5 +1,5 @@
import { Session } from '@auth/core' import { Session } from "@auth/core"
export default function useSession() { export default function useSession() {
return useState<Session | null>('session', () => null) return useState<Session | null>("session", () => null)
} }

View File

@@ -3,11 +3,11 @@ import type {
SignInOptions, SignInOptions,
SignInAuthorizationParams, SignInAuthorizationParams,
SignOutParams, SignOutParams,
} from './types' } from "./types"
import type { import type {
BuiltInProviderType, BuiltInProviderType,
RedirectableProviderType, RedirectableProviderType,
} from '@auth/core/providers' } from "@auth/core/providers"
/** /**
* Client-side method to initiate a signin flow * Client-side method to initiate a signin flow

View File

@@ -1,7 +1,7 @@
import { AuthHandler, AuthOptions, Session } from '@auth/core' import { AuthHandler, AuthOptions, Session } from "@auth/core"
import { fromNodeMiddleware, H3Event } from 'h3' import { fromNodeMiddleware, H3Event } from "h3"
import getURL from 'requrl' import getURL from "requrl"
import { createMiddleware } from "@hattip/adapter-node"; import { createMiddleware } from "@hattip/adapter-node"
export function NuxtAuthHandler(options: AuthOptions) { export function NuxtAuthHandler(options: AuthOptions) {
async function handler(ctx: { request: Request }) { async function handler(ctx: { request: Request }) {
@@ -24,7 +24,7 @@ export async function getSession(
const headers = getRequestHeaders(event) const headers = getRequestHeaders(event)
const nodeHeaders = new Headers() const nodeHeaders = new Headers()
const url = new URL('/api/auth/session', getURL(event.node.req)) const url = new URL("/api/auth/session", getURL(event.node.req))
Object.keys(headers).forEach((key) => { Object.keys(headers).forEach((key) => {
nodeHeaders.append(key, headers[key] as any) nodeHeaders.append(key, headers[key] as any)

View File

@@ -1,16 +1,18 @@
// Taken from next-auth/react // Taken from next-auth/react
import type { BuiltInProviderType, ProviderType } from '@auth/core/providers' import type { BuiltInProviderType, ProviderType } from "@auth/core/providers"
/** /**
* Util type that matches some strings literally, but allows any other string as well. * Util type that matches some strings literally, but allows any other string as well.
* @source https://github.com/microsoft/TypeScript/issues/29729#issuecomment-832522611 * @source https://github.com/microsoft/TypeScript/issues/29729#issuecomment-832522611
*/ */
export declare type LiteralUnion<T extends U, U = string> = T | (U & Record<never, never>); export declare type LiteralUnion<T extends U, U = string> =
| T
| (U & Record<never, never>)
export interface ClientSafeProvider { export interface ClientSafeProvider {
id: LiteralUnion<BuiltInProviderType>; id: LiteralUnion<BuiltInProviderType>
name: string; name: string
type: ProviderType; type: ProviderType
signinUrl: string; signinUrl: string
callbackUrl: string; callbackUrl: string
} }
export interface SignInOptions extends Record<string, unknown> { export interface SignInOptions extends Record<string, unknown> {
/** /**
@@ -18,25 +20,29 @@ export interface SignInOptions extends Record<string, unknown> {
* *
* [Documentation](https://next-auth.js.org/getting-started/client#specifying-a-callbackurl) * [Documentation](https://next-auth.js.org/getting-started/client#specifying-a-callbackurl)
*/ */
callbackUrl?: string; callbackUrl?: string
/** [Documentation](https://next-auth.js.org/getting-started/client#using-the-redirect-false-option) */ /** [Documentation](https://next-auth.js.org/getting-started/client#using-the-redirect-false-option) */
redirect?: boolean; redirect?: boolean
} }
export interface SignInResponse { export interface SignInResponse {
error: string | undefined; error: string | undefined
status: number; status: number
ok: boolean; ok: boolean
url: string | null; url: string | null
} }
/** Match `inputType` of `new URLSearchParams(inputType)` */ /** Match `inputType` of `new URLSearchParams(inputType)` */
export declare type SignInAuthorizationParams = string | string[][] | Record<string, string> | URLSearchParams; export declare type SignInAuthorizationParams =
| string
| string[][]
| Record<string, string>
| URLSearchParams
/** [Documentation](https://next-auth.js.org/getting-started/client#using-the-redirect-false-option-1) */ /** [Documentation](https://next-auth.js.org/getting-started/client#using-the-redirect-false-option-1) */
export interface SignOutResponse { export interface SignOutResponse {
url: string; url: string
} }
export interface SignOutParams<R extends boolean = true> { export interface SignOutParams<R extends boolean = true> {
/** [Documentation](https://next-auth.js.org/getting-started/client#specifying-a-callbackurl-1) */ /** [Documentation](https://next-auth.js.org/getting-started/client#specifying-a-callbackurl-1) */
callbackUrl?: string; callbackUrl?: string
/** [Documentation](https://next-auth.js.org/getting-started/client#using-the-redirect-false-option-1 */ /** [Documentation](https://next-auth.js.org/getting-started/client#using-the-redirect-false-option-1 */
redirect?: R; redirect?: R
} }

View File

@@ -4,14 +4,16 @@ export default defineNuxtConfig({
secret: process.env.NEXTAUTH_SECRET, secret: process.env.NEXTAUTH_SECRET,
github: { github: {
clientId: process.env.GITHUB_CLIENT_ID, clientId: process.env.GITHUB_CLIENT_ID,
clientSecret: process.env.GITHUB_CLIENT_SECRET clientSecret: process.env.GITHUB_CLIENT_SECRET,
} },
}, },
vite: { vite: {
define: { define: {
'process.env.NEXTAUTH_URL': JSON.stringify(process.env.NEXTAUTH_URL), "process.env.NEXTAUTH_URL": JSON.stringify(process.env.NEXTAUTH_URL),
'process.env.AUTH_TRUST_HOST': JSON.stringify(process.env.AUTH_TRUST_HOST), "process.env.AUTH_TRUST_HOST": JSON.stringify(
'process.env.VERCEL_URL': JSON.stringify(process.env.VERCEL_URL), process.env.AUTH_TRUST_HOST
} ),
} "process.env.VERCEL_URL": JSON.stringify(process.env.VERCEL_URL),
},
},
}) })

View File

@@ -2,7 +2,9 @@
<div> <div>
<h1>Nuxt Auth Example</h1> <h1>Nuxt Auth Example</h1>
<p> <p>
This is an example site to demonstrate how to use <a href="https://v3.nuxtjs.org/">Nuxt 3</a> with <a href="https://authjs.dev/">Auth.js</a> for authentication. This is an example site to demonstrate how to use
<a href="https://v3.nuxtjs.org/">Nuxt 3</a> with
<a href="https://authjs.dev/">Auth.js</a> for authentication.
</p> </p>
</div> </div>
</template> </template>

View File

@@ -2,7 +2,7 @@
const session = useSession() const session = useSession()
definePageMeta({ definePageMeta({
middleware: 'auth' middleware: "auth",
}) })
</script> </script>

View File

@@ -1,15 +1,15 @@
import { Session } from '@auth/core' import { Session } from "@auth/core"
export default defineNuxtPlugin(async () => { export default defineNuxtPlugin(async () => {
const session = useSession() const session = useSession()
addRouteMiddleware('auth', () => { addRouteMiddleware("auth", () => {
if (!session.value) return navigateTo('/') if (!session.value) return navigateTo("/")
}) })
if (process.server) { if (process.server) {
const data = await $fetch<Session>('/api/auth/session', { const data = await $fetch<Session>("/api/auth/session", {
headers: useRequestHeaders() as any headers: useRequestHeaders() as any,
}) })
const hasSession = data && Object.keys(data).length const hasSession = data && Object.keys(data).length

View File

@@ -1,6 +1,6 @@
import { NuxtAuthHandler } from '@/lib/auth/server' import { NuxtAuthHandler } from "@/lib/auth/server"
import GithubProvider from '@auth/core/providers/github' import GithubProvider from "@auth/core/providers/github"
import type { AuthOptions } from '@auth/core' import type { AuthOptions } from "@auth/core"
const runtimeConfig = useRuntimeConfig() const runtimeConfig = useRuntimeConfig()
@@ -9,9 +9,9 @@ export const authOptions: AuthOptions = {
providers: [ providers: [
GithubProvider({ GithubProvider({
clientId: runtimeConfig.github.clientId, clientId: runtimeConfig.github.clientId,
clientSecret: runtimeConfig.github.clientSecret clientSecret: runtimeConfig.github.clientSecret,
}) }),
] ],
} }
export default NuxtAuthHandler(authOptions) export default NuxtAuthHandler(authOptions)

View File

@@ -1,4 +1,4 @@
{ {
// https://v3.nuxtjs.org/concepts/typescript // https://v3.nuxtjs.org/concepts/typescript
"extends": "./.nuxt/tsconfig.json", "extends": "./.nuxt/tsconfig.json"
} }

View File

@@ -1,5 +0,0 @@
node_modules
.docusaurus
build
.turbo
static

View File

@@ -1,60 +0,0 @@
---
title: SvelteKit Auth
---
:::warning
`@auth/sveltekit` is currently experimental.
:::
## Installation
```bash npm2yarn2pnpm
npm install @auth/core @auth/sveltekit
```
## Usage
Learn more about `@auth/sveltekit` [here](https://vercel.com/blog/announcing-sveltekit-auth)
```ts title="src/hooks.server.ts"
import SvelteKitAuth from "@auth/sveltekit"
import GitHub from "@auth/core/providers/github"
import { GITHUB_ID, GITHUB_SECRET } from "$env/static/private"
export const handle = SvelteKitAuth({
providers: [GitHub({ clientId: GITHUB_ID, clientSecret: GITHUB_SECRET })],
})
```
Don't forget to set the `AUTH_SECRET` [environment variable](https://kit.svelte.dev/docs/modules#$env-static-private). This should be a random 32 character string. On unix systems you can use `openssl rand -hex 32` or check out `https://generate-secret.vercel.app/32`.
When deploying your app outside Vercel, set the `AUTH_TRUST_HOST` variable to `true` for other hosting providers like Cloudflare Pages or Netlify.
## Signing in and signing out
```ts
<script>
import { signIn, signOut } from "@auth/sveltekit/client"
import { page } from "$app/stores"
</script>
<h1>SvelteKit Auth Example</h1>
<p>
{#if $page.data.session}
{#if $page.data.session.user?.image}
<span
style="background-image: url('{$page.data.session.user.image}')"
class="avatar"
/>
{/if}
<span class="signedInText">
<small>Signed in as</small><br />
<strong>{$page.data.session.user?.name ?? "User"}</strong>
</span>
<button on:click={() => signOut()} class="button">Sign out</button>
{:else}
<span class="notSignedInText">You are not signed in</span>
<button on:click={() => signIn("github")}>Sign In with GitHub</button>
{/if}
</p>
```

View File

@@ -39,6 +39,8 @@ const docusaurusConfig = {
apiKey: "97c0894508f2d1d4a2fef4fe6db28448", apiKey: "97c0894508f2d1d4a2fef4fe6db28448",
indexName: "next-auth", indexName: "next-auth",
searchParameters: {}, searchParameters: {},
contextualSearch: false,
externalUrlRegex: "authjs\\.dev|next-auth\\.js\\.org",
}, },
navbar: { navbar: {
title: "Auth.js", title: "Auth.js",
@@ -179,10 +181,7 @@ const docusaurusConfig = {
lastVersion: "current", lastVersion: "current",
showLastUpdateAuthor: true, showLastUpdateAuthor: true,
showLastUpdateTime: true, showLastUpdateTime: true,
remarkPlugins: [ remarkPlugins: [require("@sapphire/docusaurus-plugin-npm2yarn2pnpm").npm2yarn2pnpm, require("remark-github")],
require("@sapphire/docusaurus-plugin-npm2yarn2pnpm").npm2yarn2pnpm,
require("remark-github"),
],
versions: { versions: {
current: { current: {
label: "experimental", label: "experimental",
@@ -200,22 +199,28 @@ const docusaurusConfig = {
"docusaurus-plugin-typedoc", "docusaurus-plugin-typedoc",
{ {
...typedocConfig, ...typedocConfig,
id: "core",
plugin: ["./tyepdoc"], plugin: ["./tyepdoc"],
entryPoints: [ entryPoints: ["index.ts", "adapters.ts", "errors.ts", "jwt.ts", "types.ts"].map((e) => `${coreSrc}/${e}`).concat(providers),
"index.ts",
"adapters.ts",
"errors.ts",
"jwt.ts",
"types.ts",
]
.map((e) => `${coreSrc}/${e}`)
.concat(providers),
tsconfig: "../packages/core/tsconfig.json", tsconfig: "../packages/core/tsconfig.json",
out: "reference/03-core", out: "reference/03-core",
watch: process.env.TYPEDOC_WATCH, watch: process.env.TYPEDOC_WATCH,
includeExtension: false, includeExtension: false,
}, },
], ],
[
"docusaurus-plugin-typedoc",
{
...typedocConfig,
id: "sveltekit",
plugin: ["./tyepdoc"],
entryPoints: ["index.ts", "client.ts"].map((e) => `../packages/frameworks-sveltekit/src/lib/${e}`),
tsconfig: "../packages/frameworks-sveltekit/tsconfig.json",
out: "reference/04-sveltekit",
watch: process.env.TYPEDOC_WATCH,
includeExtension: false,
},
],
], ],
} }

View File

@@ -11,12 +11,12 @@
"deploy": "docusaurus deploy", "deploy": "docusaurus deploy",
"serve": "docusaurus serve", "serve": "docusaurus serve",
"clear": "docusaurus clear", "clear": "docusaurus clear",
"lint": "eslint .", "providers": "node scripts/generate-providers.mjs",
"format": "prettier --write .", "snippets": "node scripts/generate-snippets.mjs"
"providers": "node ./scripts/generate-providers",
"snippets": "node ./scripts/generate-snippets"
}, },
"dependencies": { "dependencies": {
"@auth/core": "workspace:*",
"@auth/sveltekit": "workspace:*",
"@mdx-js/react": "1.6.22", "@mdx-js/react": "1.6.22",
"@sapphire/docusaurus-plugin-npm2yarn2pnpm": "1.1.4", "@sapphire/docusaurus-plugin-npm2yarn2pnpm": "1.1.4",
"classnames": "^2.3.2", "classnames": "^2.3.2",

View File

@@ -1,25 +0,0 @@
const path = require("path")
const fs = require("fs")
// TODO: generate from core package
const providersPath = path.join(
process.cwd(),
"/docs/reference/05-oauth-providers"
)
const files = fs.readdirSync(providersPath, "utf8")
const result = files.reduce((acc, file) => {
if (file === "index.md" || file === "_category_.json") return acc
const provider = fs.readFileSync(path.join(providersPath, file), "utf8")
const { id, title } = provider.match(
/id: (?<id>.+)\ntitle: (?<title>.+)\n/
).groups
acc[id] = title
return acc
}, {})
fs.writeFileSync(
path.join(process.cwd(), "providers.json"),
JSON.stringify(result, null, 2)
)

View File

@@ -0,0 +1,22 @@
import { join } from "path"
import { readdirSync, readFileSync, writeFileSync } from "fs"
// TODO: generate from core package
const providersPath = join(process.cwd(), "/docs/reference/05-oauth-providers")
const files = readdirSync(providersPath, "utf8")
const result = files.reduce((acc, file) => {
if (file === "index.md" || file === "_category_.json") return acc
const provider = readFileSync(join(providersPath, file), "utf8")
const { id, title } = provider.match(
/id: (?<id>.+)\ntitle: (?<title>.+)\n/
).groups
acc[id] = title
return acc
}, {})
writeFileSync(
join(process.cwd(), "providers.json"),
JSON.stringify(result, null, 2)
)

View File

@@ -1,13 +1,13 @@
const path = require("path") import { join } from "path"
const fs = require("fs") import { readdirSync, readFileSync, writeFileSync } from "fs"
const snippetsPath = path.join(process.cwd(), "snippets") const snippetsPath = join(process.cwd(), "snippets")
const files = fs.readdirSync(snippetsPath, "utf8") const files = readdirSync(snippetsPath, "utf8")
const result = {} const result = {}
for (const file of files) { for (const file of files) {
const snippet = fs.readFileSync(path.join(snippetsPath, file), "utf-8") const snippet = readFileSync(join(snippetsPath, file), "utf-8")
const body = snippet const body = snippet
.replace(/\n/g, "\n * ") .replace(/\n/g, "\n * ")
.split("\n") .split("\n")
@@ -25,7 +25,7 @@ for (const file of files) {
} }
} }
fs.writeFileSync( writeFileSync(
path.join(process.cwd(), "../.vscode/generated-snippets.code-snippets"), join(process.cwd(), "../.vscode/generated-snippets.code-snippets"),
JSON.stringify(result, null, 2) JSON.stringify(result, null, 2)
) )

View File

@@ -34,17 +34,23 @@ module.exports = {
label: "Reflections", label: "Reflections",
collapsed: true, collapsed: true,
className: "reflection-category", // See src/index.css className: "reflection-category", // See src/index.css
items: [ items: [{ type: "autogenerated", dirName: "reference/03-core" }],
{
type: "autogenerated",
dirName: "reference/03-core/functions",
},
{
type: "autogenerated",
dirName: "reference/03-core/interfaces",
}, },
], ],
}, },
{
type: "category",
label: "@auth/sveltekit",
link: { type: "doc", id: "reference/sveltekit/modules/main" },
items: [
{ type: "autogenerated", dirName: "reference/04-sveltekit/modules" },
{
type: "category",
label: "Reflections",
collapsed: true,
className: "reflection-category", // See src/index.css
items: [{ type: "autogenerated", dirName: "reference/04-sveltekit" }],
},
], ],
}, },
{ {
@@ -63,30 +69,18 @@ module.exports = {
}, },
], ],
}, },
{
type: "category",
label: "@auth/sveltekit",
link: {
type: "doc",
id: "reference/sveltekit/index",
},
items: [],
},
{ {
type: "category", type: "category",
label: "Database Adapters", label: "Database Adapters",
link: { link: { type: "doc", id: "reference/adapters/overview" },
type: "doc",
id: "reference/adapters/overview",
},
items: [ items: [
{ {
type: "autogenerated", type: "autogenerated",
dirName: "reference/06-adapters", dirName: "reference/06-adapters",
// See: https://github.com/facebook/docusaurus/issues/5689 // See: https://github.com/facebook/docusaurus/issues/5689
// exclude: ["index"], // exclude: ["index"],
} },
] ],
}, },
{ {
type: "category", type: "category",
@@ -97,8 +91,8 @@ module.exports = {
dirName: "reference/05-oauth-providers", dirName: "reference/05-oauth-providers",
// See: https://github.com/facebook/docusaurus/issues/5689 // See: https://github.com/facebook/docusaurus/issues/5689
// exclude: ["index"], // exclude: ["index"],
} },
] ],
}, },
"reference/utilities/client", "reference/utilities/client",
"reference/warnings", "reference/warnings",

View File

@@ -281,15 +281,18 @@ html[data-theme="dark"] #carbonads .carbon-poweredby {
2. the "main" module would show up twice. 2. the "main" module would show up twice.
See sidebars.js See sidebars.js
*/ */
.reflection-category, .theme-doc-sidebar-item-link-level-2 [href="/reference/core/modules/main"] { .reflection-category,
.theme-doc-sidebar-item-link-level-2 [href="/reference/core/modules/main"],
.theme-doc-sidebar-item-link-level-2
[href="/reference/sveltekit/modules/main"] {
display: none; display: none;
} }
/* /*
HACK: to hide the "Classes" header and duplicate items together with the "typedoc-plugin-markdown" patch. HACK: to hide the "Classes" header and duplicate items together with the "typedoc-plugin-markdown" patch.
See: https://github.com/TypeStrong/typedoc/issues/2006 See: https://github.com/TypeStrong/typedoc/issues/2006
*/ */
#classes, h3.anchor + p:has(code, strong) { #classes,
h3.anchor + p:has(code, strong) {
display: none; display: none;
} }

View File

@@ -1,21 +1,20 @@
// eslint-disable-next-line no-use-before-define import * as React from "react"
import * as React from 'react' import Link from "@docusaurus/Link"
import Link from '@docusaurus/Link' import useBaseUrl from "@docusaurus/useBaseUrl"
import useBaseUrl from '@docusaurus/useBaseUrl' import useDocusaurusContext from "@docusaurus/useDocusaurusContext"
import useDocusaurusContext from '@docusaurus/useDocusaurusContext' import CodeBlock from "@theme/CodeBlock"
import CodeBlock from '@theme/CodeBlock' import Layout from "@theme/Layout"
import Layout from '@theme/Layout' import classnames from "classnames"
import classnames from 'classnames' import { useEffect } from "react"
import { useEffect } from 'react' import ProviderMarquee from "../components/ProviderMarquee"
import ProviderMarquee from '../components/ProviderMarquee' import styles from "./index.module.css"
import styles from './index.module.css' import providers from "../../providers.json"
import providers from '../../providers.json'
const providersCount = Object.keys(providers).length + 2 // email, credentials const providersCount = Object.keys(providers).length + 2 // email, credentials
const features = [ const features = [
{ {
title: 'Easy', title: "Easy",
imageUrl: 'img/undraw_social.svg', imageUrl: "img/undraw_social.svg",
description: ( description: (
<ul> <ul>
<li> <li>
@@ -31,11 +30,11 @@ const features = [
Use with <i>any</i> username / password store Use with <i>any</i> username / password store
</li> </li>
</ul> </ul>
) ),
}, },
{ {
title: 'Flexible', title: "Flexible",
imageUrl: 'img/undraw_authentication.svg', imageUrl: "img/undraw_authentication.svg",
description: ( description: (
<ul> <ul>
<li> <li>
@@ -55,11 +54,11 @@ const features = [
</li> </li>
<li>Choose database sessions or JWT</li> <li>Choose database sessions or JWT</li>
</ul> </ul>
) ),
}, },
{ {
title: 'Secure', title: "Secure",
imageUrl: 'img/undraw_secure.svg', imageUrl: "img/undraw_secure.svg",
description: ( description: (
<ul> <ul>
<li>Signed, prefixed, server-only cookies</li> <li>Signed, prefixed, server-only cookies</li>
@@ -68,18 +67,18 @@ const features = [
{/* <li>Tab syncing, auto-revalidation, keepalives</li> */} {/* <li>Tab syncing, auto-revalidation, keepalives</li> */}
<li>Doesn't rely on client side JavaScript</li> <li>Doesn't rely on client side JavaScript</li>
</ul> </ul>
) ),
} },
] ]
const kFormatter = (num) => { const kFormatter = (num) => {
return Math.sign(num) * (Math.abs(num) / 1000).toFixed(1) + 'k' return Math.sign(num) * (Math.abs(num) / 1000).toFixed(1) + "k"
} }
function Feature({ imageUrl, title, description }) { function Feature({ imageUrl, title, description }) {
const imgUrl = useBaseUrl(imageUrl) const imgUrl = useBaseUrl(imageUrl)
return ( return (
<div className={classnames('col col--4', styles.feature)}> <div className={classnames("col col--4", styles.feature)}>
{imgUrl && ( {imgUrl && (
<div className="text--center"> <div className="text--center">
<div className="feature-image-wrapper"> <div className="feature-image-wrapper">
@@ -99,22 +98,22 @@ export default function Home () {
useEffect(() => { useEffect(() => {
window window
.fetch('https://api.github.com/repos/nextauthjs/next-auth') .fetch("https://api.github.com/repos/nextauthjs/next-auth")
.then((res) => res.json()) .then((res) => res.json())
.then((data) => { .then((data) => {
const navLinks = document.getElementsByClassName( const navLinks = document.getElementsByClassName(
'navbar__item navbar__link' "navbar__item navbar__link"
) )
const githubStat = document.createElement('span') const githubStat = document.createElement("span")
githubStat.innerHTML = kFormatter(data.stargazers_count) githubStat.innerHTML = kFormatter(data.stargazers_count)
githubStat.className = 'github-counter' githubStat.className = "github-counter"
navLinks[4].appendChild(githubStat) navLinks[4].appendChild(githubStat)
}) })
}, []) }, [])
return ( return (
<Layout description={siteConfig.tagline}> <Layout description={siteConfig.tagline}>
<div className="home-wrapper"> <div className="home-wrapper">
<header className={classnames('hero', styles.heroBanner)}> <header className={classnames("hero", styles.heroBanner)}>
<div className="container"> <div className="container">
<div className="hero-inner"> <div className="hero-inner">
<img <img
@@ -129,7 +128,7 @@ export default function Home () {
<div className={styles.buttons}> <div className={styles.buttons}>
<a <a
className={classnames( className={classnames(
'button button--outline button--secondary button--lg rounded-pill', "button button--outline button--secondary button--lg rounded-pill",
styles.button styles.button
)} )}
href="https://next-auth-example.vercel.app" href="https://next-auth-example.vercel.app"
@@ -138,7 +137,7 @@ export default function Home () {
</a> </a>
<a <a
className={classnames( className={classnames(
'button button--outline button--secondary button--lg rounded-pill', "button button--outline button--secondary button--lg rounded-pill",
styles.button styles.button
)} )}
href="https://sveltekit-auth-example.vercel.app" href="https://sveltekit-auth-example.vercel.app"
@@ -147,10 +146,10 @@ export default function Home () {
</a> </a>
<Link <Link
className={classnames( className={classnames(
'button button--primary button--lg rounded-pill', "button button--primary button--lg rounded-pill",
styles.button styles.button
)} )}
to={useBaseUrl('/getting-started/introduction')} to={useBaseUrl("/getting-started/introduction")}
> >
Get Started Get Started
</Link> </Link>
@@ -170,7 +169,7 @@ export default function Home () {
<div className="row"> <div className="row">
<div className="col"> <div className="col">
<h2 className={styles.featuresTitle}> <h2 className={styles.featuresTitle}>
<span>Open Source.</span> <span>Full Stack.</span>{' '} <span>Open Source.</span> <span>Full Stack.</span>{" "}
<span>Own Your Data.</span> <span>Own Your Data.</span>
</h2> </h2>
</div> </div>
@@ -198,7 +197,7 @@ export default function Home () {
</div> </div>
<div className="row"> <div className="row">
<div className="col"> <div className="col">
<h2 className="text--center" style={{ fontSize: '2.5rem' }}> <h2 className="text--center" style={{ fontSize: "2.5rem" }}>
Add authentication in minutes! Add authentication in minutes!
</h2> </h2>
</div> </div>
@@ -227,7 +226,7 @@ export default function Home () {
</div> </div>
<div className="row"> <div className="row">
<div className="col"> <div className="col">
<p className="text--center" style={{ marginTop: '2rem' }}> <p className="text--center" style={{ marginTop: "2rem" }}>
<Link <Link
to="/getting-started/introduction" to="/getting-started/introduction"
className="button button--primary button--lg rounded-pill" className="button button--primary button--lg rounded-pill"

View File

@@ -68,7 +68,7 @@
"value": "sveltekit.authjs.dev" "value": "sveltekit.authjs.dev"
} }
], ],
"destination": "https://authjs.dev/reference/sveltekit/" "destination": "https://authjs.dev/reference/sveltekit/modules/main"
}, },
{ {
"source": "/:path(.*)", "source": "/:path(.*)",

View File

@@ -6,53 +6,47 @@
"scripts": { "scripts": {
"build:app": "turbo run build --filter=next-auth-app", "build:app": "turbo run build --filter=next-auth-app",
"build": "turbo run build --filter=next-auth --filter=@next-auth/* --filter=@auth/* --no-deps", "build": "turbo run build --filter=next-auth --filter=@next-auth/* --filter=@auth/* --no-deps",
"lint": "turbo run lint --parallel", "test": "turbo run test --concurrency=1 --filter=[HEAD^1] --filter=./packages/* --filter=!*pouchdb-* --filter=!@*upstash* --filter=!*dynamodb-*",
"format": "turbo run format --parallel",
"test": "turbo run test --concurrency=1 --filter=[HEAD^1] --filter=./packages/* --filter=!*pouchdb-* --filter=!@*upstash*",
"clean": "turbo run clean --no-cache", "clean": "turbo run clean --no-cache",
"dev:db": "turbo run dev --parallel --continue --filter=next-auth-app...", "dev:db": "turbo run dev --parallel --continue --filter=next-auth-app...",
"dev": "turbo run dev --parallel --continue --filter=next-auth-app... --filter=!./packages/adapter-*", "dev": "turbo run dev --parallel --continue --filter=next-auth-app... --filter=!./packages/adapter-*",
"dev:kit": "turbo run dev --parallel --continue --filter=sveltekit-nextauth...", "dev:kit": "turbo run dev --parallel --continue --filter=sveltekit-nextauth...",
"dev:docs": "turbo run dev --filter=docs", "dev:docs": "turbo run dev --filter=docs",
"email": "cd apps/dev && pnpm email", "email": "cd apps/dev && pnpm email",
"eslint": "eslint --cache .",
"lint": "prettier --check .",
"format": "prettier --write .",
"release": "release", "release": "release",
"version:pr": "node ./config/version-pr" "version:pr": "node ./config/version-pr"
}, },
"devDependencies": { "devDependencies": {
"@actions/core": "^1.6.0", "@actions/core": "^1.10.0",
"@balazsorban/monorepo-release": "0.1.1", "@balazsorban/monorepo-release": "0.1.8",
"@types/jest": "^28.1.3", "@types/jest": "^28.1.3",
"@types/node": "^17.0.25", "@types/node": "^17.0.25",
"@typescript-eslint/eslint-plugin": "^5.10.2", "@typescript-eslint/eslint-plugin": "5.47.0",
"@typescript-eslint/parser": "^4.33.0", "@typescript-eslint/parser": "5.47.0",
"eslint": "^7.32.0", "eslint": "8.30.0",
"eslint-config-prettier": "^8.3.0", "eslint-config-prettier": "^8.5.0",
"eslint-config-standard-with-typescript": "^21.0.1", "eslint-config-standard-with-typescript": "^21.0.1",
"eslint-plugin-import": "^2.25.4", "eslint-plugin-import": "^2.25.4",
"eslint-plugin-jest": "^27.0.1", "eslint-plugin-jest": "^27.0.1",
"eslint-plugin-jsdoc": "^39.6.4", "eslint-plugin-jsdoc": "^39.6.4",
"eslint-plugin-node": "^11.1.0", "eslint-plugin-node": "^11.1.0",
"eslint-plugin-promise": "^6.0.0", "eslint-plugin-promise": "^6.0.0",
"husky": "^7.0.4", "eslint-plugin-react": "^7.31.11",
"eslint-plugin-svelte3": "^4.0.0",
"prettier": "2.8.1", "prettier": "2.8.1",
"pretty-quick": "^3.1.2", "prettier-plugin-svelte": "^2.8.1",
"semver": "7.3.5", "turbo": "1.6.3",
"stream-to-array": "2.3.0",
"ts-node": "10.5.0",
"turbo": "1.3.1",
"typedoc": "^0.23.22", "typedoc": "^0.23.22",
"typedoc-plugin-markdown": "^3.14.0", "typedoc-plugin-markdown": "^3.14.0",
"typescript": "4.8.4" "typescript": "4.9.4"
},
"release": {
"packageDirectories": [
"packages"
]
}, },
"engines": { "engines": {
"node": "^12.19.0 || ^14.15.0 || ^16.13.0 || ^18.12.0" "node": "^16.13.0 || ^18.12.0"
}, },
"packageManager": "pnpm@7.13.3", "packageManager": "pnpm@7.19.0",
"funding": [ "funding": [
{ {
"type": "github", "type": "github",
@@ -68,7 +62,8 @@
"undici": "5.11.0" "undici": "5.11.0"
}, },
"patchedDependencies": { "patchedDependencies": {
"typedoc-plugin-markdown@3.14.0": "patches/typedoc-plugin-markdown@3.14.0.patch" "typedoc-plugin-markdown@3.14.0": "patches/typedoc-plugin-markdown@3.14.0.patch",
"@balazsorban/monorepo-release@0.1.8": "patches/@balazsorban__monorepo-release@0.1.8.patch"
} }
} }
} }

View File

@@ -1,8 +0,0 @@
{
"extends": "./tsconfig.json",
"include": ["tests", "src"],
"exclude": [
"./*.js",
"./*.d.ts",
]
}

View File

@@ -1,8 +0,0 @@
{
"extends": "./tsconfig.json",
"include": ["tests", "src"],
"exclude": [
"./*.js",
"./*.d.ts",
]
}

View File

@@ -69,7 +69,7 @@ export const format = {
const newObject: Record<string, unknown> = {} const newObject: Record<string, unknown> = {}
for (const key in object) { for (const key in object) {
const value = object[key] const value = object[key]
if (value?.value && typeof value.value === 'string') { if (value?.value && typeof value.value === "string") {
newObject[key] = new Date(value.value) newObject[key] = new Date(value.value)
} else { } else {
newObject[key] = value newObject[key] = value

View File

@@ -1,8 +0,0 @@
{
"extends": "./tsconfig.json",
"include": ["tests", "src"],
"exclude": [
"./*.js",
"./*.d.ts",
]
}

View File

@@ -250,12 +250,8 @@ export function FirestoreAdapter({
const verificationTokenSnapshot = await getDoc(verificationTokenRef) const verificationTokenSnapshot = await getDoc(verificationTokenRef)
if (verificationTokenSnapshot.exists() && VerificationTokens.converter) { if (verificationTokenSnapshot.exists() && VerificationTokens.converter) {
const { const { id, ...verificationToken } =
id, VerificationTokens.converter.fromFirestore(verificationTokenSnapshot)
...verificationToken
} = VerificationTokens.converter.fromFirestore(
verificationTokenSnapshot
)
return verificationToken return verificationToken
} }
@@ -274,12 +270,8 @@ export function FirestoreAdapter({
if (verificationTokenSnapshot?.exists() && VerificationTokens.converter) { if (verificationTokenSnapshot?.exists() && VerificationTokens.converter) {
await deleteDoc(verificationTokenSnapshot.ref) await deleteDoc(verificationTokenSnapshot.ref)
const { const { id, ...verificationToken } =
id, VerificationTokens.converter.fromFirestore(verificationTokenSnapshot)
...verificationToken
} = VerificationTokens.converter.fromFirestore(
verificationTokenSnapshot
)
return verificationToken return verificationToken
} }

View File

@@ -1,76 +1,117 @@
import { runBasicTests } from "@next-auth/adapter-test" import { runBasicTests } from "@next-auth/adapter-test"
import { FirestoreAdapter } from "../src" import { FirestoreAdapter } from "../src"
import { getFirestore, connectFirestoreEmulator, terminate, collection, query, where, limit, getDocs, getDoc, doc } from "firebase/firestore" import {
import { initializeApp } from "firebase/app"; getFirestore,
import { getConverter } from "../src/converter"; connectFirestoreEmulator,
import type { AdapterSession, AdapterUser, VerificationToken } from "next-auth/adapters"; terminate,
import type { Account } from "next-auth"; collection,
query,
where,
limit,
getDocs,
getDoc,
doc,
} from "firebase/firestore"
import { initializeApp } from "firebase/app"
import { getConverter } from "../src/converter"
import type {
AdapterSession,
AdapterUser,
VerificationToken,
} from "next-auth/adapters"
import type { Account } from "next-auth"
const app = initializeApp({ projectId: "next-auth-test" }); const app = initializeApp({ projectId: "next-auth-test" })
const firestore = getFirestore(app); const firestore = getFirestore(app)
connectFirestoreEmulator(firestore, 'localhost', 8080); connectFirestoreEmulator(firestore, "localhost", 8080)
type IndexableObject = Record<string, unknown>; type IndexableObject = Record<string, unknown>
const Users = collection(firestore, 'users').withConverter(getConverter<AdapterUser & IndexableObject>()); const Users = collection(firestore, "users").withConverter(
const Sessions = collection(firestore, 'sessions').withConverter(getConverter<AdapterSession & IndexableObject>()); getConverter<AdapterUser & IndexableObject>()
const Accounts = collection(firestore, 'accounts').withConverter(getConverter<Account>()); )
const VerificationTokens = collection(firestore, 'verificationTokens').withConverter(getConverter<VerificationToken & IndexableObject>({ excludeId: true })); const Sessions = collection(firestore, "sessions").withConverter(
getConverter<AdapterSession & IndexableObject>()
)
const Accounts = collection(firestore, "accounts").withConverter(
getConverter<Account>()
)
const VerificationTokens = collection(
firestore,
"verificationTokens"
).withConverter(
getConverter<VerificationToken & IndexableObject>({ excludeId: true })
)
runBasicTests({ runBasicTests({
adapter: FirestoreAdapter({ projectId: "next-auth-test" }), adapter: FirestoreAdapter({ projectId: "next-auth-test" }),
db: { db: {
async disconnect() { async disconnect() {
await terminate(firestore); await terminate(firestore)
}, },
async session(sessionToken) { async session(sessionToken) {
const snapshotQuery = query(Sessions, where("sessionToken", "==", sessionToken), limit(1)); const snapshotQuery = query(
const snapshots = await getDocs(snapshotQuery); Sessions,
const snapshot = snapshots.docs[0]; where("sessionToken", "==", sessionToken),
limit(1)
)
const snapshots = await getDocs(snapshotQuery)
const snapshot = snapshots.docs[0]
if (snapshot?.exists() && Sessions.converter) { if (snapshot?.exists() && Sessions.converter) {
const session = Sessions.converter.fromFirestore(snapshot); const session = Sessions.converter.fromFirestore(snapshot)
return session; return session
} }
return null; return null
}, },
async user(id) { async user(id) {
const snapshot = await getDoc(doc(Users, id)); const snapshot = await getDoc(doc(Users, id))
if (snapshot?.exists() && Users.converter) { if (snapshot?.exists() && Users.converter) {
const user = Users.converter.fromFirestore(snapshot); const user = Users.converter.fromFirestore(snapshot)
return user; return user
} }
return null; return null
}, },
async account({ provider, providerAccountId }) { async account({ provider, providerAccountId }) {
const snapshotQuery = query(Accounts, where("provider", "==", provider), where("providerAccountId", "==", providerAccountId), limit(1)); const snapshotQuery = query(
const snapshots = await getDocs(snapshotQuery); Accounts,
const snapshot = snapshots.docs[0]; where("provider", "==", provider),
where("providerAccountId", "==", providerAccountId),
limit(1)
)
const snapshots = await getDocs(snapshotQuery)
const snapshot = snapshots.docs[0]
if (snapshot?.exists() && Accounts.converter) { if (snapshot?.exists() && Accounts.converter) {
const account = Accounts.converter.fromFirestore(snapshot); const account = Accounts.converter.fromFirestore(snapshot)
return account; return account
} }
return null; return null
}, },
async verificationToken({ identifier, token }) { async verificationToken({ identifier, token }) {
const snapshotQuery = query(VerificationTokens, where("identifier", "==", identifier), where("token", "==", token), limit(1)); const snapshotQuery = query(
const snapshots = await getDocs(snapshotQuery); VerificationTokens,
const snapshot = snapshots.docs[0]; where("identifier", "==", identifier),
where("token", "==", token),
limit(1)
)
const snapshots = await getDocs(snapshotQuery)
const snapshot = snapshots.docs[0]
if (snapshot?.exists() && VerificationTokens.converter) { if (snapshot?.exists() && VerificationTokens.converter) {
const verificationToken = VerificationTokens.converter.fromFirestore(snapshot); const verificationToken =
VerificationTokens.converter.fromFirestore(snapshot)
return verificationToken; return verificationToken
} }
}, },
}, },

View File

@@ -1,8 +0,0 @@
{
"extends": "./tsconfig.json",
"include": ["tests", "src"],
"exclude": [
"./*.js",
"./*.d.ts",
]
}

View File

@@ -1,6 +1,6 @@
import { MikroORM, Options } from "@mikro-orm/core"; import { MikroORM, Options } from "@mikro-orm/core"
import { SqliteDriver } from "@mikro-orm/sqlite"; import { SqliteDriver } from "@mikro-orm/sqlite"
import { defaultEntities } from "../src"; import { defaultEntities } from "../src"
const config: Options<SqliteDriver> = { const config: Options<SqliteDriver> = {
dbName: "./db.sqlite", dbName: "./db.sqlite",
@@ -18,10 +18,10 @@ it("run migrations", async () => {
await orm.getSchemaGenerator().dropSchema() await orm.getSchemaGenerator().dropSchema()
const createSchemaSQL = await orm.getSchemaGenerator().getCreateSchemaSQL() const createSchemaSQL = await orm.getSchemaGenerator().getCreateSchemaSQL()
expect(createSchemaSQL).toMatchSnapshot('createSchemaSQL') expect(createSchemaSQL).toMatchSnapshot("createSchemaSQL")
const targetSchema = await orm.getSchemaGenerator().getTargetSchema() const targetSchema = await orm.getSchemaGenerator().getTargetSchema()
expect(targetSchema).toMatchSnapshot('targetSchema') expect(targetSchema).toMatchSnapshot("targetSchema")
await orm.getSchemaGenerator().dropSchema() await orm.getSchemaGenerator().dropSchema()
await orm.close().catch(() => null) await orm.close().catch(() => null)

View File

@@ -1,8 +0,0 @@
{
"extends": "./tsconfig.json",
"include": ["tests", "src"],
"exclude": [
"./*.js",
"./*.d.ts",
]
}

View File

@@ -1,8 +0,0 @@
{
"extends": "./tsconfig.json",
"include": ["tests", "src"],
"exclude": [
"./*.js",
"./*.d.ts",
]
}

View File

@@ -1,8 +0,0 @@
{
"extends": "./tsconfig.json",
"include": ["tests", "src"],
"exclude": [
"./*.js",
"./*.d.ts",
]
}

View File

@@ -1,8 +0,0 @@
{
"extends": "./tsconfig.json",
"include": ["tests", "src"],
"exclude": [
"./*.js",
"./*.d.ts",
]
}

View File

@@ -1,8 +0,0 @@
{
"extends": "./tsconfig.json",
"include": ["tests", "src"],
"exclude": [
"./*.js",
"./*.d.ts",
]
}

View File

@@ -1,8 +0,0 @@
{
"extends": "./tsconfig.json",
"include": ["tests", "src"],
"exclude": [
"./*.js",
"./*.d.ts",
]
}

View File

@@ -137,4 +137,3 @@ export interface Database {
} }
} }
} }

View File

@@ -17,17 +17,8 @@
"@babel/preset-env": "^7.14.2", "@babel/preset-env": "^7.14.2",
"@types/jest": "^26.0.23", "@types/jest": "^26.0.23",
"@types/nodemailer": "^6.4.4", "@types/nodemailer": "^6.4.4",
"@typescript-eslint/eslint-plugin": "^4.24.0",
"@typescript-eslint/parser": "^4.24.0",
"eslint": "^7.27.0",
"eslint-config-prettier": "^8.3.0",
"eslint-config-standard-with-typescript": "^20.0.0",
"eslint-plugin-import": "^2.23.3",
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-promise": "^5.1.0",
"jest": "^27.0.3", "jest": "^27.0.3",
"next-auth": "workspace:*", "next-auth": "workspace:*",
"prettier": "^2.3.0",
"ts-jest": "^27.0.3", "ts-jest": "^27.0.3",
"typescript": "^4.2.4" "typescript": "^4.2.4"
} }

View File

@@ -1,8 +0,0 @@
{
"extends": "./tsconfig.json",
"include": ["tests", "src"],
"exclude": [
"./*.js",
"./*.d.ts",
]
}

View File

@@ -1,8 +0,0 @@
{
"extends": "./tsconfig.json",
"include": ["tests", "src"],
"exclude": [
"./*.js",
"./*.d.ts",
]
}

View File

@@ -1,3 +1,24 @@
# Auth.js <p align="center">
<br/>
<a href="https://authjs.dev" target="_blank"><img width="150px" src="https://authjs.dev/img/logo/logo-sm.png" /></a>
<h3 align="center">Auth.js core library</a></h3>
<h4 align="center">Authentication for the Web.</h4>
<p align="center" style="align: center;">
<a href="https://npm.im/next-auth">
<img src="https://img.shields.io/badge/TypeScript-blue?style=flat-square" alt="TypeScript" />
</a>
<a href="https://npm.im/@auth/core">
<img alt="npm" src="https://img.shields.io/npm/v/@auth/core?color=green&label=@auth/core&style=flat-square">
</a>
<a href="https://www.npmtrends.com/@auth/core">
<img src="https://img.shields.io/npm/dm/@auth/core?label=%20downloads&style=flat-square" alt="Downloads" />
</a>
<a href="https://github.com/nextauthjs/next-auth/stargazers">
<img src="https://img.shields.io/github/stars/nextauthjs/next-auth?style=flat-square" alt="Github Stars" />
</a>
</p>
</p>
Authentication for the web. ---
Check out the documentation at [authjs.dev](https://authjs.dev/reference/core/modules/main).

View File

@@ -1,6 +1,6 @@
{ {
"name": "@auth/core", "name": "@auth/core",
"version": "0.1.4", "version": "0.2.2",
"description": "Authentication for the web.", "description": "Authentication for the web.",
"homepage": "https://authjs.dev", "homepage": "https://authjs.dev",
"repository": "https://github.com/nextauthjs/next-auth.git", "repository": "https://github.com/nextauthjs/next-auth.git",
@@ -69,8 +69,6 @@
"build": "pnpm clean && pnpm css && tsc", "build": "pnpm clean && pnpm css && tsc",
"clean": "rm -rf *.js *.d.ts lib providers", "clean": "rm -rf *.js *.d.ts lib providers",
"css": "node ./scripts/generate-css.js", "css": "node ./scripts/generate-css.js",
"lint": "pnpm prettier --check src && eslint src",
"format": "pnpm lint --fix",
"dev": "pnpm css && tsc -w" "dev": "pnpm css && tsc -w"
}, },
"devDependencies": { "devDependencies": {

View File

@@ -158,7 +158,6 @@ export async function Auth(
* *
* const request = new Request("https://example.com") * const request = new Request("https://example.com")
* const resposne = await AuthHandler(request, authConfig) * const resposne = await AuthHandler(request, authConfig)
*
* ``` * ```
* *
* @see [Initiailzation](https://authjs.dev/reference/configuration/auth-options) * @see [Initiailzation](https://authjs.dev/reference/configuration/auth-options)
@@ -168,10 +167,8 @@ export interface AuthConfig {
* List of authentication providers for signing in * List of authentication providers for signing in
* (e.g. Google, Facebook, Twitter, GitHub, Email, etc) in any order. * (e.g. Google, Facebook, Twitter, GitHub, Email, etc) in any order.
* This can be one of the built-in providers or an object with a custom provider. * This can be one of the built-in providers or an object with a custom provider.
* * **Default value**: `[]`
* * **Required**: *Yes*
* *
* [Documentation](https://next-auth.js.org/configuration/options#providers) | [Providers documentation](https://next-auth.js.org/configuration/providers) * @default []
*/ */
providers: Provider[] providers: Provider[]
/** /**
@@ -181,35 +178,23 @@ export interface AuthConfig {
* *
* On Unix systems: `openssl rand -hex 32` * On Unix systems: `openssl rand -hex 32`
* Or go to https://generate-secret.vercel.app/32 * Or go to https://generate-secret.vercel.app/32
*
* @default process.env.AUTH_SECRET ?? process.env.NEXTAUTH_SECRET
*
* [Documentation](https://next-auth.js.org/configuration/options#secret)
*/ */
secret?: string secret?: string
/** /**
* Configure your session like if you want to use JWT or a database, * Configure your session like if you want to use JWT or a database,
* how long until an idle session expires, or to throttle write operations in case you are using a database. * how long until an idle session expires, or to throttle write operations in case you are using a database.
* * **Default value**: See the documentation page
* * **Required**: No
*
* [Documentation](https://next-auth.js.org/configuration/options#session)
*/ */
session?: Partial<SessionOptions> session?: Partial<SessionOptions>
/** /**
* JSON Web Tokens are enabled by default if you have not specified an adapter. * JSON Web Tokens are enabled by default if you have not specified an {@link AuthConfig.adapter}.
* JSON Web Tokens are encrypted (JWE) by default. We recommend you keep this behaviour. * JSON Web Tokens are encrypted (JWE) by default. We recommend you keep this behaviour.
* * **Default value**: See the documentation page
* * **Required**: *No*
*
* [Documentation](https://next-auth.js.org/configuration/options#jwt)
*/ */
jwt?: Partial<JWTOptions> jwt?: Partial<JWTOptions>
/** /**
* Specify URLs to be used if you want to create custom sign in, sign out and error pages. * Specify URLs to be used if you want to create custom sign in, sign out and error pages.
* Pages specified will override the corresponding built-in page. * Pages specified will override the corresponding built-in page.
* * **Default value**: `{}` *
* * **Required**: *No* * @default {}
* @example * @example
* *
* ```ts * ```ts
@@ -221,18 +206,12 @@ export interface AuthConfig {
* newUser: '/auth/new-user' * newUser: '/auth/new-user'
* } * }
* ``` * ```
*
* [Documentation](https://next-auth.js.org/configuration/options#pages) | [Pages documentation](https://next-auth.js.org/configuration/pages)
*/ */
pages?: Partial<PagesOptions> pages?: Partial<PagesOptions>
/** /**
* Callbacks are asynchronous functions you can use to control what happens when an action is performed. * Callbacks are asynchronous functions you can use to control what happens when an action is performed.
* Callbacks are *extremely powerful*, especially in scenarios involving JSON Web Tokens * Callbacks are *extremely powerful*, especially in scenarios involving JSON Web Tokens
* as they **allow you to implement access controls without a database** and to **integrate with external databases or APIs**. * as they **allow you to implement access controls without a database** and to **integrate with external databases or APIs**.
* * **Default value**: See the Callbacks documentation
* * **Required**: *No*
*
* [Documentation](https://next-auth.js.org/configuration/options#callbacks) | [Callbacks documentation](https://next-auth.js.org/configuration/callbacks)
*/ */
callbacks?: Partial<CallbacksOptions> callbacks?: Partial<CallbacksOptions>
/** /**
@@ -242,36 +221,23 @@ export interface AuthConfig {
* (e.g. OAuth or Email authentication flow, JWT or database sessions, etc), * (e.g. OAuth or Email authentication flow, JWT or database sessions, etc),
* but typically contains a user object and/or contents of the JSON Web Token * but typically contains a user object and/or contents of the JSON Web Token
* and other information relevant to the event. * and other information relevant to the event.
* * **Default value**: `{}`
* * **Required**: *No*
* *
* [Documentation](https://next-auth.js.org/configuration/options#events) | [Events documentation](https://next-auth.js.org/configuration/events) * @default {}
*/ */
events?: Partial<EventCallbacks> events?: Partial<EventCallbacks>
/** /** You can use the adapter option to pass in your database adapter. */
* You can use the adapter option to pass in your database adapter.
*
* * **Required**: *No*
*
* [Documentation](https://next-auth.js.org/configuration/options#adapter) |
* [Adapters Overview](https://next-auth.js.org/adapters/overview)
*/
adapter?: Adapter adapter?: Adapter
/** /**
* Set debug to true to enable debug messages for authentication and database operations. * Set debug to true to enable debug messages for authentication and database operations.
* * **Default value**: `false`
* * **Required**: *No*
* *
* - ⚠ If you added a custom `logger`, this setting is ignored. * - ⚠ If you added a custom {@link AuthConfig.logger}, this setting is ignored.
* *
* [Documentation](https://next-auth.js.org/configuration/options#debug) | [Logger documentation](https://next-auth.js.org/configuration/options#logger) * @default false
*/ */
debug?: boolean debug?: boolean
/** /**
* Override any of the logger levels (`undefined` levels will use the built-in logger), * Override any of the logger levels (`undefined` levels will use the built-in logger),
* and intercept logs in NextAuth. You can use this option to send NextAuth logs to a third-party logging service. * and intercept logs in NextAuth. You can use this option to send NextAuth logs to a third-party logging service.
* * **Default value**: `console`
* * **Required**: *No*
* *
* @example * @example
* *
@@ -293,36 +259,24 @@ export interface AuthConfig {
* }) * })
* ``` * ```
* *
* - ⚠ When set, the `debug` option is ignored * - ⚠ When set, the {@link AuthConfig.debug} option is ignored
* *
* [Documentation](https://next-auth.js.org/configuration/options#logger) | * @default console
* [Debug documentation](https://next-auth.js.org/configuration/options#debug)
*/ */
logger?: Partial<LoggerInstance> logger?: Partial<LoggerInstance>
/** /** Changes the theme of built-in {@link AuthConfig.pages}. */
* Changes the theme of pages.
* Set to `"light"` if you want to force pages to always be light.
* Set to `"dark"` if you want to force pages to always be dark.
* Set to `"auto"`, (or leave this option out)if you want the pages to follow the preferred system theme.
* * **Default value**: `"auto"`
* * **Required**: *No*
*
* [Documentation](https://next-auth.js.org/configuration/options#theme) | [Pages documentation]("https://next-auth.js.org/configuration/pages")
*/
theme?: Theme theme?: Theme
/** /**
* When set to `true` then all cookies set by NextAuth.js will only be accessible from HTTPS URLs. * When set to `true` then all cookies set by NextAuth.js will only be accessible from HTTPS URLs.
* This option defaults to `false` on URLs that start with `http://` (e.g. http://localhost:3000) for developer convenience. * This option defaults to `false` on URLs that start with `http://` (e.g. http://localhost:3000) for developer convenience.
* You can manually set this option to `false` to disable this security feature and allow cookies * You can manually set this option to `false` to disable this security feature and allow cookies
* to be accessible from non-secured URLs (this is not recommended). * to be accessible from non-secured URLs (this is not recommended).
* * **Default value**: `true` for HTTPS and `false` for HTTP sites
* * **Required**: No
*
* [Documentation](https://next-auth.js.org/configuration/options#usesecurecookies)
* *
* - ⚠ **This is an advanced option.** Advanced options are passed the same way as basic options, * - ⚠ **This is an advanced option.** Advanced options are passed the same way as basic options,
* but **may have complex implications** or side effects. * but **may have complex implications** or side effects.
* You should **try to avoid using advanced options** unless you are very comfortable using them. * You should **try to avoid using advanced options** unless you are very comfortable using them.
*
* The default is `false` HTTP and `true` for HTTPS sites.
*/ */
useSecureCookies?: boolean useSecureCookies?: boolean
/** /**
@@ -332,24 +286,14 @@ export interface AuthConfig {
* If you use this feature, you will likely want to create conditional behavior * If you use this feature, you will likely want to create conditional behavior
* to support setting different cookies policies in development and production builds, * to support setting different cookies policies in development and production builds,
* as you will be opting out of the built-in dynamic policy. * as you will be opting out of the built-in dynamic policy.
* * **Default value**: `{}`
* * **Required**: No
* *
* - ⚠ **This is an advanced option.** Advanced options are passed the same way as basic options, * - ⚠ **This is an advanced option.** Advanced options are passed the same way as basic options,
* but **may have complex implications** or side effects. * but **may have complex implications** or side effects.
* You should **try to avoid using advanced options** unless you are very comfortable using them. * You should **try to avoid using advanced options** unless you are very comfortable using them.
* *
* [Documentation](https://next-auth.js.org/configuration/options#cookies) | [Usage example](https://next-auth.js.org/configuration/options#example) * @default {}
*/ */
cookies?: Partial<CookiesOptions> cookies?: Partial<CookiesOptions>
/** /** @todo */
* If set to `true`, NextAuth.js will use either the `x-forwarded-host` or `host` headers,
* instead of `NEXTAUTH_URL`
* Make sure that reading `x-forwarded-host` on your hosting platform can be trusted.
* - ⚠ **This is an advanced option.** Advanced options are passed the same way as basic options,
* but **may have complex implications** or side effects.
* You should **try to avoid using advanced options** unless you are very comfortable using them.
* @default Boolean(process.env.NEXTAUTH_URL ?? process.env.AUTH_TRUST_HOST ?? process.env.VERCEL)
*/
trustHost?: boolean trustHost?: boolean
} }

View File

@@ -1,26 +1,26 @@
import type { import type {
InternalProvider, InternalProvider,
SignInPageErrorParam, SignInPageErrorParam,
Theme Theme,
} from '../../types.js' } from "../../types.js"
const signinErrors: Record< const signinErrors: Record<
Lowercase<SignInPageErrorParam | 'default'>, Lowercase<SignInPageErrorParam | "default">,
string string
> = { > = {
default: 'Unable to sign in.', default: "Unable to sign in.",
signin: 'Try signing in with a different account.', signin: "Try signing in with a different account.",
oauthsignin: 'Try signing in with a different account.', oauthsignin: "Try signing in with a different account.",
oauthcallback: 'Try signing in with a different account.', oauthcallback: "Try signing in with a different account.",
oauthcreateaccount: 'Try signing in with a different account.', oauthcreateaccount: "Try signing in with a different account.",
emailcreateaccount: 'Try signing in with a different account.', emailcreateaccount: "Try signing in with a different account.",
callback: 'Try signing in with a different account.', callback: "Try signing in with a different account.",
oauthaccountnotlinked: oauthaccountnotlinked:
'To confirm your identity, sign in with the same account you used originally.', "To confirm your identity, sign in with the same account you used originally.",
emailsignin: 'The e-mail could not be sent.', emailsignin: "The e-mail could not be sent.",
credentialssignin: credentialssignin:
'Sign in failed. Check the details you provided are correct.', "Sign in failed. Check the details you provided are correct.",
sessionrequired: 'Please sign in to access this page.' sessionrequired: "Please sign in to access this page.",
} }
export default function SigninPage(props: { export default function SigninPage(props: {
@@ -37,12 +37,12 @@ export default function SigninPage (props: {
callbackUrl, callbackUrl,
theme, theme,
email, email,
error: errorType error: errorType,
} = props } = props
if (typeof document !== 'undefined' && theme.brandColor) { if (typeof document !== "undefined" && theme.brandColor) {
document.documentElement.style.setProperty( document.documentElement.style.setProperty(
'--brand-color', "--brand-color",
theme.brandColor theme.brandColor
) )
} }
@@ -52,13 +52,13 @@ export default function SigninPage (props: {
// TODO: move logos // TODO: move logos
const logos = const logos =
'https://raw.githubusercontent.com/nextauthjs/next-auth/main/packages/next-auth/provider-logos' "https://raw.githubusercontent.com/nextauthjs/next-auth/main/packages/next-auth/provider-logos"
return ( return (
<div className="signin"> <div className="signin">
{theme.brandColor && ( {theme.brandColor && (
<style <style
dangerouslySetInnerHTML={{ dangerouslySetInnerHTML={{
__html: `:root {--brand-color: ${theme.brandColor}}` __html: `:root {--brand-color: ${theme.brandColor}}`,
}} }}
/> />
)} )}
@@ -71,8 +71,7 @@ export default function SigninPage (props: {
)} )}
{providers.map((provider, i) => ( {providers.map((provider, i) => (
<div key={provider.id} className="provider"> <div key={provider.id} className="provider">
{provider.type === 'oauth' || provider.type === 'oidc' {provider.type === "oauth" || provider.type === "oidc" ? (
? (
<form action={provider.signinUrl} method="POST"> <form action={provider.signinUrl} method="POST">
<input type="hidden" name="csrfToken" value={csrfToken} /> <input type="hidden" name="csrfToken" value={csrfToken} />
{callbackUrl && ( {callbackUrl && (
@@ -82,17 +81,17 @@ export default function SigninPage (props: {
type="submit" type="submit"
className="button" className="button"
style={{ style={{
'--provider-bg': provider.style?.bg ?? '', "--provider-bg": provider.style?.bg ?? "",
'--provider-dark-bg': provider.style?.bgDark ?? '', "--provider-dark-bg": provider.style?.bgDark ?? "",
'--provider-color': provider.style?.text ?? '', "--provider-color": provider.style?.text ?? "",
'--provider-dark-color': provider.style?.textDark ?? '' "--provider-dark-color": provider.style?.textDark ?? "",
}} }}
> >
{provider.style?.logo && ( {provider.style?.logo && (
<img <img
id="provider-logo" id="provider-logo"
src={`${ src={`${
provider.style.logo.startsWith('/') ? logos : '' provider.style.logo.startsWith("/") ? logos : ""
}${provider.style.logo}`} }${provider.style.logo}`}
/> />
)} )}
@@ -100,20 +99,19 @@ export default function SigninPage (props: {
<img <img
id="provider-logo-dark" id="provider-logo-dark"
src={`${ src={`${
provider.style.logo.startsWith('/') ? logos : '' provider.style.logo.startsWith("/") ? logos : ""
}${provider.style.logoDark}`} }${provider.style.logoDark}`}
/> />
)} )}
<span>Sign in with {provider.name}</span> <span>Sign in with {provider.name}</span>
</button> </button>
</form> </form>
) ) : null}
: null} {(provider.type === "email" || provider.type === "credentials") &&
{(provider.type === 'email' || provider.type === 'credentials') &&
i > 0 && i > 0 &&
providers[i - 1].type !== 'email' && providers[i - 1].type !== "email" &&
providers[i - 1].type !== 'credentials' && <hr />} providers[i - 1].type !== "credentials" && <hr />}
{provider.type === 'email' && ( {provider.type === "email" && (
<form action={provider.signinUrl} method="POST"> <form action={provider.signinUrl} method="POST">
<input type="hidden" name="csrfToken" value={csrfToken} /> <input type="hidden" name="csrfToken" value={csrfToken} />
<label <label
@@ -134,7 +132,7 @@ export default function SigninPage (props: {
<button type="submit">Sign in with {provider.name}</button> <button type="submit">Sign in with {provider.name}</button>
</form> </form>
)} )}
{provider.type === 'credentials' && ( {provider.type === "credentials" && (
<form action={provider.callbackUrl} method="POST"> <form action={provider.callbackUrl} method="POST">
<input type="hidden" name="csrfToken" value={csrfToken} /> <input type="hidden" name="csrfToken" value={csrfToken} />
{Object.keys(provider.credentials).map((credential) => { {Object.keys(provider.credentials).map((credential) => {
@@ -149,9 +147,9 @@ export default function SigninPage (props: {
<input <input
name={credential} name={credential}
id={`input-${credential}-for-${provider.id}-provider`} id={`input-${credential}-for-${provider.id}-provider`}
type={provider.credentials[credential].type ?? 'text'} type={provider.credentials[credential].type ?? "text"}
placeholder={ placeholder={
provider.credentials[credential].placeholder ?? '' provider.credentials[credential].placeholder ?? ""
} }
{...provider.credentials[credential]} {...provider.credentials[credential]}
/> />
@@ -161,7 +159,7 @@ export default function SigninPage (props: {
<button type="submit">Sign in with {provider.name}</button> <button type="submit">Sign in with {provider.name}</button>
</form> </form>
)} )}
{(provider.type === 'email' || provider.type === 'credentials') && {(provider.type === "email" || provider.type === "credentials") &&
i + 1 < providers.length && <hr />} i + 1 < providers.length && <hr />}
</div> </div>
))} ))}

View File

@@ -5,9 +5,13 @@ import { createHash } from "../web.js"
import { handleAuthorized } from "./shared.js" import { handleAuthorized } from "./shared.js"
import type { AdapterSession } from "../../adapters.js" import type { AdapterSession } from "../../adapters.js"
import type { RequestInternal, ResponseInternal, User } from "../../types.js" import type {
RequestInternal,
ResponseInternal,
User,
InternalOptions,
} from "../../types.js"
import type { Cookie, SessionStore } from "../cookie.js" import type { Cookie, SessionStore } from "../cookie.js"
import type { InternalOptions } from "../../types.js"
/** Handle callbacks from login services */ /** Handle callbacks from login services */
export async function callback(params: { export async function callback(params: {

View File

@@ -1,6 +1,6 @@
import { AuthError } from '../../errors.js' import { AuthError } from "../../errors.js"
export type WarningCode = 'debug_enabled' export type WarningCode = "debug_enabled"
/** /**
* Override any of the methods, and the rest will use the default logger. * Override any of the methods, and the rest will use the default logger.
@@ -13,10 +13,10 @@ export interface LoggerInstance extends Record<string, Function> {
debug: (message: string, metadata?: unknown) => void debug: (message: string, metadata?: unknown) => void
} }
const red = '\x1b[31m' const red = "\x1b[31m"
const yellow = '\x1b[33m' const yellow = "\x1b[33m"
const grey = '\x1b[90m' const grey = "\x1b[90m"
const reset = '\x1b[0m' const reset = "\x1b[0m"
export const logger: LoggerInstance = { export const logger: LoggerInstance = {
error(error: AuthError) { error(error: AuthError) {
@@ -36,7 +36,7 @@ export const logger: LoggerInstance = {
`${grey}[auth][debug]:${reset} ${message}`, `${grey}[auth][debug]:${reset} ${message}`,
JSON.stringify(metadata, null, 2) JSON.stringify(metadata, null, 2)
) )
} },
} }
/** /**

View File

@@ -1,5 +1,5 @@
import type { CommonProviderOptions } from "./index.js" import type { CommonProviderOptions } from "./index.js"
import type { Awaitable, RequestInternal, User } from "../types.js" import type { Awaitable, User } from "../types.js"
import type { JSXInternal } from "preact/src/jsx.js" import type { JSXInternal } from "preact/src/jsx.js"
/** /**

View File

@@ -1,6 +1,6 @@
import { Profile } from "../types.js" import { Profile } from "../types.js"
import CredentialsProvider from "./credentials.js"
import type { import type {
default as CredentialsProvider,
CredentialsConfig, CredentialsConfig,
CredentialsProviderType, CredentialsProviderType,
} from "./credentials.js" } from "./credentials.js"

View File

@@ -55,24 +55,24 @@
* @module types * @module types
*/ */
import type { CookieSerializeOptions } from 'cookie' import type { CookieSerializeOptions } from "cookie"
import type { import type {
OAuth2TokenEndpointResponse, OAuth2TokenEndpointResponse,
OpenIDTokenEndpointResponse OpenIDTokenEndpointResponse,
} from 'oauth4webapi' } from "oauth4webapi"
import type { Adapter, AdapterUser } from './adapters.js' import type { Adapter, AdapterUser } from "./adapters.js"
import type { import type {
CredentialInput, CredentialInput,
CredentialsConfig, CredentialsConfig,
EmailConfig, EmailConfig,
OAuthConfigInternal, OAuthConfigInternal,
ProviderType ProviderType,
} from './providers/index.js' } from "./providers/index.js"
import type { JWT, JWTOptions } from './jwt.js' import type { JWT, JWTOptions } from "./jwt.js"
import type { Cookie } from './lib/cookie.js' import type { Cookie } from "./lib/cookie.js"
import type { LoggerInstance } from './lib/utils/logger.js' import type { LoggerInstance } from "./lib/utils/logger.js"
export type { AuthConfig } from './index.js' export type { AuthConfig } from "./index.js"
export type Awaitable<T> = T | PromiseLike<T> export type Awaitable<T> = T | PromiseLike<T>
export type { LoggerInstance } export type { LoggerInstance }
@@ -83,7 +83,7 @@ export type { LoggerInstance }
* [Pages](https://authjs.dev/guides/basics/pages) * [Pages](https://authjs.dev/guides/basics/pages)
*/ */
export interface Theme { export interface Theme {
colorScheme?: 'auto' | 'dark' | 'light' colorScheme?: "auto" | "dark" | "light"
logo?: string logo?: string
brandColor?: string brandColor?: string
buttonText?: string buttonText?: string
@@ -260,8 +260,8 @@ export interface EventCallbacks {
*/ */
signOut: ( signOut: (
message: message:
| { session: Awaited<ReturnType<Adapter['deleteSession']>> } | { session: Awaited<ReturnType<Adapter["deleteSession"]>> }
| { token: Awaited<ReturnType<JWTOptions['decode']>> } | { token: Awaited<ReturnType<JWTOptions["decode"]>> }
) => Awaitable<void> ) => Awaitable<void>
createUser: (message: { user: User }) => Awaitable<void> createUser: (message: { user: User }) => Awaitable<void>
updateUser: (message: { user: User }) => Awaitable<void> updateUser: (message: { user: User }) => Awaitable<void>
@@ -276,26 +276,26 @@ export interface EventCallbacks {
* - `token`: The JWT token for this session. * - `token`: The JWT token for this session.
* - `session`: The session object from your adapter. * - `session`: The session object from your adapter.
*/ */
session: (message: { session: Session, token: JWT }) => Awaitable<void> session: (message: { session: Session; token: JWT }) => Awaitable<void>
} }
export type EventType = keyof EventCallbacks export type EventType = keyof EventCallbacks
/** TODO: Check if all these are used/correct */ /** TODO: Check if all these are used/correct */
export type ErrorPageParam = 'Configuration' | 'AccessDenied' | 'Verification' export type ErrorPageParam = "Configuration" | "AccessDenied" | "Verification"
/** TODO: Check if all these are used/correct */ /** TODO: Check if all these are used/correct */
export type SignInPageErrorParam = export type SignInPageErrorParam =
| 'Signin' | "Signin"
| 'OAuthSignin' | "OAuthSignin"
| 'OAuthCallback' | "OAuthCallback"
| 'OAuthCreateAccount' | "OAuthCreateAccount"
| 'EmailCreateAccount' | "EmailCreateAccount"
| 'Callback' | "Callback"
| 'OAuthAccountNotLinked' | "OAuthAccountNotLinked"
| 'EmailSignin' | "EmailSignin"
| 'CredentialsSignin' | "CredentialsSignin"
| 'SessionRequired' | "SessionRequired"
export interface PagesOptions { export interface PagesOptions {
/** /**
@@ -344,7 +344,7 @@ export interface DefaultSession {
*/ */
export interface Session extends DefaultSession {} export interface Session extends DefaultSession {}
export type SessionStrategy = 'jwt' | 'database' export type SessionStrategy = "jwt" | "database"
/** [Documentation](https://authjs.dev/reference/configuration/auth-config#session) */ /** [Documentation](https://authjs.dev/reference/configuration/auth-config#session) */
export interface SessionOptions { export interface SessionOptions {
@@ -406,11 +406,11 @@ export interface User extends DefaultUser {}
// Below are types that are only supposed be used by next-auth internally // Below are types that are only supposed be used by next-auth internally
/** @internal */ /** @internal */
export type InternalProvider<T = ProviderType> = (T extends 'oauth' export type InternalProvider<T = ProviderType> = (T extends "oauth"
? OAuthConfigInternal<any> ? OAuthConfigInternal<any>
: T extends 'email' : T extends "email"
? EmailConfig ? EmailConfig
: T extends 'credentials' : T extends "credentials"
? CredentialsConfig ? CredentialsConfig
: never) & { : never) & {
signinUrl: string signinUrl: string
@@ -418,19 +418,19 @@ export type InternalProvider<T = ProviderType> = (T extends 'oauth'
} }
export type AuthAction = export type AuthAction =
| 'providers' | "providers"
| 'session' | "session"
| 'csrf' | "csrf"
| 'signin' | "signin"
| 'signout' | "signout"
| 'callback' | "callback"
| 'verify-request' | "verify-request"
| 'error' | "error"
/** @internal */ /** @internal */
export interface RequestInternal { export interface RequestInternal {
url: URL url: URL
method: 'GET' | 'POST' method: "GET" | "POST"
cookies?: Partial<Record<string, string>> cookies?: Partial<Record<string, string>>
headers?: Record<string, any> headers?: Record<string, any>
query?: Record<string, any> query?: Record<string, any>

View File

@@ -1,18 +0,0 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"watch": true,
"emitDeclarationOnly": false
},
"watchOptions": {
"excludeDirectories": [
"jwt",
"lib",
"providers",
],
"excludeFiles": [
"./*.d.ts",
"./*.js"
]
}
}

View File

@@ -1,7 +0,0 @@
{
"extends": "./tsconfig.json",
"exclude": [
"./*.js",
"./*.d.ts"
]
}

View File

@@ -6,11 +6,7 @@
"isolatedModules": true, "isolatedModules": true,
"jsx": "react-jsx", "jsx": "react-jsx",
"jsxImportSource": "preact", "jsxImportSource": "preact",
"lib": [ "lib": ["dom", "dom.iterable", "esnext"],
"dom",
"dom.iterable",
"esnext"
],
"target": "ES2020", "target": "ES2020",
"module": "ESNext", "module": "ESNext",
"moduleResolution": "node", "moduleResolution": "node",
@@ -21,16 +17,8 @@
"strictNullChecks": true, "strictNullChecks": true,
"stripInternal": true, "stripInternal": true,
"declarationMap": true, "declarationMap": true,
"declaration": true, "declaration": true
}, },
"include": [ "include": ["src/**/*"],
"src/**/*", "exclude": ["adapters.*", "index.*", "jwt", "lib", "providers"]
],
"exclude": [
"adapters.*",
"index.*",
"jwt",
"lib",
"providers",
],
} }

View File

@@ -1,7 +0,0 @@
.DS_Store
node_modules
/build
/.svelte-kit
/package
/index.*
/client.*

View File

@@ -1,3 +1,24 @@
# SvelteKit Auth <p align="center">
<br/>
<a href="https://authjs.dev" target="_blank"><img width="150px" src="https://authjs.dev/img/logo/logo-sm.png" /></a>
<h3 align="center">SvelteKit Auth</a></h3>
<h4 align="center">Authentication for SvelteKit.</h4>
<p align="center" style="align: center;">
<a href="https://npm.im/next-auth">
<img src="https://img.shields.io/badge/TypeScript-blue?style=flat-square" alt="TypeScript" />
</a>
<a href="https://npm.im/@auth/sveltekit">
<img alt="npm" src="https://img.shields.io/npm/v/@auth/sveltekit?color=green&label=@auth/sveltekit&style=flat-square">
</a>
<a href="https://www.npmtrends.com/@auth/sveltekit">
<img src="https://img.shields.io/npm/dm/@auth/sveltekit?label=%20downloads&style=flat-square" alt="Downloads" />
</a>
<a href="https://github.com/nextauthjs/next-auth/stargazers">
<img src="https://img.shields.io/github/stars/nextauthjs/next-auth?style=flat-square" alt="Github Stars" />
</a>
</p>
</p>
Authentication for SvelteKit. ---
Check out the documentation at [sveltekit.authjs.dev](https://sveltekit.authjs.dev).

View File

@@ -1,6 +1,6 @@
{ {
"name": "@auth/sveltekit", "name": "@auth/sveltekit",
"version": "0.1.6", "version": "0.1.9",
"description": "Authentication for SvelteKit.", "description": "Authentication for SvelteKit.",
"homepage": "https://sveltekit.authjs.dev", "homepage": "https://sveltekit.authjs.dev",
"repository": "https://github.com/nextauthjs/next-auth.git", "repository": "https://github.com/nextauthjs/next-auth.git",
@@ -19,23 +19,14 @@
"preview": "vite preview", "preview": "vite preview",
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json", "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch", "check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
"test:unit": "vitest", "test:unit": "vitest"
"lint": "prettier --plugin-search-dir . --check . && eslint .",
"format": "prettier --plugin-search-dir . --write ."
}, },
"devDependencies": { "devDependencies": {
"@playwright/test": "^1.28.1", "@playwright/test": "^1.28.1",
"@sveltejs/adapter-auto": "next", "@sveltejs/adapter-auto": "^1.0.0",
"@sveltejs/kit": "next", "@sveltejs/kit": "^1.0.0",
"@sveltejs/package": "1.0.0-next.6", "@sveltejs/package": "^1.0.0",
"@typescript-eslint/eslint-plugin": "^5.45.0",
"@typescript-eslint/parser": "^5.45.0",
"eslint": "^8.28.0",
"eslint-config-prettier": "^8.5.0",
"eslint-plugin-svelte3": "^4.0.0",
"next-auth": "workspace:*", "next-auth": "workspace:*",
"prettier": "2.8.1",
"prettier-plugin-svelte": "^2.8.1",
"svelte": "^3.54.0", "svelte": "^3.54.0",
"svelte-check": "^2.9.2", "svelte-check": "^2.9.2",
"tslib": "^2.4.1", "tslib": "^2.4.1",

View File

@@ -1,32 +1,105 @@
/**
*
*
* :::warning
* `@auth/sveltekit` is currently experimental. The API _will_ change in the future.
* :::
*
* SvelteKit Auth is the official SvelteKit integration for Auth.js.
* It provides a simple way to add authentication to your SvelteKit app in a few lines of code.
*
*
* ## Installation
*
* ```bash npm2yarn2pnpm
* npm install @auth/core @auth/sveltekit
* ```
*
* ## Usage
*
* ```ts title="src/hooks.server.ts"
* import SvelteKitAuth from "@auth/sveltekit"
* import GitHub from "@auth/core/providers/github"
* import { GITHUB_ID, GITHUB_SECRET } from "$env/static/private"
*
* export const handle = SvelteKitAuth({
* providers: [GitHub({ clientId: GITHUB_ID, clientSecret: GITHUB_SECRET })],
* })
* ```
*
* Don't forget to set the `AUTH_SECRET` [environment variable](https://kit.svelte.dev/docs/modules#$env-static-private). This should be a random 32 character string. On unix systems you can use `openssl rand -hex 32` or check out `https://generate-secret.vercel.app/32`.
*
* When deploying your app outside Vercel, set the `AUTH_TRUST_HOST` variable to `true` for other hosting providers like Cloudflare Pages or Netlify.
*
* The callback URL used by the [providers](https://authjs.dev/reference/core/modules/providers) must be set to the following, unless you override {@link SvelteKitAuthConfig.prefix}:
* ```
* [origin]/auth/callback/[provider]
* ```
*
* ## Signing in and signing out
*
* ```ts
* <script>
* import { signIn, signOut } from "@auth/sveltekit/client"
* import { page } from "$app/stores"
* </script>
*
* <h1>SvelteKit Auth Example</h1>
* <p>
* {#if $page.data.session}
* {#if $page.data.session.user?.image}
* <span
* style="background-image: url('{$page.data.session.user.image}')"
* class="avatar"
* />
* {/if}
* <span class="signedInText">
* <small>Signed in as</small><br />
* <strong>{$page.data.session.user?.name ?? "User"}</strong>
* </span>
* <button on:click={() => signOut()} class="button">Sign out</button>
* {:else}
* <span class="notSignedInText">You are not signed in</span>
* <button on:click={() => signIn("github")}>Sign In with GitHub</button>
* {/if}
* </p>
* ```
*
* ## Notes
*
* :::info
* Learn more about `@auth/sveltekit` [here](https://vercel.com/blog/announcing-sveltekit-auth).
* :::
*
* :::info
* PRs to improve this documentation are welcome! See [this file](https://github.com/nextauthjs/next-auth/blob/main/packages/frameworks-sveltekit/src/lib/index.ts).
* :::
*
* @module main
*/
/// <reference types="@sveltejs/kit" /> /// <reference types="@sveltejs/kit" />
import type { Handle } from "@sveltejs/kit"
import { dev } from "$app/environment" import { dev } from "$app/environment"
import { env } from "$env/dynamic/private" import { env } from "$env/dynamic/private"
import { AUTH_SECRET } from "$env/static/private" import { AUTH_SECRET } from "$env/static/private"
import {
AuthHandler,
type AuthAction,
type AuthOptions,
type Session,
} from "@auth/core"
import type { Handle } from "@sveltejs/kit"
export type GetSessionResult = Promise<Session | null> import { Auth } from "@auth/core"
import type { AuthAction, AuthConfig, Session } from "@auth/core/types"
export async function getSession( export async function getSession(
req: Request, req: Request,
options: AuthOptions config: AuthConfig
): GetSessionResult { ): ReturnType<App.Locals["getSession"]> {
options.secret ??= AUTH_SECRET config.secret ??= AUTH_SECRET
options.trustHost ??= true config.trustHost ??= true
const url = new URL("/api/auth/session", req.url) const url = new URL("/api/auth/session", req.url)
const response = await AuthHandler( const request = new Request(url, { headers: req.headers })
new Request(url, { headers: req.headers }), const response = await Auth(request, config)
options
)
const { status = 200 } = response const { status = 200 } = response
const data = await response.json() const data = await response.json()
if (!data || !Object.keys(data).length) return null if (!data || !Object.keys(data).length) return null
@@ -34,10 +107,14 @@ export async function getSession(
throw new Error(data.message) throw new Error(data.message)
} }
export interface SvelteKitAuthOptions extends AuthOptions { /** Configure the {@link SvelteKitAuth} method. */
export interface SvelteKitAuthConfig extends AuthConfig {
/** /**
* Defines the base path for the auth routes. * Defines the base path for the auth routes.
* @default '/auth' * If you change the default value,
* you must also update the callback URL used by the [providers](https://authjs.dev/reference/core/modules/providers).
*
* @default "/auth"
*/ */
prefix?: string prefix?: string
} }
@@ -51,27 +128,23 @@ const actions: AuthAction[] = [
"callback", "callback",
"verify-request", "verify-request",
"error", "error",
"_log",
] ]
function SvelteKitAuthHandler( function AuthHandle(prefix: string, authOptions: AuthConfig): Handle {
prefix: string, return function ({ event, resolve }) {
authOptions: AuthOptions
): Handle {
return ({ event, resolve }) => {
const { url, request } = event const { url, request } = event
event.locals.getSession ??= () => getSession(request, authOptions) event.locals.getSession ??= () => getSession(request, authOptions)
const [action] = url.pathname.slice(prefix.length + 1).split("/") const action = url.pathname
if ( .slice(prefix.length + 1)
actions.includes(action as AuthAction) && .split("/")[0] as AuthAction
url.pathname.startsWith(prefix + "/")
) { if (!actions.includes(action) || !url.pathname.startsWith(prefix + "/")) {
return AuthHandler(request, authOptions) return resolve(event)
} }
return resolve(event) return Auth(request, authOptions)
} }
} }
@@ -79,19 +152,18 @@ function SvelteKitAuthHandler(
* The main entry point to `@auth/sveltekit` * The main entry point to `@auth/sveltekit`
* @see https://sveltekit.authjs.dev * @see https://sveltekit.authjs.dev
*/ */
export default function SvelteKitAuth(options: SvelteKitAuthOptions): Handle { export function SvelteKitAuth(options: SvelteKitAuthConfig): Handle {
const { prefix = "/auth", ...authOptions } = options const { prefix = "/auth", ...authOptions } = options
authOptions.secret ??= AUTH_SECRET authOptions.secret ??= AUTH_SECRET
authOptions.trustHost ??= !!(env.AUTH_TRUST_HOST ?? env.VERCEL ?? dev) authOptions.trustHost ??= !!(env.AUTH_TRUST_HOST ?? env.VERCEL ?? dev)
return AuthHandle(prefix, authOptions)
return SvelteKitAuthHandler(prefix, authOptions)
} }
declare global { declare global {
// eslint-disable-next-line @typescript-eslint/no-namespace // eslint-disable-next-line @typescript-eslint/no-namespace
namespace App { namespace App {
interface Locals { interface Locals {
getSession: () => GetSessionResult getSession(): Promise<Session | null>
} }
interface PageData { interface PageData {
session: Session | null session: Session | null

View File

@@ -1,7 +1,7 @@
module.exports = { module.exports = {
plugins: [ plugins: [
require('autoprefixer'), require("autoprefixer"),
require('postcss-nested'), require("postcss-nested"),
require('cssnano')({ preset: 'default' }) require("cssnano")({ preset: "default" }),
] ],
} }

View File

@@ -46,8 +46,7 @@
"watch:css": "postcss --config config/postcss.config.js --watch src/**/*.css --base src --dir .", "watch:css": "postcss --config config/postcss.config.js --watch src/**/*.css --base src --dir .",
"test": "jest --config ./config/jest.config.js", "test": "jest --config ./config/jest.config.js",
"prepublishOnly": "pnpm build", "prepublishOnly": "pnpm build",
"generate-providers": "node ./config/generate-providers.js", "generate-providers": "node ./config/generate-providers.js"
"lint": "eslint src config tests"
}, },
"files": [ "files": [
"lib", "lib",
@@ -103,7 +102,7 @@
"@testing-library/dom": "^8.13.0", "@testing-library/dom": "^8.13.0",
"@testing-library/jest-dom": "^5.16.4", "@testing-library/jest-dom": "^5.16.4",
"@testing-library/react": "^13.3.0", "@testing-library/react": "^13.3.0",
"@testing-library/react-hooks": "^8.0.0", "@testing-library/react-hooks": "^8.0.1",
"@testing-library/user-event": "^14.2.0", "@testing-library/user-event": "^14.2.0",
"@types/jest": "^28.1.3", "@types/jest": "^28.1.3",
"@types/node": "^17.0.42", "@types/node": "^17.0.42",

View File

@@ -181,11 +181,11 @@ export default async function callbackHandler(params: {
? await getUserByEmail(profile.email) ? await getUserByEmail(profile.email)
: null : null
if (userByEmail) { if (userByEmail) {
const provider = options.provider as OAuthConfig<any>; const provider = options.provider as OAuthConfig<any>
if (provider?.allowDangerousEmailAccountLinking) { if (provider?.allowDangerousEmailAccountLinking) {
// If you trust the oauth provider to correctly verify email addresses, you can opt-in to // If you trust the oauth provider to correctly verify email addresses, you can opt-in to
// account linking even when the user is not signed-in. // account linking even when the user is not signed-in.
user = userByEmail; user = userByEmail
} else { } else {
// We end up here when we don't have an account with the same [provider].id *BUT* // We end up here when we don't have an account with the same [provider].id *BUT*
// we do already have an account with the same email address as the one in the // we do already have an account with the same email address as the one in the

View File

@@ -114,7 +114,7 @@ export function defaultCookies(useSecureCookies: boolean): CookiesOptions {
path: "/", path: "/",
secure: useSecureCookies, secure: useSecureCookies,
}, },
} },
} }
} }

View File

@@ -1,5 +1,5 @@
export { default as callback } from './callback' export { default as callback } from "./callback"
export { default as signin } from './signin' export { default as signin } from "./signin"
export { default as signout } from './signout' export { default as signout } from "./signout"
export { default as session } from './session' export { default as session } from "./session"
export { default as providers } from './providers' export { default as providers } from "./providers"

View File

@@ -4,7 +4,12 @@
import fs from "fs" import fs from "fs"
import path from "path" import path from "path"
const pathToCss = path.join(process.cwd(), process.env.NODE_ENV === "development" ? "node_modules/next-auth/css/index.css" : "/src/css/index.css") const pathToCss = path.join(
process.cwd(),
process.env.NODE_ENV === "development"
? "node_modules/next-auth/css/index.css"
: "/src/css/index.css"
)
export default function css() { export default function css() {
return fs.readFileSync(pathToCss, "utf8") return fs.readFileSync(pathToCss, "utf8")

View File

@@ -118,8 +118,9 @@ export default function Apple<P extends AppleProfile>(
}, },
checks: ["pkce"], checks: ["pkce"],
style: { style: {
logo: 'https://raw.githubusercontent.com/nextauthjs/next-auth/main/packages/next-auth/provider-logos/apple.svg', logo: "https://raw.githubusercontent.com/nextauthjs/next-auth/main/packages/next-auth/provider-logos/apple.svg",
logoDark: 'https://raw.githubusercontent.com/nextauthjs/next-auth/main/packages/next-auth/provider-logos/apple-dark.svg', logoDark:
"https://raw.githubusercontent.com/nextauthjs/next-auth/main/packages/next-auth/provider-logos/apple-dark.svg",
bg: "#fff", bg: "#fff",
text: "#000", text: "#000",
bgDark: "#000", bgDark: "#000",

View File

@@ -17,7 +17,8 @@ export default function EVEOnline<P extends EVEOnlineProfile>(
id: "eveonline", id: "eveonline",
name: "EVE Online", name: "EVE Online",
type: "oauth", type: "oauth",
authorization: "https://login.eveonline.com/v2/oauth/authorize?scope=publicData", authorization:
"https://login.eveonline.com/v2/oauth/authorize?scope=publicData",
token: "https://login.eveonline.com/v2/oauth/token", token: "https://login.eveonline.com/v2/oauth/token",
userinfo: "https://login.eveonline.com/oauth/verify", userinfo: "https://login.eveonline.com/oauth/verify",
profile(profile) { profile(profile) {

View File

@@ -34,8 +34,9 @@ export default function LINE<P extends LineProfile>(
id_token_signed_response_alg: "HS256", id_token_signed_response_alg: "HS256",
}, },
style: { style: {
logo: 'https://raw.githubusercontent.com/nextauthjs/next-auth/main/packages/next-auth/provider-logos/line.svg', logo: "https://raw.githubusercontent.com/nextauthjs/next-auth/main/packages/next-auth/provider-logos/line.svg",
logoDark: 'https://raw.githubusercontent.com/nextauthjs/next-auth/main/packages/next-auth/provider-logos/line.svg', logoDark:
"https://raw.githubusercontent.com/nextauthjs/next-auth/main/packages/next-auth/provider-logos/line.svg",
bg: "#fff", bg: "#fff",
text: "#00C300", text: "#00C300",
bgDark: "#00C300", bgDark: "#00C300",

View File

@@ -1,27 +0,0 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"watch": true,
"emitDeclarationOnly": false
},
"watchOptions": {
"excludeDirectories": [
"lib",
"css",
"jwt",
"react",
"next",
"client",
"providers",
"core",
"utils"
],
"excludeFiles": [
"index.d.ts",
"index.js",
"adapters.d.ts",
"middleware.d.ts",
"middleware.js"
]
}
}

View File

@@ -1,8 +0,0 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"types": ["@types/jest"],
"typeRoots": ["./node_modules/@types"]
},
"exclude": ["./coverage", "./*.js", "./*.d.ts"]
}

View File

@@ -4,6 +4,6 @@
"forceConsistentCasingInFileNames": true, "forceConsistentCasingInFileNames": true,
"esModuleInterop": true, "esModuleInterop": true,
"declaration": true, "declaration": true,
"skipLibCheck": true, "skipLibCheck": true
} }
} }

View File

@@ -0,0 +1,16 @@
diff --git a/dist/publish.js b/dist/publish.js
index 1d39a76a5625a10637e3cf23f3a652441702cfb2..4b69b30645db1d1e84c8b6987a23b53c06f66438 100644
--- a/dist/publish.js
+++ b/dist/publish.js
@@ -54,8 +54,9 @@ export async function publish(packages, options) {
console.log(`Creating git tag...`);
execSync(`git tag ${gitTag}`);
execSync("git push --tags");
- console.log(`Creating GitHub release notes...`);
- execSync(`gh release create ${gitTag} --notes '${changelog}'`);
+ const prerelease = name.startsWith("@auth") ? "--prerelease " : ""
+ console.log(`Creating GitHub release notes${prerelease ? " (as prerelease)" : ""}...`);
+ execSync(`gh release create ${gitTag} ${prerelease}--notes '${changelog}'`);
}
}
console.log("Pushing commits");

1694
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,7 +1,7 @@
packages: packages:
- "packages/**" - "packages/**"
# - "packages/frameworks/**"
- "apps/dev" - "apps/dev"
- "apps/playground-sveltekit" - "apps/playground-sveltekit"
- "apps/playground-nuxt" - "apps/playground-nuxt"
- "apps/example-nextjs"
- "docs" - "docs"

View File

@@ -28,18 +28,11 @@
"dev": { "dev": {
"cache": false "cache": false
}, },
"lint": {
"outputs": []
},
"test": { "test": {
"dependsOn": ["lint"],
"outputs": []
},
"format": {
"outputs": [] "outputs": []
}, },
"@next-auth/upstash-redis-adapter#test": { "@next-auth/upstash-redis-adapter#test": {
"dependsOn": ["$UPSTASH_REDIS_KEY", "$UPSTASH_REDIS_URL"] "env": ["UPSTASH_REDIS_KEY", "UPSTASH_REDIS_URL"]
} }
} }
} }