diff --git a/apps/playground/package.json b/apps/playground/package.json index 1f301efa..cee18ad7 100644 --- a/apps/playground/package.json +++ b/apps/playground/package.json @@ -21,7 +21,7 @@ "zod-form-data": "^2.0.2" }, "devDependencies": { - "@types/node": "^20.12.10", + "@types/node": "^20.14.11", "@types/react": "^18.3.1", "@types/react-dom": "18.3.0", "autoprefixer": "10.4.19", @@ -29,6 +29,6 @@ "eslint-config-next": "15.0.0-canary.25", "postcss": "8.4.38", "tailwindcss": "3.4.3", - "typescript": "^5.4.5" + "typescript": "^5.5.3" } } diff --git a/apps/playground/src/lib/safe-action.ts b/apps/playground/src/lib/safe-action.ts index 83723938..f53569d5 100644 --- a/apps/playground/src/lib/safe-action.ts +++ b/apps/playground/src/lib/safe-action.ts @@ -2,11 +2,13 @@ import { DEFAULT_SERVER_ERROR_MESSAGE, createSafeActionClient, } from "next-safe-action"; +import { zodAdapter } from "next-safe-action/adapters/zod"; import { z } from "zod"; export class ActionError extends Error {} export const action = createSafeActionClient({ + validationAdapter: zodAdapter(), // You can provide a custom logging function, otherwise the lib will use `console.error` // as the default logging system. If you want to disable server errors logging, // just pass an empty Promise. diff --git a/packages/next-safe-action/package.json b/packages/next-safe-action/package.json index 1625e9d5..3796b898 100644 --- a/packages/next-safe-action/package.json +++ b/packages/next-safe-action/package.json @@ -11,23 +11,23 @@ ], "exports": { ".": "./dist/index.mjs", - "./typeschema": "./dist/typeschema.mjs", "./hooks": "./dist/hooks.mjs", - "./stateful-hooks": "./dist/stateful-hooks.mjs" + "./stateful-hooks": "./dist/stateful-hooks.mjs", + "./adapters/*": "./dist/adapters/*.mjs" }, "typesVersions": { "*": { ".": [ "./dist/index.d.mts" ], - "typeschema": [ - "./dist/typeschema.d.mts" - ], "hooks": [ "./dist/hooks.d.mts" ], "stateful-hooks": [ "./dist/stateful-hooks.d.mts" + ], + "adapters/*": [ + "./dist/adapters/*.d.mts" ] } }, @@ -43,7 +43,7 @@ ], "scripts": { "lint": "tsc && prettier --write . && eslint .", - "test": "node --import tsx --test ./src/__tests__/*.test.ts ./src/__tests__/typeschema/*.test.ts", + "test": "node --import tsx --test ./src/__tests__/*.test.ts", "build": "tsup", "deploy": "semantic-release" }, @@ -67,10 +67,9 @@ }, "devDependencies": { "@eslint/js": "^9.2.0", - "@types/node": "^20.12.10", + "@types/node": "^20.14.11", "@types/react": "^18.3.1", "@types/react-dom": "18.3.0", - "@typeschema/core": "^0.13.2", "eslint": "^8.57.0", "eslint-config-prettier": "^9.1.0", "eslint-define-config": "^2.1.0", @@ -82,26 +81,30 @@ "semantic-release": "^23.0.8", "tsup": "^8.0.2", "tsx": "^4.11.2", - "typescript": "^5.4.5", - "typescript-eslint": "^7.8.0" + "typescript": "^5.5.3", + "typescript-eslint": "^7.8.0", + "valibot": "^0.36.0", + "yup": "^1.4.0", + "zod": "^3.23.6" }, "peerDependencies": { "next": ">= 14.0.0", "react": ">= 18.2.0", "react-dom": ">= 18.2.0", - "zod": ">= 3.0.0" + "valibot": ">= 0.36.0", + "zod": ">= 3.0.0", + "yup": ">= 1.0.0" }, "peerDependenciesMeta": { "zod": { "optional": true + }, + "valibot": { + "optional": true } }, "repository": { "type": "git", "url": "https://github.com/TheEdoRan/next-safe-action.git" - }, - "dependencies": { - "@typeschema/main": "^0.13.10", - "@typeschema/zod": "^0.13.3" } } diff --git a/packages/next-safe-action/src/__tests__/action-callbacks.test.ts b/packages/next-safe-action/src/__tests__/action-callbacks.test.ts index c865af2e..84fb3d63 100644 --- a/packages/next-safe-action/src/__tests__/action-callbacks.test.ts +++ b/packages/next-safe-action/src/__tests__/action-callbacks.test.ts @@ -4,8 +4,10 @@ import assert from "node:assert"; import { test } from "node:test"; import { z } from "zod"; import { DEFAULT_SERVER_ERROR_MESSAGE, createSafeActionClient, returnValidationErrors } from ".."; +import { zodAdapter } from "../adapters/zod"; const ac = createSafeActionClient({ + validationAdapter: zodAdapter(), defineMetadataSchema() { return z.object({ actionName: z.string(), diff --git a/packages/next-safe-action/src/__tests__/bind-args-validation-errors.test.ts b/packages/next-safe-action/src/__tests__/bind-args-validation-errors.test.ts index 9ec1efa9..0fce6388 100644 --- a/packages/next-safe-action/src/__tests__/bind-args-validation-errors.test.ts +++ b/packages/next-safe-action/src/__tests__/bind-args-validation-errors.test.ts @@ -4,10 +4,13 @@ import assert from "node:assert"; import { test } from "node:test"; import { z } from "zod"; import { createSafeActionClient, flattenBindArgsValidationErrors, formatBindArgsValidationErrors } from ".."; +import { zodAdapter } from "../adapters/zod"; // Default client tests. -const dac = createSafeActionClient(); +const dac = createSafeActionClient({ + validationAdapter: zodAdapter(), +}); test("action with invalid bind args input gives back an object with correct `bindArgsValidationErrors` (default formatted shape)", async () => { const bindArgsSchemas: [age: z.ZodNumber, userId: z.ZodString, product: z.ZodObject<{ id: z.ZodString }>] = [ @@ -87,6 +90,7 @@ test("action with invalid bind args input gives back an object with correct `bin // Formatted shape tests (same as default). const foac = createSafeActionClient({ + validationAdapter: zodAdapter(), defaultValidationErrorsShape: "formatted", }); @@ -168,6 +172,7 @@ test("action with invalid bind args input gives back an object with correct `bin // Flattened shape tests. const flac = createSafeActionClient({ + validationAdapter: zodAdapter(), defaultValidationErrorsShape: "flattened", }); diff --git a/packages/next-safe-action/src/__tests__/combined-validation-errors.test.ts b/packages/next-safe-action/src/__tests__/combined-validation-errors.test.ts index d44c944d..1b7f3403 100644 --- a/packages/next-safe-action/src/__tests__/combined-validation-errors.test.ts +++ b/packages/next-safe-action/src/__tests__/combined-validation-errors.test.ts @@ -10,10 +10,13 @@ import { formatBindArgsValidationErrors, formatValidationErrors, } from ".."; +import { zodAdapter } from "../adapters/zod"; // Default client tests. -const dac = createSafeActionClient(); +const dac = createSafeActionClient({ + validationAdapter: zodAdapter(), +}); test("action with invalid bind args input and valid main input gives back an object with correct `bindArgsValidationErrors` (default formatted shape)", async () => { const schema = z.object({ @@ -110,6 +113,7 @@ test("action with invalid bind args input and invalid main input gives back an o // Formatted shape tests (same as default). const foac = createSafeActionClient({ + validationAdapter: zodAdapter(), defaultValidationErrorsShape: "formatted", }); @@ -209,6 +213,7 @@ test("action with invalid bind args input and valid main input gives back an obj // Flattened shape tests. const flac = createSafeActionClient({ + validationAdapter: zodAdapter(), defaultValidationErrorsShape: "flattened", }); diff --git a/packages/next-safe-action/src/__tests__/happy-path.test.ts b/packages/next-safe-action/src/__tests__/happy-path.test.ts index 32f207b6..c3f368bd 100644 --- a/packages/next-safe-action/src/__tests__/happy-path.test.ts +++ b/packages/next-safe-action/src/__tests__/happy-path.test.ts @@ -4,8 +4,11 @@ import assert from "node:assert"; import { test } from "node:test"; import { z } from "zod"; import { createSafeActionClient } from ".."; +import { zodAdapter } from "../adapters/zod"; -const ac = createSafeActionClient(); +const ac = createSafeActionClient({ + validationAdapter: zodAdapter(), +}); test("action with no input schema returns empty object", async () => { const action = ac.action(async () => { diff --git a/packages/next-safe-action/src/__tests__/metadata.test.ts b/packages/next-safe-action/src/__tests__/metadata.test.ts index 554f86e4..a9f6fbea 100644 --- a/packages/next-safe-action/src/__tests__/metadata.test.ts +++ b/packages/next-safe-action/src/__tests__/metadata.test.ts @@ -4,8 +4,10 @@ import assert from "node:assert"; import { test } from "node:test"; import { z } from "zod"; import { DEFAULT_SERVER_ERROR_MESSAGE, createSafeActionClient } from ".."; +import { zodAdapter } from "../adapters/zod"; const ac = createSafeActionClient({ + validationAdapter: zodAdapter(), handleServerErrorLog() {}, // disable server errors logging for these tests defineMetadataSchema() { return z.object({ diff --git a/packages/next-safe-action/src/__tests__/middleware.test.ts b/packages/next-safe-action/src/__tests__/middleware.test.ts index c7cac88e..60ba0ae5 100644 --- a/packages/next-safe-action/src/__tests__/middleware.test.ts +++ b/packages/next-safe-action/src/__tests__/middleware.test.ts @@ -9,8 +9,10 @@ import { formatValidationErrors, returnValidationErrors, } from ".."; +import { zodAdapter } from "../adapters/zod"; const ac = createSafeActionClient({ + validationAdapter: zodAdapter(), handleServerErrorLog() {}, // disable server errors logging for these tests handleReturnedServerError(e) { return { @@ -292,6 +294,7 @@ test("server validation errors in execution result from middleware are correct", // Flattened validation errors shape. const flac = createSafeActionClient({ + validationAdapter: zodAdapter(), handleServerErrorLog() {}, // disable server errors logging for these tests defaultValidationErrorsShape: "flattened", }); diff --git a/packages/next-safe-action/src/__tests__/server-error.test.ts b/packages/next-safe-action/src/__tests__/server-error.test.ts index 25e0306d..bdc79f8c 100644 --- a/packages/next-safe-action/src/__tests__/server-error.test.ts +++ b/packages/next-safe-action/src/__tests__/server-error.test.ts @@ -3,6 +3,7 @@ import assert from "node:assert"; import { test } from "node:test"; import { DEFAULT_SERVER_ERROR_MESSAGE, createSafeActionClient } from ".."; +import { zodAdapter } from "../adapters/zod"; class ActionError extends Error { constructor(message: string) { @@ -11,6 +12,7 @@ class ActionError extends Error { } const ac1 = createSafeActionClient({ + validationAdapter: zodAdapter(), handleServerErrorLog: () => {}, // disable server errors logging for these tests handleReturnedServerError(e) { if (e instanceof ActionError) { @@ -93,6 +95,7 @@ test("known error occurred in middleware function is unmasked", async () => { // Server error is an object with a 'message' property. const ac2 = createSafeActionClient({ + validationAdapter: zodAdapter(), handleServerErrorLog: () => {}, // disable server errors logging for these tests handleReturnedServerError(e) { return { @@ -138,6 +141,7 @@ test("error occurred in middleware function has the correct shape defined by `ha // Rethrow all server errors. const ac3 = createSafeActionClient({ + validationAdapter: zodAdapter(), handleServerErrorLog: () => {}, // disable server errors logging for these tests handleReturnedServerError(e) { throw e; diff --git a/packages/next-safe-action/src/__tests__/typeschema/action-callbacks.test.ts b/packages/next-safe-action/src/__tests__/typeschema/action-callbacks.test.ts deleted file mode 100644 index da122a8e..00000000 --- a/packages/next-safe-action/src/__tests__/typeschema/action-callbacks.test.ts +++ /dev/null @@ -1,301 +0,0 @@ -/* eslint-disable @typescript-eslint/no-floating-promises */ - -import assert from "node:assert"; -import { test } from "node:test"; -import { z } from "zod"; -import { DEFAULT_SERVER_ERROR_MESSAGE, createSafeActionClient, returnValidationErrors } from "../../typeschema"; - -const ac = createSafeActionClient({ - defineMetadataSchema() { - return z.object({ - actionName: z.string(), - }); - }, -}) - .use(async ({ next }) => { - return next({ ctx: { foo: "bar" } }); - }) - .metadata({ actionName: "test" }); - -test("typeschema - action with no input schema and no server errors calls `onSuccess` and `onSettled` callbacks", async () => { - let executed = 0; - - const action = ac.action( - async () => { - return; - }, - { - onSuccess: () => { - executed++; - }, - onError: () => { - executed++; // should not be called - }, - onSettled: () => { - executed++; - }, - } - ); - - await action(); - assert.strictEqual(executed, 2); -}); - -test("typeschema - action with input schemas and no errors calls `onSuccess` and `onSettled` callbacks with correct arguments", async () => { - let executed = 0; - const inputs = [crypto.randomUUID(), 30, { username: "johndoe" }] as const; - - const action = ac - .schema(z.object({ username: z.string().min(3) })) - .bindArgsSchemas([z.string().uuid(), z.number().positive()]) - .action( - async () => { - return { - ok: true, - }; - }, - { - onSuccess: ({ clientInput, bindArgsClientInputs, parsedInput, bindArgsParsedInputs, data, metadata, ctx }) => { - executed++; - - assert.deepStrictEqual( - { clientInput, bindArgsClientInputs, parsedInput, bindArgsParsedInputs, data, metadata, ctx }, - { - metadata: { actionName: "test" }, - ctx: { foo: "bar" }, - clientInput: inputs[2], - bindArgsClientInputs: inputs.slice(0, 2), - parsedInput: inputs[2], - bindArgsParsedInputs: inputs.slice(0, 2), - data: { - ok: true, - }, - } - ); - }, - onError: () => { - executed++; // should not be called - }, - onSettled: ({ clientInput, bindArgsClientInputs, result, metadata, ctx }) => { - executed++; - - assert.deepStrictEqual( - { clientInput, bindArgsClientInputs, result, metadata, ctx }, - { - metadata: { actionName: "test" }, - ctx: { foo: "bar" }, - clientInput: inputs[2], - bindArgsClientInputs: inputs.slice(0, 2), - result: { - data: { - ok: true, - }, - }, - } - ); - }, - } - ); - - await action(...inputs); - assert.strictEqual(executed, 2); -}); - -test("typeschema - action with input schemas and server error calls `onError` and `onSettled` callbacks with correct arguments", async () => { - let executed = 0; - const inputs = [crypto.randomUUID(), 30, { username: "johndoe" }] as const; - - const action = ac - .schema(z.object({ username: z.string().min(3) })) - .bindArgsSchemas([z.string().uuid(), z.number().positive()]) - .action( - async () => { - throw new Error("Server error"); - }, - { - onSuccess: () => { - executed++; // should not be called - }, - onError({ error, clientInput, bindArgsClientInputs, metadata, ctx }) { - executed++; - - assert.deepStrictEqual( - { error, clientInput, bindArgsClientInputs, metadata, ctx }, - { - metadata: { actionName: "test" }, - ctx: { foo: "bar" }, - error: { - serverError: DEFAULT_SERVER_ERROR_MESSAGE, - }, - clientInput: inputs[2], - bindArgsClientInputs: inputs.slice(0, 2), - } - ); - }, - onSettled({ clientInput, bindArgsClientInputs, result, metadata, ctx }) { - executed++; - - assert.deepStrictEqual( - { result, clientInput, bindArgsClientInputs, metadata, ctx }, - { - metadata: { actionName: "test" }, - ctx: { foo: "bar" }, - result: { - serverError: DEFAULT_SERVER_ERROR_MESSAGE, - }, - clientInput: inputs[2], - bindArgsClientInputs: inputs.slice(0, 2), - } - ); - }, - } - ); - - await action(...inputs); - assert.strictEqual(executed, 2); -}); - -test("typeschema - action with validation errors calls `onError` and `onSettled` callbacks with correct arguments", async () => { - let executed = 0; - const inputs = ["invalid_uuid", -30, { username: "j" }] as const; - - const action = ac - .schema(z.object({ username: z.string().min(3) })) - .bindArgsSchemas([z.string().uuid(), z.number().positive()]) - .action( - async () => { - return { - ok: true, - }; - }, - { - onSuccess: () => { - executed++; // should not be called - }, - onError({ error, clientInput, bindArgsClientInputs, metadata, ctx }) { - executed++; - - assert.deepStrictEqual( - { error, clientInput, bindArgsClientInputs, metadata, ctx }, - { - metadata: { actionName: "test" }, - ctx: { foo: "bar" }, - error: { - validationErrors: { - username: { - _errors: ["String must contain at least 3 character(s)"], - }, - }, - bindArgsValidationErrors: [ - { - _errors: ["Invalid uuid"], - }, - { - _errors: ["Number must be greater than 0"], - }, - ], - }, - clientInput: inputs[2], - bindArgsClientInputs: inputs.slice(0, 2), - } - ); - }, - onSettled({ clientInput, bindArgsClientInputs, result, metadata, ctx }) { - executed++; - - assert.deepStrictEqual( - { result, clientInput, bindArgsClientInputs, metadata, ctx }, - { - metadata: { actionName: "test" }, - ctx: { foo: "bar" }, - result: { - validationErrors: { - username: { - _errors: ["String must contain at least 3 character(s)"], - }, - }, - bindArgsValidationErrors: [ - { - _errors: ["Invalid uuid"], - }, - { - _errors: ["Number must be greater than 0"], - }, - ], - }, - clientInput: inputs[2], - bindArgsClientInputs: inputs.slice(0, 2), - } - ); - }, - } - ); - - await action(...inputs); - assert.strictEqual(executed, 2); -}); - -test("typeschema - action with server validation error calls `onError` and `onSettled` callbacks with correct arguments", async () => { - let executed = 0; - - const schema = z.object({ - username: z.string(), - }); - const action = ac.schema(z.object({ username: z.string().min(3) })).action( - async () => { - returnValidationErrors(schema, { - username: { - _errors: ["Invalid username"], - }, - }); - }, - { - onSuccess: () => { - executed++; // should not be called - }, - onError({ error, clientInput, bindArgsClientInputs, metadata, ctx }) { - executed++; - - assert.deepStrictEqual( - { error, clientInput, bindArgsClientInputs, metadata, ctx }, - { - metadata: { actionName: "test" }, - ctx: { foo: "bar" }, - error: { - validationErrors: { - username: { - _errors: ["Invalid username"], - }, - }, - }, - clientInput: { username: "johndoe" }, - bindArgsClientInputs: [], - } - ); - }, - onSettled({ clientInput, bindArgsClientInputs, result, metadata, ctx }) { - executed++; - - assert.deepStrictEqual( - { result, clientInput, bindArgsClientInputs, metadata, ctx }, - { - metadata: { actionName: "test" }, - ctx: { foo: "bar" }, - result: { - validationErrors: { - username: { - _errors: ["Invalid username"], - }, - }, - }, - clientInput: { username: "johndoe" }, - bindArgsClientInputs: [], - } - ); - }, - } - ); - - await action({ username: "johndoe" }); - assert.strictEqual(executed, 2); -}); diff --git a/packages/next-safe-action/src/__tests__/typeschema/bind-args-validation-errors.test.ts b/packages/next-safe-action/src/__tests__/typeschema/bind-args-validation-errors.test.ts deleted file mode 100644 index 6149838d..00000000 --- a/packages/next-safe-action/src/__tests__/typeschema/bind-args-validation-errors.test.ts +++ /dev/null @@ -1,251 +0,0 @@ -/* eslint-disable @typescript-eslint/no-floating-promises */ - -import assert from "node:assert"; -import { test } from "node:test"; -import { z } from "zod"; -import { - createSafeActionClient, - flattenBindArgsValidationErrors, - formatBindArgsValidationErrors, -} from "../../typeschema"; - -// Default client tests. - -const dac = createSafeActionClient(); - -test("typeschema - action with invalid bind args input gives back an object with correct `bindArgsValidationErrors` (default formatted shape)", async () => { - const bindArgsSchemas: [age: z.ZodNumber, userId: z.ZodString, product: z.ZodObject<{ id: z.ZodString }>] = [ - z.number().positive(), - z.string().uuid(), - z.object({ - id: z.string().uuid(), - }), - ]; - - const action = dac.bindArgsSchemas(bindArgsSchemas).action(async () => { - return { - ok: true, - }; - }); - - const actualResult = await action(-123, crypto.randomUUID(), { id: "invalid_uuid" }); - - const expectedResult = { - bindArgsValidationErrors: [ - { - _errors: ["Number must be greater than 0"], - }, - {}, - { - id: { - _errors: ["Invalid uuid"], - }, - }, - ], - }; - - assert.deepStrictEqual(actualResult, expectedResult); -}); - -test("typeschema - action with invalid bind args input gives back an object with correct `bindArgsValidationErrors` (default formatted shape overridden by custom flattened shape)", async () => { - const bindArgsSchemas: [age: z.ZodNumber, userId: z.ZodString, product: z.ZodObject<{ id: z.ZodString }>] = [ - z.number().positive(), - z.string().uuid(), - z.object({ - id: z.string().uuid(), - }), - ]; - - const action = dac - .bindArgsSchemas(bindArgsSchemas, { handleBindArgsValidationErrorsShape: flattenBindArgsValidationErrors }) - .action(async () => { - return { - ok: true, - }; - }); - - const actualResult = await action(-123, crypto.randomUUID(), { id: "invalid_uuid" }); - - const expectedResult = { - bindArgsValidationErrors: [ - { - formErrors: ["Number must be greater than 0"], - fieldErrors: {}, - }, - { - formErrors: [], - fieldErrors: {}, - }, - { - formErrors: [], - fieldErrors: { - id: ["Invalid uuid"], - }, - }, - ], - }; - - assert.deepStrictEqual(actualResult, expectedResult); -}); - -// Formatted shape tests (same as default). - -const foac = createSafeActionClient({ - defaultValidationErrorsShape: "formatted", -}); - -test("typeschema - action with invalid bind args input gives back an object with correct `bindArgsValidationErrors` (set formatted shape)", async () => { - const bindArgsSchemas: [age: z.ZodNumber, userId: z.ZodString, product: z.ZodObject<{ id: z.ZodString }>] = [ - z.number().positive(), - z.string().uuid(), - z.object({ - id: z.string().uuid(), - }), - ]; - - const action = foac.bindArgsSchemas(bindArgsSchemas).action(async () => { - return { - ok: true, - }; - }); - - const actualResult = await action(-123, crypto.randomUUID(), { id: "invalid_uuid" }); - - const expectedResult = { - bindArgsValidationErrors: [ - { - _errors: ["Number must be greater than 0"], - }, - {}, - { - id: { - _errors: ["Invalid uuid"], - }, - }, - ], - }; - - assert.deepStrictEqual(actualResult, expectedResult); -}); - -test("typeschema - action with invalid bind args input gives back an object with correct `bindArgsValidationErrors` (set formatted shape overridden by custom flattened shape)", async () => { - const bindArgsSchemas: [age: z.ZodNumber, userId: z.ZodString, product: z.ZodObject<{ id: z.ZodString }>] = [ - z.number().positive(), - z.string().uuid(), - z.object({ - id: z.string().uuid(), - }), - ]; - - const action = foac - .bindArgsSchemas(bindArgsSchemas, { handleBindArgsValidationErrorsShape: flattenBindArgsValidationErrors }) - .action(async () => { - return { - ok: true, - }; - }); - - const actualResult = await action(-123, crypto.randomUUID(), { id: "invalid_uuid" }); - - const expectedResult = { - bindArgsValidationErrors: [ - { - formErrors: ["Number must be greater than 0"], - fieldErrors: {}, - }, - { - formErrors: [], - fieldErrors: {}, - }, - { - formErrors: [], - fieldErrors: { - id: ["Invalid uuid"], - }, - }, - ], - }; - - assert.deepStrictEqual(actualResult, expectedResult); -}); - -// Flattened shape tests. - -const flac = createSafeActionClient({ - defaultValidationErrorsShape: "flattened", -}); - -test("typeschema - action with invalid bind args input gives back an object with correct `bindArgsValidationErrors` (set flattened shape)", async () => { - const bindArgsSchemas: [age: z.ZodNumber, userId: z.ZodString, product: z.ZodObject<{ id: z.ZodString }>] = [ - z.number().positive(), - z.string().uuid(), - z.object({ - id: z.string().uuid(), - }), - ]; - - const action = flac.bindArgsSchemas(bindArgsSchemas).action(async () => { - return { - ok: true, - }; - }); - - const actualResult = await action(-123, crypto.randomUUID(), { id: "invalid_uuid" }); - - const expectedResult = { - bindArgsValidationErrors: [ - { - formErrors: ["Number must be greater than 0"], - fieldErrors: {}, - }, - { - formErrors: [], - fieldErrors: {}, - }, - { - formErrors: [], - fieldErrors: { - id: ["Invalid uuid"], - }, - }, - ], - }; - - assert.deepStrictEqual(actualResult, expectedResult); -}); - -test("typeschema - action with invalid bind args input gives back an object with correct `bindArgsValidationErrors` (set flattened shape overridden by custom formatted shape)", async () => { - const bindArgsSchemas: [age: z.ZodNumber, userId: z.ZodString, product: z.ZodObject<{ id: z.ZodString }>] = [ - z.number().positive(), - z.string().uuid(), - z.object({ - id: z.string().uuid(), - }), - ]; - - const action = flac - .bindArgsSchemas(bindArgsSchemas, { handleBindArgsValidationErrorsShape: formatBindArgsValidationErrors }) - .action(async () => { - return { - ok: true, - }; - }); - - const actualResult = await action(-123, crypto.randomUUID(), { id: "invalid_uuid" }); - - const expectedResult = { - bindArgsValidationErrors: [ - { - _errors: ["Number must be greater than 0"], - }, - {}, - { - id: { - _errors: ["Invalid uuid"], - }, - }, - ], - }; - - assert.deepStrictEqual(actualResult, expectedResult); -}); diff --git a/packages/next-safe-action/src/__tests__/typeschema/combined-validation-errors.test.ts b/packages/next-safe-action/src/__tests__/typeschema/combined-validation-errors.test.ts deleted file mode 100644 index 10ac91e6..00000000 --- a/packages/next-safe-action/src/__tests__/typeschema/combined-validation-errors.test.ts +++ /dev/null @@ -1,316 +0,0 @@ -/* eslint-disable @typescript-eslint/no-floating-promises */ - -import assert from "node:assert"; -import { test } from "node:test"; -import { z } from "zod"; -import { - createSafeActionClient, - flattenBindArgsValidationErrors, - flattenValidationErrors, - formatBindArgsValidationErrors, - formatValidationErrors, -} from "../../typeschema"; - -// Default client tests. - -const dac = createSafeActionClient(); - -test("typeschema - action with invalid bind args input and valid main input gives back an object with correct `bindArgsValidationErrors` (default formatted shape)", async () => { - const schema = z.object({ - username: z.string().min(3), - }); - - const bindArgsSchemas: [age: z.ZodNumber, userId: z.ZodString, product: z.ZodObject<{ id: z.ZodString }>] = [ - z.number().positive(), - z.string().uuid(), - z.object({ - id: z.string().uuid(), - }), - ]; - - const action = dac - .schema(schema) - .bindArgsSchemas(bindArgsSchemas) - .action(async () => { - return { - ok: true, - }; - }); - - const actualResult = await action(-123, crypto.randomUUID(), { id: "invalid_uuid" }, { username: "johndoe" }); - - const expectedResult = { - bindArgsValidationErrors: [ - { - _errors: ["Number must be greater than 0"], - }, - {}, - { - id: { - _errors: ["Invalid uuid"], - }, - }, - ], - }; - - assert.deepStrictEqual(actualResult, expectedResult); -}); - -test("typeschema - action with invalid bind args input and invalid main input gives back an object with correct `validationErrors` and `bindArgsValidationErrors` (default formatted shape overridden by custom bind args errors flattened shape)", async () => { - const schema = z.object({ - username: z.string().min(3), - }); - - const bindArgsSchemas: [age: z.ZodNumber, userId: z.ZodString, product: z.ZodObject<{ id: z.ZodString }>] = [ - z.number().positive(), - z.string().uuid(), - z.object({ - id: z.string().uuid(), - }), - ]; - - const action = dac - .schema(schema) - .bindArgsSchemas(bindArgsSchemas, { handleBindArgsValidationErrorsShape: flattenBindArgsValidationErrors }) - .action(async () => { - return { - ok: true, - }; - }); - - const actualResult = await action(-123, crypto.randomUUID(), { id: "invalid_uuid" }, { username: "" }); - - const expectedResult = { - validationErrors: { - username: { - _errors: ["String must contain at least 3 character(s)"], - }, - }, - bindArgsValidationErrors: [ - { - formErrors: ["Number must be greater than 0"], - fieldErrors: {}, - }, - { - formErrors: [], - fieldErrors: {}, - }, - { - formErrors: [], - fieldErrors: { - id: ["Invalid uuid"], - }, - }, - ], - }; - - assert.deepStrictEqual(actualResult, expectedResult); -}); - -// Formatted shape tests (same as default). - -const foac = createSafeActionClient({ - defaultValidationErrorsShape: "formatted", -}); - -test("typeschema - action with invalid bind args input and invalid main input gives back an object with correct `validationErrors` and `bindArgsValidationErrors` (set formatted shape overridden by custom main input flattened shape)", async () => { - const schema = z.object({ - username: z.string().min(3), - }); - - const bindArgsSchemas: [age: z.ZodNumber, userId: z.ZodString, product: z.ZodObject<{ id: z.ZodString }>] = [ - z.number().positive(), - z.string().uuid(), - z.object({ - id: z.string().uuid(), - }), - ]; - - const action = foac - .schema(schema, { handleValidationErrorsShape: flattenValidationErrors }) - .bindArgsSchemas(bindArgsSchemas) - .action(async () => { - return { - ok: true, - }; - }); - - const actualResult = await action(-123, crypto.randomUUID(), { id: "invalid_uuid" }, { username: "" }); - - const expectedResult = { - validationErrors: { - formErrors: [], - fieldErrors: { - username: ["String must contain at least 3 character(s)"], - }, - }, - bindArgsValidationErrors: [ - { - _errors: ["Number must be greater than 0"], - }, - {}, - { - id: { - _errors: ["Invalid uuid"], - }, - }, - ], - }; - - assert.deepStrictEqual(actualResult, expectedResult); -}); - -test("typeschema - action with invalid bind args input and valid main input gives back an object with correct `bindArgsValidationErrors` (set formatted shape overridden by custom bind args flattened shape)", async () => { - const schema = z.object({ - username: z.string().min(3), - }); - - const bindArgsSchemas: [age: z.ZodNumber, userId: z.ZodString, product: z.ZodObject<{ id: z.ZodString }>] = [ - z.number().positive(), - z.string().uuid(), - z.object({ - id: z.string().uuid(), - }), - ]; - - const action = foac - .schema(schema) - .bindArgsSchemas(bindArgsSchemas, { handleBindArgsValidationErrorsShape: flattenBindArgsValidationErrors }) - .action(async () => { - return { - ok: true, - }; - }); - - const actualResult = await action(-123, crypto.randomUUID(), { id: "invalid_uuid" }, { username: "johndoe" }); - - const expectedResult = { - bindArgsValidationErrors: [ - { - formErrors: ["Number must be greater than 0"], - fieldErrors: {}, - }, - { - formErrors: [], - fieldErrors: {}, - }, - { - formErrors: [], - fieldErrors: { - id: ["Invalid uuid"], - }, - }, - ], - }; - - assert.deepStrictEqual(actualResult, expectedResult); -}); - -// Flattened shape tests. - -const flac = createSafeActionClient({ - defaultValidationErrorsShape: "flattened", -}); - -test("typeschema - action with invalid bind args input and invalid main input gives back an object with correct `bindArgsValidationErrors` (set flattened shape)", async () => { - const schema = z.object({ - username: z.string().min(3), - }); - - const bindArgsSchemas: [age: z.ZodNumber, userId: z.ZodString, product: z.ZodObject<{ id: z.ZodString }>] = [ - z.number().positive(), - z.string().uuid(), - z.object({ - id: z.string().uuid(), - }), - ]; - - const action = flac - .schema(schema) - .bindArgsSchemas(bindArgsSchemas) - .action(async () => { - return { - ok: true, - }; - }); - - const actualResult = await action(-123, crypto.randomUUID(), { id: "invalid_uuid" }, { username: "" }); - - const expectedResult = { - validationErrors: { - formErrors: [], - fieldErrors: { - username: ["String must contain at least 3 character(s)"], - }, - }, - bindArgsValidationErrors: [ - { - formErrors: ["Number must be greater than 0"], - fieldErrors: {}, - }, - { - formErrors: [], - fieldErrors: {}, - }, - { - formErrors: [], - fieldErrors: { - id: ["Invalid uuid"], - }, - }, - ], - }; - - assert.deepStrictEqual(actualResult, expectedResult); -}); - -test("typeschema - action with invalid bind args input, invalid main input and root level schema error gives back an object with correct `bindArgsValidationErrors` (set flattened shape overridden by custom formatted shape)", async () => { - const schema = z - .object({ - username: z.string().min(3), - }) - .refine(() => false, { - message: "Root schema error", - }); - - const bindArgsSchemas: [age: z.ZodNumber, userId: z.ZodString, product: z.ZodObject<{ id: z.ZodString }>] = [ - z.number().positive(), - z.string().uuid(), - z.object({ - id: z.string().uuid(), - }), - ]; - - const action = flac - .schema(schema, { handleValidationErrorsShape: formatValidationErrors }) - .bindArgsSchemas(bindArgsSchemas, { handleBindArgsValidationErrorsShape: formatBindArgsValidationErrors }) - .action(async () => { - return { - ok: true, - }; - }); - - const actualResult = await action(-123, crypto.randomUUID(), { id: "invalid_uuid" }, { username: "" }); - - const expectedResult = { - validationErrors: { - _errors: ["Root schema error"], - username: { - _errors: ["String must contain at least 3 character(s)"], - }, - }, - bindArgsValidationErrors: [ - { - _errors: ["Number must be greater than 0"], - }, - {}, - { - id: { - _errors: ["Invalid uuid"], - }, - }, - ], - }; - - assert.deepStrictEqual(actualResult, expectedResult); -}); diff --git a/packages/next-safe-action/src/__tests__/typeschema/happy-path.test.ts b/packages/next-safe-action/src/__tests__/typeschema/happy-path.test.ts deleted file mode 100644 index f9359332..00000000 --- a/packages/next-safe-action/src/__tests__/typeschema/happy-path.test.ts +++ /dev/null @@ -1,158 +0,0 @@ -/* eslint-disable @typescript-eslint/no-floating-promises */ - -import assert from "node:assert"; -import { test } from "node:test"; -import { z } from "zod"; -import { createSafeActionClient } from "../../typeschema"; - -const ac = createSafeActionClient(); - -test("typeschema - action with no input schema returns empty object", async () => { - const action = ac.action(async () => { - return; - }); - - const actualResult = await action(); - const expectedResult = {}; - - assert.deepStrictEqual(actualResult, expectedResult); -}); - -test("typeschema - action with no input schema and return data gives back an object with correct `data`", async () => { - const action = ac.action(async () => { - return { - ok: true, - }; - }); - - const actualResult = await action(); - const expectedResult = { - data: { - ok: true, - }, - }; - - assert.deepStrictEqual(actualResult, expectedResult); -}); - -test("typeschema - action with input schema and return data gives back an object with correct `data`", async () => { - const userId = "ed6f5b84-6bca-4d01-9a51-c3d0c49a7996"; - - const action = ac.schema(z.object({ userId: z.string().uuid() })).action(async ({ parsedInput }) => { - return { - userId: parsedInput.userId, - }; - }); - - const actualResult = await action({ userId }); - - const expectedResult = { - data: { - userId, - }, - }; - - assert.deepStrictEqual(actualResult, expectedResult); -}); - -test("typeschema - action with input schema passed via async function and return data gives back an object with correct `data`", async () => { - const userId = "ed6f5b84-6bca-4d01-9a51-c3d0c49a7996"; - - const action = ac - .schema(async () => z.object({ userId: z.string().uuid() })) - .action(async ({ parsedInput }) => { - return { - userId: parsedInput.userId, - }; - }); - - const actualResult = await action({ userId }); - - const expectedResult = { - data: { - userId, - }, - }; - - assert.deepStrictEqual(actualResult, expectedResult); -}); - -test("typeschema - action with input schema extended via async function and return data gives back an object with correct `data`", async () => { - const userId = "ed6f5b84-6bca-4d01-9a51-c3d0c49a7996"; - const password = "password"; - - const action = ac - .schema(z.object({ password: z.string() })) - .schema(async (prevSchema) => prevSchema.extend({ userId: z.string().uuid() })) - .action(async ({ parsedInput }) => { - return { - userId: parsedInput.userId, - password: parsedInput.password, - }; - }); - - const actualResult = await action({ password, userId }); - - const expectedResult = { - data: { - password, - userId, - }, - }; - - assert.deepStrictEqual(actualResult, expectedResult); -}); - -test("typeschema - action with no input schema, bind args input schemas and return data gives back an object with correct `data`", async () => { - const username = "johndoe"; - const age = 30; - - const action = ac - .bindArgsSchemas<[username: z.ZodString, age: z.ZodNumber]>([z.string(), z.number()]) - .action(async ({ bindArgsParsedInputs: [username, age] }) => { - return { - username, - age, - }; - }); - - const actualResult = await action(username, age); - - const expectedResult = { - data: { - username, - age, - }, - }; - - assert.deepStrictEqual(actualResult, expectedResult); -}); - -test("typeschema - action with input schema, bind args input schemas and return data gives back an object with correct `data`", async () => { - const userId = "ed6f5b84-6bca-4d01-9a51-c3d0c49a7996"; - const username = "johndoe"; - const age = 30; - - const action = ac - .schema(z.object({ userId: z.string().uuid() })) - .bindArgsSchemas<[username: z.ZodString, age: z.ZodNumber]>([z.string(), z.number()]) - .action(async ({ parsedInput, bindArgsParsedInputs: [username, age] }) => { - return { - userId: parsedInput.userId, - username, - age, - }; - }); - - const actualResult = await action(username, age, { userId }); - - const expectedResult = { - data: { - username, - age, - userId, - }, - }; - - assert.deepStrictEqual(actualResult, expectedResult); -}); diff --git a/packages/next-safe-action/src/__tests__/typeschema/metadata.test.ts b/packages/next-safe-action/src/__tests__/typeschema/metadata.test.ts deleted file mode 100644 index 7b7e7516..00000000 --- a/packages/next-safe-action/src/__tests__/typeschema/metadata.test.ts +++ /dev/null @@ -1,80 +0,0 @@ -/* eslint-disable @typescript-eslint/no-floating-promises */ - -import assert from "node:assert"; -import { test } from "node:test"; -import { z } from "zod"; -import { DEFAULT_SERVER_ERROR_MESSAGE, createSafeActionClient } from "../../typeschema"; - -const ac = createSafeActionClient({ - handleServerErrorLog() {}, // disable server errors logging for these tests - defineMetadataSchema() { - return z.object({ - actionName: z.string(), - }); - }, -}); - -test("typeschema - action with expected metadata format works", async () => { - const md = { actionName: "testAction" }; - const action = ac.metadata(md).action(async ({ metadata }) => { - return { - metadata, - }; - }); - - const actualResult = await action(); - const expectedResult = { - data: { - metadata: md, - }, - }; - - assert.deepStrictEqual(actualResult, expectedResult); -}); - -test("typeschema - action without expected metadata returns server error", async () => { - const action = ac.action(async ({ metadata }) => { - return { - metadata, - }; - }); - - const actualResult = await action(); - const expectedResult = { - serverError: DEFAULT_SERVER_ERROR_MESSAGE, - }; - - assert.deepStrictEqual(actualResult, expectedResult); -}); - -test("typeschema - metadata is passed to middleware functions and server code function", async () => { - const md = { actionName: "testAction" }; - - const action = ac - .use(async ({ metadata, next }) => { - return next({ ctx: { md1: metadata } }); - }) - .use(async ({ metadata, next, ctx }) => { - return next({ ctx: { ...ctx, md2: metadata } }); - }) - .metadata(md) - .action(async ({ metadata: md3, ctx: { md1, md2 } }) => { - return { - md1, - md2, - md3, - }; - }); - - const actualResult = await action(); - - const expectedResult = { - data: { - md1: md, - md2: md, - md3: md, - }, - }; - - assert.deepStrictEqual(actualResult, expectedResult); -}); diff --git a/packages/next-safe-action/src/__tests__/typeschema/middleware.test.ts b/packages/next-safe-action/src/__tests__/typeschema/middleware.test.ts deleted file mode 100644 index 510cf587..00000000 --- a/packages/next-safe-action/src/__tests__/typeschema/middleware.test.ts +++ /dev/null @@ -1,393 +0,0 @@ -/* eslint-disable @typescript-eslint/no-floating-promises */ - -import assert from "node:assert"; -import { test } from "node:test"; -import { z } from "zod"; -import { - createSafeActionClient, - formatBindArgsValidationErrors, - formatValidationErrors, - returnValidationErrors, -} from "../../typeschema"; - -const ac = createSafeActionClient({ - handleServerErrorLog() {}, // disable server errors logging for these tests - handleReturnedServerError(e) { - return { - message: e.message, - }; - }, -}).use(async ({ next }) => { - return next({ ctx: { foo: "bar" } }); -}); - -test("typeschema - instance context value is accessible in server code function", async () => { - const action = ac.action(async ({ ctx }) => { - return { - ctx, - }; - }); - - const actualResult = await action(); - const expectedResult = { - data: { - ctx: { foo: "bar" }, - }, - }; - - assert.deepStrictEqual(actualResult, expectedResult); -}); - -test("typeschema - instance context value is extended in action middleware and both values are accessible in server code function", async () => { - const action = ac - .use(async ({ next, ctx }) => { - return next({ ctx: { ...ctx, bar: "baz" } }); - }) - .action(async ({ ctx }) => { - return { - ctx, - }; - }); - - const actualResult = await action(); - const expectedResult = { - data: { - ctx: { foo: "bar", bar: "baz" }, - }, - }; - - assert.deepStrictEqual(actualResult, expectedResult); -}); - -test("typeschema - instance context value is correctly overridden in subsequent middleware", async () => { - const action = ac - .use(async ({ next }) => { - return next({ ctx: { foo: "baz" } }); - }) - .use(async ({ ctx, next }) => { - if (ctx.foo !== "baz") { - throw new Error("Expected ctx.foo to be 'baz'"); - } - return next({ ctx }); - }) - .action(async ({ ctx }) => { - return { - ctx, - }; - }); - - const actualResult = await action(); - const expectedResult = { - data: { - ctx: { foo: "baz" }, - }, - }; - - assert.deepStrictEqual(actualResult, expectedResult); -}); - -test("typeschema - action client inputs are passed to middleware", async () => { - const action = ac - .schema(async () => - z.object({ - username: z.string(), - }) - ) - .bindArgsSchemas([z.object({ age: z.number().positive() })]) - .use(async ({ clientInput, bindArgsClientInputs, next, ctx }) => { - return next({ ctx: { ...ctx, clientInput, bindArgsClientInputs } }); - }) - .action(async ({ ctx }) => { - return { - clientInput: ctx.clientInput, - bindArgsClientInputs: ctx.bindArgsClientInputs, - }; - }); - - const inputs = [{ age: 30 }, { username: "johndoe" }] as const; - - const actualResult = await action(...inputs); - - const expectedResult = { - data: { - bindArgsClientInputs: [inputs[0]], - clientInput: inputs[1], - }, - }; - - assert.deepStrictEqual(actualResult, expectedResult); -}); - -test("typeschema - happy path execution result from middleware is correct", async () => { - let middlewareResult = {}; - - const action = ac - .schema(async () => - z.object({ - username: z.string(), - }) - ) - .bindArgsSchemas([z.object({ age: z.number().positive() })]) - .use(async ({ next, ctx }) => { - // Await action execution. - const res = await next({ ctx }); - middlewareResult = res; - return res; - }) - .action(async () => { - return { - ok: "123", - }; - }); - - const inputs = [{ age: 30 }, { username: "johndoe" }] as const; - await action(...inputs); - - const expectedResult = { - success: true, - ctx: { - foo: "bar", - }, - data: { - ok: "123", - }, - parsedInput: { - username: "johndoe", - }, - bindArgsParsedInputs: [ - { - age: 30, - }, - ], - }; - - assert.deepStrictEqual(middlewareResult, expectedResult); -}); - -test("typeschema - server error execution result from middleware is correct", async () => { - let middlewareResult = {}; - - const action = ac - .schema(async () => - z.object({ - username: z.string(), - }) - ) - .bindArgsSchemas([z.object({ age: z.number().positive() })]) - .use(async ({ next, ctx }) => { - // Await action execution. - const res = await next({ ctx }); - middlewareResult = res; - return res; - }) - .action(async () => { - throw new Error("Server error message"); - }); - - const inputs = [{ age: 30 }, { username: "johndoe" }] as const; - await action(...inputs); - - const expectedResult = { - success: false, - ctx: { - foo: "bar", - }, - serverError: { - message: "Server error message", - }, - }; - - assert.deepStrictEqual(middlewareResult, expectedResult); -}); - -test("typeschema - validation errors in execution result from middleware are correct", async () => { - let middlewareResult = {}; - - const action = ac - .schema(async () => - z.object({ - username: z.string().max(3), - }) - ) - .bindArgsSchemas([z.object({ age: z.number().positive() })]) - .use(async ({ next, ctx }) => { - // Await action execution. - const res = await next({ ctx }); - middlewareResult = res; - return res; - }) - .action(async () => { - return { - ok: "123", - }; - }); - - const inputs = [{ age: -30 }, { username: "johndoe" }] as const; - await action(...inputs); - - const expectedResult = { - success: false, - ctx: { - foo: "bar", - }, - validationErrors: { - username: { - _errors: ["String must contain at most 3 character(s)"], - }, - }, - bindArgsValidationErrors: [ - { - age: { - _errors: ["Number must be greater than 0"], - }, - }, - ], - }; - - assert.deepStrictEqual(middlewareResult, expectedResult); -}); - -test("typeschema - server validation errors in execution result from middleware are correct", async () => { - let middlewareResult = {}; - - const schema = z.object({ - username: z.string(), - }); - - const action = ac - .schema(schema) - .bindArgsSchemas([z.object({ age: z.number().positive() })]) - .use(async ({ next, ctx }) => { - // Await action execution. - const res = await next({ ctx }); - middlewareResult = res; - return res; - }) - .action(async () => { - returnValidationErrors(schema, { - username: { - _errors: ["User suspended"], - }, - }); - }); - - const inputs = [{ age: 30 }, { username: "johndoe" }] as const; - await action(...inputs); - - const expectedResult = { - success: false, - ctx: { - foo: "bar", - }, - validationErrors: { - username: { - _errors: ["User suspended"], - }, - }, - }; - - assert.deepStrictEqual(middlewareResult, expectedResult); -}); - -// Flattened validation errors shape. - -const flac = createSafeActionClient({ - handleServerErrorLog() {}, // disable server errors logging for these tests - defaultValidationErrorsShape: "flattened", -}); - -test("typeschema - flattened validation errors in execution result from middleware are correct", async () => { - let middlewareResult = {}; - - const action = flac - .schema(async () => - z.object({ - username: z.string().max(3), - }) - ) - .bindArgsSchemas([z.object({ age: z.number().positive() })]) - .use(async ({ next, ctx }) => { - // Await action execution. - const res = await next({ ctx }); - middlewareResult = res; - return res; - }) - .action(async () => { - return { - ok: "123", - }; - }); - - const inputs = [{ age: -30 }, { username: "johndoe" }] as const; - await action(...inputs); - - const expectedResult = { - success: false, - ctx: undefined, - validationErrors: { - formErrors: [], - fieldErrors: { - username: ["String must contain at most 3 character(s)"], - }, - }, - bindArgsValidationErrors: [ - { - formErrors: [], - fieldErrors: { - age: ["Number must be greater than 0"], - }, - }, - ], - }; - - assert.deepStrictEqual(middlewareResult, expectedResult); -}); - -test("typeschema - overridden formatted validation errors in execution result from middleware are correct", async () => { - let middlewareResult = {}; - - const action = flac - .schema( - async () => - z.object({ - username: z.string().max(3), - }), - { handleValidationErrorsShape: formatValidationErrors } - ) - .bindArgsSchemas([z.object({ age: z.number().positive() })], { - handleBindArgsValidationErrorsShape: formatBindArgsValidationErrors, - }) - .use(async ({ next, ctx }) => { - // Await action execution. - const res = await next({ ctx }); - middlewareResult = res; - return res; - }) - .action(async () => { - return { - ok: "123", - }; - }); - - const inputs = [{ age: -30 }, { username: "johndoe" }] as const; - await action(...inputs); - - const expectedResult = { - success: false, - ctx: undefined, - validationErrors: { - username: { - _errors: ["String must contain at most 3 character(s)"], - }, - }, - bindArgsValidationErrors: [ - { - age: { - _errors: ["Number must be greater than 0"], - }, - }, - ], - }; - - assert.deepStrictEqual(middlewareResult, expectedResult); -}); diff --git a/packages/next-safe-action/src/__tests__/typeschema/server-error.test.ts b/packages/next-safe-action/src/__tests__/typeschema/server-error.test.ts deleted file mode 100644 index 08386eff..00000000 --- a/packages/next-safe-action/src/__tests__/typeschema/server-error.test.ts +++ /dev/null @@ -1,168 +0,0 @@ -/* eslint-disable @typescript-eslint/no-floating-promises */ - -import assert from "node:assert"; -import { test } from "node:test"; -import { DEFAULT_SERVER_ERROR_MESSAGE, createSafeActionClient } from "../../typeschema"; - -class ActionError extends Error { - constructor(message: string) { - super(message); - } -} - -const ac1 = createSafeActionClient({ - handleServerErrorLog: () => {}, // disable server errors logging for these tests - handleReturnedServerError(e) { - if (e instanceof ActionError) { - return e.message; - } - - return DEFAULT_SERVER_ERROR_MESSAGE; - }, -}); - -test("typeschema - unknown error occurred in server code function is masked by default", async () => { - const action = ac1.action(async () => { - throw new Error("Something bad happened"); - }); - - const actualResult = await action(); - - const expectedResult = { - serverError: DEFAULT_SERVER_ERROR_MESSAGE, - }; - - assert.deepStrictEqual(actualResult, expectedResult); -}); - -test("typeschema - unknown error occurred in middleware function is masked by default", async () => { - const action = ac1 - .use(async ({ next, ctx }) => next({ ctx })) - .use(async () => { - throw new Error("Something bad happened"); - }) - .action(async () => { - return { - ok: true, - }; - }); - - const actualResult = await action(); - - const expectedResult = { - serverError: DEFAULT_SERVER_ERROR_MESSAGE, - }; - - assert.deepStrictEqual(actualResult, expectedResult); -}); - -test("typeschema - known error occurred in server code function is unmasked", async () => { - const action = ac1.action(async () => { - throw new ActionError("Something bad happened"); - }); - - const actualResult = await action(); - - const expectedResult = { - serverError: "Something bad happened", - }; - - assert.deepStrictEqual(actualResult, expectedResult); -}); - -test("typeschema - known error occurred in middleware function is unmasked", async () => { - const action = ac1 - .use(async ({ next, ctx }) => next({ ctx })) - .use(async () => { - throw new ActionError("Something bad happened"); - }) - .action(async () => { - return { - ok: true, - }; - }); - - const actualResult = await action(); - - const expectedResult = { - serverError: "Something bad happened", - }; - - assert.deepStrictEqual(actualResult, expectedResult); -}); - -// Server error is an object with a 'message' property. -const ac2 = createSafeActionClient({ - handleServerErrorLog: () => {}, // disable server errors logging for these tests - handleReturnedServerError(e) { - return { - message: e.message, - }; - }, -}); - -test("typeschema - error occurred in server code function has the correct shape defined by `handleReturnedServerError`", async () => { - const action = ac2.action(async () => { - throw new Error("Something bad happened"); - }); - - const actualResult = await action(); - - const expectedResult = { - serverError: { message: "Something bad happened" }, - }; - - assert.deepStrictEqual(actualResult, expectedResult); -}); - -test("typeschema - error occurred in middleware function has the correct shape defined by `handleReturnedServerError`", async () => { - const action = ac2 - .use(async ({ next, ctx }) => next({ ctx })) - .use(async () => { - throw new Error("Something bad happened"); - }) - .action(async () => { - return { - ok: true, - }; - }); - - const actualResult = await action(); - - const expectedResult = { - serverError: { message: "Something bad happened" }, - }; - - assert.deepStrictEqual(actualResult, expectedResult); -}); - -// Rethrow all server errors. -const ac3 = createSafeActionClient({ - handleServerErrorLog: () => {}, // disable server errors logging for these tests - handleReturnedServerError(e) { - throw e; - }, -}); - -test("typeschema - action throws if an error occurred in server code function and `handleReturnedServerError` rethrows it", async () => { - const action = ac3.action(async () => { - throw new Error("Something bad happened"); - }); - - assert.rejects(() => action()); -}); - -test("typeschema - action throws if an error occurred in middleware function and `handleReturnedServerError` rethrows it", async () => { - const action = ac3 - .use(async ({ next, ctx }) => next({ ctx })) - .use(async () => { - throw new Error("Something bad happened"); - }) - .action(async () => { - return { - ok: true, - }; - }); - - assert.rejects(() => action()); -}); diff --git a/packages/next-safe-action/src/__tests__/typeschema/validation-errors.test.ts b/packages/next-safe-action/src/__tests__/typeschema/validation-errors.test.ts deleted file mode 100644 index 3ba7ed68..00000000 --- a/packages/next-safe-action/src/__tests__/typeschema/validation-errors.test.ts +++ /dev/null @@ -1,581 +0,0 @@ -/* eslint-disable @typescript-eslint/no-floating-promises */ - -import assert from "node:assert"; -import { test } from "node:test"; -import { z } from "zod"; -import { - createSafeActionClient, - flattenValidationErrors, - formatValidationErrors, - returnValidationErrors, -} from "../../typeschema"; - -// Default client tests. - -const dac = createSafeActionClient(); - -test("typeschema - action with invalid input gives back an object with correct `validationErrors` (default formatted shape)", async () => { - const schema = z.object({ - user: z.object({ - id: z.string().min(36).uuid(), - }), - store: z.object({ - id: z.string().min(36).uuid(), - product: z.object({ - id: z.string().min(36).uuid(), - }), - }), - }); - - const action = dac.schema(schema).action(async () => { - return { - ok: true, - }; - }); - - const actualResult = await action({ - user: { - id: "invalid_uuid", - }, - store: { - id: "invalid_uuid", - product: { - id: "invalid_uuid", - }, - }, - }); - - const expectedResult = { - validationErrors: { - user: { - id: { - _errors: ["String must contain at least 36 character(s)", "Invalid uuid"], - }, - }, - store: { - id: { - _errors: ["String must contain at least 36 character(s)", "Invalid uuid"], - }, - product: { - id: { - _errors: ["String must contain at least 36 character(s)", "Invalid uuid"], - }, - }, - }, - }, - }; - - assert.deepStrictEqual(actualResult, expectedResult); -}); - -test("typeschema - action with root level schema error gives back an object with correct `validationErrors` (default formatted shape)", async () => { - const userId = "invalid_uuid"; - - // Test with async function that returns the schema. - async function getSchema() { - return z - .object({ - userId: z.string().min(36).uuid(), - password: z.string(), - confirmPassword: z.string(), - }) - .refine((d) => d.password === d.confirmPassword, { - message: "Passwords do not match", - }); - } - - const action = dac.schema(getSchema).action(async () => { - return { - ok: true, - }; - }); - - const actualResult = await action({ - userId, - password: "test123", - confirmPassword: "test456", - }); - - const expectedResult = { - validationErrors: { - _errors: ["Passwords do not match"], - userId: { - _errors: ["String must contain at least 36 character(s)", "Invalid uuid"], - }, - }, - }; - - assert.deepStrictEqual(actualResult, expectedResult); -}); - -test("typeschema - action with invalid input gives back an object with correct `validationErrors` (default formatted shape overridden by custom flattened shape)", async () => { - const schema = z - .object({ - userId: z.string().min(36).uuid(), - storeId: z.string().min(36).uuid(), - }) - .refine((d) => d.userId !== d.storeId, { - message: "User id and store id cannot be the same", - }); - - const action = dac - .schema(schema, { - handleValidationErrorsShape: flattenValidationErrors, - }) - .action(async () => { - return { - ok: true, - }; - }); - - const actualResult = await action({ - userId: "invalid_uuid", - storeId: "invalid_uuid", - }); - - const expectedResult = { - validationErrors: { - formErrors: ["User id and store id cannot be the same"], - fieldErrors: { - userId: ["String must contain at least 36 character(s)", "Invalid uuid"], - storeId: ["String must contain at least 36 character(s)", "Invalid uuid"], - }, - }, - }; - - assert.deepStrictEqual(actualResult, expectedResult); -}); - -// Formatted shape tests (same as default). - -const foac = createSafeActionClient({ - defaultValidationErrorsShape: "formatted", -}); - -test("typeschema - action with invalid input gives back an object with correct `validationErrors` (set formatted shape)", async () => { - const schema = z.object({ - user: z.object({ - id: z.string().min(36).uuid(), - }), - store: z.object({ - id: z.string().min(36).uuid(), - product: z.object({ - id: z.string().min(36).uuid(), - }), - }), - }); - - const action = foac.schema(schema).action(async () => { - return { - ok: true, - }; - }); - - const actualResult = await action({ - user: { - id: "invalid_uuid", - }, - store: { - id: "invalid_uuid", - product: { - id: "invalid_uuid", - }, - }, - }); - - const expectedResult = { - validationErrors: { - user: { - id: { - _errors: ["String must contain at least 36 character(s)", "Invalid uuid"], - }, - }, - store: { - id: { - _errors: ["String must contain at least 36 character(s)", "Invalid uuid"], - }, - product: { - id: { - _errors: ["String must contain at least 36 character(s)", "Invalid uuid"], - }, - }, - }, - }, - }; - - assert.deepStrictEqual(actualResult, expectedResult); -}); - -test("typeschema - action with root level schema error gives back an object with correct `validationErrors` (set formatted shape)", async () => { - const userId = "invalid_uuid"; - - const schema = z - .object({ - userId: z.string().uuid(), - password: z.string(), - confirmPassword: z.string(), - }) - .refine((d) => d.password === d.confirmPassword, { - message: "Passwords do not match", - }) - .refine((d) => d.userId === "488d92e3-d394-4db8-b7c0-7b38c85280c1", { - message: "UUID mismatch", - }); - - const action = foac.schema(schema).action(async () => { - return { - ok: true, - }; - }); - - const actualResult = await action({ - userId, - password: "test123", - confirmPassword: "test456", - }); - - const expectedResult = { - validationErrors: { - _errors: ["Passwords do not match", "UUID mismatch"], - userId: { - _errors: ["Invalid uuid"], - }, - }, - }; - - assert.deepStrictEqual(actualResult, expectedResult); -}); - -test("typeschema - action with invalid input gives back an object with correct `validationErrors` (set formatted shape overridden by custom flattened shape)", async () => { - const schema = z - .object({ - userId: z.string().min(36).uuid(), - storeId: z.string().min(36).uuid(), - }) - .refine((d) => d.userId !== d.storeId, { - message: "User id and store id cannot be the same", - }); - - const action = foac - .schema(schema, { - handleValidationErrorsShape: flattenValidationErrors, - }) - .action(async () => { - return { - ok: true, - }; - }); - - const actualResult = await action({ - userId: "invalid_uuid", - storeId: "invalid_uuid", - }); - - const expectedResult = { - validationErrors: { - formErrors: ["User id and store id cannot be the same"], - fieldErrors: { - userId: ["String must contain at least 36 character(s)", "Invalid uuid"], - storeId: ["String must contain at least 36 character(s)", "Invalid uuid"], - }, - }, - }; - - assert.deepStrictEqual(actualResult, expectedResult); -}); - -// Flattened shape tests. - -const flac = createSafeActionClient({ - defaultValidationErrorsShape: "flattened", -}); - -test("typeschema - action with invalid input gives back an object with correct `validationErrors` (set flattened shape)", async () => { - const schema = z.object({ - userId: z.string().min(36).uuid(), - storeId: z.string().min(36).uuid(), - store: z.object({ - product: z.object({ - id: z.string().uuid(), - }), - }), - }); - - const action = flac.schema(schema).action(async () => { - return { - ok: true, - }; - }); - - const actualResult = await action({ - userId: "invalid_uuid", - storeId: "invalid_uuid", - store: { - product: { - id: "invalid_uuid", - }, - }, - }); - - // Flattened shape discards errors for nested properties. - const expectedResult = { - validationErrors: { - formErrors: [], - fieldErrors: { - userId: ["String must contain at least 36 character(s)", "Invalid uuid"], - storeId: ["String must contain at least 36 character(s)", "Invalid uuid"], - }, - }, - }; - - assert.deepStrictEqual(actualResult, expectedResult); -}); - -test("typeschema - action with root level schema error gives back an object with correct `validationErrors` (set flattened shape)", async () => { - const schema = z - .object({ - userId: z.string().min(36).uuid(), - storeId: z.string().min(36).uuid(), - store: z.object({ - product: z.object({ - id: z.string().uuid(), - }), - }), - }) - .refine((d) => d.userId !== d.storeId, { - message: "User and store IDs must be different", - }) - .refine((d) => d.userId !== d.storeId, { - message: "Another cool global error", - }); - - const action = flac.schema(schema).action(async () => { - return { - ok: true, - }; - }); - - const actualResult = await action({ - userId: "invalid_uuid", - storeId: "invalid_uuid", - store: { - product: { - id: "invalid_uuid", - }, - }, - }); - - // Flattened shape discards errors for nested properties. - const expectedResult = { - validationErrors: { - formErrors: ["User and store IDs must be different", "Another cool global error"], - fieldErrors: { - userId: ["String must contain at least 36 character(s)", "Invalid uuid"], - storeId: ["String must contain at least 36 character(s)", "Invalid uuid"], - }, - }, - }; - - assert.deepStrictEqual(actualResult, expectedResult); -}); - -test("typeschema - action with invalid input gives back an object with correct `validationErrors` (set flattened shape overridden by custom formatted shape)", async () => { - const schema = z - .object({ - userId: z.string().min(36).uuid(), - storeId: z.string().min(36).uuid(), - }) - .refine((d) => d.userId !== d.storeId, { - message: "User id and store id cannot be the same", - }); - - const action = flac - .schema(schema, { - handleValidationErrorsShape: formatValidationErrors, - }) - .action(async () => { - return { - ok: true, - }; - }); - - const actualResult = await action({ - userId: "invalid_uuid", - storeId: "invalid_uuid", - }); - - const expectedResult = { - validationErrors: { - _errors: ["User id and store id cannot be the same"], - userId: { - _errors: ["String must contain at least 36 character(s)", "Invalid uuid"], - }, - storeId: { - _errors: ["String must contain at least 36 character(s)", "Invalid uuid"], - }, - }, - }; - - assert.deepStrictEqual(actualResult, expectedResult); -}); - -// `returnValidationErrors` tests. - -test("typeschema - action with errors set via `returnValidationErrors` gives back an object with correct `validationErrors` (default formatted shape)", async () => { - const schema = z.object({ - username: z.string(), - password: z.string(), - }); - - const errorsObject = { - _errors: ["incorrect_credentials", "another_error"], - username: { - _errors: ["user_suspended"], - }, - password: { - _errors: ["invalid_password"], - }, - }; - - const action = dac.schema(schema).action(async ({ parsedInput }) => { - if (parsedInput.username !== "johndoe" && parsedInput.password !== "password") { - returnValidationErrors(schema, structuredClone(errorsObject)); - } - - return { - ok: true, - }; - }); - - const actualResult = await action({ - username: "123", - password: "456", - }); - - const expectedResult = { - validationErrors: structuredClone(errorsObject), - }; - - assert.deepStrictEqual(actualResult, expectedResult); -}); - -test("typeschema - action with errors set via `returnValidationErrors` gives back an object with correct `validationErrors` (set formatted shape)", async () => { - const schema = z.object({ - username: z.string(), - password: z.string(), - }); - - const errorsObject = { - _errors: ["incorrect_credentials", "another_error"], - username: { - _errors: ["user_suspended"], - }, - password: { - _errors: ["invalid_password"], - }, - }; - - const action = foac.schema(schema).action(async ({ parsedInput }) => { - if (parsedInput.username !== "johndoe" && parsedInput.password !== "password") { - returnValidationErrors(schema, structuredClone(errorsObject)); - } - - return { - ok: true, - }; - }); - - const actualResult = await action({ - username: "123", - password: "456", - }); - - const expectedResult = { - validationErrors: structuredClone(errorsObject), - }; - - assert.deepStrictEqual(actualResult, expectedResult); -}); - -test("typeschema - action with errors set via `returnValidationErrors` gives back an object with correct `validationErrors` (set flattened shape)", async () => { - const schema = z.object({ - username: z.string(), - password: z.string(), - }); - - const action = flac.schema(schema).action(async ({ parsedInput }) => { - if (parsedInput.username !== "johndoe" && parsedInput.password !== "password") { - returnValidationErrors(schema, { - _errors: ["incorrect_credentials", "another_error"], - username: { - _errors: ["user_suspended"], - }, - password: { - _errors: ["invalid_password"], - }, - }); - } - - return { - ok: true, - }; - }); - - const actualResult = await action({ - username: "123", - password: "456", - }); - - const expectedResult = { - validationErrors: { - formErrors: ["incorrect_credentials", "another_error"], - fieldErrors: { - username: ["user_suspended"], - password: ["invalid_password"], - }, - }, - }; - - assert.deepStrictEqual(actualResult, expectedResult); -}); - -// `throwValidationErrors` tests. - -const tveac = createSafeActionClient({ - throwValidationErrors: true, -}); - -test("typeschema - action with validation errors and `throwValidationErrors` option set to true in client throws", async () => { - const schema = z.object({ - username: z.string().min(3), - password: z.string().min(3), - }); - - const action = tveac.schema(schema).action(async () => { - return { - ok: true, - }; - }); - - assert.rejects(async () => await action({ username: "12", password: "34" })); -}); - -test("typeschema - action with server validation errors and `throwValidationErrors` option set to true in client throws", async () => { - const schema = z.object({ - username: z.string().min(3), - password: z.string().min(3), - }); - - const action = tveac.schema(schema).action(async () => { - returnValidationErrors(schema, { - username: { - _errors: ["user_suspended"], - }, - }); - return { - ok: true, - }; - }); - - assert.rejects(async () => await action({ username: "1234", password: "5678" })); -}); diff --git a/packages/next-safe-action/src/__tests__/validation-errors.test.ts b/packages/next-safe-action/src/__tests__/validation-errors.test.ts index 2910fd86..25e83adf 100644 --- a/packages/next-safe-action/src/__tests__/validation-errors.test.ts +++ b/packages/next-safe-action/src/__tests__/validation-errors.test.ts @@ -4,10 +4,13 @@ import assert from "node:assert"; import { test } from "node:test"; import { z } from "zod"; import { createSafeActionClient, flattenValidationErrors, formatValidationErrors, returnValidationErrors } from ".."; +import { zodAdapter } from "../adapters/zod"; // Default client tests. -const dac = createSafeActionClient(); +const dac = createSafeActionClient({ + validationAdapter: zodAdapter(), +}); test("action with invalid input gives back an object with correct `validationErrors` (default formatted shape)", async () => { const schema = z.object({ @@ -144,6 +147,7 @@ test("action with invalid input gives back an object with correct `validationErr // Formatted shape tests (same as default). const foac = createSafeActionClient({ + validationAdapter: zodAdapter(), defaultValidationErrorsShape: "formatted", }); @@ -282,6 +286,7 @@ test("action with invalid input gives back an object with correct `validationErr // Flattened shape tests. const flac = createSafeActionClient({ + validationAdapter: zodAdapter(), defaultValidationErrorsShape: "flattened", }); @@ -537,6 +542,7 @@ test("action with errors set via `returnValidationErrors` gives back an object w // `throwValidationErrors` tests. const tveac = createSafeActionClient({ + validationAdapter: zodAdapter(), throwValidationErrors: true, }); diff --git a/packages/next-safe-action/src/action-builder.ts b/packages/next-safe-action/src/action-builder.ts index 8c3cd0a8..85ef67f0 100644 --- a/packages/next-safe-action/src/action-builder.ts +++ b/packages/next-safe-action/src/action-builder.ts @@ -1,8 +1,7 @@ -import type { InferIn } from "@typeschema/main"; -import { validate, type Infer, type Schema } from "@typeschema/main"; import { isNotFoundError } from "next/dist/client/components/not-found.js"; import { isRedirectError } from "next/dist/client/components/redirect.js"; import type {} from "zod"; +import type { Infer, InferArray, InferIn, InferInArray, Schema, ValidationAdapter } from "./adapters/types"; import type { MiddlewareFn, MiddlewareResult, @@ -14,9 +13,8 @@ import type { ServerCodeFn, StateServerCodeFn, } from "./index.types"; -import type { InferArray, InferInArray } from "./utils"; -import { ActionMetadataError, DEFAULT_SERVER_ERROR_MESSAGE, isError, zodValidate } from "./utils"; -import { ActionValidationError, buildValidationErrors } from "./validation-errors"; +import { ActionMetadataError, DEFAULT_SERVER_ERROR_MESSAGE, isError } from "./utils"; +import { ActionServerValidationError, ActionValidationError, buildValidationErrors } from "./validation-errors"; import type { BindArgsValidationErrors, HandleBindArgsValidationErrorsShapeFn, @@ -37,6 +35,7 @@ export function actionBuilder< >(args: { schemaFn?: SF; bindArgsSchemas?: BAS; + validationAdapter: ValidationAdapter; handleValidationErrorsShape: HandleValidationErrorsShapeFn; handleBindArgsValidationErrorsShape: HandleBindArgsValidationErrorsShapeFn; metadataSchema: MetadataSchema; @@ -47,7 +46,6 @@ export function actionBuilder< >; middlewareFns: MiddlewareFn[]; ctxType: Ctx; - validationStrategy: "typeschema" | "zod"; throwValidationErrors: boolean; }) { const bindArgsSchemas = (args.bindArgsSchemas ?? []) as BAS; @@ -77,7 +75,6 @@ export function actionBuilder< const middlewareResult: MiddlewareResult = { success: false }; type PrevResult = SafeActionResult | undefined; let prevResult: PrevResult | undefined = undefined; - const valFn = args.validationStrategy === "zod" ? zodValidate : validate; const parsedInputDatas: any[] = []; let frameworkError: Error | null = null; @@ -108,7 +105,7 @@ export function actionBuilder< if (idx === 0) { if (args.metadataSchema) { // Validate metadata input. - if (!(await valFn(args.metadataSchema, args.metadata)).success) { + if (!(await args.validationAdapter.validate(args.metadataSchema, args.metadata)).success) { throw new ActionMetadataError( "Invalid metadata input. Please be sure to pass metadata via `metadata` method before defining the action." ); @@ -145,11 +142,11 @@ export function actionBuilder< } // Otherwise, parse input with the schema. - return valFn(await args.schemaFn(), input); + return args.validationAdapter.validate(await args.schemaFn(), input); } // Otherwise, we're processing bind args client inputs. - return valFn(bindArgsSchemas[i]!, input); + return args.validationAdapter.validate(bindArgsSchemas[i]!, input); }) ); @@ -226,15 +223,7 @@ export function actionBuilder< } // If error is `ActionServerValidationError`, return `validationErrors` as if schema validation would fail. - // Shouldn't be this difficult to check for `ActionServerValidationError`, but /typeschema clients fail - // if it's not done this way. - if ( - e instanceof Error && - "kind" in e && - "validationErrors" in e && - typeof e.kind === "string" && - e.kind === "__actionServerValidationError" - ) { + if (e instanceof ActionServerValidationError) { const ve = e.validationErrors as ValidationErrors; middlewareResult.validationErrors = await Promise.resolve(args.handleValidationErrorsShape(ve)); } else { diff --git a/packages/next-safe-action/src/adapters/types.ts b/packages/next-safe-action/src/adapters/types.ts new file mode 100644 index 00000000..8a0bda61 --- /dev/null +++ b/packages/next-safe-action/src/adapters/types.ts @@ -0,0 +1,74 @@ +// Code courtesy of/highly inspired by https://github.com/decs/typeschema + +import type { GenericSchema, GenericSchemaAsync, InferInput, InferOutput } from "valibot"; +import type { InferType, Schema as YupSchema } from "yup"; +import type { z } from "zod"; + +export type IfInstalled = any extends T ? never : T; + +export type Schema = + | IfInstalled + | IfInstalled + | IfInstalled + | IfInstalled; + +export type Infer = + S extends IfInstalled + ? z.infer + : S extends IfInstalled + ? InferOutput + : S extends IfInstalled + ? InferOutput + : S extends IfInstalled + ? InferType + : never; + +export type InferIn = + S extends IfInstalled + ? z.input + : S extends IfInstalled + ? InferInput + : S extends IfInstalled + ? InferInput + : S extends IfInstalled + ? InferType + : never; + +export type InferArray = { + [K in keyof BAS]: Infer; +}; +export type InferInArray = { + [K in keyof BAS]: InferIn; +}; + +export type ValidationIssue = { + message: string; + path?: Array; +}; + +export interface ValidationAdapter { + // generic + validate( + schema: S, + data: unknown + ): Promise<{ success: true; data: Infer } | { success: false; issues: ValidationIssue[] }>; + // zod + validate>( + schema: S, + data: unknown + ): Promise<{ success: true; data: Infer } | { success: false; issues: ValidationIssue[] }>; + // valibot + validate>( + schema: S, + data: unknown + ): Promise<{ success: true; data: Infer } | { success: false; issues: ValidationIssue[] }>; + validate>( + schema: S, + data: unknown + ): Promise<{ success: true; data: Infer } | { success: false; issues: ValidationIssue[] }>; + // yup + validate>( + schema: S, + data: unknown + ): Promise<{ success: true; data: Infer } | { success: false; issues: ValidationIssue[] }>; +} diff --git a/packages/next-safe-action/src/adapters/valibot.ts b/packages/next-safe-action/src/adapters/valibot.ts new file mode 100644 index 00000000..8d48a8cd --- /dev/null +++ b/packages/next-safe-action/src/adapters/valibot.ts @@ -0,0 +1,29 @@ +// Code courtesy of https://github.com/decs/typeschema/blob/main/packages/valibot/src/validation.ts + +import { getDotPath, safeParseAsync, type GenericSchema, type GenericSchemaAsync } from "valibot"; +import type { IfInstalled, Infer, ValidationAdapter } from "./types"; + +class ValibotAdapter implements ValidationAdapter { + async validate>(schema: S, data: unknown) { + const result = await safeParseAsync(schema, data); + + if (result.success) { + return { + success: true, + data: result.output as Infer, + } as const; + } + + return { + success: false, + issues: result.issues.map((issue) => ({ + message: issue.message, + path: getDotPath(issue)?.split("."), + })), + } as const; + } +} + +export function valibotAdapter() { + return new ValibotAdapter(); +} diff --git a/packages/next-safe-action/src/adapters/yup.ts b/packages/next-safe-action/src/adapters/yup.ts new file mode 100644 index 00000000..d9ef096b --- /dev/null +++ b/packages/next-safe-action/src/adapters/yup.ts @@ -0,0 +1,38 @@ +// https://github.com/decs/typeschema/blob/main/packages/yup/src/validation.ts + +import type { Schema as YupSchema } from "yup"; +import { ValidationError } from "yup"; +import type { IfInstalled, Infer, ValidationAdapter, ValidationIssue } from "./types"; + +class YupAdapter implements ValidationAdapter { + async validate>(schema: S, data: unknown) { + try { + const result = await schema.validate(data, { strict: true }); + + return { + success: true, + data: result as Infer, + } as const; + } catch (e) { + if (e instanceof ValidationError) { + const { message, path } = e; + + return { + success: false, + issues: [ + { + message, + path: path && path.length > 0 ? [path] : undefined, + }, + ] as ValidationIssue[], + } as const; + } + + throw e; + } + } +} + +export function yupAdapter() { + return new YupAdapter(); +} diff --git a/packages/next-safe-action/src/adapters/zod.ts b/packages/next-safe-action/src/adapters/zod.ts new file mode 100644 index 00000000..f41c0d01 --- /dev/null +++ b/packages/next-safe-action/src/adapters/zod.ts @@ -0,0 +1,28 @@ +// https://github.com/decs/typeschema/blob/main/packages/zod/src/validation.ts + +import type { z } from "zod"; +import type { IfInstalled, Infer, ValidationAdapter } from "./types"; + +export type ZodSchema = z.ZodType; + +class ZodAdapter implements ValidationAdapter { + async validate>(schema: S, data: unknown) { + const result = await schema.safeParseAsync(data); + + if (result.success) { + return { + success: true, + data: result.data as Infer, + } as const; + } + + return { + success: false, + issues: result.error.issues.map(({ message, path }) => ({ message, path })), + } as const; + } +} + +export function zodAdapter() { + return new ZodAdapter(); +} diff --git a/packages/next-safe-action/src/hooks-utils.ts b/packages/next-safe-action/src/hooks-utils.ts index df1e1a3a..c1190ab0 100644 --- a/packages/next-safe-action/src/hooks-utils.ts +++ b/packages/next-safe-action/src/hooks-utils.ts @@ -1,7 +1,7 @@ -import type { InferIn, Schema } from "@typeschema/main"; import * as React from "react"; import {} from "react/experimental"; import type {} from "zod"; +import type { InferIn, Schema } from "./adapters/types"; import type { HookActionStatus, HookCallbacks, HookResult } from "./hooks.types"; export const getActionStatus = < diff --git a/packages/next-safe-action/src/hooks.ts b/packages/next-safe-action/src/hooks.ts index d79d33a3..bfef56e6 100644 --- a/packages/next-safe-action/src/hooks.ts +++ b/packages/next-safe-action/src/hooks.ts @@ -1,12 +1,12 @@ "use client"; -import type { InferIn, Schema } from "@typeschema/main"; import { isNotFoundError } from "next/dist/client/components/not-found.js"; import { isRedirectError } from "next/dist/client/components/redirect.js"; import * as React from "react"; import * as ReactDOM from "react-dom"; import {} from "react/experimental"; import type {} from "zod"; +import type { InferIn, Schema } from "./adapters/types"; import { getActionShorthandStatusObject, getActionStatus, useActionCallbacks } from "./hooks-utils"; import type { HookCallbacks, HookResult, HookSafeActionFn } from "./hooks.types"; import { isError } from "./utils"; @@ -249,4 +249,6 @@ export const useOptimisticAction = < }; }; +export { useStateAction } from "./stateful-hooks"; + export type * from "./hooks.types"; diff --git a/packages/next-safe-action/src/hooks.types.ts b/packages/next-safe-action/src/hooks.types.ts index 0bed2b2d..f285d5d5 100644 --- a/packages/next-safe-action/src/hooks.types.ts +++ b/packages/next-safe-action/src/hooks.types.ts @@ -1,6 +1,6 @@ -import type { InferIn, Schema } from "@typeschema/main"; +import type { InferIn, Schema } from "./adapters/types"; import type { SafeActionResult } from "./index.types"; -import type { MaybePromise, Prettify } from "./utils"; +import type { MaybePromise, Prettify } from "./utils.types"; /** * Type of `result` object returned by `useAction`, `useOptimisticAction` and `useStateAction` hooks. diff --git a/packages/next-safe-action/src/index.ts b/packages/next-safe-action/src/index.ts index 35125384..033c4368 100644 --- a/packages/next-safe-action/src/index.ts +++ b/packages/next-safe-action/src/index.ts @@ -1,4 +1,5 @@ -import type { Infer, Schema } from "@typeschema/main"; +import type { Infer, Schema } from "./adapters/types"; +import { zodAdapter } from "./adapters/zod"; import type { DVES, SafeActionClientOpts } from "./index.types"; import { SafeActionClient } from "./safe-action-client"; import { DEFAULT_SERVER_ERROR_MESSAGE } from "./utils"; @@ -25,8 +26,7 @@ export type * from "./validation-errors.types"; /** * Create a new safe action client. * Note: this client only works with Zod as the validation library. - * If you want to use a validation library supported by [TypeSchema](https://typeschema.com), import this client from `/typeschema` path. - * @param createOpts Optional initialization options + * @param createOpts Initialization options * * {@link https://next-safe-action.dev/docs/safe-action-client/initialization-options See docs for more information} */ @@ -58,9 +58,9 @@ export const createSafeActionClient = < middlewareFns: [async ({ next }) => next({ ctx: undefined })], handleServerErrorLog, handleReturnedServerError, - validationStrategy: "zod", schemaFn: undefined, bindArgsSchemas: [], + validationAdapter: createOpts?.validationAdapter ?? zodAdapter(), // use zod adapter by default ctxType: undefined, metadataSchema: (createOpts?.defineMetadataSchema?.() ?? undefined) as MetadataSchema, metadata: undefined as MetadataSchema extends Schema ? Infer : undefined, diff --git a/packages/next-safe-action/src/index.types.ts b/packages/next-safe-action/src/index.types.ts index 41bc8d25..1cb4a4a3 100644 --- a/packages/next-safe-action/src/index.types.ts +++ b/packages/next-safe-action/src/index.types.ts @@ -1,5 +1,5 @@ -import type { Infer, InferIn, Schema } from "@typeschema/main"; -import type { InferArray, InferInArray, MaybePromise, Prettify } from "./utils"; +import type { Infer, InferArray, InferIn, InferInArray, Schema, ValidationAdapter } from "./adapters/types"; +import type { MaybePromise, Prettify } from "./utils.types"; import type { BindArgsValidationErrors, ValidationErrors } from "./validation-errors.types"; /** @@ -26,6 +26,7 @@ export type SafeActionClientOpts< MetadataSchema extends Schema | undefined, ODVES extends DVES | undefined, > = { + validationAdapter?: ValidationAdapter; defineMetadataSchema?: () => MetadataSchema; handleReturnedServerError?: ( error: Error, diff --git a/packages/next-safe-action/src/safe-action-client.ts b/packages/next-safe-action/src/safe-action-client.ts index 7a85dc10..f0938437 100644 --- a/packages/next-safe-action/src/safe-action-client.ts +++ b/packages/next-safe-action/src/safe-action-client.ts @@ -1,6 +1,6 @@ -import type { Infer, Schema } from "@typeschema/main"; import type {} from "zod"; import { actionBuilder } from "./action-builder"; +import type { Infer, Schema, ValidationAdapter } from "./adapters/types"; import type { DVES, MiddlewareFn, @@ -30,7 +30,6 @@ export class SafeActionClient< CVE = undefined, const CBAVE = undefined, > { - readonly #validationStrategy: "typeschema" | "zod"; readonly #handleServerErrorLog: NonNullable< SafeActionClientOpts["handleServerErrorLog"] >; @@ -43,6 +42,7 @@ export class SafeActionClient< readonly #metadata: MD; readonly #schemaFn: SF; readonly #bindArgsSchemas: BAS; + readonly #validationAdapter: ValidationAdapter; readonly #handleValidationErrorsShape: HandleValidationErrorsShapeFn; readonly #handleBindArgsValidationErrorsShape: HandleBindArgsValidationErrorsShapeFn; readonly #defaultValidationErrorsShape: ODVES; @@ -51,11 +51,11 @@ export class SafeActionClient< constructor( opts: { middlewareFns: MiddlewareFn[]; - validationStrategy: "typeschema" | "zod"; metadataSchema: MetadataSchema; metadata: MD; schemaFn: SF; bindArgsSchemas: BAS; + validationAdapter: ValidationAdapter; handleValidationErrorsShape: HandleValidationErrorsShapeFn; handleBindArgsValidationErrorsShape: HandleBindArgsValidationErrorsShapeFn; ctxType: Ctx; @@ -69,11 +69,11 @@ export class SafeActionClient< this.#middlewareFns = opts.middlewareFns; this.#handleServerErrorLog = opts.handleServerErrorLog; this.#handleReturnedServerError = opts.handleReturnedServerError; - this.#validationStrategy = opts.validationStrategy; this.#metadataSchema = opts.metadataSchema; this.#metadata = opts.metadata; this.#schemaFn = (opts.schemaFn ?? undefined) as SF; this.#bindArgsSchemas = opts.bindArgsSchemas ?? []; + this.#validationAdapter = opts.validationAdapter; this.#handleValidationErrorsShape = opts.handleValidationErrorsShape; this.#handleBindArgsValidationErrorsShape = opts.handleBindArgsValidationErrorsShape; this.#defaultValidationErrorsShape = opts.defaultValidationErrorsShape; @@ -91,11 +91,11 @@ export class SafeActionClient< middlewareFns: [...this.#middlewareFns, middlewareFn], handleReturnedServerError: this.#handleReturnedServerError, handleServerErrorLog: this.#handleServerErrorLog, - validationStrategy: this.#validationStrategy, metadataSchema: this.#metadataSchema, metadata: this.#metadata, schemaFn: this.#schemaFn, bindArgsSchemas: this.#bindArgsSchemas, + validationAdapter: this.#validationAdapter, handleValidationErrorsShape: this.#handleValidationErrorsShape, handleBindArgsValidationErrorsShape: this.#handleBindArgsValidationErrorsShape, ctxType: undefined as NextCtx, @@ -115,11 +115,11 @@ export class SafeActionClient< middlewareFns: this.#middlewareFns, handleReturnedServerError: this.#handleReturnedServerError, handleServerErrorLog: this.#handleServerErrorLog, - validationStrategy: this.#validationStrategy, metadataSchema: this.#metadataSchema, metadata: data, schemaFn: this.#schemaFn, bindArgsSchemas: this.#bindArgsSchemas, + validationAdapter: this.#validationAdapter, handleValidationErrorsShape: this.#handleValidationErrorsShape, handleBindArgsValidationErrorsShape: this.#handleBindArgsValidationErrorsShape, ctxType: undefined as Ctx, @@ -149,7 +149,6 @@ export class SafeActionClient< middlewareFns: this.#middlewareFns, handleReturnedServerError: this.#handleReturnedServerError, handleServerErrorLog: this.#handleServerErrorLog, - validationStrategy: this.#validationStrategy, metadataSchema: this.#metadataSchema, metadata: this.#metadata, // @ts-expect-error @@ -161,6 +160,7 @@ export class SafeActionClient< } : async () => schema) as SF, bindArgsSchemas: this.#bindArgsSchemas, + validationAdapter: this.#validationAdapter, handleValidationErrorsShape: (utils?.handleValidationErrorsShape ?? this.#handleValidationErrorsShape) as HandleValidationErrorsShapeFn, handleBindArgsValidationErrorsShape: this.#handleBindArgsValidationErrorsShape, @@ -190,11 +190,11 @@ export class SafeActionClient< middlewareFns: this.#middlewareFns, handleReturnedServerError: this.#handleReturnedServerError, handleServerErrorLog: this.#handleServerErrorLog, - validationStrategy: this.#validationStrategy, metadataSchema: this.#metadataSchema, metadata: this.#metadata, schemaFn: this.#schemaFn, bindArgsSchemas, + validationAdapter: this.#validationAdapter, handleValidationErrorsShape: this.#handleValidationErrorsShape, handleBindArgsValidationErrorsShape: (utils?.handleBindArgsValidationErrorsShape ?? this.#handleBindArgsValidationErrorsShape) as HandleBindArgsValidationErrorsShapeFn, @@ -216,7 +216,6 @@ export class SafeActionClient< cb?: SafeActionCallbacks ) { return actionBuilder({ - validationStrategy: this.#validationStrategy, handleReturnedServerError: this.#handleReturnedServerError, handleServerErrorLog: this.#handleServerErrorLog, middlewareFns: this.#middlewareFns, @@ -225,6 +224,7 @@ export class SafeActionClient< metadata: this.#metadata, schemaFn: this.#schemaFn, bindArgsSchemas: this.#bindArgsSchemas, + validationAdapter: this.#validationAdapter, handleValidationErrorsShape: this.#handleValidationErrorsShape, handleBindArgsValidationErrorsShape: this.#handleBindArgsValidationErrorsShape, throwValidationErrors: this.#throwValidationErrors, @@ -244,7 +244,6 @@ export class SafeActionClient< cb?: SafeActionCallbacks ) { return actionBuilder({ - validationStrategy: this.#validationStrategy, handleReturnedServerError: this.#handleReturnedServerError, handleServerErrorLog: this.#handleServerErrorLog, middlewareFns: this.#middlewareFns, @@ -253,6 +252,7 @@ export class SafeActionClient< metadata: this.#metadata, schemaFn: this.#schemaFn, bindArgsSchemas: this.#bindArgsSchemas, + validationAdapter: this.#validationAdapter, handleValidationErrorsShape: this.#handleValidationErrorsShape, handleBindArgsValidationErrorsShape: this.#handleBindArgsValidationErrorsShape, throwValidationErrors: this.#throwValidationErrors, diff --git a/packages/next-safe-action/src/stateful-hooks.ts b/packages/next-safe-action/src/stateful-hooks.ts index 71223729..7cc27398 100644 --- a/packages/next-safe-action/src/stateful-hooks.ts +++ b/packages/next-safe-action/src/stateful-hooks.ts @@ -1,10 +1,10 @@ "use client"; -import type { InferIn, Schema } from "@typeschema/main"; import * as React from "react"; import * as ReactDOM from "react-dom"; import {} from "react/experimental"; import type {} from "zod"; +import type { InferIn, Schema } from "./adapters/types"; import { getActionShorthandStatusObject, getActionStatus, useActionCallbacks } from "./hooks-utils"; import type { HookCallbacks, HookSafeStateActionFn } from "./hooks.types"; /** diff --git a/packages/next-safe-action/src/typeschema.ts b/packages/next-safe-action/src/typeschema.ts deleted file mode 100644 index 3f61d916..00000000 --- a/packages/next-safe-action/src/typeschema.ts +++ /dev/null @@ -1,77 +0,0 @@ -import type { Infer, Schema } from "@typeschema/main"; -import type { DVES, SafeActionClientOpts } from "./index.types"; -import { SafeActionClient } from "./safe-action-client"; -import { DEFAULT_SERVER_ERROR_MESSAGE } from "./utils"; -import { - flattenBindArgsValidationErrors, - flattenValidationErrors, - formatBindArgsValidationErrors, - formatValidationErrors, -} from "./validation-errors"; - -export { ActionMetadataError, DEFAULT_SERVER_ERROR_MESSAGE } from "./utils"; -export { - ActionValidationError, - flattenBindArgsValidationErrors, - flattenValidationErrors, - formatBindArgsValidationErrors, - formatValidationErrors, - returnValidationErrors, -} from "./validation-errors"; - -export type * from "./index.types"; -export type * from "./validation-errors.types"; - -/** - * Create a new safe action client. - * Note: this client is for validation libraries other than Zod, and can cause some problems with deployments, check out - * [the troubleshooting page](https://next-safe-action.dev/docs/troubleshooting#typeschema-issues-with-edge-runtime) on the website. - * If you want to use a validation library supported by [TypeSchema](https://typeschema.com), import this client from `/typeschema` path. - * @param createOpts Optional initialization options - * - * {@link https://next-safe-action.dev/docs/safe-action-client/initialization-options See docs for more information} - */ -export const createSafeActionClient = < - ODVES extends DVES | undefined = undefined, - ServerError = string, - MetadataSchema extends Schema | undefined = undefined, ->( - createOpts?: SafeActionClientOpts -) => { - // If server log function is not provided, default to `console.error` for logging - // server error messages. - const handleServerErrorLog = - createOpts?.handleServerErrorLog || - (((originalError: Error) => { - console.error("Action error:", originalError.message); - }) as unknown as NonNullable["handleServerErrorLog"]>); - - // If `handleReturnedServerError` is provided, use it to handle server error - // messages returned on the client. - // Otherwise mask the error and use a generic message. - const handleReturnedServerError = - createOpts?.handleReturnedServerError || - ((() => DEFAULT_SERVER_ERROR_MESSAGE) as unknown as NonNullable< - SafeActionClientOpts["handleReturnedServerError"] - >); - - return new SafeActionClient({ - middlewareFns: [async ({ next }) => next({ ctx: undefined })], - handleServerErrorLog, - handleReturnedServerError, - validationStrategy: "typeschema", - schemaFn: undefined, - bindArgsSchemas: [], - ctxType: undefined, - metadataSchema: (createOpts?.defineMetadataSchema?.() ?? undefined) as MetadataSchema, - metadata: undefined as MetadataSchema extends Schema ? Infer : undefined, - defaultValidationErrorsShape: (createOpts?.defaultValidationErrorsShape ?? "formatted") as ODVES, - throwValidationErrors: Boolean(createOpts?.throwValidationErrors), - handleValidationErrorsShape: - createOpts?.defaultValidationErrorsShape === "flattened" ? flattenValidationErrors : formatValidationErrors, - handleBindArgsValidationErrorsShape: - createOpts?.defaultValidationErrorsShape === "flattened" - ? flattenBindArgsValidationErrors - : formatBindArgsValidationErrors, - }); -}; diff --git a/packages/next-safe-action/src/utils.ts b/packages/next-safe-action/src/utils.ts index af14f67e..78def49c 100644 --- a/packages/next-safe-action/src/utils.ts +++ b/packages/next-safe-action/src/utils.ts @@ -1,46 +1,7 @@ -import type { Infer, InferIn, Schema } from "@typeschema/main"; - export const DEFAULT_SERVER_ERROR_MESSAGE = "Something went wrong while executing the operation."; export const isError = (error: unknown): error is Error => error instanceof Error; -// UTIL TYPES - -// Takes an object type and makes it more readable. -export type Prettify = { - [K in keyof T]: T[K]; -} & {}; - -// Returns type or promise of type. -export type MaybePromise = Promise | T; - -// Infers output schema type in array of schemas. -export type InferArray = { - [K in keyof BAS]: Infer; -}; - -// Infers input schema type in array of schemas. -export type InferInArray = { - [K in keyof BAS]: InferIn; -}; - -// Validate with Zod. -export async function zodValidate(s: S, data: unknown) { - const result = await s.safeParseAsync(data); - - if (result.success) { - return { - success: true, - data: result.data as Infer, - } as const; - } - - return { - success: false, - issues: result.error.issues.map(({ message, path }) => ({ message, path })), - } as const; -} - /** * This error is thrown when an action's metadata input is invalid, i.e. when there's a mismatch between the * type of the metadata schema returned from `defineMetadataSchema` and the actual input. diff --git a/packages/next-safe-action/src/utils.types.ts b/packages/next-safe-action/src/utils.types.ts new file mode 100644 index 00000000..3946e98c --- /dev/null +++ b/packages/next-safe-action/src/utils.types.ts @@ -0,0 +1,7 @@ +// Takes an object type and makes it more readable. +export type Prettify = { + [K in keyof T]: T[K]; +} & {}; + +// Returns type or promise of type. +export type MaybePromise = Promise | T; diff --git a/packages/next-safe-action/src/validation-errors.ts b/packages/next-safe-action/src/validation-errors.ts index e848fbd9..130e3fd5 100644 --- a/packages/next-safe-action/src/validation-errors.ts +++ b/packages/next-safe-action/src/validation-errors.ts @@ -1,11 +1,11 @@ /* eslint-disable @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-assignment */ -import type { ValidationIssue } from "@typeschema/core"; -import type { Schema } from "@typeschema/main"; +import type { Schema } from "./adapters/types"; import type { FlattenedBindArgsValidationErrors, FlattenedValidationErrors, ValidationErrors, + ValidationIssue, } from "./validation-errors.types"; // This function is used internally to build the validation errors object from a list of validation issues. @@ -53,12 +53,10 @@ export const buildValidationErrors = (issues: Vali // This class is internally used to throw validation errors in action's server code function, using // `returnValidationErrors`. export class ActionServerValidationError extends Error { - public kind: string; public validationErrors: ValidationErrors; constructor(validationErrors: ValidationErrors) { super("Server Action server validation error(s) occurred"); this.validationErrors = validationErrors; - this.kind = "__actionServerValidationError"; } } diff --git a/packages/next-safe-action/src/validation-errors.types.ts b/packages/next-safe-action/src/validation-errors.types.ts index c81e213f..9288800f 100644 --- a/packages/next-safe-action/src/validation-errors.types.ts +++ b/packages/next-safe-action/src/validation-errors.types.ts @@ -1,5 +1,10 @@ -import type { Infer, Schema } from "@typeschema/main"; -import type { Prettify } from "./utils"; +import type { Infer, Schema } from "./adapters/types"; +import type { Prettify } from "./utils.types"; + +export type ValidationIssue = { + message: string; + path?: Array; +}; // Object with an optional list of validation errors. type VEList = Prettify<{ _errors?: string[] }>; diff --git a/packages/next-safe-action/tsup.config.ts b/packages/next-safe-action/tsup.config.ts index 0b72aebb..cf5c4d13 100644 --- a/packages/next-safe-action/tsup.config.ts +++ b/packages/next-safe-action/tsup.config.ts @@ -1,7 +1,8 @@ import { defineConfig } from "tsup"; export default defineConfig({ - entry: ["src/index.ts", "src/typeschema.ts", "src/hooks.ts", "src/stateful-hooks.ts"], + entry: ["src/*.ts", "src/adapters/*.ts"], + bundle: false, format: ["esm"], clean: true, splitting: false, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 2d2ffde1..69ddf7d3 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -10,7 +10,7 @@ importers: dependencies: '@commitlint/cli': specifier: ^19.3.0 - version: 19.3.0(@types/node@20.12.12)(typescript@5.4.5) + version: 19.3.0(@types/node@20.14.11)(typescript@5.5.3) '@commitlint/config-conventional': specifier: ^19.2.2 version: 19.2.2 @@ -19,10 +19,10 @@ importers: version: 0.21.4 commitizen: specifier: ^4.3.0 - version: 4.3.0(@types/node@20.12.12)(typescript@5.4.5) + version: 4.3.0(@types/node@20.14.11)(typescript@5.5.3) cz-conventional-changelog: specifier: ^3.3.0 - version: 3.3.0(@types/node@20.12.12)(typescript@5.4.5) + version: 3.3.0(@types/node@20.14.11)(typescript@5.5.3) husky: specifier: ^9.0.11 version: 9.0.11 @@ -64,8 +64,8 @@ importers: version: 2.0.2(zod@3.23.8) devDependencies: '@types/node': - specifier: ^20.12.10 - version: 20.12.12 + specifier: ^20.14.11 + version: 20.14.11 '@types/react': specifier: ^18.3.1 version: 18.3.3 @@ -80,7 +80,7 @@ importers: version: 8.57.0 eslint-config-next: specifier: 15.0.0-canary.25 - version: 15.0.0-canary.25(eslint@8.57.0)(typescript@5.4.5) + version: 15.0.0-canary.25(eslint@8.57.0)(typescript@5.5.3) postcss: specifier: 8.4.38 version: 8.4.38 @@ -88,36 +88,23 @@ importers: specifier: 3.4.3 version: 3.4.3 typescript: - specifier: ^5.4.5 - version: 5.4.5 + specifier: ^5.5.3 + version: 5.5.3 packages/next-safe-action: - dependencies: - '@typeschema/main': - specifier: ^0.13.10 - version: 0.13.10(@typeschema/zod@0.13.3(zod@3.23.8)) - '@typeschema/zod': - specifier: ^0.13.3 - version: 0.13.3(zod@3.23.8) - zod: - specifier: '>= 3.0.0' - version: 3.23.8 devDependencies: '@eslint/js': specifier: ^9.2.0 version: 9.3.0 '@types/node': - specifier: ^20.12.10 - version: 20.12.12 + specifier: ^20.14.11 + version: 20.14.11 '@types/react': specifier: ^18.3.1 version: 18.3.3 '@types/react-dom': specifier: 18.3.0 version: 18.3.0 - '@typeschema/core': - specifier: ^0.13.2 - version: 0.13.2 eslint: specifier: ^8.57.0 version: 8.57.0 @@ -144,19 +131,28 @@ importers: version: 18.3.1(react@18.3.1) semantic-release: specifier: ^23.0.8 - version: 23.1.1(typescript@5.4.5) + version: 23.1.1(typescript@5.5.3) tsup: specifier: ^8.0.2 - version: 8.0.2(postcss@8.4.38)(typescript@5.4.5) + version: 8.0.2(postcss@8.4.38)(typescript@5.5.3) tsx: specifier: ^4.11.2 version: 4.11.2 typescript: - specifier: ^5.4.5 - version: 5.4.5 + specifier: ^5.5.3 + version: 5.5.3 typescript-eslint: specifier: ^7.8.0 - version: 7.10.0(eslint@8.57.0)(typescript@5.4.5) + version: 7.10.0(eslint@8.57.0)(typescript@5.5.3) + valibot: + specifier: ^0.36.0 + version: 0.36.0 + yup: + specifier: ^1.4.0 + version: 1.4.0 + zod: + specifier: ^3.23.6 + version: 3.23.8 packages: @@ -562,6 +558,7 @@ packages: '@humanwhocodes/config-array@0.11.14': resolution: {integrity: sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==} engines: {node: '>=10.10.0'} + deprecated: Use @eslint/config-array instead '@humanwhocodes/module-importer@1.0.1': resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} @@ -569,6 +566,7 @@ packages: '@humanwhocodes/object-schema@2.0.3': resolution: {integrity: sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==} + deprecated: Use @eslint/object-schema instead '@img/sharp-darwin-arm64@0.33.4': resolution: {integrity: sha512-p0suNqXufJs9t3RqLBO6vvrgr5OhgbWp76s5gTRvdmxmuv9E1rcaqGUsl3l4mKVmXPkTkTErXediAui4x+8PSA==} @@ -1064,8 +1062,8 @@ packages: '@types/json5@0.0.29': resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==} - '@types/node@20.12.12': - resolution: {integrity: sha512-eWLDGF/FOSPtAvEqeRAQ4C8LSA7M1I7i0ky1I8U7kD1J5ITyW3AsRhQrKVoWf5pFKZ2kILsEGJhsI9r93PYnOw==} + '@types/node@20.14.11': + resolution: {integrity: sha512-kprQpL8MMeszbz6ojB5/tU8PLN4kesnN8Gjzw349rDlNgsSzg90lAVj3llK99Dh7JON+t9AuscPPFW6mPbTnSA==} '@types/normalize-package-data@2.4.4': resolution: {integrity: sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==} @@ -1082,87 +1080,6 @@ packages: '@types/semver@6.2.7': resolution: {integrity: sha512-blctEWbzUFzQx799RZjzzIdBJOXmE37YYEyDtKkx5Dg+V7o/zyyAxLPiI98A2jdTtDgxZleMdfV+7p8WbRJ1OQ==} - '@typeschema/core@0.13.2': - resolution: {integrity: sha512-pAt0MK249/9szYaoPuvzhSfOd3smrLhhwCCpUNB4onX32mRx5F3lzDIveIYGQkLYRq58xOX5sjoW+n72f/MLLw==} - peerDependencies: - '@types/json-schema': ^7.0.15 - peerDependenciesMeta: - '@types/json-schema': - optional: true - - '@typeschema/main@0.13.10': - resolution: {integrity: sha512-ArdFC4GbgdVWWgPKg2tymxx2KHMus3xZ8I2kHwqw/0P4FtWBXCmSNAiBqDtpoXXF8h9cbcm7fVpcs5ftoWT9+A==} - peerDependencies: - '@typeschema/arktype': 0.13.2 - '@typeschema/class-validator': 0.1.2 - '@typeschema/deepkit': 0.13.4 - '@typeschema/effect': 0.13.4 - '@typeschema/fastest-validator': 0.1.0 - '@typeschema/function': 0.13.2 - '@typeschema/io-ts': 0.13.3 - '@typeschema/joi': 0.13.3 - '@typeschema/json': 0.13.3 - '@typeschema/ow': 0.13.3 - '@typeschema/runtypes': 0.13.2 - '@typeschema/superstruct': 0.13.2 - '@typeschema/suretype': 0.1.0 - '@typeschema/typebox': 0.13.4 - '@typeschema/valibot': 0.13.5 - '@typeschema/valita': 0.1.0 - '@typeschema/vine': 0.1.0 - '@typeschema/yup': 0.13.3 - '@typeschema/zod': 0.13.3 - peerDependenciesMeta: - '@typeschema/arktype': - optional: true - '@typeschema/class-validator': - optional: true - '@typeschema/deepkit': - optional: true - '@typeschema/effect': - optional: true - '@typeschema/fastest-validator': - optional: true - '@typeschema/function': - optional: true - '@typeschema/io-ts': - optional: true - '@typeschema/joi': - optional: true - '@typeschema/json': - optional: true - '@typeschema/ow': - optional: true - '@typeschema/runtypes': - optional: true - '@typeschema/superstruct': - optional: true - '@typeschema/suretype': - optional: true - '@typeschema/typebox': - optional: true - '@typeschema/valibot': - optional: true - '@typeschema/valita': - optional: true - '@typeschema/vine': - optional: true - '@typeschema/yup': - optional: true - '@typeschema/zod': - optional: true - - '@typeschema/zod@0.13.3': - resolution: {integrity: sha512-p5Hs22WIKkM/vZTAvw5QOLSA0EJ6QBUsQMGUrXlYnTAE2LSR/F5MLsDUb18O6S5VxGjrzU7x3VIznD5qOafJRw==} - peerDependencies: - zod: ^3.22.4 - zod-to-json-schema: ^3.22.4 - peerDependenciesMeta: - zod: - optional: true - zod-to-json-schema: - optional: true - '@typescript-eslint/eslint-plugin@7.10.0': resolution: {integrity: sha512-PzCr+a/KAef5ZawX7nbyNwBDtM1HdLIT53aSA2DDlxmxMngZ43O8SIePOeX8H5S+FHXeI6t97mTt/dDdzY4Fyw==} engines: {node: ^18.18.0 || >=20.0.0} @@ -2172,6 +2089,7 @@ packages: glob@7.2.3: resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} + deprecated: Glob versions prior to v9 are no longer supported global-directory@4.0.1: resolution: {integrity: sha512-wHTUcDUoZ1H5/0iVqEudYW4/kAlN5cZ3j/bXn0Dpbizl9iaUVeWSHqiOjsgk6OW2bkLclbBjzewBz6weQ1zA2Q==} @@ -3280,6 +3198,9 @@ packages: prop-types@15.8.1: resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==} + property-expr@2.0.6: + resolution: {integrity: sha512-SVtmxhRE/CGkn3eZY1T6pC8Nln6Fr/lu1mKSgRud0eC73whjGfoAogbn78LkD8aFL0zz3bAFerKSnOl7NlErBA==} + proto-list@1.2.4: resolution: {integrity: sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==} @@ -3754,6 +3675,9 @@ packages: resolution: {integrity: sha512-75voc/9G4rDIJleOo4jPvN4/YC4GRZrY8yy1uU4lwrB3XEQbWve8zXoO5No4eFrGcTAMYyoY67p8jRQdtA1HbA==} engines: {node: '>=12'} + tiny-case@1.0.3: + resolution: {integrity: sha512-Eet/eeMhkO6TX8mnUteS9zgPbUMQa4I6Kkp5ORiBD5476/m+PIRiumP5tmh5ioJpH7k51Kehawy2UDfsnxxY8Q==} + tmp@0.0.33: resolution: {integrity: sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==} engines: {node: '>=0.6.0'} @@ -3762,6 +3686,9 @@ packages: resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} engines: {node: '>=8.0'} + toposort@2.0.2: + resolution: {integrity: sha512-0a5EOkAUp8D4moMi2W8ZF8jcga7BgZd91O/yabJCFY8az+XSzeGyTKs0Aoo897iV1Nj6guFq8orWDS96z91oGg==} + tr46@1.0.1: resolution: {integrity: sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA==} @@ -3900,8 +3827,8 @@ packages: typescript: optional: true - typescript@5.4.5: - resolution: {integrity: sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==} + typescript@5.5.3: + resolution: {integrity: sha512-/hreyEujaB0w76zKo6717l3L0o/qEUtRgdvUBvlkhoWeOVMjMuHNHk0BRBzikzuGDqNmPQbg5ifMEqsHLiIUcQ==} engines: {node: '>=14.17'} hasBin: true @@ -3955,6 +3882,9 @@ packages: util-deprecate@1.0.2: resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + valibot@0.36.0: + resolution: {integrity: sha512-CjF1XN4sUce8sBK9TixrDqFM7RwNkuXdJu174/AwmQUB62QbCQADg5lLe8ldBalFgtj1uKj+pKwDJiNo4Mn+eQ==} + validate-npm-package-license@3.0.4: resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==} @@ -4056,6 +3986,9 @@ packages: resolution: {integrity: sha512-Ct97huExsu7cWeEjmrXlofevF8CvzUglJ4iGUet5B8xn1oumtAZBpHU4GzYuoE6PVqcZ5hghtBrSlhwHuR1Jmw==} engines: {node: '>=18'} + yup@1.4.0: + resolution: {integrity: sha512-wPbgkJRCqIf+OHyiTBQoJiP5PFuAXaWiJK6AmYkzQAh5/c2K9hzSApBZG5wV9KoKSePF7sAxmNSvh/13YHkFDg==} + zod-form-data@2.0.2: resolution: {integrity: sha512-sKTi+k0fvkxdakD0V5rq+9WVJA3cuTQUfEmNqvHrTzPLvjfLmkkBLfR0ed3qOi9MScJXTHIDH/jUNnEJ3CBX4g==} peerDependencies: @@ -4089,11 +4022,11 @@ snapshots: '@colors/colors@1.5.0': optional: true - '@commitlint/cli@19.3.0(@types/node@20.12.12)(typescript@5.4.5)': + '@commitlint/cli@19.3.0(@types/node@20.14.11)(typescript@5.5.3)': dependencies: '@commitlint/format': 19.3.0 '@commitlint/lint': 19.2.2 - '@commitlint/load': 19.2.0(@types/node@20.12.12)(typescript@5.4.5) + '@commitlint/load': 19.2.0(@types/node@20.14.11)(typescript@5.5.3) '@commitlint/read': 19.2.1 '@commitlint/types': 19.0.3 execa: 8.0.1 @@ -4140,15 +4073,15 @@ snapshots: '@commitlint/rules': 19.0.3 '@commitlint/types': 19.0.3 - '@commitlint/load@19.2.0(@types/node@20.12.12)(typescript@5.4.5)': + '@commitlint/load@19.2.0(@types/node@20.14.11)(typescript@5.5.3)': dependencies: '@commitlint/config-validator': 19.0.3 '@commitlint/execute-rule': 19.0.0 '@commitlint/resolve-extends': 19.1.0 '@commitlint/types': 19.0.3 chalk: 5.3.0 - cosmiconfig: 9.0.0(typescript@5.4.5) - cosmiconfig-typescript-loader: 5.0.0(@types/node@20.12.12)(cosmiconfig@9.0.0(typescript@5.4.5))(typescript@5.4.5) + cosmiconfig: 9.0.0(typescript@5.5.3) + cosmiconfig-typescript-loader: 5.0.0(@types/node@20.14.11)(cosmiconfig@9.0.0(typescript@5.5.3))(typescript@5.5.3) lodash.isplainobject: 4.0.6 lodash.merge: 4.6.2 lodash.uniq: 4.5.0 @@ -4718,7 +4651,7 @@ snapshots: '@sec-ant/readable-stream@0.4.1': {} - '@semantic-release/commit-analyzer@12.0.0(semantic-release@23.1.1(typescript@5.4.5))': + '@semantic-release/commit-analyzer@12.0.0(semantic-release@23.1.1(typescript@5.5.3))': dependencies: conventional-changelog-angular: 7.0.0 conventional-commits-filter: 4.0.0 @@ -4727,13 +4660,13 @@ snapshots: import-from-esm: 1.3.4 lodash-es: 4.17.21 micromatch: 4.0.7 - semantic-release: 23.1.1(typescript@5.4.5) + semantic-release: 23.1.1(typescript@5.5.3) transitivePeerDependencies: - supports-color '@semantic-release/error@4.0.0': {} - '@semantic-release/github@10.0.5(semantic-release@23.1.1(typescript@5.4.5))': + '@semantic-release/github@10.0.5(semantic-release@23.1.1(typescript@5.5.3))': dependencies: '@octokit/core': 6.1.2 '@octokit/plugin-paginate-rest': 11.3.0(@octokit/core@6.1.2) @@ -4750,12 +4683,12 @@ snapshots: lodash-es: 4.17.21 mime: 4.0.3 p-filter: 4.1.0 - semantic-release: 23.1.1(typescript@5.4.5) + semantic-release: 23.1.1(typescript@5.5.3) url-join: 5.0.0 transitivePeerDependencies: - supports-color - '@semantic-release/npm@12.0.1(semantic-release@23.1.1(typescript@5.4.5))': + '@semantic-release/npm@12.0.1(semantic-release@23.1.1(typescript@5.5.3))': dependencies: '@semantic-release/error': 4.0.0 aggregate-error: 5.0.0 @@ -4768,11 +4701,11 @@ snapshots: rc: 1.2.8 read-pkg: 9.0.1 registry-auth-token: 5.0.2 - semantic-release: 23.1.1(typescript@5.4.5) + semantic-release: 23.1.1(typescript@5.5.3) semver: 7.6.2 tempy: 3.1.0 - '@semantic-release/release-notes-generator@13.0.0(semantic-release@23.1.1(typescript@5.4.5))': + '@semantic-release/release-notes-generator@13.0.0(semantic-release@23.1.1(typescript@5.5.3))': dependencies: conventional-changelog-angular: 7.0.0 conventional-changelog-writer: 7.0.1 @@ -4784,7 +4717,7 @@ snapshots: into-stream: 7.0.0 lodash-es: 4.17.21 read-pkg-up: 11.0.0 - semantic-release: 23.1.1(typescript@5.4.5) + semantic-release: 23.1.1(typescript@5.5.3) transitivePeerDependencies: - supports-color @@ -4806,7 +4739,7 @@ snapshots: '@types/conventional-commits-parser@5.0.0': dependencies: - '@types/node': 20.12.12 + '@types/node': 20.14.11 '@types/estree@1.0.5': {} @@ -4814,7 +4747,7 @@ snapshots: '@types/json5@0.0.29': {} - '@types/node@20.12.12': + '@types/node@20.14.11': dependencies: undici-types: 5.26.5 @@ -4833,65 +4766,47 @@ snapshots: '@types/semver@6.2.7': {} - '@typeschema/core@0.13.2': {} - - '@typeschema/main@0.13.10(@typeschema/zod@0.13.3(zod@3.23.8))': - dependencies: - '@typeschema/core': 0.13.2 - optionalDependencies: - '@typeschema/zod': 0.13.3(zod@3.23.8) - transitivePeerDependencies: - - '@types/json-schema' - - '@typeschema/zod@0.13.3(zod@3.23.8)': - dependencies: - '@typeschema/core': 0.13.2 - optionalDependencies: - zod: 3.23.8 - transitivePeerDependencies: - - '@types/json-schema' - - '@typescript-eslint/eslint-plugin@7.10.0(@typescript-eslint/parser@7.10.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(typescript@5.4.5)': + '@typescript-eslint/eslint-plugin@7.10.0(@typescript-eslint/parser@7.10.0(eslint@8.57.0)(typescript@5.5.3))(eslint@8.57.0)(typescript@5.5.3)': dependencies: '@eslint-community/regexpp': 4.10.0 - '@typescript-eslint/parser': 7.10.0(eslint@8.57.0)(typescript@5.4.5) + '@typescript-eslint/parser': 7.10.0(eslint@8.57.0)(typescript@5.5.3) '@typescript-eslint/scope-manager': 7.10.0 - '@typescript-eslint/type-utils': 7.10.0(eslint@8.57.0)(typescript@5.4.5) - '@typescript-eslint/utils': 7.10.0(eslint@8.57.0)(typescript@5.4.5) + '@typescript-eslint/type-utils': 7.10.0(eslint@8.57.0)(typescript@5.5.3) + '@typescript-eslint/utils': 7.10.0(eslint@8.57.0)(typescript@5.5.3) '@typescript-eslint/visitor-keys': 7.10.0 eslint: 8.57.0 graphemer: 1.4.0 ignore: 5.3.1 natural-compare: 1.4.0 - ts-api-utils: 1.3.0(typescript@5.4.5) + ts-api-utils: 1.3.0(typescript@5.5.3) optionalDependencies: - typescript: 5.4.5 + typescript: 5.5.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@7.10.0(eslint@8.57.0)(typescript@5.4.5)': + '@typescript-eslint/parser@7.10.0(eslint@8.57.0)(typescript@5.5.3)': dependencies: '@typescript-eslint/scope-manager': 7.10.0 '@typescript-eslint/types': 7.10.0 - '@typescript-eslint/typescript-estree': 7.10.0(typescript@5.4.5) + '@typescript-eslint/typescript-estree': 7.10.0(typescript@5.5.3) '@typescript-eslint/visitor-keys': 7.10.0 debug: 4.3.4 eslint: 8.57.0 optionalDependencies: - typescript: 5.4.5 + typescript: 5.5.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.4.5)': + '@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.5.3)': dependencies: '@typescript-eslint/scope-manager': 7.2.0 '@typescript-eslint/types': 7.2.0 - '@typescript-eslint/typescript-estree': 7.2.0(typescript@5.4.5) + '@typescript-eslint/typescript-estree': 7.2.0(typescript@5.5.3) '@typescript-eslint/visitor-keys': 7.2.0 debug: 4.3.4 eslint: 8.57.0 optionalDependencies: - typescript: 5.4.5 + typescript: 5.5.3 transitivePeerDependencies: - supports-color @@ -4905,15 +4820,15 @@ snapshots: '@typescript-eslint/types': 7.2.0 '@typescript-eslint/visitor-keys': 7.2.0 - '@typescript-eslint/type-utils@7.10.0(eslint@8.57.0)(typescript@5.4.5)': + '@typescript-eslint/type-utils@7.10.0(eslint@8.57.0)(typescript@5.5.3)': dependencies: - '@typescript-eslint/typescript-estree': 7.10.0(typescript@5.4.5) - '@typescript-eslint/utils': 7.10.0(eslint@8.57.0)(typescript@5.4.5) + '@typescript-eslint/typescript-estree': 7.10.0(typescript@5.5.3) + '@typescript-eslint/utils': 7.10.0(eslint@8.57.0)(typescript@5.5.3) debug: 4.3.4 eslint: 8.57.0 - ts-api-utils: 1.3.0(typescript@5.4.5) + ts-api-utils: 1.3.0(typescript@5.5.3) optionalDependencies: - typescript: 5.4.5 + typescript: 5.5.3 transitivePeerDependencies: - supports-color @@ -4921,7 +4836,7 @@ snapshots: '@typescript-eslint/types@7.2.0': {} - '@typescript-eslint/typescript-estree@7.10.0(typescript@5.4.5)': + '@typescript-eslint/typescript-estree@7.10.0(typescript@5.5.3)': dependencies: '@typescript-eslint/types': 7.10.0 '@typescript-eslint/visitor-keys': 7.10.0 @@ -4930,13 +4845,13 @@ snapshots: is-glob: 4.0.3 minimatch: 9.0.4 semver: 7.6.2 - ts-api-utils: 1.3.0(typescript@5.4.5) + ts-api-utils: 1.3.0(typescript@5.5.3) optionalDependencies: - typescript: 5.4.5 + typescript: 5.5.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/typescript-estree@7.2.0(typescript@5.4.5)': + '@typescript-eslint/typescript-estree@7.2.0(typescript@5.5.3)': dependencies: '@typescript-eslint/types': 7.2.0 '@typescript-eslint/visitor-keys': 7.2.0 @@ -4945,18 +4860,18 @@ snapshots: is-glob: 4.0.3 minimatch: 9.0.3 semver: 7.6.2 - ts-api-utils: 1.3.0(typescript@5.4.5) + ts-api-utils: 1.3.0(typescript@5.5.3) optionalDependencies: - typescript: 5.4.5 + typescript: 5.5.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/utils@7.10.0(eslint@8.57.0)(typescript@5.4.5)': + '@typescript-eslint/utils@7.10.0(eslint@8.57.0)(typescript@5.5.3)': dependencies: '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) '@typescript-eslint/scope-manager': 7.10.0 '@typescript-eslint/types': 7.10.0 - '@typescript-eslint/typescript-estree': 7.10.0(typescript@5.4.5) + '@typescript-eslint/typescript-estree': 7.10.0(typescript@5.5.3) eslint: 8.57.0 transitivePeerDependencies: - supports-color @@ -5333,10 +5248,10 @@ snapshots: commander@4.1.1: {} - commitizen@4.3.0(@types/node@20.12.12)(typescript@5.4.5): + commitizen@4.3.0(@types/node@20.14.11)(typescript@5.5.3): dependencies: cachedir: 2.3.0 - cz-conventional-changelog: 3.3.0(@types/node@20.12.12)(typescript@5.4.5) + cz-conventional-changelog: 3.3.0(@types/node@20.14.11)(typescript@5.5.3) dedent: 0.7.0 detect-indent: 6.1.0 find-node-modules: 2.1.3 @@ -5397,21 +5312,21 @@ snapshots: core-util-is@1.0.3: {} - cosmiconfig-typescript-loader@5.0.0(@types/node@20.12.12)(cosmiconfig@9.0.0(typescript@5.4.5))(typescript@5.4.5): + cosmiconfig-typescript-loader@5.0.0(@types/node@20.14.11)(cosmiconfig@9.0.0(typescript@5.5.3))(typescript@5.5.3): dependencies: - '@types/node': 20.12.12 - cosmiconfig: 9.0.0(typescript@5.4.5) + '@types/node': 20.14.11 + cosmiconfig: 9.0.0(typescript@5.5.3) jiti: 1.21.0 - typescript: 5.4.5 + typescript: 5.5.3 - cosmiconfig@9.0.0(typescript@5.4.5): + cosmiconfig@9.0.0(typescript@5.5.3): dependencies: env-paths: 2.2.1 import-fresh: 3.3.0 js-yaml: 4.1.0 parse-json: 5.2.0 optionalDependencies: - typescript: 5.4.5 + typescript: 5.5.3 cross-spawn@5.1.0: dependencies: @@ -5433,16 +5348,16 @@ snapshots: csstype@3.1.3: {} - cz-conventional-changelog@3.3.0(@types/node@20.12.12)(typescript@5.4.5): + cz-conventional-changelog@3.3.0(@types/node@20.14.11)(typescript@5.5.3): dependencies: chalk: 2.4.2 - commitizen: 4.3.0(@types/node@20.12.12)(typescript@5.4.5) + commitizen: 4.3.0(@types/node@20.14.11)(typescript@5.5.3) conventional-commit-types: 3.0.0 lodash.map: 4.6.0 longest: 2.0.1 word-wrap: 1.2.5 optionalDependencies: - '@commitlint/load': 19.2.0(@types/node@20.12.12)(typescript@5.4.5) + '@commitlint/load': 19.2.0(@types/node@20.14.11)(typescript@5.5.3) transitivePeerDependencies: - '@types/node' - typescript @@ -5716,20 +5631,20 @@ snapshots: escape-string-regexp@5.0.0: {} - eslint-config-next@15.0.0-canary.25(eslint@8.57.0)(typescript@5.4.5): + eslint-config-next@15.0.0-canary.25(eslint@8.57.0)(typescript@5.5.3): dependencies: '@next/eslint-plugin-next': 15.0.0-canary.25 '@rushstack/eslint-patch': 1.10.3 - '@typescript-eslint/parser': 7.2.0(eslint@8.57.0)(typescript@5.4.5) + '@typescript-eslint/parser': 7.2.0(eslint@8.57.0)(typescript@5.5.3) eslint: 8.57.0 eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(eslint@8.57.0))(eslint@8.57.0) - eslint-plugin-import: 2.29.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(eslint@8.57.0))(eslint@8.57.0))(eslint@8.57.0) + eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.5.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(eslint@8.57.0))(eslint@8.57.0) + eslint-plugin-import: 2.29.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.5.3))(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0) eslint-plugin-jsx-a11y: 6.8.0(eslint@8.57.0) eslint-plugin-react: 7.34.1(eslint@8.57.0) eslint-plugin-react-hooks: 4.6.2(eslint@8.57.0) optionalDependencies: - typescript: 5.4.5 + typescript: 5.5.3 transitivePeerDependencies: - eslint-import-resolver-webpack - supports-color @@ -5748,13 +5663,13 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(eslint@8.57.0))(eslint@8.57.0): + eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.5.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(eslint@8.57.0))(eslint@8.57.0): dependencies: debug: 4.3.4 enhanced-resolve: 5.16.1 eslint: 8.57.0 - eslint-module-utils: 2.8.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(eslint@8.57.0))(eslint@8.57.0))(eslint@8.57.0) - eslint-plugin-import: 2.29.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(eslint@8.57.0))(eslint@8.57.0))(eslint@8.57.0) + eslint-module-utils: 2.8.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.5.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.5.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(eslint@8.57.0))(eslint@8.57.0))(eslint@8.57.0) + eslint-plugin-import: 2.29.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.5.3))(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0) fast-glob: 3.3.2 get-tsconfig: 4.7.5 is-core-module: 2.13.1 @@ -5765,18 +5680,18 @@ snapshots: - eslint-import-resolver-webpack - supports-color - eslint-module-utils@2.8.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(eslint@8.57.0))(eslint@8.57.0))(eslint@8.57.0): + eslint-module-utils@2.8.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.5.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.5.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(eslint@8.57.0))(eslint@8.57.0))(eslint@8.57.0): dependencies: debug: 3.2.7 optionalDependencies: - '@typescript-eslint/parser': 7.2.0(eslint@8.57.0)(typescript@5.4.5) + '@typescript-eslint/parser': 7.2.0(eslint@8.57.0)(typescript@5.5.3) eslint: 8.57.0 eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(eslint@8.57.0))(eslint@8.57.0) + eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.5.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(eslint@8.57.0))(eslint@8.57.0) transitivePeerDependencies: - supports-color - eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(eslint@8.57.0))(eslint@8.57.0))(eslint@8.57.0): + eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.5.3))(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0): dependencies: array-includes: 3.1.8 array.prototype.findlastindex: 1.2.5 @@ -5786,7 +5701,7 @@ snapshots: doctrine: 2.1.0 eslint: 8.57.0 eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.8.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(eslint@8.57.0))(eslint@8.57.0))(eslint@8.57.0) + eslint-module-utils: 2.8.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.5.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.5.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(eslint@8.57.0))(eslint@8.57.0))(eslint@8.57.0) hasown: 2.0.2 is-core-module: 2.13.1 is-glob: 4.0.3 @@ -5797,7 +5712,7 @@ snapshots: semver: 6.3.1 tsconfig-paths: 3.15.0 optionalDependencies: - '@typescript-eslint/parser': 7.2.0(eslint@8.57.0)(typescript@5.4.5) + '@typescript-eslint/parser': 7.2.0(eslint@8.57.0)(typescript@5.5.3) transitivePeerDependencies: - eslint-import-resolver-typescript - eslint-import-resolver-webpack @@ -7156,6 +7071,8 @@ snapshots: object-assign: 4.1.1 react-is: 16.13.1 + property-expr@2.0.6: {} + proto-list@1.2.4: {} pseudomap@1.0.2: {} @@ -7375,15 +7292,15 @@ snapshots: scheduler@0.25.0-rc-6230622a1a-20240610: {} - semantic-release@23.1.1(typescript@5.4.5): + semantic-release@23.1.1(typescript@5.5.3): dependencies: - '@semantic-release/commit-analyzer': 12.0.0(semantic-release@23.1.1(typescript@5.4.5)) + '@semantic-release/commit-analyzer': 12.0.0(semantic-release@23.1.1(typescript@5.5.3)) '@semantic-release/error': 4.0.0 - '@semantic-release/github': 10.0.5(semantic-release@23.1.1(typescript@5.4.5)) - '@semantic-release/npm': 12.0.1(semantic-release@23.1.1(typescript@5.4.5)) - '@semantic-release/release-notes-generator': 13.0.0(semantic-release@23.1.1(typescript@5.4.5)) + '@semantic-release/github': 10.0.5(semantic-release@23.1.1(typescript@5.5.3)) + '@semantic-release/npm': 12.0.1(semantic-release@23.1.1(typescript@5.5.3)) + '@semantic-release/release-notes-generator': 13.0.0(semantic-release@23.1.1(typescript@5.5.3)) aggregate-error: 5.0.0 - cosmiconfig: 9.0.0(typescript@5.4.5) + cosmiconfig: 9.0.0(typescript@5.5.3) debug: 4.3.4 env-ci: 11.0.0 execa: 9.1.0 @@ -7731,6 +7648,8 @@ snapshots: dependencies: convert-hrtime: 5.0.0 + tiny-case@1.0.3: {} + tmp@0.0.33: dependencies: os-tmpdir: 1.0.2 @@ -7739,6 +7658,8 @@ snapshots: dependencies: is-number: 7.0.0 + toposort@2.0.2: {} + tr46@1.0.1: dependencies: punycode: 2.3.1 @@ -7751,9 +7672,9 @@ snapshots: tree-kill@1.2.2: {} - ts-api-utils@1.3.0(typescript@5.4.5): + ts-api-utils@1.3.0(typescript@5.5.3): dependencies: - typescript: 5.4.5 + typescript: 5.5.3 ts-interface-checker@0.1.13: {} @@ -7766,7 +7687,7 @@ snapshots: tslib@2.6.2: {} - tsup@8.0.2(postcss@8.4.38)(typescript@5.4.5): + tsup@8.0.2(postcss@8.4.38)(typescript@5.5.3): dependencies: bundle-require: 4.1.0(esbuild@0.19.12) cac: 6.7.14 @@ -7784,7 +7705,7 @@ snapshots: tree-kill: 1.2.2 optionalDependencies: postcss: 8.4.38 - typescript: 5.4.5 + typescript: 5.5.3 transitivePeerDependencies: - supports-color - ts-node @@ -7878,18 +7799,18 @@ snapshots: typed-array-buffer: 1.0.2 typed-array-byte-offset: 1.0.2 - typescript-eslint@7.10.0(eslint@8.57.0)(typescript@5.4.5): + typescript-eslint@7.10.0(eslint@8.57.0)(typescript@5.5.3): dependencies: - '@typescript-eslint/eslint-plugin': 7.10.0(@typescript-eslint/parser@7.10.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(typescript@5.4.5) - '@typescript-eslint/parser': 7.10.0(eslint@8.57.0)(typescript@5.4.5) - '@typescript-eslint/utils': 7.10.0(eslint@8.57.0)(typescript@5.4.5) + '@typescript-eslint/eslint-plugin': 7.10.0(@typescript-eslint/parser@7.10.0(eslint@8.57.0)(typescript@5.5.3))(eslint@8.57.0)(typescript@5.5.3) + '@typescript-eslint/parser': 7.10.0(eslint@8.57.0)(typescript@5.5.3) + '@typescript-eslint/utils': 7.10.0(eslint@8.57.0)(typescript@5.5.3) eslint: 8.57.0 optionalDependencies: - typescript: 5.4.5 + typescript: 5.5.3 transitivePeerDependencies: - supports-color - typescript@5.4.5: {} + typescript@5.5.3: {} uglify-js@3.17.4: optional: true @@ -7931,6 +7852,8 @@ snapshots: util-deprecate@1.0.2: {} + valibot@0.36.0: {} + validate-npm-package-license@3.0.4: dependencies: spdx-correct: 3.2.0 @@ -8054,6 +7977,13 @@ snapshots: yoctocolors@2.0.2: {} + yup@1.4.0: + dependencies: + property-expr: 2.0.6 + tiny-case: 1.0.3 + toposort: 2.0.2 + type-fest: 2.19.0 + zod-form-data@2.0.2(zod@3.23.8): dependencies: zod: 3.23.8 diff --git a/website/docs/getting-started.md b/website/docs/getting-started.md index be935486..1bfe41f5 100644 --- a/website/docs/getting-started.md +++ b/website/docs/getting-started.md @@ -10,7 +10,7 @@ description: Getting started with next-safe-action version 7. - Next.js >= 14 (>= 15 for [`useStateAction`](/docs/execution/hooks/usestateaction) hook) - React >= 18.2.0 - TypeScript >= 5 -- Zod or a validation library supported by [TypeSchema](https://typeschema.com/#coverage) +- Zod or Valibot or Yup ::: **next-safe-action** provides a typesafe Server Actions implementation for Next.js App Router. @@ -24,20 +24,7 @@ npm i next-safe-action zod ``` :::note -Zod is the default validation library for next-safe-action, because TypeSchema can cause some issues with deployments, so this documentation uses it for that reason. If you know what you're doing, though, you can use your validation library of choice, or even multiple ones at the same time, thanks to the **TypeSchema** package. - -To use this feature, you just need to update the import path for the safe client initialization function from: -```typescript -import { createSafeActionClient } from "next-safe-action"; -``` - -to: - -```typescript -import { createSafeActionClient } from "next-safe-action/typeschema"; -``` - -and install the related [TypeSchema adapter](https://typeschema.com/#coverage). +Zod is the default validation library for next-safe-action. If you want to use a different validation library, check out the [validation libraries support](/docs/recipes/validation-libraries-support) recipe. ::: ## Usage diff --git a/website/docs/recipes/additional-validation-errors.md b/website/docs/recipes/additional-validation-errors.md index c69c6b3a..353587e5 100644 --- a/website/docs/recipes/additional-validation-errors.md +++ b/website/docs/recipes/additional-validation-errors.md @@ -1,5 +1,5 @@ --- -sidebar_position: 4 +sidebar_position: 5 description: Set additional custom validation errors in schema or in action's server code function. --- diff --git a/website/docs/recipes/customize-validation-errors-format.md b/website/docs/recipes/customize-validation-errors-format.md index 66305b26..0d313d81 100644 --- a/website/docs/recipes/customize-validation-errors-format.md +++ b/website/docs/recipes/customize-validation-errors-format.md @@ -1,5 +1,5 @@ --- -sidebar_position: 5 +sidebar_position: 6 description: Learn how to customize validation errors format returned to the client. --- diff --git a/website/docs/recipes/extend-base-client.md b/website/docs/recipes/extend-base-client.md index 44c43c83..b01a5d00 100644 --- a/website/docs/recipes/extend-base-client.md +++ b/website/docs/recipes/extend-base-client.md @@ -1,5 +1,5 @@ --- -sidebar_position: 2 +sidebar_position: 3 description: Learn how to use both a basic and an authorization client at the same time in your project. --- diff --git a/website/docs/recipes/extend-previous-schema.md b/website/docs/recipes/extend-previous-schema.md index 69e7ddc4..bc28a1e4 100644 --- a/website/docs/recipes/extend-previous-schema.md +++ b/website/docs/recipes/extend-previous-schema.md @@ -1,5 +1,5 @@ --- -sidebar_position: 3 +sidebar_position: 4 description: Learn how to use next-safe-action with a i18n solution. --- diff --git a/website/docs/recipes/form-actions.md b/website/docs/recipes/form-actions.md index 355d898d..2ba36ee8 100644 --- a/website/docs/recipes/form-actions.md +++ b/website/docs/recipes/form-actions.md @@ -1,5 +1,5 @@ --- -sidebar_position: 6 +sidebar_position: 7 description: Learn how to use next-safe-action with Form Actions. --- diff --git a/website/docs/recipes/i18n.md b/website/docs/recipes/i18n.md index 2072dcd6..6c02e9cd 100644 --- a/website/docs/recipes/i18n.md +++ b/website/docs/recipes/i18n.md @@ -1,5 +1,5 @@ --- -sidebar_position: 8 +sidebar_position: 9 description: Learn how to use next-safe-action with a i18n solution. --- diff --git a/website/docs/recipes/upload-files.md b/website/docs/recipes/upload-files.md index bc84039f..88782eb8 100644 --- a/website/docs/recipes/upload-files.md +++ b/website/docs/recipes/upload-files.md @@ -1,5 +1,5 @@ --- -sidebar_position: 7 +sidebar_position: 8 description: Learn how to upload a file using next-safe-action. --- diff --git a/website/docs/recipes/validation-libraries-support.md b/website/docs/recipes/validation-libraries-support.md new file mode 100644 index 00000000..7ecc208f --- /dev/null +++ b/website/docs/recipes/validation-libraries-support.md @@ -0,0 +1,43 @@ +--- +sidebar_position: 2 +description: Use a validation library of your choice with next-safe-action. +--- + +# Validation libraries support + +Starting from version 6.0.0, and up to version 7.1.3, next-safe-action used [TypeSchema](https://typeschema.com/) to enable support for multiple validation libraries. This has worked pretty well, but caused some issues too, such as the [Edge Runtime incompatibility](/docs/troubleshooting#typeschema-issues-with-edge-runtime) or [lack of support for TypeScript >= 5.5](/docs/troubleshooting#schema-and-parsedinput-are-typed-any-broken-types-and-build-issues). + +To solve these issues, next-safe-action v7.2.0 and later versions ship with a built-in modular support for multiple validation libraries, at this time: Zod, Valibot and Yup. + +If you used a TypeSchema adapter before, you should uninstall it, since you just need the validation library of your choice from now on. + +The configuration is pretty simple. If you use Zod, you don't have to do anything. If you choose to use Valibot or Yup, other than obviously installing the validation library itself, you need to specify the correct validation adapter when you're initializing the safe action client: + + +For Valibot: + +```typescript title="@/lib/safe-action.ts" +import { createSafeActionClient } from "next-safe-action"; +import { valibotAdapter } from "next-safe-action/adapters/valibot"; // import the adapter + +export const actionClient = createSafeActionClient({ + validationAdapter: valibotAdapter(), // <-- and then pass it to the client + // other options here... +}); +``` + +For Yup: + +```typescript title="@/lib/safe-action.ts" +import { createSafeActionClient } from "next-safe-action"; +import { yupAdapter } from "next-safe-action/adapters/yup"; // import the adapter + +export const actionClient = createSafeActionClient({ + validationAdapter: yupAdapter(), // <-- and then pass it to the client + // other options here... +}); +``` + +And you're done! You could also do the same thing for Zod, but it's not required right now, as it's the default validation library. + +If you want more information about the TypeSchema to built-in system change, there's a dedicated discussion on GitHub for that, [here](https://github.com/TheEdoRan/next-safe-action/discussions/201). diff --git a/website/docs/safe-action-client/initialization-options.md b/website/docs/safe-action-client/initialization-options.md index cebd119a..0c976efc 100644 --- a/website/docs/safe-action-client/initialization-options.md +++ b/website/docs/safe-action-client/initialization-options.md @@ -5,6 +5,10 @@ description: You can initialize a safe action client with these options. # Initialization options +## `validationAdapter?` + +You can provide this optional function to the safe action client. It is used to define which validation adapter should be used to validate the client input, based on the validation library of your choice. If not provided, the default `zodAdapter()` is used. The other two options, at this time, are `valibotAdapter()` and `yupAdapter()`. More information about that in the [validation libraries support](/docs/recipes/validation-libraries-support) recipe page. + ## `handleReturnedServerError?` You can provide this optional function to the safe action client. It is used to customize the server error returned to the client, if one occurs during action's server execution. This includes errors thrown by the action server code, and errors thrown by the middleware. You also have access to useful properties via the `utils` object, which is the second argument of the function. diff --git a/website/docs/safe-action-client/instance-methods.md b/website/docs/safe-action-client/instance-methods.md index fb7d5d7f..eadaa195 100644 --- a/website/docs/safe-action-client/instance-methods.md +++ b/website/docs/safe-action-client/instance-methods.md @@ -31,7 +31,7 @@ metadata(data: Metadata) => new SafeActionClient() schema(schema: S, utils?: { handleValidationErrorsShape?: HandleValidationErrorsShapeFn } }) => new SafeActionClient() ``` -`schema` accepts an input schema of type `Schema` (from TypeSchema) or a function that returns a promise of type `Schema` and an optional `utils` object that accepts a [`handleValidationErrorsShape`](/docs/recipes/customize-validation-errors-format) function. The schema is used to define the arguments that the safe action will receive, the optional [`handleValidationErrorsShape`](/docs/recipes/customize-validation-errors-format) function is used to return a custom format for validation errors. If you don't pass an input schema, `parsedInput` and validation errors will be typed `undefined`, and `clientInput` will be typed `void`. It returns a new instance of the safe action client. +`schema` accepts an input schema of type `Schema` or a function that returns a promise of type `Schema` and an optional `utils` object that accepts a [`handleValidationErrorsShape`](/docs/recipes/customize-validation-errors-format) function. The schema is used to define the arguments that the safe action will receive, the optional [`handleValidationErrorsShape`](/docs/recipes/customize-validation-errors-format) function is used to return a custom format for validation errors. If you don't pass an input schema, `parsedInput` and validation errors will be typed `undefined`, and `clientInput` will be typed `void`. It returns a new instance of the safe action client. ## `bindArgsSchemas` @@ -39,7 +39,7 @@ schema(schema: S, utils?: { handleValidationErrorsShape?: HandleValidationErrors bindArgsSchemas(bindArgsSchemas: BAS, bindArgsUtils?: { handleBindArgsValidationErrorsShape?: HandleBindArgsValidationErrorsShapeFn }) => new SafeActionClient() ``` -`bindArgsSchemas` accepts an array of bind input schemas of type `Schema[]` (from TypeSchema) and an optional `bindArgsUtils` object that accepts a `handleBindArgsValidationErrorsShape` function. The schema is used to define the bind arguments that the safe action will receive, the optional `handleBindArgsValidationErrorsShape` function is used to [return a custom format for bind arguments validation errors](/docs/recipes/customize-validation-errors-format). It returns a new instance of the safe action client. +`bindArgsSchemas` accepts an array of bind input schemas of type `Schema[]` and an optional `bindArgsUtils` object that accepts a `handleBindArgsValidationErrorsShape` function. The schema is used to define the bind arguments that the safe action will receive, the optional `handleBindArgsValidationErrorsShape` function is used to [return a custom format for bind arguments validation errors](/docs/recipes/customize-validation-errors-format). It returns a new instance of the safe action client. ## `action` / `stateAction` diff --git a/website/docs/troubleshooting.md b/website/docs/troubleshooting.md index 910031c9..4fd205f6 100644 --- a/website/docs/troubleshooting.md +++ b/website/docs/troubleshooting.md @@ -5,33 +5,21 @@ description: Troubleshoot common issues with next-safe-action. # Troubleshooting -## Common issues +## TypeSchema issues (pre v7.2.0) -### `Schema` and `parsedInput` are typed `any` (broken types) and build issues - -At this time, TypeSchema (the library used under the hood for supporting multiple validation libraries) doesn't work with TypeScript >= 5.5; the resulting types for inputs and schemas are `any`, so type inference is broken. +**NOTE**: next-safe-action used TypeSchema up to version 7.1.3. If you use version 7.2.0 or later, these issues are fixed. -If you're in this situation, you have two paths to choose from to fix it: - -1. If you're using a library other than Zod, you have to downgrade your TypeScript version to 5.4 and, assuming you're using VS Code, add the following to your `.vscode/settings.json`, to tell the editor to use the workspace version of TypeScript: +### `Schema` and `parsedInput` are typed `any` (broken types) and build issues -```json title=".vscode/settings.json" -{ - "typescript.tsdk": "node_modules/typescript/lib" -} -``` +At this time, TypeSchema (the library used under the hood up to v7.1.3 for supporting multiple validation libraries) doesn't work with TypeScript >= 5.5; the resulting types for inputs and schemas are `any`, so type inference is broken. -2. If you're using Zod and TypeScript 5.5, you can install the experimental version of next-safe-action. It shares the same codebase as the stable version, the only difference it's that it supports just Zod. More information about this can be found in [this issue](https://github.com/TheEdoRan/next-safe-action/issues/180#issuecomment-2201607407) on GitHub. You can install it in your project by running the following command: - -```bash npm2yarn -npm i next-safe-action@experimental -``` +If you're in this situation, please upgrade to v7.2.0 or later to fix the issue. ### TypeSchema issues with Edge Runtime -TypeSchema enables support for many validation libraries, via adapters. However, since it relies on the dynamic import feature, it won't work with the Edge Runtime, so you'll need to use the default Zod client if you want to render on the Edge. +TypeSchema enables support for many validation libraries, via adapters. However, since it relies on the dynamic import feature, it won't work with the Edge Runtime. Please upgrade to v7.2.0 or later to fix the issue. -### TypeScript error in monorepo +## TypeScript error in monorepo If you use next-safe-action in a monorepo, you'll likely experience this error: diff --git a/website/docs/types.md b/website/docs/types.md index 25346cfa..337413d5 100644 --- a/website/docs/types.md +++ b/website/docs/types.md @@ -442,6 +442,6 @@ type SchemaErrors = { --- -## TypeSchema library +## Adapters types -`Infer`, `InferIn`, `Schema` types used in this documentation come from [TypeSchema](https://typeschema.com) library. +`Infer`, `InferIn`, `Schema` types used in this documentation come from `next-safe-action/adapters/types` path. diff --git a/website/package.json b/website/package.json index 790c1edb..255a9fb8 100644 --- a/website/package.json +++ b/website/package.json @@ -34,7 +34,7 @@ "postcss-nested": "^6.0.1", "tailwindcss": "^3.4.3", "tailwindcss-bg-patterns": "^0.3.0", - "typescript": "^5.4.5" + "typescript": "^5.5.3" }, "browserslist": { "production": [ diff --git a/website/pnpm-lock.yaml b/website/pnpm-lock.yaml index b325dd58..0616877c 100644 --- a/website/pnpm-lock.yaml +++ b/website/pnpm-lock.yaml @@ -10,10 +10,10 @@ importers: dependencies: '@docusaurus/core': specifier: 3.4.0 - version: 3.4.0(@docusaurus/types@3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.4.5) + version: 3.4.0(@docusaurus/types@3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3) '@docusaurus/preset-classic': specifier: 3.4.0 - version: 3.4.0(@algolia/client-search@4.23.3)(@types/react@18.2.79)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(search-insights@2.13.0)(typescript@5.4.5) + version: 3.4.0(@algolia/client-search@4.23.3)(@types/react@18.2.79)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(search-insights@2.13.0)(typescript@5.5.3) '@docusaurus/remark-plugin-npm2yarn': specifier: ^3.4.0 version: 3.4.0 @@ -61,8 +61,8 @@ importers: specifier: ^0.3.0 version: 0.3.0(tailwindcss@3.4.3) typescript: - specifier: ^5.4.5 - version: 5.4.5 + specifier: ^5.5.3 + version: 5.5.3 packages: @@ -1251,8 +1251,8 @@ packages: '@types/node@17.0.45': resolution: {integrity: sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw==} - '@types/node@20.12.7': - resolution: {integrity: sha512-wq0cICSkRLVaf3UGLMGItu/PtdY7oaXaI/RVU+xliKVOtRna3PRY57ZDfztpDL0n11vfymMUnXv8QwYCO7L1wg==} + '@types/node@20.14.11': + resolution: {integrity: sha512-kprQpL8MMeszbz6ojB5/tU8PLN4kesnN8Gjzw349rDlNgsSzg90lAVj3llK99Dh7JON+t9AuscPPFW6mPbTnSA==} '@types/parse-json@4.0.2': resolution: {integrity: sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==} @@ -4428,8 +4428,8 @@ packages: typedarray-to-buffer@3.1.5: resolution: {integrity: sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==} - typescript@5.4.5: - resolution: {integrity: sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==} + typescript@5.5.3: + resolution: {integrity: sha512-/hreyEujaB0w76zKo6717l3L0o/qEUtRgdvUBvlkhoWeOVMjMuHNHk0BRBzikzuGDqNmPQbg5ifMEqsHLiIUcQ==} engines: {node: '>=14.17'} hasBin: true @@ -5632,7 +5632,7 @@ snapshots: transitivePeerDependencies: - '@algolia/client-search' - '@docusaurus/core@3.4.0(@docusaurus/types@3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.4.5)': + '@docusaurus/core@3.4.0(@docusaurus/types@3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3)': dependencies: '@babel/core': 7.24.4 '@babel/generator': 7.24.4 @@ -5646,10 +5646,10 @@ snapshots: '@babel/traverse': 7.24.1 '@docusaurus/cssnano-preset': 3.4.0 '@docusaurus/logger': 3.4.0 - '@docusaurus/mdx-loader': 3.4.0(@docusaurus/types@3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.4.5) - '@docusaurus/utils': 3.4.0(@docusaurus/types@3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(typescript@5.4.5) + '@docusaurus/mdx-loader': 3.4.0(@docusaurus/types@3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3) + '@docusaurus/utils': 3.4.0(@docusaurus/types@3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(typescript@5.5.3) '@docusaurus/utils-common': 3.4.0(@docusaurus/types@3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)) - '@docusaurus/utils-validation': 3.4.0(@docusaurus/types@3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(typescript@5.4.5) + '@docusaurus/utils-validation': 3.4.0(@docusaurus/types@3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(typescript@5.5.3) autoprefixer: 10.4.19(postcss@8.4.38) babel-loader: 9.1.3(@babel/core@7.24.4)(webpack@5.91.0) babel-plugin-dynamic-import-node: 2.3.3 @@ -5680,10 +5680,10 @@ snapshots: mini-css-extract-plugin: 2.9.0(webpack@5.91.0) p-map: 4.0.0 postcss: 8.4.38 - postcss-loader: 7.3.4(postcss@8.4.38)(typescript@5.4.5)(webpack@5.91.0) + postcss-loader: 7.3.4(postcss@8.4.38)(typescript@5.5.3)(webpack@5.91.0) prompts: 2.4.2 react: 18.3.1 - react-dev-utils: 12.0.1(typescript@5.4.5)(webpack@5.91.0) + react-dev-utils: 12.0.1(typescript@5.5.3)(webpack@5.91.0) react-dom: 18.3.1(react@18.3.1) react-helmet-async: 1.3.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react-loadable: '@docusaurus/react-loadable@6.0.0(react@18.3.1)' @@ -5735,11 +5735,11 @@ snapshots: chalk: 4.1.2 tslib: 2.6.2 - '@docusaurus/mdx-loader@3.4.0(@docusaurus/types@3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.4.5)': + '@docusaurus/mdx-loader@3.4.0(@docusaurus/types@3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3)': dependencies: '@docusaurus/logger': 3.4.0 - '@docusaurus/utils': 3.4.0(@docusaurus/types@3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(typescript@5.4.5) - '@docusaurus/utils-validation': 3.4.0(@docusaurus/types@3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(typescript@5.4.5) + '@docusaurus/utils': 3.4.0(@docusaurus/types@3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(typescript@5.5.3) + '@docusaurus/utils-validation': 3.4.0(@docusaurus/types@3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(typescript@5.5.3) '@mdx-js/mdx': 3.0.1 '@slorber/remark-comment': 1.0.0 escape-html: 1.0.3 @@ -5790,15 +5790,15 @@ snapshots: - uglify-js - webpack-cli - '@docusaurus/plugin-content-blog@3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.4.5)': + '@docusaurus/plugin-content-blog@3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3)': dependencies: - '@docusaurus/core': 3.4.0(@docusaurus/types@3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.4.5) + '@docusaurus/core': 3.4.0(@docusaurus/types@3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3) '@docusaurus/logger': 3.4.0 - '@docusaurus/mdx-loader': 3.4.0(@docusaurus/types@3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.4.5) + '@docusaurus/mdx-loader': 3.4.0(@docusaurus/types@3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3) '@docusaurus/types': 3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@docusaurus/utils': 3.4.0(@docusaurus/types@3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(typescript@5.4.5) + '@docusaurus/utils': 3.4.0(@docusaurus/types@3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(typescript@5.5.3) '@docusaurus/utils-common': 3.4.0(@docusaurus/types@3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)) - '@docusaurus/utils-validation': 3.4.0(@docusaurus/types@3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(typescript@5.4.5) + '@docusaurus/utils-validation': 3.4.0(@docusaurus/types@3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(typescript@5.5.3) cheerio: 1.0.0-rc.12 feed: 4.2.2 fs-extra: 11.2.0 @@ -5829,16 +5829,16 @@ snapshots: - vue-template-compiler - webpack-cli - '@docusaurus/plugin-content-docs@3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.4.5)': + '@docusaurus/plugin-content-docs@3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3)': dependencies: - '@docusaurus/core': 3.4.0(@docusaurus/types@3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.4.5) + '@docusaurus/core': 3.4.0(@docusaurus/types@3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3) '@docusaurus/logger': 3.4.0 - '@docusaurus/mdx-loader': 3.4.0(@docusaurus/types@3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.4.5) + '@docusaurus/mdx-loader': 3.4.0(@docusaurus/types@3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3) '@docusaurus/module-type-aliases': 3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@docusaurus/types': 3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@docusaurus/utils': 3.4.0(@docusaurus/types@3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(typescript@5.4.5) + '@docusaurus/utils': 3.4.0(@docusaurus/types@3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(typescript@5.5.3) '@docusaurus/utils-common': 3.4.0(@docusaurus/types@3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)) - '@docusaurus/utils-validation': 3.4.0(@docusaurus/types@3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(typescript@5.4.5) + '@docusaurus/utils-validation': 3.4.0(@docusaurus/types@3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(typescript@5.5.3) '@types/react-router-config': 5.0.11 combine-promises: 1.2.0 fs-extra: 11.2.0 @@ -5867,13 +5867,13 @@ snapshots: - vue-template-compiler - webpack-cli - '@docusaurus/plugin-content-pages@3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.4.5)': + '@docusaurus/plugin-content-pages@3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3)': dependencies: - '@docusaurus/core': 3.4.0(@docusaurus/types@3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.4.5) - '@docusaurus/mdx-loader': 3.4.0(@docusaurus/types@3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.4.5) + '@docusaurus/core': 3.4.0(@docusaurus/types@3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3) + '@docusaurus/mdx-loader': 3.4.0(@docusaurus/types@3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3) '@docusaurus/types': 3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@docusaurus/utils': 3.4.0(@docusaurus/types@3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(typescript@5.4.5) - '@docusaurus/utils-validation': 3.4.0(@docusaurus/types@3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(typescript@5.4.5) + '@docusaurus/utils': 3.4.0(@docusaurus/types@3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(typescript@5.5.3) + '@docusaurus/utils-validation': 3.4.0(@docusaurus/types@3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(typescript@5.5.3) fs-extra: 11.2.0 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) @@ -5897,11 +5897,11 @@ snapshots: - vue-template-compiler - webpack-cli - '@docusaurus/plugin-debug@3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.4.5)': + '@docusaurus/plugin-debug@3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3)': dependencies: - '@docusaurus/core': 3.4.0(@docusaurus/types@3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.4.5) + '@docusaurus/core': 3.4.0(@docusaurus/types@3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3) '@docusaurus/types': 3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@docusaurus/utils': 3.4.0(@docusaurus/types@3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(typescript@5.4.5) + '@docusaurus/utils': 3.4.0(@docusaurus/types@3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(typescript@5.5.3) fs-extra: 11.2.0 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) @@ -5925,11 +5925,11 @@ snapshots: - vue-template-compiler - webpack-cli - '@docusaurus/plugin-google-analytics@3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.4.5)': + '@docusaurus/plugin-google-analytics@3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3)': dependencies: - '@docusaurus/core': 3.4.0(@docusaurus/types@3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.4.5) + '@docusaurus/core': 3.4.0(@docusaurus/types@3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3) '@docusaurus/types': 3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@docusaurus/utils-validation': 3.4.0(@docusaurus/types@3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(typescript@5.4.5) + '@docusaurus/utils-validation': 3.4.0(@docusaurus/types@3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(typescript@5.5.3) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) tslib: 2.6.2 @@ -5951,11 +5951,11 @@ snapshots: - vue-template-compiler - webpack-cli - '@docusaurus/plugin-google-gtag@3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.4.5)': + '@docusaurus/plugin-google-gtag@3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3)': dependencies: - '@docusaurus/core': 3.4.0(@docusaurus/types@3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.4.5) + '@docusaurus/core': 3.4.0(@docusaurus/types@3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3) '@docusaurus/types': 3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@docusaurus/utils-validation': 3.4.0(@docusaurus/types@3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(typescript@5.4.5) + '@docusaurus/utils-validation': 3.4.0(@docusaurus/types@3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(typescript@5.5.3) '@types/gtag.js': 0.0.12 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) @@ -5978,11 +5978,11 @@ snapshots: - vue-template-compiler - webpack-cli - '@docusaurus/plugin-google-tag-manager@3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.4.5)': + '@docusaurus/plugin-google-tag-manager@3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3)': dependencies: - '@docusaurus/core': 3.4.0(@docusaurus/types@3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.4.5) + '@docusaurus/core': 3.4.0(@docusaurus/types@3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3) '@docusaurus/types': 3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@docusaurus/utils-validation': 3.4.0(@docusaurus/types@3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(typescript@5.4.5) + '@docusaurus/utils-validation': 3.4.0(@docusaurus/types@3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(typescript@5.5.3) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) tslib: 2.6.2 @@ -6004,14 +6004,14 @@ snapshots: - vue-template-compiler - webpack-cli - '@docusaurus/plugin-sitemap@3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.4.5)': + '@docusaurus/plugin-sitemap@3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3)': dependencies: - '@docusaurus/core': 3.4.0(@docusaurus/types@3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.4.5) + '@docusaurus/core': 3.4.0(@docusaurus/types@3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3) '@docusaurus/logger': 3.4.0 '@docusaurus/types': 3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@docusaurus/utils': 3.4.0(@docusaurus/types@3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(typescript@5.4.5) + '@docusaurus/utils': 3.4.0(@docusaurus/types@3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(typescript@5.5.3) '@docusaurus/utils-common': 3.4.0(@docusaurus/types@3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)) - '@docusaurus/utils-validation': 3.4.0(@docusaurus/types@3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(typescript@5.4.5) + '@docusaurus/utils-validation': 3.4.0(@docusaurus/types@3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(typescript@5.5.3) fs-extra: 11.2.0 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) @@ -6035,20 +6035,20 @@ snapshots: - vue-template-compiler - webpack-cli - '@docusaurus/preset-classic@3.4.0(@algolia/client-search@4.23.3)(@types/react@18.2.79)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(search-insights@2.13.0)(typescript@5.4.5)': - dependencies: - '@docusaurus/core': 3.4.0(@docusaurus/types@3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.4.5) - '@docusaurus/plugin-content-blog': 3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.4.5) - '@docusaurus/plugin-content-docs': 3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.4.5) - '@docusaurus/plugin-content-pages': 3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.4.5) - '@docusaurus/plugin-debug': 3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.4.5) - '@docusaurus/plugin-google-analytics': 3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.4.5) - '@docusaurus/plugin-google-gtag': 3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.4.5) - '@docusaurus/plugin-google-tag-manager': 3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.4.5) - '@docusaurus/plugin-sitemap': 3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.4.5) - '@docusaurus/theme-classic': 3.4.0(@types/react@18.2.79)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.4.5) - '@docusaurus/theme-common': 3.4.0(@docusaurus/types@3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.4.5) - '@docusaurus/theme-search-algolia': 3.4.0(@algolia/client-search@4.23.3)(@docusaurus/types@3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@types/react@18.2.79)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(search-insights@2.13.0)(typescript@5.4.5) + '@docusaurus/preset-classic@3.4.0(@algolia/client-search@4.23.3)(@types/react@18.2.79)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(search-insights@2.13.0)(typescript@5.5.3)': + dependencies: + '@docusaurus/core': 3.4.0(@docusaurus/types@3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3) + '@docusaurus/plugin-content-blog': 3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3) + '@docusaurus/plugin-content-docs': 3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3) + '@docusaurus/plugin-content-pages': 3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3) + '@docusaurus/plugin-debug': 3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3) + '@docusaurus/plugin-google-analytics': 3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3) + '@docusaurus/plugin-google-gtag': 3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3) + '@docusaurus/plugin-google-tag-manager': 3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3) + '@docusaurus/plugin-sitemap': 3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3) + '@docusaurus/theme-classic': 3.4.0(@types/react@18.2.79)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3) + '@docusaurus/theme-common': 3.4.0(@docusaurus/types@3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3) + '@docusaurus/theme-search-algolia': 3.4.0(@algolia/client-search@4.23.3)(@docusaurus/types@3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@types/react@18.2.79)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(search-insights@2.13.0)(typescript@5.5.3) '@docusaurus/types': 3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) @@ -6088,20 +6088,20 @@ snapshots: transitivePeerDependencies: - supports-color - '@docusaurus/theme-classic@3.4.0(@types/react@18.2.79)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.4.5)': + '@docusaurus/theme-classic@3.4.0(@types/react@18.2.79)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3)': dependencies: - '@docusaurus/core': 3.4.0(@docusaurus/types@3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.4.5) - '@docusaurus/mdx-loader': 3.4.0(@docusaurus/types@3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.4.5) + '@docusaurus/core': 3.4.0(@docusaurus/types@3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3) + '@docusaurus/mdx-loader': 3.4.0(@docusaurus/types@3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3) '@docusaurus/module-type-aliases': 3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@docusaurus/plugin-content-blog': 3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.4.5) - '@docusaurus/plugin-content-docs': 3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.4.5) - '@docusaurus/plugin-content-pages': 3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.4.5) - '@docusaurus/theme-common': 3.4.0(@docusaurus/types@3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.4.5) + '@docusaurus/plugin-content-blog': 3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3) + '@docusaurus/plugin-content-docs': 3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3) + '@docusaurus/plugin-content-pages': 3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3) + '@docusaurus/theme-common': 3.4.0(@docusaurus/types@3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3) '@docusaurus/theme-translations': 3.4.0 '@docusaurus/types': 3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@docusaurus/utils': 3.4.0(@docusaurus/types@3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(typescript@5.4.5) + '@docusaurus/utils': 3.4.0(@docusaurus/types@3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(typescript@5.5.3) '@docusaurus/utils-common': 3.4.0(@docusaurus/types@3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)) - '@docusaurus/utils-validation': 3.4.0(@docusaurus/types@3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(typescript@5.4.5) + '@docusaurus/utils-validation': 3.4.0(@docusaurus/types@3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(typescript@5.5.3) '@mdx-js/react': 3.0.1(@types/react@18.2.79)(react@18.3.1) clsx: 2.1.1 copy-text-to-clipboard: 3.2.0 @@ -6136,14 +6136,14 @@ snapshots: - vue-template-compiler - webpack-cli - '@docusaurus/theme-common@3.4.0(@docusaurus/types@3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.4.5)': + '@docusaurus/theme-common@3.4.0(@docusaurus/types@3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3)': dependencies: - '@docusaurus/mdx-loader': 3.4.0(@docusaurus/types@3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.4.5) + '@docusaurus/mdx-loader': 3.4.0(@docusaurus/types@3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3) '@docusaurus/module-type-aliases': 3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@docusaurus/plugin-content-blog': 3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.4.5) - '@docusaurus/plugin-content-docs': 3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.4.5) - '@docusaurus/plugin-content-pages': 3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.4.5) - '@docusaurus/utils': 3.4.0(@docusaurus/types@3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(typescript@5.4.5) + '@docusaurus/plugin-content-blog': 3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3) + '@docusaurus/plugin-content-docs': 3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3) + '@docusaurus/plugin-content-pages': 3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3) + '@docusaurus/utils': 3.4.0(@docusaurus/types@3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(typescript@5.5.3) '@docusaurus/utils-common': 3.4.0(@docusaurus/types@3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)) '@types/history': 4.7.11 '@types/react': 18.2.79 @@ -6174,16 +6174,16 @@ snapshots: - vue-template-compiler - webpack-cli - '@docusaurus/theme-search-algolia@3.4.0(@algolia/client-search@4.23.3)(@docusaurus/types@3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@types/react@18.2.79)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(search-insights@2.13.0)(typescript@5.4.5)': + '@docusaurus/theme-search-algolia@3.4.0(@algolia/client-search@4.23.3)(@docusaurus/types@3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@types/react@18.2.79)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(search-insights@2.13.0)(typescript@5.5.3)': dependencies: '@docsearch/react': 3.6.0(@algolia/client-search@4.23.3)(@types/react@18.2.79)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(search-insights@2.13.0) - '@docusaurus/core': 3.4.0(@docusaurus/types@3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.4.5) + '@docusaurus/core': 3.4.0(@docusaurus/types@3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3) '@docusaurus/logger': 3.4.0 - '@docusaurus/plugin-content-docs': 3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.4.5) - '@docusaurus/theme-common': 3.4.0(@docusaurus/types@3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.4.5) + '@docusaurus/plugin-content-docs': 3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3) + '@docusaurus/theme-common': 3.4.0(@docusaurus/types@3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3) '@docusaurus/theme-translations': 3.4.0 - '@docusaurus/utils': 3.4.0(@docusaurus/types@3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(typescript@5.4.5) - '@docusaurus/utils-validation': 3.4.0(@docusaurus/types@3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(typescript@5.4.5) + '@docusaurus/utils': 3.4.0(@docusaurus/types@3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(typescript@5.5.3) + '@docusaurus/utils-validation': 3.4.0(@docusaurus/types@3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(typescript@5.5.3) algoliasearch: 4.23.3 algoliasearch-helper: 3.18.0(algoliasearch@4.23.3) clsx: 2.1.1 @@ -6249,10 +6249,10 @@ snapshots: optionalDependencies: '@docusaurus/types': 3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@docusaurus/utils-validation@3.4.0(@docusaurus/types@3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(typescript@5.4.5)': + '@docusaurus/utils-validation@3.4.0(@docusaurus/types@3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(typescript@5.5.3)': dependencies: '@docusaurus/logger': 3.4.0 - '@docusaurus/utils': 3.4.0(@docusaurus/types@3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(typescript@5.4.5) + '@docusaurus/utils': 3.4.0(@docusaurus/types@3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(typescript@5.5.3) '@docusaurus/utils-common': 3.4.0(@docusaurus/types@3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)) fs-extra: 11.2.0 joi: 17.13.0 @@ -6268,11 +6268,11 @@ snapshots: - uglify-js - webpack-cli - '@docusaurus/utils@3.4.0(@docusaurus/types@3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(typescript@5.4.5)': + '@docusaurus/utils@3.4.0(@docusaurus/types@3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(typescript@5.5.3)': dependencies: '@docusaurus/logger': 3.4.0 '@docusaurus/utils-common': 3.4.0(@docusaurus/types@3.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)) - '@svgr/webpack': 8.1.0(typescript@5.4.5) + '@svgr/webpack': 8.1.0(typescript@5.5.3) escape-string-regexp: 4.0.0 file-loader: 6.2.0(webpack@5.91.0) fs-extra: 11.2.0 @@ -6324,7 +6324,7 @@ snapshots: '@jest/schemas': 29.6.3 '@types/istanbul-lib-coverage': 2.0.6 '@types/istanbul-reports': 3.0.4 - '@types/node': 20.12.7 + '@types/node': 20.14.11 '@types/yargs': 17.0.32 chalk: 4.1.2 @@ -6479,12 +6479,12 @@ snapshots: '@svgr/babel-plugin-transform-react-native-svg': 8.1.0(@babel/core@7.24.4) '@svgr/babel-plugin-transform-svg-component': 8.0.0(@babel/core@7.24.4) - '@svgr/core@8.1.0(typescript@5.4.5)': + '@svgr/core@8.1.0(typescript@5.5.3)': dependencies: '@babel/core': 7.24.4 '@svgr/babel-preset': 8.1.0(@babel/core@7.24.4) camelcase: 6.3.0 - cosmiconfig: 8.3.6(typescript@5.4.5) + cosmiconfig: 8.3.6(typescript@5.5.3) snake-case: 3.0.4 transitivePeerDependencies: - supports-color @@ -6495,35 +6495,35 @@ snapshots: '@babel/types': 7.24.0 entities: 4.5.0 - '@svgr/plugin-jsx@8.1.0(@svgr/core@8.1.0(typescript@5.4.5))': + '@svgr/plugin-jsx@8.1.0(@svgr/core@8.1.0(typescript@5.5.3))': dependencies: '@babel/core': 7.24.4 '@svgr/babel-preset': 8.1.0(@babel/core@7.24.4) - '@svgr/core': 8.1.0(typescript@5.4.5) + '@svgr/core': 8.1.0(typescript@5.5.3) '@svgr/hast-util-to-babel-ast': 8.0.0 svg-parser: 2.0.4 transitivePeerDependencies: - supports-color - '@svgr/plugin-svgo@8.1.0(@svgr/core@8.1.0(typescript@5.4.5))(typescript@5.4.5)': + '@svgr/plugin-svgo@8.1.0(@svgr/core@8.1.0(typescript@5.5.3))(typescript@5.5.3)': dependencies: - '@svgr/core': 8.1.0(typescript@5.4.5) - cosmiconfig: 8.3.6(typescript@5.4.5) + '@svgr/core': 8.1.0(typescript@5.5.3) + cosmiconfig: 8.3.6(typescript@5.5.3) deepmerge: 4.3.1 svgo: 3.2.0 transitivePeerDependencies: - typescript - '@svgr/webpack@8.1.0(typescript@5.4.5)': + '@svgr/webpack@8.1.0(typescript@5.5.3)': dependencies: '@babel/core': 7.24.4 '@babel/plugin-transform-react-constant-elements': 7.24.1(@babel/core@7.24.4) '@babel/preset-env': 7.24.4(@babel/core@7.24.4) '@babel/preset-react': 7.24.1(@babel/core@7.24.4) '@babel/preset-typescript': 7.24.1(@babel/core@7.24.4) - '@svgr/core': 8.1.0(typescript@5.4.5) - '@svgr/plugin-jsx': 8.1.0(@svgr/core@8.1.0(typescript@5.4.5)) - '@svgr/plugin-svgo': 8.1.0(@svgr/core@8.1.0(typescript@5.4.5))(typescript@5.4.5) + '@svgr/core': 8.1.0(typescript@5.5.3) + '@svgr/plugin-jsx': 8.1.0(@svgr/core@8.1.0(typescript@5.5.3)) + '@svgr/plugin-svgo': 8.1.0(@svgr/core@8.1.0(typescript@5.5.3))(typescript@5.5.3) transitivePeerDependencies: - supports-color - typescript @@ -6541,20 +6541,20 @@ snapshots: '@types/body-parser@1.19.5': dependencies: '@types/connect': 3.4.38 - '@types/node': 20.12.7 + '@types/node': 20.14.11 '@types/bonjour@3.5.13': dependencies: - '@types/node': 20.12.7 + '@types/node': 20.14.11 '@types/connect-history-api-fallback@1.5.4': dependencies: '@types/express-serve-static-core': 4.19.0 - '@types/node': 20.12.7 + '@types/node': 20.14.11 '@types/connect@3.4.38': dependencies: - '@types/node': 20.12.7 + '@types/node': 20.14.11 '@types/debug@4.1.12': dependencies: @@ -6578,7 +6578,7 @@ snapshots: '@types/express-serve-static-core@4.19.0': dependencies: - '@types/node': 20.12.7 + '@types/node': 20.14.11 '@types/qs': 6.9.15 '@types/range-parser': 1.2.7 '@types/send': 0.17.4 @@ -6606,7 +6606,7 @@ snapshots: '@types/http-proxy@1.17.14': dependencies: - '@types/node': 20.12.7 + '@types/node': 20.14.11 '@types/istanbul-lib-coverage@2.0.6': {} @@ -6632,11 +6632,11 @@ snapshots: '@types/node-forge@1.3.11': dependencies: - '@types/node': 20.12.7 + '@types/node': 20.14.11 '@types/node@17.0.45': {} - '@types/node@20.12.7': + '@types/node@20.14.11': dependencies: undici-types: 5.26.5 @@ -6676,12 +6676,12 @@ snapshots: '@types/sax@1.2.7': dependencies: - '@types/node': 20.12.7 + '@types/node': 17.0.45 '@types/send@0.17.4': dependencies: '@types/mime': 1.3.5 - '@types/node': 20.12.7 + '@types/node': 20.14.11 '@types/serve-index@1.9.4': dependencies: @@ -6690,12 +6690,12 @@ snapshots: '@types/serve-static@1.15.7': dependencies: '@types/http-errors': 2.0.4 - '@types/node': 20.12.7 + '@types/node': 20.14.11 '@types/send': 0.17.4 '@types/sockjs@0.3.36': dependencies: - '@types/node': 20.12.7 + '@types/node': 20.14.11 '@types/unist@2.0.10': {} @@ -6703,7 +6703,7 @@ snapshots: '@types/ws@8.5.10': dependencies: - '@types/node': 20.12.7 + '@types/node': 20.14.11 '@types/yargs-parser@21.0.3': {} @@ -7276,14 +7276,14 @@ snapshots: path-type: 4.0.0 yaml: 1.10.2 - cosmiconfig@8.3.6(typescript@5.4.5): + cosmiconfig@8.3.6(typescript@5.5.3): dependencies: import-fresh: 3.3.0 js-yaml: 4.1.0 parse-json: 5.2.0 path-type: 4.0.0 optionalDependencies: - typescript: 5.4.5 + typescript: 5.5.3 cross-spawn@7.0.3: dependencies: @@ -7664,7 +7664,7 @@ snapshots: eval@0.1.8: dependencies: - '@types/node': 20.12.7 + '@types/node': 20.14.11 require-like: 0.1.2 eventemitter3@4.0.7: {} @@ -7809,7 +7809,7 @@ snapshots: cross-spawn: 7.0.3 signal-exit: 4.1.0 - fork-ts-checker-webpack-plugin@6.5.3(typescript@5.4.5)(webpack@5.91.0): + fork-ts-checker-webpack-plugin@6.5.3(typescript@5.5.3)(webpack@5.91.0): dependencies: '@babel/code-frame': 7.24.2 '@types/json-schema': 7.0.15 @@ -7824,7 +7824,7 @@ snapshots: schema-utils: 2.7.0 semver: 7.6.0 tapable: 1.1.3 - typescript: 5.4.5 + typescript: 5.5.3 webpack: 5.91.0 form-data-encoder@2.1.4: {} @@ -8357,7 +8357,7 @@ snapshots: jest-util@29.7.0: dependencies: '@jest/types': 29.6.3 - '@types/node': 20.12.7 + '@types/node': 20.14.11 chalk: 4.1.2 ci-info: 3.9.0 graceful-fs: 4.2.11 @@ -8365,13 +8365,13 @@ snapshots: jest-worker@27.5.1: dependencies: - '@types/node': 20.12.7 + '@types/node': 20.14.11 merge-stream: 2.0.0 supports-color: 8.1.1 jest-worker@29.7.0: dependencies: - '@types/node': 20.12.7 + '@types/node': 20.14.11 jest-util: 29.7.0 merge-stream: 2.0.0 supports-color: 8.1.1 @@ -9346,9 +9346,9 @@ snapshots: optionalDependencies: postcss: 8.4.38 - postcss-loader@7.3.4(postcss@8.4.38)(typescript@5.4.5)(webpack@5.91.0): + postcss-loader@7.3.4(postcss@8.4.38)(typescript@5.5.3)(webpack@5.91.0): dependencies: - cosmiconfig: 8.3.6(typescript@5.4.5) + cosmiconfig: 8.3.6(typescript@5.5.3) jiti: 1.21.0 postcss: 8.4.38 semver: 7.6.0 @@ -9605,7 +9605,7 @@ snapshots: minimist: 1.2.8 strip-json-comments: 2.0.1 - react-dev-utils@12.0.1(typescript@5.4.5)(webpack@5.91.0): + react-dev-utils@12.0.1(typescript@5.5.3)(webpack@5.91.0): dependencies: '@babel/code-frame': 7.24.2 address: 1.2.2 @@ -9616,7 +9616,7 @@ snapshots: escape-string-regexp: 4.0.0 filesize: 8.0.7 find-up: 5.0.0 - fork-ts-checker-webpack-plugin: 6.5.3(typescript@5.4.5)(webpack@5.91.0) + fork-ts-checker-webpack-plugin: 6.5.3(typescript@5.5.3)(webpack@5.91.0) global-modules: 2.0.0 globby: 11.1.0 gzip-size: 6.0.0 @@ -9633,7 +9633,7 @@ snapshots: text-table: 0.2.0 webpack: 5.91.0 optionalDependencies: - typescript: 5.4.5 + typescript: 5.5.3 transitivePeerDependencies: - eslint - supports-color @@ -10334,7 +10334,7 @@ snapshots: dependencies: is-typedarray: 1.0.0 - typescript@5.4.5: {} + typescript@5.5.3: {} undici-types@5.26.5: {} diff --git a/website/src/components/landing/features.tsx b/website/src/components/landing/features.tsx index 24c35955..5821db64 100644 --- a/website/src/components/landing/features.tsx +++ b/website/src/components/landing/features.tsx @@ -24,7 +24,7 @@ const features: { title: string; description: string }[] = [ }, { title: "Input validation using multiple validation libraries", - description: `Input passed from the client to the server is validated using Zod or other validation libraries supported by TypeSchema.`, + description: `Input passed from the client to the server is validated using Zod, Valibot or Yup.`, }, { title: "Advanced server error handling",