From aea09bad08b12073dd58851d1863e9de1f32ad7b Mon Sep 17 00:00:00 2001 From: Peter Budai Date: Sat, 13 Jul 2024 13:56:37 +0200 Subject: [PATCH 1/5] feat(adapter): add `sqlserver` adapter --- .github/pr-labeler.yml | 1 + .github/workflows/release.yml | 2 + .../getting-started/adapters/sqlserver.mdx | 581 ++++++++++++++++++ docs/public/img/adapters/sqlserver.svg | 65 ++ packages/adapter-sqlserver/README.md | 28 + packages/adapter-sqlserver/package.json | 50 ++ packages/adapter-sqlserver/schema.sql | 512 +++++++++++++++ packages/adapter-sqlserver/src/index.ts | 201 ++++++ packages/adapter-sqlserver/test/index.test.ts | 66 ++ packages/adapter-sqlserver/test/test.sh | 25 + packages/adapter-sqlserver/tsconfig.json | 9 + packages/adapter-sqlserver/typedoc.config.cjs | 14 + pnpm-lock.yaml | 348 ++++++++--- turbo.json | 1 + 14 files changed, 1813 insertions(+), 90 deletions(-) create mode 100644 docs/pages/getting-started/adapters/sqlserver.mdx create mode 100644 docs/public/img/adapters/sqlserver.svg create mode 100644 packages/adapter-sqlserver/README.md create mode 100644 packages/adapter-sqlserver/package.json create mode 100644 packages/adapter-sqlserver/schema.sql create mode 100644 packages/adapter-sqlserver/src/index.ts create mode 100644 packages/adapter-sqlserver/test/index.test.ts create mode 100755 packages/adapter-sqlserver/test/test.sh create mode 100644 packages/adapter-sqlserver/tsconfig.json create mode 100644 packages/adapter-sqlserver/typedoc.config.cjs diff --git a/.github/pr-labeler.yml b/.github/pr-labeler.yml index 9e44ccb35f..3fcf87338f 100644 --- a/.github/pr-labeler.yml +++ b/.github/pr-labeler.yml @@ -25,6 +25,7 @@ kysely: ["packages/adapter-kysely/**/*"] providers: ["packages/core/src/providers/**/*"] sequelize: ["packages/adapter-sequelize/**/*"] solidjs: ["packages/frameworks-solid-start/**/*"] +sqlserver: ["packages/adapter-sqlserver/**/*"] supabase: ["packages/adapter-supabase/**/*"] surrealdb: ["packages/adapter-surrealdb/**/*"] svelte: ["packages/frameworks-sveltekit/**/*"] diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 947a2b2e85..de349d3a1a 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -28,6 +28,7 @@ on: - "@auth/pouchdb-adapter" - "@auth/prisma-adapter" - "@auth/sequelize-adapter" + - "@auth/sqlserver-adapter" - "@auth/supabase-adapter" - "@auth/surrealdb-adapter" - "@auth/typeorm-adapter" @@ -55,6 +56,7 @@ on: - "adapter-pouchdb" - "adapter-prisma" - "adapter-sequelize" + - "adapter-sqlserver" - "adapter-supabase" - "adapter-surrealdb" - "adapter-typeorm" diff --git a/docs/pages/getting-started/adapters/sqlserver.mdx b/docs/pages/getting-started/adapters/sqlserver.mdx new file mode 100644 index 0000000000..dc874242bd --- /dev/null +++ b/docs/pages/getting-started/adapters/sqlserver.mdx @@ -0,0 +1,581 @@ +import { Code } from "@/components/Code" + + + +# SQL Server Adapter + +## Resources + +- [SQL Server documentation](https://www.microsoft.com/en-us/sql-server/) + +## Setup + +### Installation + +```bash npm2yarn +npm install @auth/sqlserver-adapter mssql +``` + +### Environment Variables + +```sh +DATABASE_HOST= +DATABASE_NAME= +DATABASE_USER= +DATABASE_PASSWORD= +``` + +### Configuration + + + + +```ts filename="./auth.ts" +import NextAuth from "next-auth" +import SqlServerAdapter from "@auth/sqlserver-adapter" +import sql from "mssql" + +const client = new sql.ConnectionPool({ + server: process.env.DATABASE_HOST, + database: process.env.DATABASE_NAME, + user: process.env.DATABASE_USER, + password: process.env.DATABASE_PASSWORD, + pool: { + max: 10, + min: 0, + idleTimeoutMillis: 30000, + }, + options: { + encrypt: true, + trustServerCertificate: true, + }, +}) + +export const { handlers, auth, signIn, signOut } = NextAuth({ + adapter: SqlServerAdapter(pool), + providers: [], +}) +``` + + + + +### Schema + +The SQL schema for the tables used by this adapter is as follows. Learn more about the models at our +doc page on [Database Models](/guides/creating-a-database-adapter). + +```sql +-- USERS table +IF NOT EXISTS + (SELECT 1 + FROM sys.objects + WHERE object_id = OBJECT_ID(N'[users]') + AND type IN ( N'U' ) + ) +BEGIN + CREATE TABLE [users] + ( + [id] UNIQUEIDENTIFIER NOT NULL CONSTRAINT [df_users_id] DEFAULT NEWSEQUENTIALID(), + [name] NVARCHAR(100) NULL, + [email] NVARCHAR(100) NOT NULL, + [emailVerified] DATETIME2 NULL, + [image] VARCHAR(8000) NULL + ); +END +GO + +-- PK constraint and index +IF NOT EXISTS + (SELECT 1 + FROM sys.indexes + WHERE object_id = OBJECT_ID(N'[users]') + AND name = N'pk_users' +) +BEGIN + ALTER TABLE [users] + ADD CONSTRAINT [pk_users] + PRIMARY KEY CLUSTERED ( + [id] ASC + ) + WITH (STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ONLINE = OFF) ON [PRIMARY]; +END +GO + +-- ACCOUNTS table +IF NOT EXISTS + (SELECT 1 + FROM sys.objects + WHERE object_id = OBJECT_ID(N'[accounts]') + AND type IN ( N'U' ) + ) +BEGIN + CREATE TABLE [accounts] + ( + [id] UNIQUEIDENTIFIER NOT NULL CONSTRAINT [df_accounts_id] DEFAULT NEWSEQUENTIALID(), + [userId] UNIQUEIDENTIFIER NOT NULL, + [type] NVARCHAR(100) NOT NULL, + [provider] NVARCHAR(100) NOT NULL, + [providerAccountId] NVARCHAR(100) NOT NULL, + [refresh_token] VARCHAR(8000) NULL, + [access_token] VARCHAR(8000) NULL, + [expires_at] INT NULL, + [token_type] NVARCHAR(100) NULL, + [scope] NVARCHAR(100) NULL, + [id_token] VARCHAR(8000) NULL, + [session_state] NVARCHAR(100) NULL + ); +END +GO + +-- PK constraint and index +IF NOT EXISTS + (SELECT 1 + FROM sys.indexes + WHERE object_id = OBJECT_ID(N'[accounts]') + AND name = N'pk_accounts' +) +BEGIN + ALTER TABLE [accounts] + ADD CONSTRAINT [pk_accounts] + PRIMARY KEY CLUSTERED ( + [id] ASC + ) + WITH (STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ONLINE = OFF) ON [PRIMARY]; +END +GO + +-- FK index +IF NOT EXISTS + (SELECT 1 + FROM sys.indexes + WHERE object_id = OBJECT_ID(N'[accounts]') + AND name = N'ix_accounts_users' +) +BEGIN + CREATE INDEX [ix_accounts_users] ON [accounts] (userId); +END +GO + +-- FK constraint +IF NOT EXISTS + (SELECT 1 + FROM sys.foreign_keys + WHERE parent_object_id = OBJECT_ID(N'[accounts]') + AND name = N'fk_accounts_users' +) +BEGIN + ALTER TABLE [accounts] WITH CHECK + ADD CONSTRAINT [fk_accounts_users] + FOREIGN KEY ([userId]) + REFERENCES [users] ([id]) ON DELETE CASCADE; +END +GO + +-- SESSION table +IF NOT EXISTS + (SELECT 1 + FROM sys.objects + WHERE object_id = OBJECT_ID(N'[sessions]') + AND type IN ( N'U' ) + ) +BEGIN + CREATE TABLE [sessions] + ( + [id] UNIQUEIDENTIFIER NOT NULL CONSTRAINT [df_sessions_id] DEFAULT NEWSEQUENTIALID(), + [expires] DATETIME2 NOT NULL, + [userId] UNIQUEIDENTIFIER NOT NULL, + [sessionToken] VARCHAR(8000) NULL + ); +END +GO + +-- PK index and constraint +IF NOT EXISTS + (SELECT 1 + FROM sys.indexes + WHERE object_id = OBJECT_ID(N'[sessions]') + AND name = N'pk_sessions' +) +BEGIN + ALTER TABLE [sessions] + ADD CONSTRAINT [pk_sessions] + PRIMARY KEY CLUSTERED ( + [id] ASC + ) + WITH (STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ONLINE = OFF) ON [PRIMARY]; +END +GO + +-- FK index +IF NOT EXISTS + (SELECT 1 + FROM sys.indexes + WHERE object_id = OBJECT_ID(N'[sessions]') + AND name = N'ix_sessions_users' +) +BEGIN + CREATE INDEX [ix_sessions_users] ON [sessions] (userId) +END +GO + +-- FK constraint +IF NOT EXISTS + (SELECT 1 + FROM sys.foreign_keys + WHERE parent_object_id = OBJECT_ID(N'[sessions]') + AND name = N'fk_sessions_users' +) +BEGIN + ALTER TABLE [sessions] WITH CHECK + ADD CONSTRAINT [fk_sessions_users] + FOREIGN KEY ([userId]) + REFERENCES [users] ([id]) ON DELETE CASCADE; +END +GO + +-- VERIFICATION_TOKENS table +IF NOT EXISTS + (SELECT 1 + FROM sys.objects + WHERE object_id = OBJECT_ID(N'[verification_tokens]') + AND type IN ( N'U' ) + ) +BEGIN + CREATE TABLE [verification_tokens] + ( + [identifier] NVARCHAR(100) NOT NULL, + [token] VARCHAR(700) NOT NULL, + [expires] DATETIME2 NOT NULL + ); +END +GO + +-- PK index and constraint +IF NOT EXISTS + (SELECT 1 + FROM sys.indexes + WHERE object_id = OBJECT_ID(N'[verification_tokens]') + AND name = N'pk_verification_tokens' +) +BEGIN + ALTER TABLE [verification_tokens] + ADD CONSTRAINT [pk_verification_tokens] + PRIMARY KEY CLUSTERED ( + [identifier] ASC, + [token] ASC + ) + WITH (STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ONLINE = OFF) ON [PRIMARY]; +END +GO + +CREATE OR ALTER PROCEDURE dbo.create_user + @name NVARCHAR(100), + @email NVARCHAR(100), + @emailVerified DATETIME2, + @image VARCHAR(8000) +AS +BEGIN + + DECLARE @new_id TABLE + ( + id UNIQUEIDENTIFIER + ); + + INSERT INTO [users] + ( + [name], + [email], + [emailVerified], + [image] + ) + OUTPUT INSERTED.id + INTO @new_id + VALUES + (@name, @email, @emailVerified, @image); + + -- only return IUser fields + SELECT + [id], + [name], + [email], + [emailVerified], + [image] + FROM [users] + WHERE [id] = + (SELECT TOP 1 id FROM @new_id); + +END +GO + +CREATE OR ALTER PROCEDURE dbo.get_user_by_id @id UNIQUEIDENTIFIER +AS +BEGIN + + SELECT + * + FROM [users] + WHERE [id] = @id; + +END +GO + +CREATE OR ALTER PROCEDURE dbo.get_user_by_email @email NVARCHAR(100) +AS +BEGIN + + SELECT + * + FROM [users] + WHERE [email] = @email; + +END +GO + +CREATE OR ALTER PROCEDURE dbo.get_user_by_account + @providerAccountId NVARCHAR(100), + @provider NVARCHAR(100) +AS +BEGIN + + SELECT + u.* + FROM [users] u + LEFT JOIN [accounts] a + ON a.[userId] = u.[id] + WHERE a.[providerAccountId] = @providerAccountId + AND a.[provider] = @provider; + +END +GO + +CREATE OR ALTER PROCEDURE dbo.update_user + @id UNIQUEIDENTIFIER, + @name NVARCHAR(100) = NULL, + @email NVARCHAR(100) = NULL, + @emailVerified DATETIME2 = NULL, + @image VARCHAR(8000) = NULL +AS +BEGIN + + UPDATE [users] + SET + [name] = COALESCE(@name, [name]), + [email] = COALESCE(@email, [email]), + [emailVerified] = COALESCE(@emailVerified, [emailVerified]), + [image] = COALESCE(@image, [image]) + WHERE [id] = @id; + + SELECT + [id], + [name], + [email], + [emailVerified], + [image] + FROM [users] + WHERE [id] = @id; + +END +GO + +CREATE OR ALTER PROCEDURE dbo.link_account_to_user + @provider NVARCHAR(100), + @type NVARCHAR(100), + @providerAccountId NVARCHAR(100), + @refresh_token VARCHAR(8000), + @token_type NVARCHAR(100), + @scope NVARCHAR(100), + @expires_at INT, + @access_token VARCHAR(8000), + @id_token VARCHAR(8000), + @session_state NVARCHAR(100), + @userId UNIQUEIDENTIFIER +AS +BEGIN + + DECLARE @new_id TABLE + ( + id UNIQUEIDENTIFIER + ); + + INSERT INTO [accounts] + ( + [provider], + [type], + [providerAccountId], + [refresh_token], + [token_type], + [scope], + [expires_at], + [access_token], + [id_token], + [session_state], + [userId] + ) + OUTPUT INSERTED.id + INTO @new_id + VALUES + (@provider, @type, @providerAccountId, @refresh_token, @token_type, @scope, + @expires_at, @access_token, @id_token, @session_state, @userId); + + SELECT + [id], + [userId], + [type], + [provider], + [providerAccountId], + [refresh_token], + [access_token], + [expires_at], + [token_type], + [scope], + [id_token], + [session_state] + FROM [accounts] + WHERE [id] = + (SELECT TOP 1 id FROM @new_id); + +END +GO + +CREATE OR ALTER PROCEDURE dbo.create_session_for_user + @sessionToken VARCHAR(100), + @userId UNIQUEIDENTIFIER, + @expires DATETIME2 +AS +BEGIN + + DECLARE @new_id TABLE + ( + id UNIQUEIDENTIFIER + ); + + INSERT INTO [sessions] + ( + [sessionToken], + [userId], + [expires] + ) + OUTPUT INSERTED.id + INTO @new_id + VALUES + (@sessionToken, @userId, @expires); + + + SELECT + [sessionToken], + [userId], + [expires] + FROM [sessions] + WHERE [id] = + (SELECT TOP 1 id FROM @new_id); + +END +GO + +CREATE OR ALTER PROCEDURE dbo.get_session_and_user @sessionToken VARCHAR(100) +AS +BEGIN + + DECLARE @userId UNIQUEIDENTIFIER; + + SELECT + * + FROM [sessions] + WHERE [sessionToken] = @sessionToken; + + SELECT @userId = [userId] + FROM [sessions] + WHERE [sessionToken] = @sessionToken; + + EXEC dbo.get_user_by_id @userId; +END +GO + +CREATE OR ALTER PROCEDURE dbo.update_session + @sessionToken VARCHAR(100), + @userId UNIQUEIDENTIFIER, + @expires DATETIME2 +AS +BEGIN + + UPDATE [sessions] + SET + [userId] = @userId, + [expires] = @expires + WHERE [sessionToken] = @sessionToken; + +END +GO + +CREATE OR ALTER PROCEDURE dbo.delete_session + @sessionToken VARCHAR(100) +AS +BEGIN + + DELETE FROM [sessions] + WHERE [sessionToken] = @sessionToken; +END +GO + +CREATE OR ALTER PROCEDURE dbo.delete_user + @userId UNIQUEIDENTIFIER +AS +BEGIN + + DELETE FROM [users] + WHERE [id] = @userId; +END +GO + +CREATE OR ALTER PROCEDURE dbo.create_verification_token + @identifier NVARCHAR(100), + @token VARCHAR(8000), + @expires DATETIME2 +AS +BEGIN + + INSERT INTO [verification_tokens] + ( + [identifier], + [token], + [expires] + ) + VALUES + (@identifier, @token, @expires); + + SELECT + [identifier], + [token], + [expires] + FROM [verification_tokens] + WHERE [identifier] = @identifier AND [token] = @token; + +END +GO + +CREATE OR ALTER PROCEDURE dbo.use_verification_token + @identifier NVARCHAR(100), + @token VARCHAR(8000) +AS +BEGIN + + DELETE FROM [verification_tokens] + OUTPUT DELETED.identifier, DELETED.token, DELETED.expires + WHERE [identifier] = @identifier AND [token] = @token; + +END +GO + +CREATE OR ALTER PROCEDURE dbo.unlink_account + @providerAccountId NVARCHAR(100), + @provider NVARCHAR(100) +AS +BEGIN + + DELETE FROM [accounts] + WHERE [providerAccountId] = @providerAccountId AND [provider] = @provider; + +END +GO +``` diff --git a/docs/public/img/adapters/sqlserver.svg b/docs/public/img/adapters/sqlserver.svg new file mode 100644 index 0000000000..88bd975d96 --- /dev/null +++ b/docs/public/img/adapters/sqlserver.svg @@ -0,0 +1,65 @@ + + + + + + + + + + + + + + + + + + diff --git a/packages/adapter-sqlserver/README.md b/packages/adapter-sqlserver/README.md new file mode 100644 index 0000000000..e89cc804eb --- /dev/null +++ b/packages/adapter-sqlserver/README.md @@ -0,0 +1,28 @@ +

+
+ + + + + + +

SQL Server Adapter - NextAuth.js / Auth.js

+

+ + TypeScript + + + npm + + + Downloads + + + GitHub Stars + +

+

+ +--- + +Check out the documentation at [authjs.dev](https://authjs.dev/reference/adapter/pg). diff --git a/packages/adapter-sqlserver/package.json b/packages/adapter-sqlserver/package.json new file mode 100644 index 0000000000..3b6bf227b4 --- /dev/null +++ b/packages/adapter-sqlserver/package.json @@ -0,0 +1,50 @@ +{ + "name": "@auth/sqlserver-adapter", + "version": "0.0.1", + "description": "SQL Server adapter for next-auth.", + "homepage": "https://authjs.dev", + "repository": "https://github.com/nextauthjs/next-auth", + "bugs": { + "url": "https://github.com/nextauthjs/next-auth/issues" + }, + "author": "Peter Budai", + "license": "ISC", + "keywords": [ + "next-auth", + "@auth", + "Auth.js", + "next.js", + "oauth", + "sqlserver" + ], + "type": "module", + "exports": { + ".": { + "types": "./index.d.ts", + "import": "./index.js" + } + }, + "files": [ + "*.d.ts*", + "*.js", + "src" + ], + "private": false, + "publishConfig": { + "access": "public" + }, + "scripts": { + "test": "./test/test.sh", + "build": "tsc" + }, + "dependencies": { + "@auth/core": "workspace:*" + }, + "peerDependencies": { + "mssql": "^11.0.1" + }, + "devDependencies": { + "@types/mssql": "^9.1.5", + "mssql": "^11.0.1" + } +} diff --git a/packages/adapter-sqlserver/schema.sql b/packages/adapter-sqlserver/schema.sql new file mode 100644 index 0000000000..c3a1f90cb5 --- /dev/null +++ b/packages/adapter-sqlserver/schema.sql @@ -0,0 +1,512 @@ +-- USERS table +IF NOT EXISTS + (SELECT 1 + FROM sys.objects + WHERE object_id = OBJECT_ID(N'[users]') + AND type IN ( N'U' ) + ) +BEGIN + CREATE TABLE [users] + ( + [id] UNIQUEIDENTIFIER NOT NULL CONSTRAINT [df_users_id] DEFAULT NEWSEQUENTIALID(), + [name] NVARCHAR(100) NULL, + [email] NVARCHAR(100) NOT NULL, + [emailVerified] DATETIME2 NULL, + [image] VARCHAR(8000) NULL + ); +END +GO + +-- PK constraint and index +IF NOT EXISTS + (SELECT 1 + FROM sys.indexes + WHERE object_id = OBJECT_ID(N'[users]') + AND name = N'pk_users' +) +BEGIN + ALTER TABLE [users] + ADD CONSTRAINT [pk_users] + PRIMARY KEY CLUSTERED ( + [id] ASC + ) + WITH (STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ONLINE = OFF) ON [PRIMARY]; +END +GO + +-- ACCOUNTS table +IF NOT EXISTS + (SELECT 1 + FROM sys.objects + WHERE object_id = OBJECT_ID(N'[accounts]') + AND type IN ( N'U' ) + ) +BEGIN + CREATE TABLE [accounts] + ( + [id] UNIQUEIDENTIFIER NOT NULL CONSTRAINT [df_accounts_id] DEFAULT NEWSEQUENTIALID(), + [userId] UNIQUEIDENTIFIER NOT NULL, + [type] NVARCHAR(100) NOT NULL, + [provider] NVARCHAR(100) NOT NULL, + [providerAccountId] NVARCHAR(100) NOT NULL, + [refresh_token] VARCHAR(8000) NULL, + [access_token] VARCHAR(8000) NULL, + [expires_at] INT NULL, + [token_type] NVARCHAR(100) NULL, + [scope] NVARCHAR(100) NULL, + [id_token] VARCHAR(8000) NULL, + [session_state] NVARCHAR(100) NULL + ); +END +GO + +-- PK constraint and index +IF NOT EXISTS + (SELECT 1 + FROM sys.indexes + WHERE object_id = OBJECT_ID(N'[accounts]') + AND name = N'pk_accounts' +) +BEGIN + ALTER TABLE [accounts] + ADD CONSTRAINT [pk_accounts] + PRIMARY KEY CLUSTERED ( + [id] ASC + ) + WITH (STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ONLINE = OFF) ON [PRIMARY]; +END +GO + +-- FK index +IF NOT EXISTS + (SELECT 1 + FROM sys.indexes + WHERE object_id = OBJECT_ID(N'[accounts]') + AND name = N'ix_accounts_users' +) +BEGIN + CREATE INDEX [ix_accounts_users] ON [accounts] (userId); +END +GO + +-- FK constraint +IF NOT EXISTS + (SELECT 1 + FROM sys.foreign_keys + WHERE parent_object_id = OBJECT_ID(N'[accounts]') + AND name = N'fk_accounts_users' +) +BEGIN + ALTER TABLE [accounts] WITH CHECK + ADD CONSTRAINT [fk_accounts_users] + FOREIGN KEY ([userId]) + REFERENCES [users] ([id]) ON DELETE CASCADE; +END +GO + +-- SESSION table +IF NOT EXISTS + (SELECT 1 + FROM sys.objects + WHERE object_id = OBJECT_ID(N'[sessions]') + AND type IN ( N'U' ) + ) +BEGIN + CREATE TABLE [sessions] + ( + [id] UNIQUEIDENTIFIER NOT NULL CONSTRAINT [df_sessions_id] DEFAULT NEWSEQUENTIALID(), + [expires] DATETIME2 NOT NULL, + [userId] UNIQUEIDENTIFIER NOT NULL, + [sessionToken] VARCHAR(8000) NULL + ); +END +GO + +-- PK index and constraint +IF NOT EXISTS + (SELECT 1 + FROM sys.indexes + WHERE object_id = OBJECT_ID(N'[sessions]') + AND name = N'pk_sessions' +) +BEGIN + ALTER TABLE [sessions] + ADD CONSTRAINT [pk_sessions] + PRIMARY KEY CLUSTERED ( + [id] ASC + ) + WITH (STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ONLINE = OFF) ON [PRIMARY]; +END +GO + +-- FK index +IF NOT EXISTS + (SELECT 1 + FROM sys.indexes + WHERE object_id = OBJECT_ID(N'[sessions]') + AND name = N'ix_sessions_users' +) +BEGIN + CREATE INDEX [ix_sessions_users] ON [sessions] (userId) +END +GO + +-- FK constraint +IF NOT EXISTS + (SELECT 1 + FROM sys.foreign_keys + WHERE parent_object_id = OBJECT_ID(N'[sessions]') + AND name = N'fk_sessions_users' +) +BEGIN + ALTER TABLE [sessions] WITH CHECK + ADD CONSTRAINT [fk_sessions_users] + FOREIGN KEY ([userId]) + REFERENCES [users] ([id]) ON DELETE CASCADE; +END +GO + +-- VERIFICATION_TOKENS table +IF NOT EXISTS + (SELECT 1 + FROM sys.objects + WHERE object_id = OBJECT_ID(N'[verification_tokens]') + AND type IN ( N'U' ) + ) +BEGIN + CREATE TABLE [verification_tokens] + ( + [identifier] NVARCHAR(100) NOT NULL, + [token] VARCHAR(700) NOT NULL, + [expires] DATETIME2 NOT NULL + ); +END +GO + +-- PK index and constraint +IF NOT EXISTS + (SELECT 1 + FROM sys.indexes + WHERE object_id = OBJECT_ID(N'[verification_tokens]') + AND name = N'pk_verification_tokens' +) +BEGIN + ALTER TABLE [verification_tokens] + ADD CONSTRAINT [pk_verification_tokens] + PRIMARY KEY CLUSTERED ( + [identifier] ASC, + [token] ASC + ) + WITH (STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ONLINE = OFF) ON [PRIMARY]; +END +GO + +CREATE OR ALTER PROCEDURE dbo.create_user + @name NVARCHAR(100), + @email NVARCHAR(100), + @emailVerified DATETIME2, + @image VARCHAR(8000) +AS +BEGIN + + DECLARE @new_id TABLE + ( + id UNIQUEIDENTIFIER + ); + + INSERT INTO [users] + ( + [name], + [email], + [emailVerified], + [image] + ) + OUTPUT INSERTED.id + INTO @new_id + VALUES + (@name, @email, @emailVerified, @image); + + -- only return IUser fields + SELECT + [id], + [name], + [email], + [emailVerified], + [image] + FROM [users] + WHERE [id] = + (SELECT TOP 1 id FROM @new_id); + +END +GO + +CREATE OR ALTER PROCEDURE dbo.get_user_by_id @id UNIQUEIDENTIFIER +AS +BEGIN + + SELECT + * + FROM [users] + WHERE [id] = @id; + +END +GO + +CREATE OR ALTER PROCEDURE dbo.get_user_by_email @email NVARCHAR(100) +AS +BEGIN + + SELECT + * + FROM [users] + WHERE [email] = @email; + +END +GO + +CREATE OR ALTER PROCEDURE dbo.get_user_by_account + @providerAccountId NVARCHAR(100), + @provider NVARCHAR(100) +AS +BEGIN + + SELECT + u.* + FROM [users] u + LEFT JOIN [accounts] a + ON a.[userId] = u.[id] + WHERE a.[providerAccountId] = @providerAccountId + AND a.[provider] = @provider; + +END +GO + +CREATE OR ALTER PROCEDURE dbo.update_user + @id UNIQUEIDENTIFIER, + @name NVARCHAR(100) = NULL, + @email NVARCHAR(100) = NULL, + @emailVerified DATETIME2 = NULL, + @image VARCHAR(8000) = NULL +AS +BEGIN + + UPDATE [users] + SET + [name] = COALESCE(@name, [name]), + [email] = COALESCE(@email, [email]), + [emailVerified] = COALESCE(@emailVerified, [emailVerified]), + [image] = COALESCE(@image, [image]) + WHERE [id] = @id; + + SELECT + [id], + [name], + [email], + [emailVerified], + [image] + FROM [users] + WHERE [id] = @id; + +END +GO + +CREATE OR ALTER PROCEDURE dbo.link_account_to_user + @provider NVARCHAR(100), + @type NVARCHAR(100), + @providerAccountId NVARCHAR(100), + @refresh_token VARCHAR(8000), + @token_type NVARCHAR(100), + @scope NVARCHAR(100), + @expires_at INT, + @access_token VARCHAR(8000), + @id_token VARCHAR(8000), + @session_state NVARCHAR(100), + @userId UNIQUEIDENTIFIER +AS +BEGIN + + DECLARE @new_id TABLE + ( + id UNIQUEIDENTIFIER + ); + + INSERT INTO [accounts] + ( + [provider], + [type], + [providerAccountId], + [refresh_token], + [token_type], + [scope], + [expires_at], + [access_token], + [id_token], + [session_state], + [userId] + ) + OUTPUT INSERTED.id + INTO @new_id + VALUES + (@provider, @type, @providerAccountId, @refresh_token, @token_type, @scope, + @expires_at, @access_token, @id_token, @session_state, @userId); + + SELECT + [id], + [userId], + [type], + [provider], + [providerAccountId], + [refresh_token], + [access_token], + [expires_at], + [token_type], + [scope], + [id_token], + [session_state] + FROM [accounts] + WHERE [id] = + (SELECT TOP 1 id FROM @new_id); + +END +GO + +CREATE OR ALTER PROCEDURE dbo.create_session_for_user + @sessionToken VARCHAR(100), + @userId UNIQUEIDENTIFIER, + @expires DATETIME2 +AS +BEGIN + + DECLARE @new_id TABLE + ( + id UNIQUEIDENTIFIER + ); + + INSERT INTO [sessions] + ( + [sessionToken], + [userId], + [expires] + ) + OUTPUT INSERTED.id + INTO @new_id + VALUES + (@sessionToken, @userId, @expires); + + + SELECT + [sessionToken], + [userId], + [expires] + FROM [sessions] + WHERE [id] = + (SELECT TOP 1 id FROM @new_id); + +END +GO + +CREATE OR ALTER PROCEDURE dbo.get_session_and_user @sessionToken VARCHAR(100) +AS +BEGIN + + DECLARE @userId UNIQUEIDENTIFIER; + + SELECT + * + FROM [sessions] + WHERE [sessionToken] = @sessionToken; + + SELECT @userId = [userId] + FROM [sessions] + WHERE [sessionToken] = @sessionToken; + + EXEC dbo.get_user_by_id @userId; +END +GO + +CREATE OR ALTER PROCEDURE dbo.update_session + @sessionToken VARCHAR(100), + @userId UNIQUEIDENTIFIER, + @expires DATETIME2 +AS +BEGIN + + UPDATE [sessions] + SET + [userId] = @userId, + [expires] = @expires + WHERE [sessionToken] = @sessionToken; + +END +GO + +CREATE OR ALTER PROCEDURE dbo.delete_session + @sessionToken VARCHAR(100) +AS +BEGIN + + DELETE FROM [sessions] + WHERE [sessionToken] = @sessionToken; +END +GO + +CREATE OR ALTER PROCEDURE dbo.delete_user + @userId UNIQUEIDENTIFIER +AS +BEGIN + + DELETE FROM [users] + WHERE [id] = @userId; +END +GO + +CREATE OR ALTER PROCEDURE dbo.create_verification_token + @identifier NVARCHAR(100), + @token VARCHAR(8000), + @expires DATETIME2 +AS +BEGIN + + INSERT INTO [verification_tokens] + ( + [identifier], + [token], + [expires] + ) + VALUES + (@identifier, @token, @expires); + + SELECT + [identifier], + [token], + [expires] + FROM [verification_tokens] + WHERE [identifier] = @identifier AND [token] = @token; + +END +GO + +CREATE OR ALTER PROCEDURE dbo.use_verification_token + @identifier NVARCHAR(100), + @token VARCHAR(8000) +AS +BEGIN + + DELETE FROM [verification_tokens] + OUTPUT DELETED.identifier, DELETED.token, DELETED.expires + WHERE [identifier] = @identifier AND [token] = @token; + +END +GO + +CREATE OR ALTER PROCEDURE dbo.unlink_account + @providerAccountId NVARCHAR(100), + @provider NVARCHAR(100) +AS +BEGIN + + DELETE FROM [accounts] + WHERE [providerAccountId] = @providerAccountId AND [provider] = @provider; + +END +GO \ No newline at end of file diff --git a/packages/adapter-sqlserver/src/index.ts b/packages/adapter-sqlserver/src/index.ts new file mode 100644 index 0000000000..efa14c300d --- /dev/null +++ b/packages/adapter-sqlserver/src/index.ts @@ -0,0 +1,201 @@ +/** + *
+ *

Official MS SQL Server adapter for Auth.js / NextAuth.js.

+ * + * + * + *
+ * + * ## Installation + * + * ```bash npm2yarn + * npm install @auth/sqlserver-adapter mssql + * ``` + * + * @module @auth/sqlserver-adapter + */ + +import type { + Adapter, + AdapterUser, + AdapterAccount, + AdapterSession, + VerificationToken, +} from "@auth/core/adapters" +import sql from "mssql" + +export function mapExpiresAt(account: any): any { + const expires_at: number = parseInt(account.expires_at) + return { + ...account, + expires_at, + } +} + +export default function TSqlAdapter(connection: sql.ConnectionPool): Adapter { + const conn = connection + + return { + async createUser(user) { + const request = conn.request() + request.input("name", sql.VarChar, user.name) + request.input("email", sql.VarChar, user.email) + request.input("emailVerified", sql.DateTime2, user.emailVerified) + request.input("image", sql.VarChar, user.image) + + const result = await request.execute("dbo.create_user") + + return { ...result.recordset[0] } + }, + async getUser(id) { + const request = conn.request() + request.input("id", sql.VarChar, id) + const result = await request.execute("dbo.get_user_by_id") + + return result.recordset[0] ?? null + }, + async getUserByEmail(email) { + const request = conn.request() + request.input("email", sql.VarChar, email) + + const result = await request.execute("dbo.get_user_by_email") + + return result.recordset[0] ?? null + }, + async getUserByAccount({ providerAccountId, provider }) { + const request = conn.request() + request.input("providerAccountId", sql.VarChar, providerAccountId) + request.input("provider", sql.VarChar, provider) + const result = await request.execute( + "dbo.get_user_by_account" + ) + + return result.recordset[0] ? { ...result.recordset[0] } : null + }, + async updateUser(user) { + const request = conn.request() + request.input("id", sql.VarChar, user.id) + request.input("name", sql.VarChar, user.name) + request.input("email", sql.VarChar, user.email) + request.input("emailVerified", sql.DateTime2, user.emailVerified) + request.input("image", sql.VarChar, user.image) + const result = await request.execute("dbo.update_user") + + return result.recordset[0] + }, + async deleteUser(userId) { + const request = conn.request() + request.input("userId", sql.UniqueIdentifier, userId) + await request.execute("dbo.delete_user") + }, + async linkAccount(account) { + const request = conn.request() + request.input("provider", sql.VarChar, account.provider) + request.input("type", sql.VarChar, account.type) + request.input("providerAccountId", sql.VarChar, account.providerAccountId) + request.input("refresh_token", sql.VarChar, account.refresh_token) + request.input("token_type", sql.VarChar, account.token_type) + request.input("scope", sql.VarChar, account.scope) + request.input("expires_at", sql.Int, account.expires_at) + request.input("access_token", sql.VarChar, account.access_token) + request.input("id_token", sql.VarChar, account.id_token) + request.input("session_state", sql.VarChar, account.session_state) + request.input("userId", sql.VarChar, account.userId) + const result = await request.execute( + "dbo.link_account_to_user" + ) + + return { ...result.recordset[0] } + }, + async unlinkAccount({ providerAccountId, provider }) { + const request = conn.request() + request.input("providerAccountId", sql.VarChar, providerAccountId) + request.input("provider", sql.VarChar, provider) + await request.execute("dbo.unlink_account") + }, + async createSession({ sessionToken, userId, expires }) { + const request = conn.request() + request.input("sessionToken", sql.VarChar, sessionToken) + request.input("userId", sql.VarChar, userId) + request.input("expires", sql.DateTime2, expires) + const result = await request.execute( + "dbo.create_session_for_user" + ) + + return { ...result.recordset[0] } + }, + async getSessionAndUser(sessionToken) { + const request = conn.request() + request.input("sessionToken", sql.VarChar, sessionToken) + const result = await request.execute<[AdapterSession, AdapterUser]>( + "dbo.get_session_and_user" + ) + + const session = result.recordsets[0][0] + const user = result.recordsets[1][0] + + if (session && user) { + return { + session, + user, + } + } else { + return null + } + }, + async updateSession(updatedSession) { + const request = conn.request() + request.input("sessionToken", sql.VarChar, updatedSession.sessionToken) + const result = await request.execute<[AdapterSession, AdapterUser]>( + "dbo.get_session_and_user" + ) + + const previousSession = result.recordsets[0][0] + + if (previousSession) { + const currentSession = { + ...previousSession, + ...updatedSession, + } + + const updateRequest = conn.request() + updateRequest.input( + "sessionToken", + sql.VarChar, + currentSession.sessionToken + ) + updateRequest.input("userId", sql.VarChar, currentSession.userId) + updateRequest.input("expires", sql.DateTime2, currentSession.expires) + await updateRequest.execute("dbo.update_session") + + return currentSession as AdapterSession + } + return null + }, + async deleteSession(sessionToken) { + const request = conn.request() + request.input("sessionToken", sql.VarChar, sessionToken) + await request.execute<[AdapterSession, AdapterUser]>("dbo.delete_session") + }, + async createVerificationToken(data) { + const request = conn.request() + request.input("identifier", sql.VarChar, data.identifier) + request.input("token", sql.VarChar, data.token) + request.input("expires", sql.DateTime2, data.expires) + await request.execute<[AdapterSession, AdapterUser]>( + "dbo.create_verification_token" + ) + return data + }, + async useVerificationToken({ identifier, token }) { + const request = conn.request() + request.input("identifier", sql.VarChar, identifier) + request.input("token", sql.VarChar, token) + const result = await request.execute( + "dbo.use_verification_token" + ) + + return result.recordset[0] ?? null + }, + } +} diff --git a/packages/adapter-sqlserver/test/index.test.ts b/packages/adapter-sqlserver/test/index.test.ts new file mode 100644 index 0000000000..ba41f7bda7 --- /dev/null +++ b/packages/adapter-sqlserver/test/index.test.ts @@ -0,0 +1,66 @@ +import { runBasicTests } from "utils/adapter" +import SqlServerAdapter, { mapExpiresAt } from "../src" +import sql from "mssql" + +const POOL_SIZE = 10 + +const client = new sql.ConnectionPool({ + server: "localhost", + database: "adapter-sqlserver-test", + user: "sa", + password: "Authjs!password", + pool: { + max: POOL_SIZE, + min: POOL_SIZE, + idleTimeoutMillis: 30000, + }, + options: { + encrypt: true, + trustServerCertificate: true, + }, +}) + +runBasicTests({ + adapter: SqlServerAdapter(client), + db: { + connect: async () => { + await client.connect() + }, + disconnect: async () => { + await client.close() + }, + user: async (id: string) => { + const sql = `select * from users where id = @id` + const result = await client.request().input("id", id).query(sql) + return result.recordset[0] ?? null + }, + account: async (account) => { + const sql = `select * from accounts where providerAccountId = @account_id` + + const result = await client + .request() + .input("account_id", account.providerAccountId) + .query(sql) + return result.recordset[0] ? mapExpiresAt(result.recordset[0]) : null + }, + session: async (sessionToken) => { + const result = await client + .request() + .input("session_token", sessionToken) + .query(`select * from sessions where sessionToken = @session_token`) + + return result.recordset[0] ?? null + }, + verificationToken: async (identifier_token) => { + const { identifier, token } = identifier_token + const result = await client + .request() + .input("identifier", identifier) + .input("token", token) + .query( + "select * from verification_tokens where identifier = @identifier and token = @token" + ) + return result.recordset[0] ?? null + }, + }, +}) diff --git a/packages/adapter-sqlserver/test/test.sh b/packages/adapter-sqlserver/test/test.sh new file mode 100755 index 0000000000..b7d7c5c112 --- /dev/null +++ b/packages/adapter-sqlserver/test/test.sh @@ -0,0 +1,25 @@ +#!/usr/bin/env bash + +CONTAINER_NAME=authjs-sqlserver-test +DATABASE_NAME=adapter-sqlserver-test + +docker run -d --rm \ + --name ${CONTAINER_NAME} \ + -e MSSQL_SA_PASSWORD=Authjs!password \ + -e ACCEPT_EULA=Y \ + -p 1433:1433 \ + -v "$(pwd)"/schema.sql:/home/schema.sql \ + mcr.microsoft.com/mssql/server:2022-latest + +echo "waiting 5s for db to start..." +sleep 10 + +docker exec ${CONTAINER_NAME} /opt/mssql-tools/bin/sqlcmd -S localhost -U sa -P Authjs!password -d master -Q "CREATE DATABASE [${DATABASE_NAME}]" +docker exec ${CONTAINER_NAME} /opt/mssql-tools/bin/sqlcmd -S localhost -U sa -P Authjs!password -d ${DATABASE_NAME} -i /home/schema.sql + +# Always stop container, but exit with 1 when tests are failing +if vitest run -c ../utils/vitest.config.ts; then + docker stop ${CONTAINER_NAME} +else + docker stop ${CONTAINER_NAME} && exit 1 +fi diff --git a/packages/adapter-sqlserver/tsconfig.json b/packages/adapter-sqlserver/tsconfig.json new file mode 100644 index 0000000000..df8621c516 --- /dev/null +++ b/packages/adapter-sqlserver/tsconfig.json @@ -0,0 +1,9 @@ +{ + "extends": "utils/tsconfig.json", + "compilerOptions": { + "outDir": ".", + "rootDir": "src" + }, + "exclude": ["*.js", "*.d.ts"], + "include": ["src/**/*"] +} diff --git a/packages/adapter-sqlserver/typedoc.config.cjs b/packages/adapter-sqlserver/typedoc.config.cjs new file mode 100644 index 0000000000..25b6c09877 --- /dev/null +++ b/packages/adapter-sqlserver/typedoc.config.cjs @@ -0,0 +1,14 @@ +// @ts-check + +/** + * @type {import('typedoc').TypeDocOptions & import('typedoc-plugin-markdown').MarkdownTheme} + */ +module.exports = { + entryPoints: ["src/index.ts"], + entryPointStrategy: "expand", + tsconfig: "./tsconfig.json", + entryModule: "@auth/sqlserver-adapter", + entryFileName: "../sqlserver-adapter.mdx", + includeVersion: true, + readme: 'none', +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 4d7b90ef4a..eeec5abcab 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -66,7 +66,7 @@ importers: version: 7.33.2(eslint@8.30.0) eslint-plugin-svelte: specifier: ^2.38.0 - version: 2.38.0(eslint@8.30.0)(svelte@4.2.9)(ts-node@10.9.2(@swc/core@1.3.106(@swc/helpers@0.5.11))(@types/node@20.11.7)(typescript@5.3.3)) + version: 2.38.0(eslint@8.30.0)(svelte@4.2.9)(ts-node@10.9.2(@types/node@20.11.7)(typescript@5.3.3)) fake-smtp-server: specifier: ^0.8.0 version: 0.8.0 @@ -224,7 +224,7 @@ importers: version: link:../../../packages/adapter-unstorage unstorage: specifier: ^1.10.2 - version: 1.10.2(@azure/data-tables@13.2.2)(@azure/identity@1.5.2)(@upstash/redis@1.28.2)(@vercel/kv@1.0.1)(ioredis@5.4.1) + version: 1.10.2(@azure/data-tables@13.2.2)(@azure/identity@4.3.0)(@vercel/kv@1.0.1)(ioredis@5.4.1) devDependencies: '@sveltejs/adapter-auto': specifier: next @@ -240,7 +240,7 @@ importers: version: 4.2.9 svelte-check: specifier: 2.10.2 - version: 2.10.2(@babel/core@7.23.9)(postcss-load-config@4.0.2(postcss@8.4.38)(ts-node@10.9.2(@swc/core@1.3.106(@swc/helpers@0.5.11))(@types/node@20.12.7)(typescript@5.2.2)))(postcss@8.4.38)(pug@3.0.2)(sass@1.70.0)(svelte@4.2.9) + version: 2.10.2(@babel/core@7.23.9)(postcss-load-config@4.0.2(postcss@8.4.38)(ts-node@10.9.2(@types/node@20.11.7)(typescript@5.3.3)))(postcss@8.4.38)(pug@3.0.2)(sass@1.70.0)(svelte@4.2.9) typescript: specifier: 5.2.2 version: 5.2.2 @@ -322,7 +322,7 @@ importers: version: 1.3.0 tailwindcss: specifier: ^3.4.3 - version: 3.4.3(ts-node@10.9.2(@swc/core@1.3.106(@swc/helpers@0.5.11))(@types/node@20.12.7)(typescript@5.4.5)) + version: 3.4.3(ts-node@10.9.2(@types/node@20.12.7)(typescript@5.4.5)) typedoc: specifier: ^0.25.13 version: 0.25.13(typescript@5.4.5) @@ -383,7 +383,7 @@ importers: version: 0.20.17 drizzle-orm: specifier: ^0.30.9 - version: 0.30.9(@cloudflare/workers-types@4.20240117.0)(@libsql/client@0.6.0)(@opentelemetry/api@1.7.0)(@types/better-sqlite3@7.6.9)(@types/pg@8.11.0)(@types/react@18.2.78)(@xata.io/client@0.28.0(typescript@5.4.5))(better-sqlite3@9.6.0)(knex@2.5.1(better-sqlite3@9.6.0)(mysql2@3.9.7)(pg@8.11.3)(sqlite3@5.1.6(encoding@0.1.13)))(kysely@0.24.2)(mysql2@3.9.7)(pg@8.11.3)(postgres@3.4.3)(react@18.3.1)(sqlite3@5.1.6(encoding@0.1.13)) + version: 0.30.9(@cloudflare/workers-types@4.20240117.0)(@libsql/client@0.6.0)(@opentelemetry/api@1.7.0)(@types/better-sqlite3@7.6.9)(@types/pg@8.11.0)(@types/react@18.2.78)(@xata.io/client@0.28.0(typescript@5.3.3))(better-sqlite3@9.6.0)(knex@2.5.1(better-sqlite3@9.6.0)(mysql2@3.9.7)(pg@8.11.3)(sqlite3@5.1.6))(kysely@0.24.2)(mysql2@3.9.7)(pg@8.11.3)(postgres@3.4.3)(react@18.3.1)(sqlite3@5.1.6) libsql: specifier: ^0.3.18 version: 0.3.18 @@ -431,7 +431,7 @@ importers: version: 1.3.1 fauna-shell: specifier: 1.2.1 - version: 1.2.1(@swc/core@1.3.106(@swc/helpers@0.5.11))(@types/node@20.12.7)(encoding@0.1.13)(typescript@5.4.5) + version: 1.2.1(@swc/core@1.3.106)(@types/node@20.12.7)(encoding@0.1.13)(typescript@5.4.5) packages/adapter-firebase: dependencies: @@ -492,7 +492,7 @@ importers: version: 5.9.7(@mikro-orm/sqlite@5.9.7) '@mikro-orm/sqlite': specifier: ^5 - version: 5.9.7(@mikro-orm/core@5.9.7)(better-sqlite3@9.6.0)(encoding@0.1.13)(mssql@7.3.5(encoding@0.1.13))(mysql2@3.9.7)(mysql@2.18.1)(pg@8.11.3) + version: 5.9.7(@mikro-orm/core@5.9.7)(better-sqlite3@9.6.0)(encoding@0.1.13)(mssql@11.0.1)(mysql2@3.9.7)(mysql@2.18.1)(pg@8.11.3) packages/adapter-mongodb: dependencies: @@ -502,7 +502,7 @@ importers: devDependencies: mongodb: specifier: ^6.0.0 - version: 6.3.0(@aws-sdk/credential-providers@3.499.0)(gcp-metadata@5.3.0(encoding@0.1.13))(socks@2.7.1) + version: 6.3.0(@aws-sdk/credential-providers@3.499.0)(gcp-metadata@5.3.0)(socks@2.7.1) packages/adapter-neo4j: dependencies: @@ -578,6 +578,19 @@ importers: specifier: ^6.6.5 version: 6.35.2 + packages/adapter-sqlserver: + dependencies: + '@auth/core': + specifier: workspace:* + version: link:../core + devDependencies: + '@types/mssql': + specifier: ^9.1.5 + version: 9.1.5 + mssql: + specifier: ^11.0.1 + version: 11.0.1 + packages/adapter-supabase: dependencies: '@auth/core': @@ -620,10 +633,10 @@ importers: version: 8.11.3 typeorm: specifier: 0.3.17 - version: 0.3.17(better-sqlite3@9.6.0)(ioredis@5.4.1)(mongodb@6.3.0(@aws-sdk/credential-providers@3.499.0)(gcp-metadata@5.3.0(encoding@0.1.13))(socks@2.7.1))(mssql@7.3.5(encoding@0.1.13))(mysql2@3.9.7)(pg@8.11.3)(redis@4.6.12)(sqlite3@5.1.6(encoding@0.1.13))(ts-node@10.9.2(@swc/core@1.3.106(@swc/helpers@0.5.11))(@types/node@20.12.7)(typescript@5.4.5)) + version: 0.3.17(ioredis@5.4.1)(mssql@7.3.5(encoding@0.1.13))(mysql2@3.9.7)(pg@8.11.3)(redis@4.6.12)(sqlite3@5.1.6(encoding@0.1.13))(ts-node@10.9.2(@types/node@20.11.7)(typescript@5.3.3)) typeorm-naming-strategies: specifier: ^4.1.0 - version: 4.1.0(typeorm@0.3.17(better-sqlite3@9.6.0)(ioredis@5.4.1)(mongodb@6.3.0(@aws-sdk/credential-providers@3.499.0)(gcp-metadata@5.3.0(encoding@0.1.13))(socks@2.7.1))(mssql@7.3.5(encoding@0.1.13))(mysql2@3.9.7)(pg@8.11.3)(redis@4.6.12)(sqlite3@5.1.6(encoding@0.1.13))(ts-node@10.9.2(@swc/core@1.3.106(@swc/helpers@0.5.11))(@types/node@20.12.7)(typescript@5.4.5))) + version: 4.1.0(typeorm@0.3.17(ioredis@5.4.1)(mssql@7.3.5(encoding@0.1.13))(mysql2@3.9.7)(pg@8.11.3)(redis@4.6.12)(sqlite3@5.1.6(encoding@0.1.13))(ts-node@10.9.2(@types/node@20.11.7)(typescript@5.3.3))) packages/adapter-unstorage: dependencies: @@ -636,7 +649,7 @@ importers: version: 4.6.12 unstorage: specifier: ^1.10.1 - version: 1.10.1(@azure/data-tables@13.2.2)(@azure/identity@1.5.2)(@upstash/redis@1.28.2)(@vercel/kv@1.0.1) + version: 1.10.1(@azure/data-tables@13.2.2)(@upstash/redis@1.28.2) packages/adapter-upstash-redis: dependencies: @@ -829,7 +842,7 @@ importers: version: 4.2.9 svelte-check: specifier: ^3.4.3 - version: 3.6.3(@babel/core@7.23.9)(postcss-load-config@4.0.2(postcss@8.4.38)(ts-node@10.9.2(@swc/core@1.3.106(@swc/helpers@0.5.11))(@types/node@20.12.7)(typescript@5.4.5)))(postcss@8.4.38)(pug@3.0.2)(sass@1.70.0)(svelte@4.2.9) + version: 3.6.3(@babel/core@7.23.9)(postcss-load-config@4.0.2(postcss@8.4.38)(ts-node@10.9.2(@types/node@20.11.7)(typescript@5.3.3)))(postcss@8.4.38)(pug@3.0.2)(sass@1.70.0)(svelte@4.2.9) tslib: specifier: ^2.4.1 version: 2.6.2 @@ -1163,6 +1176,10 @@ packages: resolution: {integrity: sha512-TrRLIoSQVzfAJX9H1JeFjzAoDGcoK1IYX1UImfceTZpsyYfWr09Ss1aHW1y5TrrR3iq6RZLBwJ3E24uwPhwahw==} engines: {node: '>=12.0.0'} + '@azure/abort-controller@2.1.2': + resolution: {integrity: sha512-nBrLsEWm4J2u5LpAPjxADTlq3trDgVZZXHNKabeXZtpq3d3AbN/KGO82R87rdDz5/lYB024rtEf10/q0urNgsA==} + engines: {node: '>=18.0.0'} + '@azure/core-auth@1.5.0': resolution: {integrity: sha512-udzoBuYG1VBoHVohDTrvKjyzel34zt77Bhp7dQntVGGD0ehVq48owENbBG8fIgkHRNUBQH5k1r0hpoMu5L8+kw==} engines: {node: '>=14.0.0'} @@ -1171,6 +1188,10 @@ packages: resolution: {integrity: sha512-kleJ1iUTxcO32Y06dH9Pfi9K4U+Tlb111WXEnbt7R/ne+NLRwppZiTGJuTD5VVoxTMK5NTbEtm5t2vcdNCFe2g==} engines: {node: '>=14.0.0'} + '@azure/core-client@1.9.2': + resolution: {integrity: sha512-kRdry/rav3fUKHl/aDLd/pDLcB+4pOFwPPTVEExuMyaI5r+JBbMWqRbCY1pn5BniDaU3lRxO9eaQ1AmSMehl/w==} + engines: {node: '>=18.0.0'} + '@azure/core-http-compat@1.3.0': resolution: {integrity: sha512-ZN9avruqbQ5TxopzG3ih3KRy52n8OAbitX3fnZT5go4hzu0J+KVPSzkL+Wt3hpJpdG8WIfg1sBD1tWkgUdEpBA==} engines: {node: '>=12.0.0'} @@ -1211,6 +1232,10 @@ packages: resolution: {integrity: sha512-vqyeRbd2i0h9F4mqW5JbkP1xfabqKQ21l/81osKhpOQ2LtwaJW6nw4+0PsVYnxcbPHFCIZt6EWAk74a3OGYZJA==} engines: {node: '>=12.0.0'} + '@azure/identity@4.3.0': + resolution: {integrity: sha512-LHZ58/RsIpIWa4hrrE2YuJ/vzG1Jv9f774RfTTAVDZDriubvJ0/S5u4pnw4akJDlS0TiJb6VMphmVUFsWmgodQ==} + engines: {node: '>=18.0.0'} + '@azure/keyvault-keys@4.7.2': resolution: {integrity: sha512-VdIH6PjbQ3J5ntK+xeI8eOe1WsDxF9ndXw8BPR/9MZVnIj0vQNtNCS6gpR7EFQeGcs8XjzMfHm0AvKGErobqJQ==} engines: {node: '>=14.0.0'} @@ -1228,12 +1253,25 @@ packages: '@azure/ms-rest-nodeauth@3.1.1': resolution: {integrity: sha512-UA/8dgLy3+ZiwJjAZHxL4MUB14fFQPkaAOZ94jsTW/Z6WmoOeny2+cLk0+dyIX/iH6qSrEWKwbStEeB970B9pA==} + '@azure/msal-browser@3.18.0': + resolution: {integrity: sha512-jvK5bDUWbpOaJt2Io/rjcaOVcUzkqkrCme/WntdV1SMUc67AiTcEdKuY6G/nMQ7N5Cfsk9SfpugflQwDku53yg==} + engines: {node: '>=0.8.0'} + + '@azure/msal-common@14.13.0': + resolution: {integrity: sha512-b4M/tqRzJ4jGU91BiwCsLTqChveUEyFK3qY2wGfZ0zBswIBZjAxopx5CYt5wzZFKuN15HqRDYXQbztttuIC3nA==} + engines: {node: '>=0.8.0'} + '@azure/msal-common@4.5.1': resolution: {integrity: sha512-/i5dXM+QAtO+6atYd5oHGBAx48EGSISkXNXViheliOQe+SIFMDo3gSq3lL54W0suOSAsVPws3XnTaIHlla0PIQ==} engines: {node: '>=0.8.0'} '@azure/msal-node@1.0.0-beta.6': resolution: {integrity: sha512-ZQI11Uz1j0HJohb9JZLRD8z0moVcPks1AFW4Q/Gcl67+QvH4aKEJti7fjCcipEEZYb/qzLSO8U6IZgPYytsiJQ==} + deprecated: A newer major version of this library is available. Please upgrade to the latest available version. + + '@azure/msal-node@2.10.0': + resolution: {integrity: sha512-JxsSE0464a8IA/+q5EHKmchwNyUFJHtCH00tSXsLaOddwLjG6yVvTH6lGgPcWMhO7YWUXj/XVgVgeE9kZtsPUQ==} + engines: {node: '>=16'} '@babel/code-frame@7.23.5': resolution: {integrity: sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==} @@ -3264,6 +3302,9 @@ packages: '@js-joda/core@3.2.0': resolution: {integrity: sha512-PMqgJ0sw5B7FKb2d5bWYIoxjri+QlW/Pys7+Rw82jSH0QN3rB05jZ/VrrsUdh1w4+i2kw9JOejXGq/KhDOX7Kg==} + '@js-joda/core@5.6.3': + resolution: {integrity: sha512-T1rRxzdqkEXcou0ZprN1q9yDRlvzCPLqmlNt5IIsGBzoEVgLCCYrKEwc84+TvsXuAc95VAZwtWD2zVsKPY4bcA==} + '@jsdoc/salty@0.2.7': resolution: {integrity: sha512-mh8LbS9d4Jq84KLw8pzho7XC2q2/IJGiJss3xwRoLD1A+EE16SjN4PfaG4jRCzKegTFLlN0Zd8SdUPE6XdoPFg==} engines: {node: '>=v12.0.0'} @@ -4843,6 +4884,9 @@ packages: '@tediousjs/connection-string@0.3.0': resolution: {integrity: sha512-d/keJiNKfpHo+GmSB8QcsAwBx8h+V1UbdozA5TD+eSLXprNY53JAYub47J9evsSKWDdNG5uVj0FiMozLKuzowQ==} + '@tediousjs/connection-string@0.5.0': + resolution: {integrity: sha512-7qSgZbincDDDFyRweCIEvZULFAw5iz/DeunhvuxpL31nfntX3P4Yd4HkHBRg9H8CdqY1e5WFN1PZIz/REL9MVQ==} + '@theguild/remark-mermaid@0.0.5': resolution: {integrity: sha512-e+ZIyJkEv9jabI4m7q29wZtZv+2iwPGsXJ2d46Zi7e+QcFudiyuqhLhHG/3gX3ZEB+hxTch+fpItyMS8jwbIcw==} peerDependencies: @@ -5043,6 +5087,9 @@ packages: '@types/ms@0.7.34': resolution: {integrity: sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g==} + '@types/mssql@9.1.5': + resolution: {integrity: sha512-Q9EsgXwuRoX5wvUSu24YfbKMbFChv7pZ/jeCzPkj47ehcuXYsBcfogwrtVFosSjinD4Q/MY2YPGk9Yy1cM2Ywg==} + '@types/mute-stream@0.0.4': resolution: {integrity: sha512-CPM9nzrCPPJHQNA9keH9CVkVI+WR5kMa+7XEs5jcGQ0VoAGnLv242w8lIVgwAEfmE4oufJRaTc9PNLQl0ioAow==} @@ -5157,6 +5204,9 @@ packages: '@types/react@18.2.78': resolution: {integrity: sha512-qOwdPnnitQY4xKlKayt42q5W5UQrSHjgoXNVEtxeqdITJ99k4VXJOP3vt8Rkm9HmgJpH50UNU+rlqfkfWOqp0A==} + '@types/readable-stream@4.0.15': + resolution: {integrity: sha512-oAZ3kw+kJFkEqyh7xORZOku1YAKvsFTogRY8kVl4vHpEKiDkfnSA/My8haRE7fvmix5Zyy+1pwzOi7yycGLBJw==} + '@types/rimraf@3.0.2': resolution: {integrity: sha512-F3OznnSLAUxFrCEu/L5PY8+ny8DtcFRjx7fZZ9bycvXRi3KPTRS9HOitGZwvPg0juRhXFWIeKX58cnX5YqLohQ==} @@ -5188,6 +5238,9 @@ packages: '@types/supertest@2.0.16': resolution: {integrity: sha512-6c2ogktZ06tr2ENoZivgm7YnprnhYE4ZoXGMY+oA7IuAf17M8FWvujXZGmxLv8y0PTyts4x5A+erSwVUFA8XSg==} + '@types/tedious@4.0.14': + resolution: {integrity: sha512-KHPsfX/FoVbUGbyYvk1q9MMQHLPeRZhRJZdO45Q4YjvFkv4hMNghCWTvy7rdKessBsmtz4euWCWAB6/tVpI1Iw==} + '@types/unist@2.0.10': resolution: {integrity: sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA==} @@ -6241,6 +6294,9 @@ packages: bl@5.1.0: resolution: {integrity: sha512-tv1ZJHLfTDnXE6tMHv73YgSJaWR2AFuPwMntBe7XL/GBFHnT0CLnsHMogfk5+GzCDC5ZWarSCYaIGATZt9dNsQ==} + bl@6.0.14: + resolution: {integrity: sha512-TJfbvGdL7KFGxTsEbsED7avqpFdY56q9IW0/aiytyheJzxST/+Io6cx/4Qx0K2/u0BPRDs65mjaQzYvMZeNocQ==} + bluebird@3.7.2: resolution: {integrity: sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==} @@ -6647,6 +6703,10 @@ packages: resolution: {integrity: sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==} engines: {node: '>=14'} + commander@11.1.0: + resolution: {integrity: sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==} + engines: {node: '>=16'} + commander@2.20.3: resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==} @@ -9010,6 +9070,9 @@ packages: js-base64@3.7.7: resolution: {integrity: sha512-7rCnleh0z2CkXhH67J8K1Ytz0b2Y+yxTPL+/KOJoa20hfnVQ/3/T6W/KflYI4bRHRagNeXeU2bkNGI3v1oS/lw==} + js-md4@0.3.2: + resolution: {integrity: sha512-/GDnfQYsltsjRswQhN9fhv3EMw2sCpUdrdxyWDOUK7eyD++r3gRhzgiQgc/x4MAv2i1iuQ4lxO5mvqM3vj4bwA==} + js-sdsl@4.4.2: resolution: {integrity: sha512-dwXFwByc/ajSV6m5bcKAPwe4yDDF6D614pxmIi5odytzxRlwqF6nwoiCek80Ixc7Cvma5awClxrzFtxCQvcM8w==} @@ -9276,7 +9339,6 @@ packages: libsql@0.3.18: resolution: {integrity: sha512-lvhKr7WV3NLWRbXkjn/MeKqXOAqWKU0PX9QYrvDh7fneukapj+iUQ4qgJASrQyxcCrEsClXCQiiK5W6OoYPAlA==} - cpu: [x64, arm64, wasm32] os: [darwin, linux, win32] lil-fp@1.4.5: @@ -10074,6 +10136,11 @@ packages: engines: {node: '>=0.8.0'} deprecated: This package is no longer supported. Please use @azure/msal-browser instead. + mssql@11.0.1: + resolution: {integrity: sha512-KlGNsugoT90enKlR8/G36H0kTxPthDhmtNUCwEHvgRza5Cjpjoj+P2X6eMpFUDN7pFrJZsKadL4x990G8RBE1w==} + engines: {node: '>=18'} + hasBin: true + mssql@7.3.5: resolution: {integrity: sha512-LTOSQ3k8yZTBfO/5XwH7zC6fDPBx1sYgMXZyP/k+ErWrhZN8faAvDq+/gMlm9DaFG9yaOipHedF5JSPV17EHNw==} engines: {node: '>=10'} @@ -11085,6 +11152,10 @@ packages: process-nextick-args@2.0.1: resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==} + process@0.11.10: + resolution: {integrity: sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==} + engines: {node: '>= 0.6.0'} + promise-inflight@1.0.1: resolution: {integrity: sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==} peerDependencies: @@ -11375,6 +11446,10 @@ packages: resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} engines: {node: '>= 6'} + readable-stream@4.5.2: + resolution: {integrity: sha512-yjavECdqeZ3GLXNgRXgeQEdz9fvDDkNKyHnbHRFtOr7/LcfgBcmct7t/ET+HaCTqfh06OzoAxrkN/IfjJBVe+g==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + readdirp@3.6.0: resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} engines: {node: '>=8.10.0'} @@ -12460,6 +12535,10 @@ packages: resolution: {integrity: sha512-GtFrO694x/7CRiUBt0AI4jrMtrkXV+ywifiOrDy4K0ufJLeKB4rgmPjy5Ws366fCaBaKlqQ9RnJ+sCJ1Jbd1lw==} engines: {node: '>= 10'} + tedious@18.2.4: + resolution: {integrity: sha512-+6Nzn/aURTQ+8OxLAJ8fKK5Fbb84HRTI3bHiAC3ZzBKrBg9BHtcHxjmlIni5Zn46hzKiZ5WrDMSwDH8oIYjV8w==} + engines: {node: '>=18'} + teeny-request@8.0.3: resolution: {integrity: sha512-jJZpA5He2y52yUhA7pyAGZlgQpcB+xLjcN0eUFxr9c8hP/H7uOXbBNVo/O0C/xVfJLJs680jvkFgVJEEvk9+ww==} engines: {node: '>=12'} @@ -14493,6 +14572,10 @@ snapshots: dependencies: tslib: 2.6.2 + '@azure/abort-controller@2.1.2': + dependencies: + tslib: 2.6.2 + '@azure/core-auth@1.5.0': dependencies: '@azure/abort-controller': 1.1.0 @@ -14511,6 +14594,18 @@ snapshots: transitivePeerDependencies: - supports-color + '@azure/core-client@1.9.2': + dependencies: + '@azure/abort-controller': 2.1.2 + '@azure/core-auth': 1.5.0 + '@azure/core-rest-pipeline': 1.13.0 + '@azure/core-tracing': 1.0.1 + '@azure/core-util': 1.6.1 + '@azure/logger': 1.0.4 + tslib: 2.6.2 + transitivePeerDependencies: + - supports-color + '@azure/core-http-compat@1.3.0': dependencies: '@azure/abort-controller': 1.1.0 @@ -14600,6 +14695,25 @@ snapshots: - debug - supports-color + '@azure/identity@4.3.0': + dependencies: + '@azure/abort-controller': 1.1.0 + '@azure/core-auth': 1.5.0 + '@azure/core-client': 1.9.2 + '@azure/core-rest-pipeline': 1.13.0 + '@azure/core-tracing': 1.0.1 + '@azure/core-util': 1.6.1 + '@azure/logger': 1.0.4 + '@azure/msal-browser': 3.18.0 + '@azure/msal-node': 2.10.0 + events: 3.3.0 + jws: 4.0.0 + open: 8.4.2 + stoppable: 1.1.0 + tslib: 2.6.2 + transitivePeerDependencies: + - supports-color + '@azure/keyvault-keys@4.7.2': dependencies: '@azure/abort-controller': 1.1.0 @@ -14644,6 +14758,12 @@ snapshots: - debug - encoding + '@azure/msal-browser@3.18.0': + dependencies: + '@azure/msal-common': 14.13.0 + + '@azure/msal-common@14.13.0': {} + '@azure/msal-common@4.5.1': dependencies: debug: 4.3.4(supports-color@8.1.1) @@ -14660,6 +14780,12 @@ snapshots: - debug - supports-color + '@azure/msal-node@2.10.0': + dependencies: + '@azure/msal-common': 14.13.0 + jsonwebtoken: 9.0.2 + uuid: 8.3.2 + '@babel/code-frame@7.23.5': dependencies: '@babel/highlight': 7.23.4 @@ -16866,6 +16992,8 @@ snapshots: '@js-joda/core@3.2.0': {} + '@js-joda/core@5.6.3': {} + '@jsdoc/salty@0.2.7': dependencies: lodash: 4.17.21 @@ -17086,9 +17214,9 @@ snapshots: mikro-orm: 5.9.7 reflect-metadata: 0.1.13 optionalDependencies: - '@mikro-orm/sqlite': 5.9.7(@mikro-orm/core@5.9.7)(better-sqlite3@9.6.0)(encoding@0.1.13)(mssql@7.3.5(encoding@0.1.13))(mysql2@3.9.7)(mysql@2.18.1)(pg@8.11.3) + '@mikro-orm/sqlite': 5.9.7(@mikro-orm/core@5.9.7)(better-sqlite3@9.6.0)(encoding@0.1.13)(mssql@11.0.1)(mysql2@3.9.7)(mysql@2.18.1)(pg@8.11.3) - '@mikro-orm/knex@5.9.7(@mikro-orm/core@5.9.7(@mikro-orm/sqlite@5.9.7))(better-sqlite3@9.6.0)(mssql@7.3.5(encoding@0.1.13))(mysql2@3.9.7)(mysql@2.18.1)(pg@8.11.3)(sqlite3@5.1.6(encoding@0.1.13))': + '@mikro-orm/knex@5.9.7(@mikro-orm/core@5.9.7(@mikro-orm/sqlite@5.9.7))(better-sqlite3@9.6.0)(mssql@11.0.1)(mysql2@3.9.7)(mysql@2.18.1)(pg@8.11.3)(sqlite3@5.1.6(encoding@0.1.13))': dependencies: '@mikro-orm/core': 5.9.7(@mikro-orm/sqlite@5.9.7) fs-extra: 11.1.1 @@ -17096,7 +17224,7 @@ snapshots: sqlstring: 2.3.3 optionalDependencies: better-sqlite3: 9.6.0 - mssql: 7.3.5(encoding@0.1.13) + mssql: 11.0.1 mysql: 2.18.1 mysql2: 3.9.7 pg: 8.11.3 @@ -17106,10 +17234,10 @@ snapshots: - supports-color - tedious - '@mikro-orm/sqlite@5.9.7(@mikro-orm/core@5.9.7)(better-sqlite3@9.6.0)(encoding@0.1.13)(mssql@7.3.5(encoding@0.1.13))(mysql2@3.9.7)(mysql@2.18.1)(pg@8.11.3)': + '@mikro-orm/sqlite@5.9.7(@mikro-orm/core@5.9.7)(better-sqlite3@9.6.0)(encoding@0.1.13)(mssql@11.0.1)(mysql2@3.9.7)(mysql@2.18.1)(pg@8.11.3)': dependencies: '@mikro-orm/core': 5.9.7(@mikro-orm/sqlite@5.9.7) - '@mikro-orm/knex': 5.9.7(@mikro-orm/core@5.9.7(@mikro-orm/sqlite@5.9.7))(better-sqlite3@9.6.0)(mssql@7.3.5(encoding@0.1.13))(mysql2@3.9.7)(mysql@2.18.1)(pg@8.11.3)(sqlite3@5.1.6(encoding@0.1.13)) + '@mikro-orm/knex': 5.9.7(@mikro-orm/core@5.9.7(@mikro-orm/sqlite@5.9.7))(better-sqlite3@9.6.0)(mssql@11.0.1)(mysql2@3.9.7)(mysql@2.18.1)(pg@8.11.3)(sqlite3@5.1.6(encoding@0.1.13)) fs-extra: 11.1.1 sqlite3: 5.1.6(encoding@0.1.13) sqlstring-sqlite: 0.1.1 @@ -17309,7 +17437,7 @@ snapshots: supports-color: 8.1.1 tslib: 2.6.2 - '@oclif/core@2.15.0(@swc/core@1.3.106(@swc/helpers@0.5.11))(@types/node@20.12.7)(typescript@5.4.5)': + '@oclif/core@2.15.0(@swc/core@1.3.106)(@types/node@20.12.7)(typescript@5.4.5)': dependencies: '@types/cli-progress': 3.11.5 ansi-escapes: 4.3.2 @@ -17334,7 +17462,7 @@ snapshots: strip-ansi: 6.0.1 supports-color: 8.1.1 supports-hyperlinks: 2.3.0 - ts-node: 10.9.2(@swc/core@1.3.106(@swc/helpers@0.5.11))(@types/node@20.12.7)(typescript@5.4.5) + ts-node: 10.9.2(@swc/core@1.3.106)(@types/node@20.12.7)(typescript@5.4.5) tslib: 2.6.2 widest-line: 3.1.0 wordwrap: 1.0.0 @@ -17355,19 +17483,19 @@ snapshots: '@oclif/linewrap@1.0.0': {} - '@oclif/plugin-help@5.2.20(@swc/core@1.3.106(@swc/helpers@0.5.11))(@types/node@20.12.7)(typescript@5.4.5)': + '@oclif/plugin-help@5.2.20(@swc/core@1.3.106)(@types/node@20.12.7)(typescript@5.4.5)': dependencies: - '@oclif/core': 2.15.0(@swc/core@1.3.106(@swc/helpers@0.5.11))(@types/node@20.12.7)(typescript@5.4.5) + '@oclif/core': 2.15.0(@swc/core@1.3.106)(@types/node@20.12.7)(typescript@5.4.5) transitivePeerDependencies: - '@swc/core' - '@swc/wasm' - '@types/node' - typescript - '@oclif/plugin-plugins@2.4.7(@swc/core@1.3.106(@swc/helpers@0.5.11))(@types/node@20.12.7)(typescript@5.4.5)': + '@oclif/plugin-plugins@2.4.7(@swc/core@1.3.106)(@types/node@20.12.7)(typescript@5.4.5)': dependencies: '@oclif/color': 1.0.13 - '@oclif/core': 2.15.0(@swc/core@1.3.106(@swc/helpers@0.5.11))(@types/node@20.12.7)(typescript@5.4.5) + '@oclif/core': 2.15.0(@swc/core@1.3.106)(@types/node@20.12.7)(typescript@5.4.5) chalk: 4.1.2 debug: 4.3.4(supports-color@8.1.1) fs-extra: 9.1.0 @@ -18728,6 +18856,8 @@ snapshots: '@tediousjs/connection-string@0.3.0': {} + '@tediousjs/connection-string@0.5.0': {} + '@theguild/remark-mermaid@0.0.5(react@18.3.1)': dependencies: mermaid: 10.6.0 @@ -18944,6 +19074,12 @@ snapshots: '@types/ms@0.7.34': {} + '@types/mssql@9.1.5': + dependencies: + '@types/node': 20.12.7 + '@types/tedious': 4.0.14 + tarn: 3.0.2 + '@types/mute-stream@0.0.4': dependencies: '@types/node': 20.12.7 @@ -19108,6 +19244,11 @@ snapshots: '@types/prop-types': 15.7.11 csstype: 3.1.3 + '@types/readable-stream@4.0.15': + dependencies: + '@types/node': 20.12.7 + safe-buffer: 5.1.2 + '@types/rimraf@3.0.2': dependencies: '@types/glob': 8.1.0 @@ -19151,6 +19292,10 @@ snapshots: dependencies: '@types/superagent': 8.1.3 + '@types/tedious@4.0.14': + dependencies: + '@types/node': 20.12.7 + '@types/unist@2.0.10': {} '@types/unist@3.0.2': {} @@ -19579,6 +19724,11 @@ snapshots: dependencies: tslib: 2.6.2 + '@xata.io/client@0.28.0(typescript@5.3.3)': + dependencies: + typescript: 5.3.3 + optional: true + '@xata.io/client@0.28.0(typescript@5.4.5)': dependencies: typescript: 5.4.5 @@ -20897,6 +21047,13 @@ snapshots: inherits: 2.0.4 readable-stream: 3.6.2 + bl@6.0.14: + dependencies: + '@types/readable-stream': 4.0.15 + buffer: 6.0.3 + inherits: 2.0.4 + readable-stream: 4.5.2 + bluebird@3.7.2: optional: true @@ -21418,6 +21575,8 @@ snapshots: commander@10.0.1: {} + commander@11.1.0: {} + commander@2.20.3: {} commander@4.1.1: {} @@ -22047,7 +22206,7 @@ snapshots: transitivePeerDependencies: - supports-color - drizzle-orm@0.30.9(@cloudflare/workers-types@4.20240117.0)(@libsql/client@0.6.0)(@opentelemetry/api@1.7.0)(@types/better-sqlite3@7.6.9)(@types/pg@8.11.0)(@types/react@18.2.78)(@xata.io/client@0.28.0(typescript@5.4.5))(better-sqlite3@9.6.0)(knex@2.5.1(better-sqlite3@9.6.0)(mysql2@3.9.7)(pg@8.11.3)(sqlite3@5.1.6(encoding@0.1.13)))(kysely@0.24.2)(mysql2@3.9.7)(pg@8.11.3)(postgres@3.4.3)(react@18.3.1)(sqlite3@5.1.6(encoding@0.1.13)): + drizzle-orm@0.30.9(@cloudflare/workers-types@4.20240117.0)(@libsql/client@0.6.0)(@opentelemetry/api@1.7.0)(@types/better-sqlite3@7.6.9)(@types/pg@8.11.0)(@types/react@18.2.78)(@xata.io/client@0.28.0(typescript@5.3.3))(better-sqlite3@9.6.0)(knex@2.5.1(better-sqlite3@9.6.0)(mysql2@3.9.7)(pg@8.11.3)(sqlite3@5.1.6))(kysely@0.24.2)(mysql2@3.9.7)(pg@8.11.3)(postgres@3.4.3)(react@18.3.1)(sqlite3@5.1.6): optionalDependencies: '@cloudflare/workers-types': 4.20240117.0 '@libsql/client': 0.6.0 @@ -22055,7 +22214,7 @@ snapshots: '@types/better-sqlite3': 7.6.9 '@types/pg': 8.11.0 '@types/react': 18.2.78 - '@xata.io/client': 0.28.0(typescript@5.4.5) + '@xata.io/client': 0.28.0(typescript@5.3.3) better-sqlite3: 9.6.0 knex: 2.5.1(better-sqlite3@9.6.0)(mysql2@3.9.7)(mysql@2.18.1)(pg@8.11.3)(sqlite3@5.1.6(encoding@0.1.13)) kysely: 0.24.2 @@ -22555,7 +22714,7 @@ snapshots: semver: 6.3.1 string.prototype.matchall: 4.0.10 - eslint-plugin-svelte@2.38.0(eslint@8.30.0)(svelte@4.2.9)(ts-node@10.9.2(@swc/core@1.3.106(@swc/helpers@0.5.11))(@types/node@20.11.7)(typescript@5.3.3)): + eslint-plugin-svelte@2.38.0(eslint@8.30.0)(svelte@4.2.9)(ts-node@10.9.2(@types/node@20.11.7)(typescript@5.3.3)): dependencies: '@eslint-community/eslint-utils': 4.4.0(eslint@8.30.0) '@jridgewell/sourcemap-codec': 1.4.15 @@ -22565,7 +22724,7 @@ snapshots: esutils: 2.0.3 known-css-properties: 0.30.0 postcss: 8.4.38 - postcss-load-config: 3.1.4(postcss@8.4.38)(ts-node@10.9.2(@swc/core@1.3.106(@swc/helpers@0.5.11))(@types/node@20.11.7)(typescript@5.3.3)) + postcss-load-config: 3.1.4(postcss@8.4.38)(ts-node@10.9.2(@types/node@20.11.7)(typescript@5.3.3)) postcss-safe-parser: 6.0.0(postcss@8.4.38) postcss-selector-parser: 6.0.16 semver: 7.6.0 @@ -22978,12 +23137,12 @@ snapshots: dependencies: format: 0.2.2 - fauna-shell@1.2.1(@swc/core@1.3.106(@swc/helpers@0.5.11))(@types/node@20.12.7)(encoding@0.1.13)(typescript@5.4.5): + fauna-shell@1.2.1(@swc/core@1.3.106)(@types/node@20.12.7)(encoding@0.1.13)(typescript@5.4.5): dependencies: '@inquirer/prompts': 3.3.2 - '@oclif/core': 2.15.0(@swc/core@1.3.106(@swc/helpers@0.5.11))(@types/node@20.12.7)(typescript@5.4.5) - '@oclif/plugin-help': 5.2.20(@swc/core@1.3.106(@swc/helpers@0.5.11))(@types/node@20.12.7)(typescript@5.4.5) - '@oclif/plugin-plugins': 2.4.7(@swc/core@1.3.106(@swc/helpers@0.5.11))(@types/node@20.12.7)(typescript@5.4.5) + '@oclif/core': 2.15.0(@swc/core@1.3.106)(@types/node@20.12.7)(typescript@5.4.5) + '@oclif/plugin-help': 5.2.20(@swc/core@1.3.106)(@types/node@20.12.7)(typescript@5.4.5) + '@oclif/plugin-plugins': 2.4.7(@swc/core@1.3.106)(@types/node@20.12.7)(typescript@5.4.5) chalk: 4.1.2 cli-table: 0.3.11 cli-ux: 4.9.3 @@ -24350,6 +24509,8 @@ snapshots: js-base64@3.7.7: {} + js-md4@0.3.2: {} + js-sdsl@4.4.2: {} js-stringify@1.0.2: {} @@ -25900,7 +26061,7 @@ snapshots: transitivePeerDependencies: - aws-crt - mongodb@6.3.0(@aws-sdk/credential-providers@3.499.0)(gcp-metadata@5.3.0(encoding@0.1.13))(socks@2.7.1): + mongodb@6.3.0(@aws-sdk/credential-providers@3.499.0)(gcp-metadata@5.3.0)(socks@2.7.1): dependencies: '@mongodb-js/saslprep': 1.1.4 bson: 6.2.0 @@ -25934,6 +26095,17 @@ snapshots: dependencies: tslib: 1.14.1 + mssql@11.0.1: + dependencies: + '@tediousjs/connection-string': 0.5.0 + commander: 11.1.0 + debug: 4.3.4(supports-color@8.1.1) + rfdc: 1.3.1 + tarn: 3.0.2 + tedious: 18.2.4 + transitivePeerDependencies: + - supports-color + mssql@7.3.5(encoding@0.1.13): dependencies: '@tediousjs/connection-string': 0.3.0 @@ -26751,30 +26923,30 @@ snapshots: camelcase-css: 2.0.1 postcss: 8.4.38 - postcss-load-config@3.1.4(postcss@8.4.38)(ts-node@10.9.2(@swc/core@1.3.106(@swc/helpers@0.5.11))(@types/node@20.11.7)(typescript@5.3.3)): + postcss-load-config@3.1.4(postcss@8.4.38)(ts-node@10.9.2(@types/node@20.11.7)(typescript@5.3.3)): dependencies: lilconfig: 2.1.0 yaml: 1.10.2 optionalDependencies: postcss: 8.4.38 - ts-node: 10.9.2(@swc/core@1.3.106(@swc/helpers@0.5.11))(@types/node@20.11.7)(typescript@5.3.3) + ts-node: 10.9.2(@types/node@20.11.7)(typescript@5.3.3) - postcss-load-config@4.0.2(postcss@8.4.38)(ts-node@10.9.2(@swc/core@1.3.106(@swc/helpers@0.5.11))(@types/node@20.12.7)(typescript@5.2.2)): + postcss-load-config@4.0.2(postcss@8.4.38)(ts-node@10.9.2(@types/node@20.11.7)(typescript@5.3.3)): dependencies: lilconfig: 3.1.1 yaml: 2.3.4 optionalDependencies: postcss: 8.4.38 - ts-node: 10.9.2(@swc/core@1.3.106(@swc/helpers@0.5.11))(@types/node@20.12.7)(typescript@5.2.2) + ts-node: 10.9.2(@types/node@20.11.7)(typescript@5.3.3) optional: true - postcss-load-config@4.0.2(postcss@8.4.38)(ts-node@10.9.2(@swc/core@1.3.106(@swc/helpers@0.5.11))(@types/node@20.12.7)(typescript@5.4.5)): + postcss-load-config@4.0.2(postcss@8.4.38)(ts-node@10.9.2(@types/node@20.12.7)(typescript@5.4.5)): dependencies: lilconfig: 3.1.1 yaml: 2.3.4 optionalDependencies: postcss: 8.4.38 - ts-node: 10.9.2(@swc/core@1.3.106(@swc/helpers@0.5.11))(@types/node@20.12.7)(typescript@5.4.5) + ts-node: 10.9.2(@swc/core@1.3.106)(@types/node@20.12.7)(typescript@5.4.5) postcss-merge-rules@6.0.4(postcss@8.4.38): dependencies: @@ -27102,6 +27274,8 @@ snapshots: process-nextick-args@2.0.1: {} + process@0.11.10: {} + promise-inflight@1.0.1: optional: true @@ -27495,6 +27669,14 @@ snapshots: string_decoder: 1.3.0 util-deprecate: 1.0.2 + readable-stream@4.5.2: + dependencies: + abort-controller: 3.0.0 + buffer: 6.0.3 + events: 3.3.0 + process: 0.11.10 + string_decoder: 1.3.0 + readdirp@3.6.0: dependencies: picomatch: 2.3.1 @@ -28608,7 +28790,7 @@ snapshots: - bufferutil - utf-8-validate - svelte-check@2.10.2(@babel/core@7.23.9)(postcss-load-config@4.0.2(postcss@8.4.38)(ts-node@10.9.2(@swc/core@1.3.106(@swc/helpers@0.5.11))(@types/node@20.12.7)(typescript@5.2.2)))(postcss@8.4.38)(pug@3.0.2)(sass@1.70.0)(svelte@4.2.9): + svelte-check@2.10.2(@babel/core@7.23.9)(postcss-load-config@4.0.2(postcss@8.4.38)(ts-node@10.9.2(@types/node@20.11.7)(typescript@5.3.3)))(postcss@8.4.38)(pug@3.0.2)(sass@1.70.0)(svelte@4.2.9): dependencies: '@jridgewell/trace-mapping': 0.3.22 chokidar: 3.5.3 @@ -28617,7 +28799,7 @@ snapshots: picocolors: 1.0.0 sade: 1.8.1 svelte: 4.2.9 - svelte-preprocess: 4.10.7(@babel/core@7.23.9)(postcss-load-config@4.0.2(postcss@8.4.38)(ts-node@10.9.2(@swc/core@1.3.106(@swc/helpers@0.5.11))(@types/node@20.12.7)(typescript@5.2.2)))(postcss@8.4.38)(pug@3.0.2)(sass@1.70.0)(svelte@4.2.9)(typescript@5.4.5) + svelte-preprocess: 4.10.7(@babel/core@7.23.9)(postcss-load-config@4.0.2(postcss@8.4.38)(ts-node@10.9.2(@types/node@20.11.7)(typescript@5.3.3)))(postcss@8.4.38)(pug@3.0.2)(sass@1.70.0)(svelte@4.2.9)(typescript@5.4.5) typescript: 5.4.5 transitivePeerDependencies: - '@babel/core' @@ -28631,7 +28813,7 @@ snapshots: - stylus - sugarss - svelte-check@3.6.3(@babel/core@7.23.9)(postcss-load-config@4.0.2(postcss@8.4.38)(ts-node@10.9.2(@swc/core@1.3.106(@swc/helpers@0.5.11))(@types/node@20.12.7)(typescript@5.4.5)))(postcss@8.4.38)(pug@3.0.2)(sass@1.70.0)(svelte@4.2.9): + svelte-check@3.6.3(@babel/core@7.23.9)(postcss-load-config@4.0.2(postcss@8.4.38)(ts-node@10.9.2(@types/node@20.11.7)(typescript@5.3.3)))(postcss@8.4.38)(pug@3.0.2)(sass@1.70.0)(svelte@4.2.9): dependencies: '@jridgewell/trace-mapping': 0.3.22 chokidar: 3.5.3 @@ -28640,7 +28822,7 @@ snapshots: picocolors: 1.0.0 sade: 1.8.1 svelte: 4.2.9 - svelte-preprocess: 5.1.3(@babel/core@7.23.9)(postcss-load-config@4.0.2(postcss@8.4.38)(ts-node@10.9.2(@swc/core@1.3.106(@swc/helpers@0.5.11))(@types/node@20.12.7)(typescript@5.4.5)))(postcss@8.4.38)(pug@3.0.2)(sass@1.70.0)(svelte@4.2.9)(typescript@5.4.5) + svelte-preprocess: 5.1.3(@babel/core@7.23.9)(postcss-load-config@4.0.2(postcss@8.4.38)(ts-node@10.9.2(@types/node@20.11.7)(typescript@5.3.3)))(postcss@8.4.38)(pug@3.0.2)(sass@1.70.0)(svelte@4.2.9)(typescript@5.4.5) typescript: 5.4.5 transitivePeerDependencies: - '@babel/core' @@ -28667,7 +28849,7 @@ snapshots: dependencies: svelte: 4.2.9 - svelte-preprocess@4.10.7(@babel/core@7.23.9)(postcss-load-config@4.0.2(postcss@8.4.38)(ts-node@10.9.2(@swc/core@1.3.106(@swc/helpers@0.5.11))(@types/node@20.12.7)(typescript@5.2.2)))(postcss@8.4.38)(pug@3.0.2)(sass@1.70.0)(svelte@4.2.9)(typescript@5.4.5): + svelte-preprocess@4.10.7(@babel/core@7.23.9)(postcss-load-config@4.0.2(postcss@8.4.38)(ts-node@10.9.2(@types/node@20.11.7)(typescript@5.3.3)))(postcss@8.4.38)(pug@3.0.2)(sass@1.70.0)(svelte@4.2.9)(typescript@5.4.5): dependencies: '@types/pug': 2.0.10 '@types/sass': 1.45.0 @@ -28679,12 +28861,12 @@ snapshots: optionalDependencies: '@babel/core': 7.23.9 postcss: 8.4.38 - postcss-load-config: 4.0.2(postcss@8.4.38)(ts-node@10.9.2(@swc/core@1.3.106(@swc/helpers@0.5.11))(@types/node@20.12.7)(typescript@5.2.2)) + postcss-load-config: 4.0.2(postcss@8.4.38)(ts-node@10.9.2(@types/node@20.11.7)(typescript@5.3.3)) pug: 3.0.2 sass: 1.70.0 typescript: 5.4.5 - svelte-preprocess@5.1.3(@babel/core@7.23.9)(postcss-load-config@4.0.2(postcss@8.4.38)(ts-node@10.9.2(@swc/core@1.3.106(@swc/helpers@0.5.11))(@types/node@20.12.7)(typescript@5.4.5)))(postcss@8.4.38)(pug@3.0.2)(sass@1.70.0)(svelte@4.2.9)(typescript@5.4.5): + svelte-preprocess@5.1.3(@babel/core@7.23.9)(postcss-load-config@4.0.2(postcss@8.4.38)(ts-node@10.9.2(@types/node@20.11.7)(typescript@5.3.3)))(postcss@8.4.38)(pug@3.0.2)(sass@1.70.0)(svelte@4.2.9)(typescript@5.4.5): dependencies: '@types/pug': 2.0.10 detect-indent: 6.1.0 @@ -28695,7 +28877,7 @@ snapshots: optionalDependencies: '@babel/core': 7.23.9 postcss: 8.4.38 - postcss-load-config: 4.0.2(postcss@8.4.38)(ts-node@10.9.2(@swc/core@1.3.106(@swc/helpers@0.5.11))(@types/node@20.12.7)(typescript@5.4.5)) + postcss-load-config: 4.0.2(postcss@8.4.38)(ts-node@10.9.2(@types/node@20.11.7)(typescript@5.3.3)) pug: 3.0.2 sass: 1.70.0 typescript: 5.4.5 @@ -28744,7 +28926,7 @@ snapshots: tabbable@6.2.0: {} - tailwindcss@3.4.3(ts-node@10.9.2(@swc/core@1.3.106(@swc/helpers@0.5.11))(@types/node@20.12.7)(typescript@5.4.5)): + tailwindcss@3.4.3(ts-node@10.9.2(@types/node@20.12.7)(typescript@5.4.5)): dependencies: '@alloc/quick-lru': 5.2.0 arg: 5.0.2 @@ -28763,7 +28945,7 @@ snapshots: postcss: 8.4.38 postcss-import: 15.1.0(postcss@8.4.38) postcss-js: 4.0.1(postcss@8.4.38) - postcss-load-config: 4.0.2(postcss@8.4.38)(ts-node@10.9.2(@swc/core@1.3.106(@swc/helpers@0.5.11))(@types/node@20.12.7)(typescript@5.4.5)) + postcss-load-config: 4.0.2(postcss@8.4.38)(ts-node@10.9.2(@types/node@20.12.7)(typescript@5.4.5)) postcss-nested: 6.0.1(postcss@8.4.38) postcss-selector-parser: 6.0.15 resolve: 1.22.8 @@ -28826,6 +29008,20 @@ snapshots: - encoding - supports-color + tedious@18.2.4: + dependencies: + '@azure/identity': 4.3.0 + '@azure/keyvault-keys': 4.7.2 + '@js-joda/core': 5.6.3 + '@types/node': 20.12.7 + bl: 6.0.14 + iconv-lite: 0.6.3 + js-md4: 0.3.2 + native-duplexpair: 1.0.0 + sprintf-js: 1.1.3 + transitivePeerDependencies: + - supports-color + teeny-request@8.0.3(encoding@0.1.13): dependencies: http-proxy-agent: 5.0.0 @@ -28994,28 +29190,7 @@ snapshots: '@ts-morph/common': 0.20.0 code-block-writer: 12.0.0 - ts-node@10.9.2(@swc/core@1.3.106(@swc/helpers@0.5.11))(@types/node@20.11.7)(typescript@5.3.3): - dependencies: - '@cspotcode/source-map-support': 0.8.1 - '@tsconfig/node10': 1.0.9 - '@tsconfig/node12': 1.0.11 - '@tsconfig/node14': 1.0.3 - '@tsconfig/node16': 1.0.4 - '@types/node': 20.11.7 - acorn: 8.11.3 - acorn-walk: 8.3.2 - arg: 4.1.3 - create-require: 1.1.1 - diff: 4.0.2 - make-error: 1.3.6 - typescript: 5.3.3 - v8-compile-cache-lib: 3.0.1 - yn: 3.1.1 - optionalDependencies: - '@swc/core': 1.3.106(@swc/helpers@0.5.11) - optional: true - - ts-node@10.9.2(@swc/core@1.3.106(@swc/helpers@0.5.11))(@types/node@20.12.7)(typescript@5.2.2): + ts-node@10.9.2(@swc/core@1.3.106)(@types/node@20.12.7)(typescript@5.4.5): dependencies: '@cspotcode/source-map-support': 0.8.1 '@tsconfig/node10': 1.0.9 @@ -29029,32 +29204,30 @@ snapshots: create-require: 1.1.1 diff: 4.0.2 make-error: 1.3.6 - typescript: 5.2.2 + typescript: 5.4.5 v8-compile-cache-lib: 3.0.1 yn: 3.1.1 optionalDependencies: '@swc/core': 1.3.106(@swc/helpers@0.5.11) - optional: true - ts-node@10.9.2(@swc/core@1.3.106(@swc/helpers@0.5.11))(@types/node@20.12.7)(typescript@5.4.5): + ts-node@10.9.2(@types/node@20.11.7)(typescript@5.3.3): dependencies: '@cspotcode/source-map-support': 0.8.1 '@tsconfig/node10': 1.0.9 '@tsconfig/node12': 1.0.11 '@tsconfig/node14': 1.0.3 '@tsconfig/node16': 1.0.4 - '@types/node': 20.12.7 + '@types/node': 20.11.7 acorn: 8.11.3 acorn-walk: 8.3.2 arg: 4.1.3 create-require: 1.1.1 diff: 4.0.2 make-error: 1.3.6 - typescript: 5.4.5 + typescript: 5.3.3 v8-compile-cache-lib: 3.0.1 yn: 3.1.1 - optionalDependencies: - '@swc/core': 1.3.106(@swc/helpers@0.5.11) + optional: true ts-pattern@5.0.5: {} @@ -29223,11 +29396,11 @@ snapshots: shiki: 0.14.7 typescript: 5.4.5 - typeorm-naming-strategies@4.1.0(typeorm@0.3.17(better-sqlite3@9.6.0)(ioredis@5.4.1)(mongodb@6.3.0(@aws-sdk/credential-providers@3.499.0)(gcp-metadata@5.3.0(encoding@0.1.13))(socks@2.7.1))(mssql@7.3.5(encoding@0.1.13))(mysql2@3.9.7)(pg@8.11.3)(redis@4.6.12)(sqlite3@5.1.6(encoding@0.1.13))(ts-node@10.9.2(@swc/core@1.3.106(@swc/helpers@0.5.11))(@types/node@20.12.7)(typescript@5.4.5))): + typeorm-naming-strategies@4.1.0(typeorm@0.3.17(ioredis@5.4.1)(mssql@7.3.5(encoding@0.1.13))(mysql2@3.9.7)(pg@8.11.3)(redis@4.6.12)(sqlite3@5.1.6(encoding@0.1.13))(ts-node@10.9.2(@types/node@20.11.7)(typescript@5.3.3))): dependencies: - typeorm: 0.3.17(better-sqlite3@9.6.0)(ioredis@5.4.1)(mongodb@6.3.0(@aws-sdk/credential-providers@3.499.0)(gcp-metadata@5.3.0(encoding@0.1.13))(socks@2.7.1))(mssql@7.3.5(encoding@0.1.13))(mysql2@3.9.7)(pg@8.11.3)(redis@4.6.12)(sqlite3@5.1.6(encoding@0.1.13))(ts-node@10.9.2(@swc/core@1.3.106(@swc/helpers@0.5.11))(@types/node@20.12.7)(typescript@5.4.5)) + typeorm: 0.3.17(ioredis@5.4.1)(mssql@7.3.5(encoding@0.1.13))(mysql2@3.9.7)(pg@8.11.3)(redis@4.6.12)(sqlite3@5.1.6(encoding@0.1.13))(ts-node@10.9.2(@types/node@20.11.7)(typescript@5.3.3)) - typeorm@0.3.17(better-sqlite3@9.6.0)(ioredis@5.4.1)(mongodb@6.3.0(@aws-sdk/credential-providers@3.499.0)(gcp-metadata@5.3.0(encoding@0.1.13))(socks@2.7.1))(mssql@7.3.5(encoding@0.1.13))(mysql2@3.9.7)(pg@8.11.3)(redis@4.6.12)(sqlite3@5.1.6(encoding@0.1.13))(ts-node@10.9.2(@swc/core@1.3.106(@swc/helpers@0.5.11))(@types/node@20.12.7)(typescript@5.4.5)): + typeorm@0.3.17(ioredis@5.4.1)(mssql@7.3.5(encoding@0.1.13))(mysql2@3.9.7)(pg@8.11.3)(redis@4.6.12)(sqlite3@5.1.6(encoding@0.1.13))(ts-node@10.9.2(@types/node@20.11.7)(typescript@5.3.3)): dependencies: '@sqltools/formatter': 1.2.5 app-root-path: 3.1.0 @@ -29245,15 +29418,13 @@ snapshots: uuid: 9.0.1 yargs: 17.7.2 optionalDependencies: - better-sqlite3: 9.6.0 ioredis: 5.4.1 - mongodb: 6.3.0(@aws-sdk/credential-providers@3.499.0)(gcp-metadata@5.3.0(encoding@0.1.13))(socks@2.7.1) mssql: 7.3.5(encoding@0.1.13) mysql2: 3.9.7 pg: 8.11.3 redis: 4.6.12 sqlite3: 5.1.6(encoding@0.1.13) - ts-node: 10.9.2(@swc/core@1.3.106(@swc/helpers@0.5.11))(@types/node@20.12.7)(typescript@5.4.5) + ts-node: 10.9.2(@types/node@20.11.7)(typescript@5.3.3) transitivePeerDependencies: - supports-color @@ -29465,7 +29636,7 @@ snapshots: webpack-sources: 3.2.3 webpack-virtual-modules: 0.6.1 - unstorage@1.10.1(@azure/data-tables@13.2.2)(@azure/identity@1.5.2)(@upstash/redis@1.28.2)(@vercel/kv@1.0.1): + unstorage@1.10.1(@azure/data-tables@13.2.2)(@upstash/redis@1.28.2): dependencies: anymatch: 3.1.3 chokidar: 3.5.3 @@ -29480,13 +29651,11 @@ snapshots: ufo: 1.3.2 optionalDependencies: '@azure/data-tables': 13.2.2 - '@azure/identity': 1.5.2(debug@4.3.4) '@upstash/redis': 1.28.2 - '@vercel/kv': 1.0.1 transitivePeerDependencies: - supports-color - unstorage@1.10.2(@azure/data-tables@13.2.2)(@azure/identity@1.5.2)(@upstash/redis@1.28.2)(@vercel/kv@1.0.1)(ioredis@5.4.1): + unstorage@1.10.2(@azure/data-tables@13.2.2)(@azure/identity@4.3.0)(@vercel/kv@1.0.1)(ioredis@5.4.1): dependencies: anymatch: 3.1.3 chokidar: 3.6.0 @@ -29500,8 +29669,7 @@ snapshots: ufo: 1.5.3 optionalDependencies: '@azure/data-tables': 13.2.2 - '@azure/identity': 1.5.2(debug@4.3.4) - '@upstash/redis': 1.28.2 + '@azure/identity': 4.3.0 '@vercel/kv': 1.0.1 ioredis: 5.4.1 transitivePeerDependencies: diff --git a/turbo.json b/turbo.json index 991e8123bb..d4dd3a5e72 100644 --- a/turbo.json +++ b/turbo.json @@ -93,6 +93,7 @@ "@auth/prisma-adapter#build", "@auth/sequelize-adapter#build", "@auth/solid-start#build", + "@auth/sqlserver-adapter#build", "@auth/supabase-adapter#build", "@auth/surrealdb-adapter#build", "@auth/sveltekit#build", From 2bd81d307d31d2c01917594b7070bd5860d52762 Mon Sep 17 00:00:00 2001 From: Peter Budai Date: Sat, 17 Aug 2024 13:30:55 +0200 Subject: [PATCH 2/5] Update script to latest image --- packages/adapter-sqlserver/test/test.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/adapter-sqlserver/test/test.sh b/packages/adapter-sqlserver/test/test.sh index b7d7c5c112..c595e54a44 100755 --- a/packages/adapter-sqlserver/test/test.sh +++ b/packages/adapter-sqlserver/test/test.sh @@ -14,8 +14,8 @@ docker run -d --rm \ echo "waiting 5s for db to start..." sleep 10 -docker exec ${CONTAINER_NAME} /opt/mssql-tools/bin/sqlcmd -S localhost -U sa -P Authjs!password -d master -Q "CREATE DATABASE [${DATABASE_NAME}]" -docker exec ${CONTAINER_NAME} /opt/mssql-tools/bin/sqlcmd -S localhost -U sa -P Authjs!password -d ${DATABASE_NAME} -i /home/schema.sql +docker exec ${CONTAINER_NAME} /opt/mssql-tools18/bin/sqlcmd -C -S localhost -U sa -P Authjs!password -d master -Q "CREATE DATABASE [${DATABASE_NAME}]" +docker exec ${CONTAINER_NAME} /opt/mssql-tools18/bin/sqlcmd -C -S localhost -U sa -P Authjs!password -d ${DATABASE_NAME} -i /home/schema.sql # Always stop container, but exit with 1 when tests are failing if vitest run -c ../utils/vitest.config.ts; then From df00310356a445f56772181a3efc08f22ec55731 Mon Sep 17 00:00:00 2001 From: Peter Budai Date: Sat, 17 Aug 2024 13:33:00 +0200 Subject: [PATCH 3/5] Simplify stored procedures --- packages/adapter-sqlserver/schema.sql | 113 +++++++++----------------- 1 file changed, 38 insertions(+), 75 deletions(-) diff --git a/packages/adapter-sqlserver/schema.sql b/packages/adapter-sqlserver/schema.sql index c3a1f90cb5..7c7c9d5eba 100644 --- a/packages/adapter-sqlserver/schema.sql +++ b/packages/adapter-sqlserver/schema.sql @@ -209,11 +209,6 @@ CREATE OR ALTER PROCEDURE dbo.create_user AS BEGIN - DECLARE @new_id TABLE - ( - id UNIQUEIDENTIFIER - ); - INSERT INTO [users] ( [name], @@ -221,22 +216,15 @@ BEGIN [emailVerified], [image] ) - OUTPUT INSERTED.id - INTO @new_id + OUTPUT + INSERTED.[id], + INSERTED.[name], + INSERTED.[email], + INSERTED.[emailVerified], + INSERTED.[image] VALUES (@name, @email, @emailVerified, @image); - -- only return IUser fields - SELECT - [id], - [name], - [email], - [emailVerified], - [image] - FROM [users] - WHERE [id] = - (SELECT TOP 1 id FROM @new_id); - END GO @@ -296,15 +284,12 @@ BEGIN [email] = COALESCE(@email, [email]), [emailVerified] = COALESCE(@emailVerified, [emailVerified]), [image] = COALESCE(@image, [image]) - WHERE [id] = @id; - - SELECT - [id], - [name], - [email], - [emailVerified], - [image] - FROM [users] + OUTPUT + INSERTED.[id], + INSERTED.[name], + INSERTED.[email], + INSERTED.[emailVerified], + INSERTED.[image] WHERE [id] = @id; END @@ -325,11 +310,6 @@ CREATE OR ALTER PROCEDURE dbo.link_account_to_user AS BEGIN - DECLARE @new_id TABLE - ( - id UNIQUEIDENTIFIER - ); - INSERT INTO [accounts] ( [provider], @@ -344,29 +324,23 @@ BEGIN [session_state], [userId] ) - OUTPUT INSERTED.id - INTO @new_id + OUTPUT + INSERTED.[id], + INSERTED.[userId], + INSERTED.[type], + INSERTED.[provider], + INSERTED.[providerAccountId], + INSERTED.[refresh_token], + INSERTED.[access_token], + INSERTED.[expires_at], + INSERTED.[token_type], + INSERTED.[scope], + INSERTED.[id_token], + INSERTED.[session_state] VALUES (@provider, @type, @providerAccountId, @refresh_token, @token_type, @scope, @expires_at, @access_token, @id_token, @session_state, @userId); - SELECT - [id], - [userId], - [type], - [provider], - [providerAccountId], - [refresh_token], - [access_token], - [expires_at], - [token_type], - [scope], - [id_token], - [session_state] - FROM [accounts] - WHERE [id] = - (SELECT TOP 1 id FROM @new_id); - END GO @@ -377,31 +351,20 @@ CREATE OR ALTER PROCEDURE dbo.create_session_for_user AS BEGIN - DECLARE @new_id TABLE - ( - id UNIQUEIDENTIFIER - ); - INSERT INTO [sessions] ( [sessionToken], [userId], [expires] ) - OUTPUT INSERTED.id - INTO @new_id + OUTPUT + INSERTED.[id], + INSERTED.[sessionToken], + INSERTED.[userId], + INSERTED.[expires] VALUES (@sessionToken, @userId, @expires); - - SELECT - [sessionToken], - [userId], - [expires] - FROM [sessions] - WHERE [id] = - (SELECT TOP 1 id FROM @new_id); - END GO @@ -473,16 +436,13 @@ BEGIN [token], [expires] ) + OUTPUT + INSERTED.[identifier], + INSERTED.[token], + INSERTED.[expires] VALUES (@identifier, @token, @expires); - SELECT - [identifier], - [token], - [expires] - FROM [verification_tokens] - WHERE [identifier] = @identifier AND [token] = @token; - END GO @@ -493,7 +453,10 @@ AS BEGIN DELETE FROM [verification_tokens] - OUTPUT DELETED.identifier, DELETED.token, DELETED.expires + OUTPUT + DELETED.[identifier], + DELETED.[token], + DELETED.[expires] WHERE [identifier] = @identifier AND [token] = @token; END From 26c11e672fb495b6b0477dfb4ecd479348d94cbf Mon Sep 17 00:00:00 2001 From: Peter Budai Date: Sat, 17 Aug 2024 17:27:20 +0200 Subject: [PATCH 4/5] Add WebAuthn tables, procedures and tests --- packages/adapter-sqlserver/schema.sql | 145 +++++++++++++++++- packages/adapter-sqlserver/src/index.ts | 82 ++++++++++ packages/adapter-sqlserver/test/index.test.ts | 10 ++ packages/adapter-sqlserver/test/test.sh | 2 +- 4 files changed, 237 insertions(+), 2 deletions(-) diff --git a/packages/adapter-sqlserver/schema.sql b/packages/adapter-sqlserver/schema.sql index 7c7c9d5eba..b6afea4475 100644 --- a/packages/adapter-sqlserver/schema.sql +++ b/packages/adapter-sqlserver/schema.sql @@ -201,6 +201,48 @@ BEGIN END GO +-- AUTHENTICATOR table +IF NOT EXISTS + (SELECT 1 + FROM sys.objects + WHERE object_id = OBJECT_ID(N'[authenticators]') + AND type IN ( N'U' ) + ) +BEGIN + CREATE TABLE [authenticators] + ( + [credentialID] NVARCHAR(100) NOT NULL, + INDEX [ix_authenticators_credentialId] ([credentialId]), + [userId] UNIQUEIDENTIFIER NOT NULL + CONSTRAINT [fk_authenticators_user_id] FOREIGN KEY REFERENCES [dbo].[users]([id]), + [providerAccountId] NVARCHAR(100) NOT NULL, + [credentialPublicKey] VARCHAR(1000) NOT NULL, + [counter] INT NOT NULL, + [credentialDeviceType] NVARCHAR(100) NOT NULL, + [credentialBackedUp] BIT NOT NULL, + [transports] NVARCHAR(1000) NOT NULL + ); +END +GO + +-- PK index and constraint +IF NOT EXISTS + (SELECT 1 + FROM sys.indexes + WHERE object_id = OBJECT_ID(N'[authenticators]') + AND name = N'pk_authenticators' +) +BEGIN + ALTER TABLE [authenticators] + ADD CONSTRAINT [pk_authenticators] + PRIMARY KEY CLUSTERED ( + [userId] ASC, + [credentialID] ASC + ) + WITH (STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ONLINE = OFF) ON [PRIMARY]; +END +GO + CREATE OR ALTER PROCEDURE dbo.create_user @name NVARCHAR(100), @email NVARCHAR(100), @@ -472,4 +514,105 @@ BEGIN WHERE [providerAccountId] = @providerAccountId AND [provider] = @provider; END -GO \ No newline at end of file +GO + +CREATE OR ALTER PROCEDURE dbo.get_accounts_by_provider + @providerAccountId NVARCHAR(100), + @provider NVARCHAR(100) +AS +BEGIN + + SELECT + * + FROM [accounts] + WHERE [providerAccountId] = @providerAccountId AND [provider] = @provider; + +END +GO + +CREATE OR ALTER PROCEDURE dbo.create_authenticator + @credentialID NVARCHAR(100), + @userId UNIQUEIDENTIFIER, + @providerAccountId NVARCHAR(100), + @credentialPublicKey VARCHAR(1000), + @counter INT, + @credentialDeviceType NVARCHAR(100), + @credentialBackedUp BIT, + @transports NVARCHAR(1000) +AS +BEGIN + + INSERT INTO [authenticators] + ( + [credentialID], + [userId], + [providerAccountId], + [credentialPublicKey], + [counter], + [credentialDeviceType], + [credentialBackedUp], + [transports] + ) + OUTPUT + INSERTED.[credentialID], + INSERTED.[userId], + INSERTED.[providerAccountId], + INSERTED.[credentialPublicKey], + INSERTED.[counter], + INSERTED.[credentialDeviceType], + INSERTED.[credentialBackedUp], + INSERTED.[transports] + VALUES + (@credentialID, @userId, @providerAccountId, @credentialPublicKey, @counter, + @credentialDeviceType, @credentialBackedUp, @transports); + +END +GO + +CREATE OR ALTER PROCEDURE dbo.get_authenticator + @credentialID NVARCHAR(100) +AS +BEGIN + + SELECT + * + FROM [authenticators] + WHERE [credentialID] = @credentialID; + +END +GO + +CREATE OR ALTER PROCEDURE dbo.list_authenticators_by_user_id + @userId UNIQUEIDENTIFIER +AS +BEGIN + + SELECT + * + FROM [authenticators] + WHERE [userId] = @userId; + +END +GO + +CREATE OR ALTER PROCEDURE dbo.update_authenticator_counter + @credentialID NVARCHAR(100), + @counter INT +AS +BEGIN + + UPDATE [authenticators] + SET + [counter] = @counter + OUTPUT + INSERTED.[credentialID], + INSERTED.[userId], + INSERTED.[providerAccountId], + INSERTED.[credentialPublicKey], + INSERTED.[counter], + INSERTED.[credentialDeviceType], + INSERTED.[credentialBackedUp], + INSERTED.[transports] + WHERE [credentialID] = @credentialID; + +END \ No newline at end of file diff --git a/packages/adapter-sqlserver/src/index.ts b/packages/adapter-sqlserver/src/index.ts index efa14c300d..4136b75581 100644 --- a/packages/adapter-sqlserver/src/index.ts +++ b/packages/adapter-sqlserver/src/index.ts @@ -21,6 +21,7 @@ import type { AdapterAccount, AdapterSession, VerificationToken, + AdapterAuthenticator, } from "@auth/core/adapters" import sql from "mssql" @@ -195,6 +196,87 @@ export default function TSqlAdapter(connection: sql.ConnectionPool): Adapter { "dbo.use_verification_token" ) + return result.recordset[0] ?? null + }, + async getAccount(providerAccountId, provider) { + const request = conn.request() + request.input("providerAccountId", sql.VarChar, providerAccountId) + request.input("provider", sql.VarChar, provider) + const result = await request.execute( + "dbo.get_accounts_by_provider" + ) + + return result.recordset[0] ? mapExpiresAt(result.recordset[0]) : null + }, + + async createAuthenticator(authenticator) { + const request = conn.request() + request.input("credentialID", sql.VarChar, authenticator.credentialID) + request.input("userId", sql.VarChar, authenticator.userId) + request.input( + "providerAccountId", + sql.VarChar, + authenticator.providerAccountId + ) + request.input( + "credentialPublicKey", + sql.VarChar, + authenticator.credentialPublicKey + ) + request.input("counter", sql.Int, authenticator.counter) + request.input( + "credentialDeviceType", + sql.VarChar, + authenticator.credentialDeviceType + ) + request.input( + "credentialBackedUp", + sql.Bit, + authenticator.credentialBackedUp + ) + request.input("transports", sql.VarChar, authenticator.transports) + + const result = await request.execute( + "dbo.create_authenticator" + ) + + return { ...result.recordset[0] } + }, + + async getAuthenticator(credentialId) { + const request = conn.request() + request.input("credentialId", sql.VarChar, credentialId) + const result = await request.execute( + "dbo.get_authenticator" + ) + + return result.recordset[0] ?? null + }, + + async listAuthenticatorsByUserId(userId) { + const request = conn.request() + request.input("userId", sql.UniqueIdentifier, userId) + try { + const result = await request.execute( + "dbo.list_authenticators_by_user_id" + ) + return result.recordset ?? [] + } catch (_) { + // if incoming userId is not a valid GUID, return empty array + return [] + } + }, + + async updateAuthenticatorCounter(credentialID: string, newCounter: number) { + const request = conn.request() + request.input("credentialID", sql.VarChar, credentialID) + request.input("counter", sql.Int, newCounter) + const result = await request.execute( + "dbo.update_authenticator_counter" + ) + + if (!result.recordset[0]) throw new Error("Authenticator not found.") + return result.recordset[0] ?? null }, } diff --git a/packages/adapter-sqlserver/test/index.test.ts b/packages/adapter-sqlserver/test/index.test.ts index ba41f7bda7..4eef0d15f2 100644 --- a/packages/adapter-sqlserver/test/index.test.ts +++ b/packages/adapter-sqlserver/test/index.test.ts @@ -22,6 +22,7 @@ const client = new sql.ConnectionPool({ runBasicTests({ adapter: SqlServerAdapter(client), + testWebAuthnMethods: true, db: { connect: async () => { await client.connect() @@ -62,5 +63,14 @@ runBasicTests({ ) return result.recordset[0] ?? null }, + authenticator: async (credentialId) => { + const result = await client + .request() + .input("credentialId", credentialId) + .query( + "select * from authenticators where credentialID = @credentialId " + ) + return result.recordset[0] ?? null + }, }, }) diff --git a/packages/adapter-sqlserver/test/test.sh b/packages/adapter-sqlserver/test/test.sh index c595e54a44..282ee87d9e 100755 --- a/packages/adapter-sqlserver/test/test.sh +++ b/packages/adapter-sqlserver/test/test.sh @@ -11,7 +11,7 @@ docker run -d --rm \ -v "$(pwd)"/schema.sql:/home/schema.sql \ mcr.microsoft.com/mssql/server:2022-latest -echo "waiting 5s for db to start..." +echo "waiting 10s for db to start..." sleep 10 docker exec ${CONTAINER_NAME} /opt/mssql-tools18/bin/sqlcmd -C -S localhost -U sa -P Authjs!password -d master -Q "CREATE DATABASE [${DATABASE_NAME}]" From c6461f874ea141d92dfe64495f4823bd780759e8 Mon Sep 17 00:00:00 2001 From: Peter Budai Date: Sat, 17 Aug 2024 22:07:26 +0200 Subject: [PATCH 5/5] Simplify schema, update docs --- .../getting-started/adapters/sqlserver.mdx | 382 +++++++++--------- packages/adapter-sqlserver/README.md | 6 +- packages/adapter-sqlserver/schema.sql | 180 ++------- 3 files changed, 213 insertions(+), 355 deletions(-) diff --git a/docs/pages/getting-started/adapters/sqlserver.mdx b/docs/pages/getting-started/adapters/sqlserver.mdx index dc874242bd..2216f80500 100644 --- a/docs/pages/getting-started/adapters/sqlserver.mdx +++ b/docs/pages/getting-started/adapters/sqlserver.mdx @@ -76,7 +76,9 @@ IF NOT EXISTS BEGIN CREATE TABLE [users] ( - [id] UNIQUEIDENTIFIER NOT NULL CONSTRAINT [df_users_id] DEFAULT NEWSEQUENTIALID(), + [id] UNIQUEIDENTIFIER NOT NULL + CONSTRAINT [df_users_id] DEFAULT NEWSEQUENTIALID() + CONSTRAINT [pk_users] PRIMARY KEY CLUSTERED ([id]), [name] NVARCHAR(100) NULL, [email] NVARCHAR(100) NOT NULL, [emailVerified] DATETIME2 NULL, @@ -85,23 +87,6 @@ BEGIN END GO --- PK constraint and index -IF NOT EXISTS - (SELECT 1 - FROM sys.indexes - WHERE object_id = OBJECT_ID(N'[users]') - AND name = N'pk_users' -) -BEGIN - ALTER TABLE [users] - ADD CONSTRAINT [pk_users] - PRIMARY KEY CLUSTERED ( - [id] ASC - ) - WITH (STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ONLINE = OFF) ON [PRIMARY]; -END -GO - -- ACCOUNTS table IF NOT EXISTS (SELECT 1 @@ -112,8 +97,12 @@ IF NOT EXISTS BEGIN CREATE TABLE [accounts] ( - [id] UNIQUEIDENTIFIER NOT NULL CONSTRAINT [df_accounts_id] DEFAULT NEWSEQUENTIALID(), - [userId] UNIQUEIDENTIFIER NOT NULL, + [id] UNIQUEIDENTIFIER NOT NULL + CONSTRAINT [df_accounts_id] DEFAULT NEWSEQUENTIALID() + CONSTRAINT [pk_accounts] PRIMARY KEY CLUSTERED ([id]), + [userId] UNIQUEIDENTIFIER NOT NULL + CONSTRAINT [fk_accounts_users] FOREIGN KEY ([userId]) + REFERENCES [users] ([id]) ON DELETE CASCADE, [type] NVARCHAR(100) NOT NULL, [provider] NVARCHAR(100) NOT NULL, [providerAccountId] NVARCHAR(100) NOT NULL, @@ -123,52 +112,10 @@ BEGIN [token_type] NVARCHAR(100) NULL, [scope] NVARCHAR(100) NULL, [id_token] VARCHAR(8000) NULL, - [session_state] NVARCHAR(100) NULL - ); -END -GO - --- PK constraint and index -IF NOT EXISTS - (SELECT 1 - FROM sys.indexes - WHERE object_id = OBJECT_ID(N'[accounts]') - AND name = N'pk_accounts' -) -BEGIN - ALTER TABLE [accounts] - ADD CONSTRAINT [pk_accounts] - PRIMARY KEY CLUSTERED ( - [id] ASC - ) - WITH (STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ONLINE = OFF) ON [PRIMARY]; -END -GO - --- FK index -IF NOT EXISTS - (SELECT 1 - FROM sys.indexes - WHERE object_id = OBJECT_ID(N'[accounts]') - AND name = N'ix_accounts_users' -) -BEGIN - CREATE INDEX [ix_accounts_users] ON [accounts] (userId); -END -GO + [session_state] NVARCHAR(100) NULL, --- FK constraint -IF NOT EXISTS - (SELECT 1 - FROM sys.foreign_keys - WHERE parent_object_id = OBJECT_ID(N'[accounts]') - AND name = N'fk_accounts_users' -) -BEGIN - ALTER TABLE [accounts] WITH CHECK - ADD CONSTRAINT [fk_accounts_users] - FOREIGN KEY ([userId]) - REFERENCES [users] ([id]) ON DELETE CASCADE; + INDEX [ix_accounts_users] (userId) + ); END GO @@ -182,55 +129,17 @@ IF NOT EXISTS BEGIN CREATE TABLE [sessions] ( - [id] UNIQUEIDENTIFIER NOT NULL CONSTRAINT [df_sessions_id] DEFAULT NEWSEQUENTIALID(), + [id] UNIQUEIDENTIFIER NOT NULL + CONSTRAINT [df_sessions_id] DEFAULT NEWSEQUENTIALID() + CONSTRAINT [pk_sessions] PRIMARY KEY CLUSTERED ([id]), [expires] DATETIME2 NOT NULL, - [userId] UNIQUEIDENTIFIER NOT NULL, - [sessionToken] VARCHAR(8000) NULL - ); -END -GO - --- PK index and constraint -IF NOT EXISTS - (SELECT 1 - FROM sys.indexes - WHERE object_id = OBJECT_ID(N'[sessions]') - AND name = N'pk_sessions' -) -BEGIN - ALTER TABLE [sessions] - ADD CONSTRAINT [pk_sessions] - PRIMARY KEY CLUSTERED ( - [id] ASC - ) - WITH (STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ONLINE = OFF) ON [PRIMARY]; -END -GO - --- FK index -IF NOT EXISTS - (SELECT 1 - FROM sys.indexes - WHERE object_id = OBJECT_ID(N'[sessions]') - AND name = N'ix_sessions_users' -) -BEGIN - CREATE INDEX [ix_sessions_users] ON [sessions] (userId) -END -GO + [userId] UNIQUEIDENTIFIER NOT NULL + CONSTRAINT [fk_sessions_users] FOREIGN KEY ([userId]) + REFERENCES [users] ([id]) ON DELETE CASCADE, + [sessionToken] VARCHAR(8000) NULL, --- FK constraint -IF NOT EXISTS - (SELECT 1 - FROM sys.foreign_keys - WHERE parent_object_id = OBJECT_ID(N'[sessions]') - AND name = N'fk_sessions_users' -) -BEGIN - ALTER TABLE [sessions] WITH CHECK - ADD CONSTRAINT [fk_sessions_users] - FOREIGN KEY ([userId]) - REFERENCES [users] ([id]) ON DELETE CASCADE; + INDEX [ix_sessions_users] (userId) + ); END GO @@ -244,28 +153,37 @@ IF NOT EXISTS BEGIN CREATE TABLE [verification_tokens] ( - [identifier] NVARCHAR(100) NOT NULL, + [identifier] NVARCHAR(100) NOT NULL + CONSTRAINT [pk_verification_tokens] PRIMARY KEY CLUSTERED ([identifier], [token]), [token] VARCHAR(700) NOT NULL, [expires] DATETIME2 NOT NULL ); END GO --- PK index and constraint +-- AUTHENTICATOR table IF NOT EXISTS (SELECT 1 - FROM sys.indexes - WHERE object_id = OBJECT_ID(N'[verification_tokens]') - AND name = N'pk_verification_tokens' -) + FROM sys.objects + WHERE object_id = OBJECT_ID(N'[authenticators]') + AND type IN ( N'U' ) + ) BEGIN - ALTER TABLE [verification_tokens] - ADD CONSTRAINT [pk_verification_tokens] - PRIMARY KEY CLUSTERED ( - [identifier] ASC, - [token] ASC - ) - WITH (STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ONLINE = OFF) ON [PRIMARY]; + CREATE TABLE [authenticators] + ( + [credentialID] NVARCHAR(100) NOT NULL + CONSTRAINT [pk_authenticators] PRIMARY KEY CLUSTERED ([userId], [credentialID]), + [userId] UNIQUEIDENTIFIER NOT NULL + CONSTRAINT [fk_authenticators_user_id] FOREIGN KEY REFERENCES [dbo].[users]([id]), + [providerAccountId] NVARCHAR(100) NOT NULL, + [credentialPublicKey] VARCHAR(1000) NOT NULL, + [counter] INT NOT NULL, + [credentialDeviceType] NVARCHAR(100) NOT NULL, + [credentialBackedUp] BIT NOT NULL, + [transports] NVARCHAR(1000) NOT NULL, + + INDEX [ix_authenticators_credentialId] ([credentialId]), + ); END GO @@ -277,11 +195,6 @@ CREATE OR ALTER PROCEDURE dbo.create_user AS BEGIN - DECLARE @new_id TABLE - ( - id UNIQUEIDENTIFIER - ); - INSERT INTO [users] ( [name], @@ -289,22 +202,15 @@ BEGIN [emailVerified], [image] ) - OUTPUT INSERTED.id - INTO @new_id + OUTPUT + INSERTED.[id], + INSERTED.[name], + INSERTED.[email], + INSERTED.[emailVerified], + INSERTED.[image] VALUES (@name, @email, @emailVerified, @image); - -- only return IUser fields - SELECT - [id], - [name], - [email], - [emailVerified], - [image] - FROM [users] - WHERE [id] = - (SELECT TOP 1 id FROM @new_id); - END GO @@ -364,15 +270,12 @@ BEGIN [email] = COALESCE(@email, [email]), [emailVerified] = COALESCE(@emailVerified, [emailVerified]), [image] = COALESCE(@image, [image]) - WHERE [id] = @id; - - SELECT - [id], - [name], - [email], - [emailVerified], - [image] - FROM [users] + OUTPUT + INSERTED.[id], + INSERTED.[name], + INSERTED.[email], + INSERTED.[emailVerified], + INSERTED.[image] WHERE [id] = @id; END @@ -393,11 +296,6 @@ CREATE OR ALTER PROCEDURE dbo.link_account_to_user AS BEGIN - DECLARE @new_id TABLE - ( - id UNIQUEIDENTIFIER - ); - INSERT INTO [accounts] ( [provider], @@ -412,29 +310,23 @@ BEGIN [session_state], [userId] ) - OUTPUT INSERTED.id - INTO @new_id + OUTPUT + INSERTED.[id], + INSERTED.[userId], + INSERTED.[type], + INSERTED.[provider], + INSERTED.[providerAccountId], + INSERTED.[refresh_token], + INSERTED.[access_token], + INSERTED.[expires_at], + INSERTED.[token_type], + INSERTED.[scope], + INSERTED.[id_token], + INSERTED.[session_state] VALUES (@provider, @type, @providerAccountId, @refresh_token, @token_type, @scope, @expires_at, @access_token, @id_token, @session_state, @userId); - SELECT - [id], - [userId], - [type], - [provider], - [providerAccountId], - [refresh_token], - [access_token], - [expires_at], - [token_type], - [scope], - [id_token], - [session_state] - FROM [accounts] - WHERE [id] = - (SELECT TOP 1 id FROM @new_id); - END GO @@ -445,31 +337,20 @@ CREATE OR ALTER PROCEDURE dbo.create_session_for_user AS BEGIN - DECLARE @new_id TABLE - ( - id UNIQUEIDENTIFIER - ); - INSERT INTO [sessions] ( [sessionToken], [userId], [expires] ) - OUTPUT INSERTED.id - INTO @new_id + OUTPUT + INSERTED.[id], + INSERTED.[sessionToken], + INSERTED.[userId], + INSERTED.[expires] VALUES (@sessionToken, @userId, @expires); - - SELECT - [sessionToken], - [userId], - [expires] - FROM [sessions] - WHERE [id] = - (SELECT TOP 1 id FROM @new_id); - END GO @@ -541,16 +422,13 @@ BEGIN [token], [expires] ) + OUTPUT + INSERTED.[identifier], + INSERTED.[token], + INSERTED.[expires] VALUES (@identifier, @token, @expires); - SELECT - [identifier], - [token], - [expires] - FROM [verification_tokens] - WHERE [identifier] = @identifier AND [token] = @token; - END GO @@ -561,7 +439,10 @@ AS BEGIN DELETE FROM [verification_tokens] - OUTPUT DELETED.identifier, DELETED.token, DELETED.expires + OUTPUT + DELETED.[identifier], + DELETED.[token], + DELETED.[expires] WHERE [identifier] = @identifier AND [token] = @token; END @@ -578,4 +459,105 @@ BEGIN END GO + +CREATE OR ALTER PROCEDURE dbo.get_accounts_by_provider + @providerAccountId NVARCHAR(100), + @provider NVARCHAR(100) +AS +BEGIN + + SELECT + * + FROM [accounts] + WHERE [providerAccountId] = @providerAccountId AND [provider] = @provider; + +END +GO + +CREATE OR ALTER PROCEDURE dbo.create_authenticator + @credentialID NVARCHAR(100), + @userId UNIQUEIDENTIFIER, + @providerAccountId NVARCHAR(100), + @credentialPublicKey VARCHAR(1000), + @counter INT, + @credentialDeviceType NVARCHAR(100), + @credentialBackedUp BIT, + @transports NVARCHAR(1000) +AS +BEGIN + + INSERT INTO [authenticators] + ( + [credentialID], + [userId], + [providerAccountId], + [credentialPublicKey], + [counter], + [credentialDeviceType], + [credentialBackedUp], + [transports] + ) + OUTPUT + INSERTED.[credentialID], + INSERTED.[userId], + INSERTED.[providerAccountId], + INSERTED.[credentialPublicKey], + INSERTED.[counter], + INSERTED.[credentialDeviceType], + INSERTED.[credentialBackedUp], + INSERTED.[transports] + VALUES + (@credentialID, @userId, @providerAccountId, @credentialPublicKey, @counter, + @credentialDeviceType, @credentialBackedUp, @transports); + +END +GO + +CREATE OR ALTER PROCEDURE dbo.get_authenticator + @credentialID NVARCHAR(100) +AS +BEGIN + + SELECT + * + FROM [authenticators] + WHERE [credentialID] = @credentialID; + +END +GO + +CREATE OR ALTER PROCEDURE dbo.list_authenticators_by_user_id + @userId UNIQUEIDENTIFIER +AS +BEGIN + + SELECT + * + FROM [authenticators] + WHERE [userId] = @userId; + +END +GO + +CREATE OR ALTER PROCEDURE dbo.update_authenticator_counter + @credentialID NVARCHAR(100), + @counter INT +AS +BEGIN + + UPDATE [authenticators] + SET + [counter] = @counter + OUTPUT + INSERTED.[credentialID], + INSERTED.[userId], + INSERTED.[providerAccountId], + INSERTED.[credentialPublicKey], + INSERTED.[counter], + INSERTED.[credentialDeviceType], + INSERTED.[credentialBackedUp], + INSERTED.[transports] + WHERE [credentialID] = @credentialID; + +END ``` diff --git a/packages/adapter-sqlserver/README.md b/packages/adapter-sqlserver/README.md index e89cc804eb..d7af103d9d 100644 --- a/packages/adapter-sqlserver/README.md +++ b/packages/adapter-sqlserver/README.md @@ -12,10 +12,10 @@ TypeScript - npm + npm - Downloads + Downloads GitHub Stars @@ -25,4 +25,4 @@ --- -Check out the documentation at [authjs.dev](https://authjs.dev/reference/adapter/pg). +Check out the documentation at [authjs.dev](https://authjs.dev/reference/adapter/sqlserver). diff --git a/packages/adapter-sqlserver/schema.sql b/packages/adapter-sqlserver/schema.sql index b6afea4475..b17a87e894 100644 --- a/packages/adapter-sqlserver/schema.sql +++ b/packages/adapter-sqlserver/schema.sql @@ -8,7 +8,9 @@ IF NOT EXISTS BEGIN CREATE TABLE [users] ( - [id] UNIQUEIDENTIFIER NOT NULL CONSTRAINT [df_users_id] DEFAULT NEWSEQUENTIALID(), + [id] UNIQUEIDENTIFIER NOT NULL + CONSTRAINT [df_users_id] DEFAULT NEWSEQUENTIALID() + CONSTRAINT [pk_users] PRIMARY KEY CLUSTERED ([id]), [name] NVARCHAR(100) NULL, [email] NVARCHAR(100) NOT NULL, [emailVerified] DATETIME2 NULL, @@ -17,23 +19,6 @@ BEGIN END GO --- PK constraint and index -IF NOT EXISTS - (SELECT 1 - FROM sys.indexes - WHERE object_id = OBJECT_ID(N'[users]') - AND name = N'pk_users' -) -BEGIN - ALTER TABLE [users] - ADD CONSTRAINT [pk_users] - PRIMARY KEY CLUSTERED ( - [id] ASC - ) - WITH (STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ONLINE = OFF) ON [PRIMARY]; -END -GO - -- ACCOUNTS table IF NOT EXISTS (SELECT 1 @@ -44,8 +29,12 @@ IF NOT EXISTS BEGIN CREATE TABLE [accounts] ( - [id] UNIQUEIDENTIFIER NOT NULL CONSTRAINT [df_accounts_id] DEFAULT NEWSEQUENTIALID(), - [userId] UNIQUEIDENTIFIER NOT NULL, + [id] UNIQUEIDENTIFIER NOT NULL + CONSTRAINT [df_accounts_id] DEFAULT NEWSEQUENTIALID() + CONSTRAINT [pk_accounts] PRIMARY KEY CLUSTERED ([id]), + [userId] UNIQUEIDENTIFIER NOT NULL + CONSTRAINT [fk_accounts_users] FOREIGN KEY ([userId]) + REFERENCES [users] ([id]) ON DELETE CASCADE, [type] NVARCHAR(100) NOT NULL, [provider] NVARCHAR(100) NOT NULL, [providerAccountId] NVARCHAR(100) NOT NULL, @@ -55,52 +44,10 @@ BEGIN [token_type] NVARCHAR(100) NULL, [scope] NVARCHAR(100) NULL, [id_token] VARCHAR(8000) NULL, - [session_state] NVARCHAR(100) NULL - ); -END -GO + [session_state] NVARCHAR(100) NULL, --- PK constraint and index -IF NOT EXISTS - (SELECT 1 - FROM sys.indexes - WHERE object_id = OBJECT_ID(N'[accounts]') - AND name = N'pk_accounts' -) -BEGIN - ALTER TABLE [accounts] - ADD CONSTRAINT [pk_accounts] - PRIMARY KEY CLUSTERED ( - [id] ASC - ) - WITH (STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ONLINE = OFF) ON [PRIMARY]; -END -GO - --- FK index -IF NOT EXISTS - (SELECT 1 - FROM sys.indexes - WHERE object_id = OBJECT_ID(N'[accounts]') - AND name = N'ix_accounts_users' -) -BEGIN - CREATE INDEX [ix_accounts_users] ON [accounts] (userId); -END -GO - --- FK constraint -IF NOT EXISTS - (SELECT 1 - FROM sys.foreign_keys - WHERE parent_object_id = OBJECT_ID(N'[accounts]') - AND name = N'fk_accounts_users' -) -BEGIN - ALTER TABLE [accounts] WITH CHECK - ADD CONSTRAINT [fk_accounts_users] - FOREIGN KEY ([userId]) - REFERENCES [users] ([id]) ON DELETE CASCADE; + INDEX [ix_accounts_users] (userId) + ); END GO @@ -114,55 +61,17 @@ IF NOT EXISTS BEGIN CREATE TABLE [sessions] ( - [id] UNIQUEIDENTIFIER NOT NULL CONSTRAINT [df_sessions_id] DEFAULT NEWSEQUENTIALID(), + [id] UNIQUEIDENTIFIER NOT NULL + CONSTRAINT [df_sessions_id] DEFAULT NEWSEQUENTIALID() + CONSTRAINT [pk_sessions] PRIMARY KEY CLUSTERED ([id]), [expires] DATETIME2 NOT NULL, - [userId] UNIQUEIDENTIFIER NOT NULL, - [sessionToken] VARCHAR(8000) NULL - ); -END -GO - --- PK index and constraint -IF NOT EXISTS - (SELECT 1 - FROM sys.indexes - WHERE object_id = OBJECT_ID(N'[sessions]') - AND name = N'pk_sessions' -) -BEGIN - ALTER TABLE [sessions] - ADD CONSTRAINT [pk_sessions] - PRIMARY KEY CLUSTERED ( - [id] ASC - ) - WITH (STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ONLINE = OFF) ON [PRIMARY]; -END -GO - --- FK index -IF NOT EXISTS - (SELECT 1 - FROM sys.indexes - WHERE object_id = OBJECT_ID(N'[sessions]') - AND name = N'ix_sessions_users' -) -BEGIN - CREATE INDEX [ix_sessions_users] ON [sessions] (userId) -END -GO + [userId] UNIQUEIDENTIFIER NOT NULL + CONSTRAINT [fk_sessions_users] FOREIGN KEY ([userId]) + REFERENCES [users] ([id]) ON DELETE CASCADE, + [sessionToken] VARCHAR(8000) NULL, --- FK constraint -IF NOT EXISTS - (SELECT 1 - FROM sys.foreign_keys - WHERE parent_object_id = OBJECT_ID(N'[sessions]') - AND name = N'fk_sessions_users' -) -BEGIN - ALTER TABLE [sessions] WITH CHECK - ADD CONSTRAINT [fk_sessions_users] - FOREIGN KEY ([userId]) - REFERENCES [users] ([id]) ON DELETE CASCADE; + INDEX [ix_sessions_users] (userId) + ); END GO @@ -176,31 +85,14 @@ IF NOT EXISTS BEGIN CREATE TABLE [verification_tokens] ( - [identifier] NVARCHAR(100) NOT NULL, + [identifier] NVARCHAR(100) NOT NULL + CONSTRAINT [pk_verification_tokens] PRIMARY KEY CLUSTERED ([identifier], [token]), [token] VARCHAR(700) NOT NULL, [expires] DATETIME2 NOT NULL ); END GO --- PK index and constraint -IF NOT EXISTS - (SELECT 1 - FROM sys.indexes - WHERE object_id = OBJECT_ID(N'[verification_tokens]') - AND name = N'pk_verification_tokens' -) -BEGIN - ALTER TABLE [verification_tokens] - ADD CONSTRAINT [pk_verification_tokens] - PRIMARY KEY CLUSTERED ( - [identifier] ASC, - [token] ASC - ) - WITH (STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ONLINE = OFF) ON [PRIMARY]; -END -GO - -- AUTHENTICATOR table IF NOT EXISTS (SELECT 1 @@ -211,8 +103,8 @@ IF NOT EXISTS BEGIN CREATE TABLE [authenticators] ( - [credentialID] NVARCHAR(100) NOT NULL, - INDEX [ix_authenticators_credentialId] ([credentialId]), + [credentialID] NVARCHAR(100) NOT NULL + CONSTRAINT [pk_authenticators] PRIMARY KEY CLUSTERED ([userId], [credentialID]), [userId] UNIQUEIDENTIFIER NOT NULL CONSTRAINT [fk_authenticators_user_id] FOREIGN KEY REFERENCES [dbo].[users]([id]), [providerAccountId] NVARCHAR(100) NOT NULL, @@ -220,26 +112,10 @@ BEGIN [counter] INT NOT NULL, [credentialDeviceType] NVARCHAR(100) NOT NULL, [credentialBackedUp] BIT NOT NULL, - [transports] NVARCHAR(1000) NOT NULL - ); -END -GO + [transports] NVARCHAR(1000) NOT NULL, --- PK index and constraint -IF NOT EXISTS - (SELECT 1 - FROM sys.indexes - WHERE object_id = OBJECT_ID(N'[authenticators]') - AND name = N'pk_authenticators' -) -BEGIN - ALTER TABLE [authenticators] - ADD CONSTRAINT [pk_authenticators] - PRIMARY KEY CLUSTERED ( - [userId] ASC, - [credentialID] ASC - ) - WITH (STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ONLINE = OFF) ON [PRIMARY]; + INDEX [ix_authenticators_credentialId] ([credentialId]), + ); END GO