diff --git a/apps/openpage-api/package.json b/apps/openpage-api/package.json
index 0a82e1fff..f2ca53995 100644
--- a/apps/openpage-api/package.json
+++ b/apps/openpage-api/package.json
@@ -12,11 +12,14 @@
"dependencies": {
"@documenso/prisma": "*",
"luxon": "^3.7.2",
- "next": "15.5.12"
+ "next": "15.5.12",
+ "react": "^18",
+ "react-dom": "^18"
},
"devDependencies": {
"@types/node": "^20",
"@types/react": "18.3.27",
+ "@types/react-dom": "^18",
"typescript": "5.6.2"
}
}
diff --git a/package-lock.json b/package-lock.json
index 89276da45..325bd8871 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -39,6 +39,8 @@
"@ts-rest/core": "^3.52.1",
"@ts-rest/open-api": "^3.52.1",
"@ts-rest/serverless": "^3.52.1",
+ "@types/react": "18.3.27",
+ "@types/react-dom": "^18",
"dotenv": "^17.2.3",
"dotenv-cli": "^11.0.0",
"husky": "^9.1.7",
@@ -57,6 +59,7 @@
"prisma-extension-kysely": "^3.0.0",
"prisma-json-types-generator": "^3.6.2",
"prisma-kysely": "^2.3.0",
+ "react-dom": "^18",
"rimraf": "^6.1.2",
"superjson": "^2.2.5",
"syncpack": "^14.0.0-alpha.27",
@@ -100,6 +103,26 @@
"typescript": "^5.9.3"
}
},
+ "apps/docs/node_modules/@types/react": {
+ "version": "19.2.14",
+ "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.14.tgz",
+ "integrity": "sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "csstype": "^3.2.2"
+ }
+ },
+ "apps/docs/node_modules/@types/react-dom": {
+ "version": "19.2.3",
+ "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.2.3.tgz",
+ "integrity": "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==",
+ "dev": true,
+ "license": "MIT",
+ "peerDependencies": {
+ "@types/react": "^19.2.0"
+ }
+ },
"apps/docs/node_modules/react": {
"version": "19.2.4",
"resolved": "https://registry.npmjs.org/react/-/react-19.2.4.tgz",
@@ -109,31 +132,38 @@
"node": ">=0.10.0"
}
},
- "apps/docs/node_modules/typescript": {
- "version": "5.9.3",
- "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz",
- "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
- "dev": true,
- "license": "Apache-2.0",
- "bin": {
- "tsc": "bin/tsc",
- "tsserver": "bin/tsserver"
+ "apps/docs/node_modules/react-dom": {
+ "version": "19.2.4",
+ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.4.tgz",
+ "integrity": "sha512-AXJdLo8kgMbimY95O2aKQqsz2iWi9jMgKJhRBAxECE4IFxfcazB2LmzloIoibJI3C12IlY20+KFaLv+71bUJeQ==",
+ "license": "MIT",
+ "dependencies": {
+ "scheduler": "^0.27.0"
},
- "engines": {
- "node": ">=14.17"
+ "peerDependencies": {
+ "react": "^19.2.4"
}
},
+ "apps/docs/node_modules/scheduler": {
+ "version": "0.27.0",
+ "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz",
+ "integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==",
+ "license": "MIT"
+ },
"apps/openpage-api": {
"name": "@documenso/openpage-api",
"version": "1.0.0",
"dependencies": {
"@documenso/prisma": "*",
"luxon": "^3.7.2",
- "next": "15.5.12"
+ "next": "15.5.12",
+ "react": "^18",
+ "react-dom": "^18"
},
"devDependencies": {
"@types/node": "^20",
"@types/react": "18.3.27",
+ "@types/react-dom": "^18",
"typescript": "5.6.2"
}
},
@@ -147,17 +177,6 @@
"undici-types": "~6.21.0"
}
},
- "apps/openpage-api/node_modules/@types/react": {
- "version": "18.3.27",
- "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.27.tgz",
- "integrity": "sha512-cisd7gxkzjBKU2GgdYrTdtQx1SORymWyaAFhaxQPK9bYO9ot3Y5OikQRvY0VYQtvwjeQnizCINJAenh/V7MK2w==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@types/prop-types": "*",
- "csstype": "^3.2.2"
- }
- },
"apps/openpage-api/node_modules/nanoid": {
"version": "3.3.11",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz",
@@ -362,27 +381,6 @@
"undici-types": "~6.21.0"
}
},
- "apps/remix/node_modules/@types/react": {
- "version": "18.3.27",
- "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.27.tgz",
- "integrity": "sha512-cisd7gxkzjBKU2GgdYrTdtQx1SORymWyaAFhaxQPK9bYO9ot3Y5OikQRvY0VYQtvwjeQnizCINJAenh/V7MK2w==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@types/prop-types": "*",
- "csstype": "^3.2.2"
- }
- },
- "apps/remix/node_modules/@types/react-dom": {
- "version": "18.3.7",
- "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.7.tgz",
- "integrity": "sha512-MEe3UeoENYVFXzoXEWsvcpg6ZvlrFNlOQ7EOsvhI3CfAXwzPfO8Qwuxd40nepsYKqyyVQnTdEfv68q91yLcKrQ==",
- "dev": true,
- "license": "MIT",
- "peerDependencies": {
- "@types/react": "^18.0.0"
- }
- },
"apps/remix/node_modules/lucide-react": {
"version": "0.554.0",
"resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.554.0.tgz",
@@ -392,19 +390,6 @@
"react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0"
}
},
- "apps/remix/node_modules/react-dom": {
- "version": "18.3.1",
- "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz",
- "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==",
- "license": "MIT",
- "dependencies": {
- "loose-envify": "^1.1.0",
- "scheduler": "^0.23.2"
- },
- "peerDependencies": {
- "react": "^18.3.1"
- }
- },
"apps/remix/node_modules/tailwindcss": {
"version": "3.4.19",
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.19.tgz",
@@ -13465,26 +13450,26 @@
"version": "15.7.15",
"resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.15.tgz",
"integrity": "sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw==",
- "dev": true,
"license": "MIT"
},
"node_modules/@types/react": {
- "version": "19.2.14",
- "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.14.tgz",
- "integrity": "sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w==",
+ "version": "18.3.27",
+ "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.27.tgz",
+ "integrity": "sha512-cisd7gxkzjBKU2GgdYrTdtQx1SORymWyaAFhaxQPK9bYO9ot3Y5OikQRvY0VYQtvwjeQnizCINJAenh/V7MK2w==",
"license": "MIT",
"dependencies": {
+ "@types/prop-types": "*",
"csstype": "^3.2.2"
}
},
"node_modules/@types/react-dom": {
- "version": "19.2.3",
- "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.2.3.tgz",
- "integrity": "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==",
+ "version": "18.3.7",
+ "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.7.tgz",
+ "integrity": "sha512-MEe3UeoENYVFXzoXEWsvcpg6ZvlrFNlOQ7EOsvhI3CfAXwzPfO8Qwuxd40nepsYKqyyVQnTdEfv68q91yLcKrQ==",
"dev": true,
"license": "MIT",
"peerDependencies": {
- "@types/react": "^19.2.0"
+ "@types/react": "^18.0.0"
}
},
"node_modules/@types/resolve": {
@@ -24659,23 +24644,18 @@
}
},
"node_modules/react-dom": {
- "version": "19.2.4",
- "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.4.tgz",
- "integrity": "sha512-AXJdLo8kgMbimY95O2aKQqsz2iWi9jMgKJhRBAxECE4IFxfcazB2LmzloIoibJI3C12IlY20+KFaLv+71bUJeQ==",
+ "version": "18.3.1",
+ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz",
+ "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==",
"license": "MIT",
"dependencies": {
- "scheduler": "^0.27.0"
+ "loose-envify": "^1.1.0",
+ "scheduler": "^0.23.2"
},
"peerDependencies": {
- "react": "^19.2.4"
+ "react": "^18.3.1"
}
},
- "node_modules/react-dom/node_modules/scheduler": {
- "version": "0.27.0",
- "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz",
- "integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==",
- "license": "MIT"
- },
"node_modules/react-draggable": {
"version": "4.4.6",
"resolved": "https://registry.npmjs.org/react-draggable/-/react-draggable-4.4.6.tgz",
@@ -29762,27 +29742,6 @@
"typescript": "5.6.2"
}
},
- "packages/ui/node_modules/@types/react": {
- "version": "18.3.27",
- "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.27.tgz",
- "integrity": "sha512-cisd7gxkzjBKU2GgdYrTdtQx1SORymWyaAFhaxQPK9bYO9ot3Y5OikQRvY0VYQtvwjeQnizCINJAenh/V7MK2w==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@types/prop-types": "*",
- "csstype": "^3.2.2"
- }
- },
- "packages/ui/node_modules/@types/react-dom": {
- "version": "18.3.7",
- "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.7.tgz",
- "integrity": "sha512-MEe3UeoENYVFXzoXEWsvcpg6ZvlrFNlOQ7EOsvhI3CfAXwzPfO8Qwuxd40nepsYKqyyVQnTdEfv68q91yLcKrQ==",
- "dev": true,
- "license": "MIT",
- "peerDependencies": {
- "@types/react": "^18.0.0"
- }
- },
"packages/ui/node_modules/lucide-react": {
"version": "0.554.0",
"resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.554.0.tgz",
@@ -29792,19 +29751,6 @@
"react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0"
}
},
- "packages/ui/node_modules/react-dom": {
- "version": "18.3.1",
- "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz",
- "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==",
- "license": "MIT",
- "dependencies": {
- "loose-envify": "^1.1.0",
- "scheduler": "^0.23.2"
- },
- "peerDependencies": {
- "react": "^18.3.1"
- }
- },
"packages/ui/node_modules/tailwind-merge": {
"version": "1.14.0",
"resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-1.14.0.tgz",
diff --git a/package.json b/package.json
index 6ec72cadd..c258869fd 100644
--- a/package.json
+++ b/package.json
@@ -76,12 +76,15 @@
"prisma-extension-kysely": "^3.0.0",
"prisma-json-types-generator": "^3.6.2",
"prisma-kysely": "^2.3.0",
+ "react-dom": "^18",
"rimraf": "^6.1.2",
"superjson": "^2.2.5",
"syncpack": "^14.0.0-alpha.27",
"turbo": "^1.13.4",
"vite": "^7.2.4",
"vite-plugin-static-copy": "^3.1.4",
+ "@types/react": "18.3.27",
+ "@types/react-dom": "^18",
"zod-openapi": "^4.2.4",
"zod-prisma-types": "3.3.5"
},
diff --git a/packages/api/v1/implementation.ts b/packages/api/v1/implementation.ts
index 3181537f5..dcde5466d 100644
--- a/packages/api/v1/implementation.ts
+++ b/packages/api/v1/implementation.ts
@@ -189,7 +189,7 @@ export const ApiContractV1Implementation = tsr.router(ApiContractV1, {
fields: parsedMetaFields,
},
};
- } catch (err) {
+ } catch {
return {
status: 404,
body: {
@@ -276,7 +276,7 @@ export const ApiContractV1Implementation = tsr.router(ApiContractV1, {
status: 200,
body: { downloadUrl: url },
};
- } catch (err) {
+ } catch {
return {
status: 500,
body: {
@@ -341,7 +341,7 @@ export const ApiContractV1Implementation = tsr.router(ApiContractV1, {
completedAt: deletedDocument.completedAt,
},
};
- } catch (err) {
+ } catch {
return {
status: 404,
body: {
@@ -478,7 +478,7 @@ export const ApiContractV1Implementation = tsr.router(ApiContractV1, {
})),
},
};
- } catch (err) {
+ } catch {
return {
status: 404,
body: {
@@ -593,7 +593,7 @@ export const ApiContractV1Implementation = tsr.router(ApiContractV1, {
template: fullTemplate,
},
};
- } catch (err) {
+ } catch {
return {
status: 404,
body: {
@@ -637,7 +637,7 @@ export const ApiContractV1Implementation = tsr.router(ApiContractV1, {
updatedAt: deletedTemplate.updatedAt,
},
};
- } catch (err) {
+ } catch {
return {
status: 404,
body: {
@@ -1077,7 +1077,7 @@ export const ApiContractV1Implementation = tsr.router(ApiContractV1, {
message: 'Document resend successfully initiated',
},
};
- } catch (err) {
+ } catch {
return {
status: 500,
body: {
@@ -1185,7 +1185,7 @@ export const ApiContractV1Implementation = tsr.router(ApiContractV1, {
signingUrl: `${NEXT_PUBLIC_WEBAPP_URL()}/sign/${newRecipient.token}`,
},
};
- } catch (err) {
+ } catch {
return {
status: 500,
body: {
diff --git a/packages/email/transports/mailchannels.ts b/packages/email/transports/mailchannels.ts
index 45b12f739..bed9c3f49 100644
--- a/packages/email/transports/mailchannels.ts
+++ b/packages/email/transports/mailchannels.ts
@@ -54,13 +54,11 @@ export class MailChannelsTransport implements Transport {
const mailCc = this.toMailChannelsAddresses(mail.data.cc);
const mailBcc = this.toMailChannelsAddresses(mail.data.bcc);
- const from: MailChannelsAddress =
- typeof mail.data.from === 'string'
- ? { email: mail.data.from }
- : {
- email: mail.data.from?.address,
- name: mail.data.from?.name,
- };
+ const [from] = this.toMailChannelsAddresses(mail.data.from);
+
+ if (!from) {
+ return callback(new Error('Missing required field "from"'), null);
+ }
const requestHeaders: Record = {
'Content-Type': 'application/json',
@@ -70,56 +68,15 @@ export class MailChannelsTransport implements Transport {
requestHeaders['X-Auth-Token'] = this._options.apiKey;
}
- fetch(this._options.endpoint, {
- method: 'POST',
- headers: requestHeaders,
- body: JSON.stringify({
- from: from,
- subject: mail.data.subject,
- personalizations: [
- {
- to: mailTo,
- cc: mailCc.length > 0 ? mailCc : undefined,
- bcc: mailBcc.length > 0 ? mailBcc : undefined,
- dkim_domain: env('NEXT_PRIVATE_MAILCHANNELS_DKIM_DOMAIN') || undefined,
- dkim_selector: env('NEXT_PRIVATE_MAILCHANNELS_DKIM_SELECTOR') || undefined,
- dkim_private_key: env('NEXT_PRIVATE_MAILCHANNELS_DKIM_PRIVATE_KEY') || undefined,
- },
- ],
- content: [
- {
- type: 'text/plain',
- value: mail.data.text?.toString('utf-8') ?? '',
- },
- {
- type: 'text/html',
- value: mail.data.html?.toString('utf-8') ?? '',
- },
- ],
- }),
- })
- .then((res) => {
- if (res.status >= 200 && res.status <= 299) {
- return callback(null, {
- messageId: '',
- envelope: {
- from: mail.data.from,
- to: mail.data.to,
- },
- accepted: mail.data.to,
- rejected: [],
- pending: [],
- });
- }
-
- res
- .json()
- .then((data) => callback(new Error(`MailChannels error: ${data.message}`), null))
- .catch((err) => callback(err, null));
- })
- .catch((err) => {
- return callback(err, null);
- });
+ void this.sendMailRequest({
+ callback,
+ from,
+ mail,
+ mailBcc,
+ mailCc,
+ mailTo,
+ requestHeaders,
+ });
}
/**
@@ -154,4 +111,72 @@ export class MailChannelsTransport implements Transport {
},
];
}
+
+ private async sendMailRequest({
+ callback,
+ from,
+ mail,
+ mailBcc,
+ mailCc,
+ mailTo,
+ requestHeaders,
+ }: {
+ callback: (_err: Error | null, _info: SentMessageInfo) => void;
+ from: MailChannelsAddress;
+ mail: MailMessage;
+ mailBcc: Array;
+ mailCc: Array;
+ mailTo: Array;
+ requestHeaders: Record;
+ }) {
+ try {
+ const response = await fetch(this._options.endpoint, {
+ method: 'POST',
+ headers: requestHeaders,
+ body: JSON.stringify({
+ from,
+ subject: mail.data.subject,
+ personalizations: [
+ {
+ to: mailTo,
+ cc: mailCc.length > 0 ? mailCc : undefined,
+ bcc: mailBcc.length > 0 ? mailBcc : undefined,
+ dkim_domain: env('NEXT_PRIVATE_MAILCHANNELS_DKIM_DOMAIN') || undefined,
+ dkim_selector: env('NEXT_PRIVATE_MAILCHANNELS_DKIM_SELECTOR') || undefined,
+ dkim_private_key: env('NEXT_PRIVATE_MAILCHANNELS_DKIM_PRIVATE_KEY') || undefined,
+ },
+ ],
+ content: [
+ {
+ type: 'text/plain',
+ value: mail.data.text?.toString('utf-8') ?? '',
+ },
+ {
+ type: 'text/html',
+ value: mail.data.html?.toString('utf-8') ?? '',
+ },
+ ],
+ }),
+ });
+
+ if (response.status >= 200 && response.status <= 299) {
+ return callback(null, {
+ messageId: '',
+ envelope: {
+ from: mail.data.from,
+ to: mail.data.to,
+ },
+ accepted: mail.data.to,
+ rejected: [],
+ pending: [],
+ });
+ }
+
+ const data = await response.json();
+
+ return callback(new Error(`MailChannels error: ${data.message}`), null);
+ } catch (error) {
+ return callback(error instanceof Error ? error : new Error('Failed to send email'), null);
+ }
+ }
}
diff --git a/packages/lib/client-only/hooks/use-analytics.ts b/packages/lib/client-only/hooks/use-analytics.ts
index 92a92c40c..840ac1777 100644
--- a/packages/lib/client-only/hooks/use-analytics.ts
+++ b/packages/lib/client-only/hooks/use-analytics.ts
@@ -39,7 +39,7 @@ export function useAnalytics() {
*
* @param eventFlag The event to check against feature flags to determine whether tracking is enabled.
*/
- const startSessionRecording = (eventFlag?: string) => {
+ const startSessionRecording = (_eventFlag?: string) => {
return;
// const isSessionRecordingEnabled = featureFlags.getFlag(FEATURE_FLAG_GLOBAL_SESSION_RECORDING);
// const isSessionRecordingEnabledForEvent = Boolean(eventFlag && featureFlags.getFlag(eventFlag));
diff --git a/packages/lib/client-only/hooks/use-copy-share-link.ts b/packages/lib/client-only/hooks/use-copy-share-link.ts
index a8bef34af..6f9f58164 100644
--- a/packages/lib/client-only/hooks/use-copy-share-link.ts
+++ b/packages/lib/client-only/hooks/use-copy-share-link.ts
@@ -40,7 +40,7 @@ export function useCopyShareLink({ onSuccess, onError }: UseCopyShareLinkOptions
}
onSuccess?.();
- } catch (e) {
+ } catch {
onError?.();
}
};
diff --git a/packages/lib/client-only/hooks/use-copy-to-clipboard.ts b/packages/lib/client-only/hooks/use-copy-to-clipboard.ts
index 7ca41d404..f6644bc5f 100644
--- a/packages/lib/client-only/hooks/use-copy-to-clipboard.ts
+++ b/packages/lib/client-only/hooks/use-copy-to-clipboard.ts
@@ -14,13 +14,16 @@ export function useCopyToClipboard(): [CopiedValue, CopyFn] {
return false;
}
- const isClipboardApiSupported = Boolean(typeof ClipboardItem && navigator.clipboard.write);
+ const isClipboardApiSupported =
+ typeof ClipboardItem !== 'undefined' && typeof navigator.clipboard.write === 'function';
// Try to save to clipboard then save it in the state if worked
try {
- isClipboardApiSupported
- ? await handleClipboardApiCopy(text, blobType)
- : await handleWriteTextCopy(text);
+ if (isClipboardApiSupported) {
+ await handleClipboardApiCopy(text, blobType);
+ } else {
+ await handleWriteTextCopy(text);
+ }
setCopiedText(await text);
return true;
@@ -41,7 +44,7 @@ export function useCopyToClipboard(): [CopiedValue, CopyFn] {
const handleClipboardApiCopy = async (value: CopyValue, blobType = 'text/plain') => {
try {
await navigator.clipboard.write([new ClipboardItem({ [blobType]: value })]);
- } catch (e) {
+ } catch {
// Fallback attempt.
await handleWriteTextCopy(value);
}
diff --git a/packages/lib/client-only/hooks/use-editor-fields.ts b/packages/lib/client-only/hooks/use-editor-fields.ts
index 6b0b37776..eb118f52c 100644
--- a/packages/lib/client-only/hooks/use-editor-fields.ts
+++ b/packages/lib/client-only/hooks/use-editor-fields.ts
@@ -251,7 +251,7 @@ export const useEditorFields = ({
const getFieldByFormId = useCallback(
(formId: string): TLocalField | undefined => {
- return localFields.find((field) => field.formId === formId) as TLocalField | undefined;
+ return localFields.find((field) => field.formId === formId);
},
[localFields],
);
diff --git a/packages/lib/client-only/hooks/use-element-scale-size.ts b/packages/lib/client-only/hooks/use-element-scale-size.ts
index 1c8ab320e..842586639 100644
--- a/packages/lib/client-only/hooks/use-element-scale-size.ts
+++ b/packages/lib/client-only/hooks/use-element-scale-size.ts
@@ -1,5 +1,5 @@
/* eslint-disable @typescript-eslint/consistent-type-assertions */
-import { RefObject, useEffect, useState } from 'react';
+import { useEffect, useState } from 'react';
/**
* Calculate the width and height of a text element.
diff --git a/packages/lib/client-only/providers/envelope-editor-provider.tsx b/packages/lib/client-only/providers/envelope-editor-provider.tsx
index bdcfd3217..1b2fe946f 100644
--- a/packages/lib/client-only/providers/envelope-editor-provider.tsx
+++ b/packages/lib/client-only/providers/envelope-editor-provider.tsx
@@ -276,7 +276,7 @@ export const EnvelopeEditorProvider = ({
[envelope.recipients],
);
- const { refetch: reloadEnvelope, isLoading: isReloadingEnvelope } = trpc.envelope.get.useQuery(
+ const { refetch: reloadEnvelope, isLoading: _isReloadingEnvelope } = trpc.envelope.get.useQuery(
{
envelopeId: envelope.id,
},
diff --git a/packages/lib/client-only/providers/envelope-render-provider.tsx b/packages/lib/client-only/providers/envelope-render-provider.tsx
index d9fb64cb6..b79d511aa 100644
--- a/packages/lib/client-only/providers/envelope-render-provider.tsx
+++ b/packages/lib/client-only/providers/envelope-render-provider.tsx
@@ -189,7 +189,7 @@ export const EnvelopeRenderProvider = ({
}, [envelope.envelopeItems]);
const recipientIds = useMemo(
- () => recipients.map((recipient) => recipient.id).sort(),
+ () => recipients.map((recipient) => recipient.id).sort((left, right) => left - right),
[recipients],
);
diff --git a/packages/lib/constants/date-formats.ts b/packages/lib/constants/date-formats.ts
index 1f9b75929..5d319f1c7 100644
--- a/packages/lib/constants/date-formats.ts
+++ b/packages/lib/constants/date-formats.ts
@@ -170,5 +170,8 @@ export const convertToLocalSystemFormat = (
};
export const isValidDateFormat = (dateFormat: unknown): dateFormat is ValidDateFormat => {
- return VALID_DATE_FORMAT_VALUES.includes(dateFormat as ValidDateFormat);
+ return (
+ typeof dateFormat === 'string' &&
+ VALID_DATE_FORMAT_VALUES.some((validDateFormat) => validDateFormat === dateFormat)
+ );
};
diff --git a/packages/lib/constants/i18n.ts b/packages/lib/constants/i18n.ts
index 42c9cdd94..027088a4e 100644
--- a/packages/lib/constants/i18n.ts
+++ b/packages/lib/constants/i18n.ts
@@ -73,4 +73,5 @@ export const SUPPORTED_LANGUAGES: Record = {
} satisfies Record;
export const isValidLanguageCode = (code: unknown): code is SupportedLanguageCodes =>
- SUPPORTED_LANGUAGE_CODES.includes(code as SupportedLanguageCodes);
+ typeof code === 'string' &&
+ SUPPORTED_LANGUAGE_CODES.some((languageCode) => languageCode === code);
diff --git a/packages/lib/jobs/client/inngest.ts b/packages/lib/jobs/client/inngest.ts
index 702fc1de7..64d127263 100644
--- a/packages/lib/jobs/client/inngest.ts
+++ b/packages/lib/jobs/client/inngest.ts
@@ -91,11 +91,11 @@ export class InngestJobProvider extends BaseJobProvider {
return {
wait: step.sleep,
logger: {
- info: ctx.logger.info,
- debug: ctx.logger.debug,
- error: ctx.logger.error,
- warn: ctx.logger.warn,
- log: ctx.logger.info,
+ info: (...args) => ctx.logger.info(...args),
+ debug: (...args) => ctx.logger.debug(...args),
+ error: (...args) => ctx.logger.error(...args),
+ warn: (...args) => ctx.logger.warn(...args),
+ log: (...args) => ctx.logger.info(...args),
},
runTask: async (cacheKey, callback) => {
const result = await step.run(cacheKey, callback);
diff --git a/packages/lib/jobs/definitions/internal/execute-webhook.handler.ts b/packages/lib/jobs/definitions/internal/execute-webhook.handler.ts
index 2e1799d70..fde7c6e7c 100644
--- a/packages/lib/jobs/definitions/internal/execute-webhook.handler.ts
+++ b/packages/lib/jobs/definitions/internal/execute-webhook.handler.ts
@@ -7,7 +7,7 @@ import type { TExecuteWebhookJobDefinition } from './execute-webhook';
export const run = async ({
payload,
- io,
+ io: _io,
}: {
payload: TExecuteWebhookJobDefinition;
io: JobRunIO;
@@ -28,10 +28,11 @@ export const run = async ({
createdAt: new Date().toISOString(),
webhookEndpoint: url,
};
+ const requestBody: Prisma.InputJsonValue = JSON.parse(JSON.stringify(payloadData));
const response = await fetch(url, {
method: 'POST',
- body: JSON.stringify(payloadData),
+ body: JSON.stringify(requestBody),
headers: {
'Content-Type': 'application/json',
'X-Documenso-Secret': secret ?? '',
@@ -44,7 +45,7 @@ export const run = async ({
try {
responseBody = JSON.parse(body);
- } catch (err) {
+ } catch {
responseBody = body;
}
@@ -53,7 +54,7 @@ export const run = async ({
url,
event,
status: response.ok ? WebhookCallStatus.SUCCESS : WebhookCallStatus.FAILED,
- requestBody: payloadData as Prisma.InputJsonValue,
+ requestBody,
responseCode: response.status,
responseBody,
responseHeaders: Object.fromEntries(response.headers.entries()),
diff --git a/packages/lib/server-only/admin/admin-find-unsealed-documents.ts b/packages/lib/server-only/admin/admin-find-unsealed-documents.ts
index 41eefc9e8..2a368f2b6 100644
--- a/packages/lib/server-only/admin/admin-find-unsealed-documents.ts
+++ b/packages/lib/server-only/admin/admin-find-unsealed-documents.ts
@@ -91,9 +91,13 @@ export const adminFindUnsealedDocuments = async ({
]);
const count = Number(countResult[0]?.count ?? 0);
+ const formattedData: AdminUnsealedDocument[] = data.map((document) => ({
+ ...document,
+ id: String(document.id),
+ }));
return {
- data: data as unknown as AdminUnsealedDocument[],
+ data: formattedData,
count,
currentPage: Math.max(page, 1),
perPage,
diff --git a/packages/lib/server-only/admin/get-organisation-detailed-insights.ts b/packages/lib/server-only/admin/get-organisation-detailed-insights.ts
index 100c32b31..3c8bb289b 100644
--- a/packages/lib/server-only/admin/get-organisation-detailed-insights.ts
+++ b/packages/lib/server-only/admin/get-organisation-detailed-insights.ts
@@ -32,7 +32,7 @@ export type TeamInsights = {
export type UserInsights = {
id: number;
- name: string;
+ name: string | null;
email: string;
documentCount: number;
signedDocumentCount: number;
@@ -98,7 +98,7 @@ export async function getOrganisationDetailedInsights({
case 'documents':
return await getDocumentInsights(organisationId, offset, perPage, createdAtFrom);
default:
- throw new Error(`Invalid view: ${view}`);
+ throw new Error('Invalid view');
}
})();
@@ -149,9 +149,14 @@ async function getTeamInsights(
const [teams, countResult] = await Promise.all([teamsQuery.execute(), countQuery.execute()]);
const count = Number(countResult[0]?.count || 0);
+ const teamInsights: TeamInsights[] = teams.map((team) => ({
+ ...team,
+ memberCount: Number(team.memberCount),
+ documentCount: Number(team.documentCount),
+ }));
return {
- teams: teams as TeamInsights[],
+ teams: teamInsights,
users: [],
documents: [],
totalPages: Math.ceil(Number(count) / perPage),
@@ -208,10 +213,15 @@ async function getUserInsights(
const [users, countResult] = await Promise.all([usersQuery.execute(), countQuery.execute()]);
const count = Number(countResult[0]?.count || 0);
+ const userInsights: UserInsights[] = users.map((user) => ({
+ ...user,
+ documentCount: Number(user.documentCount),
+ signedDocumentCount: Number(user.signedDocumentCount),
+ }));
return {
teams: [],
- users: users as UserInsights[],
+ users: userInsights,
documents: [],
totalPages: Math.ceil(Number(count) / perPage),
};
@@ -223,18 +233,13 @@ async function getDocumentInsights(
perPage: number,
createdAtFrom: Date | null,
): Promise {
- let documentsQuery = kyselyPrisma.$kysely
+ const documentsQuery = kyselyPrisma.$kysely
.selectFrom('Envelope as e')
.innerJoin('Team as t', 'e.teamId', 't.id')
.where('t.organisationId', '=', organisationId)
.where('e.deletedAt', 'is', null)
- .where(() => sql`e.type = ${EnvelopeType.DOCUMENT}::"EnvelopeType"`);
-
- if (createdAtFrom) {
- documentsQuery = documentsQuery.where('e.createdAt', '>=', createdAtFrom);
- }
-
- documentsQuery = documentsQuery
+ .where(() => sql`e.type = ${EnvelopeType.DOCUMENT}::"EnvelopeType"`)
+ .$if(!!createdAtFrom, (qb) => qb.where('e.createdAt', '>=', createdAtFrom!))
.select([
'e.id as id',
'e.title as title',
@@ -247,33 +252,33 @@ async function getDocumentInsights(
.limit(perPage)
.offset(offset);
- let countQuery = kyselyPrisma.$kysely
+ const countQuery = kyselyPrisma.$kysely
.selectFrom('Envelope as e')
.innerJoin('Team as t', 'e.teamId', 't.id')
.where('t.organisationId', '=', organisationId)
.where('e.deletedAt', 'is', null)
- .where(() => sql`e.type = ${EnvelopeType.DOCUMENT}::"EnvelopeType"`);
-
- if (createdAtFrom) {
- countQuery = countQuery.where('e.createdAt', '>=', createdAtFrom);
- }
-
- countQuery = countQuery.select(({ fn }) => [fn.countAll().as('count')]);
+ .where(() => sql`e.type = ${EnvelopeType.DOCUMENT}::"EnvelopeType"`)
+ .$if(!!createdAtFrom, (qb) => qb.where('e.createdAt', '>=', createdAtFrom!))
+ .select(sql`count(*)`.as('count'));
const [documents, countResult] = await Promise.all([
documentsQuery.execute(),
- countQuery.execute(),
+ countQuery.executeTakeFirst(),
]);
-
- const count = Number((countResult[0] as { count: number })?.count || 0);
+ const count = Number(countResult?.count || 0);
+ const documentInsights: DocumentInsights[] = documents.map((document) => ({
+ title: document.title,
+ status: document.status,
+ createdAt: document.createdAt,
+ completedAt: document.completedAt,
+ teamName: document.teamName,
+ id: String(document.id),
+ }));
return {
teams: [],
users: [],
- documents: documents.map((doc) => ({
- ...doc,
- id: String((doc as { id: number }).id),
- })) as DocumentInsights[],
+ documents: documentInsights,
totalPages: Math.ceil(Number(count) / perPage),
};
}
diff --git a/packages/lib/server-only/ai/pdf-to-images.ts b/packages/lib/server-only/ai/pdf-to-images.ts
index e14128278..b982e7d14 100644
--- a/packages/lib/server-only/ai/pdf-to-images.ts
+++ b/packages/lib/server-only/ai/pdf-to-images.ts
@@ -47,7 +47,7 @@ export type PdfToImagesOptions = {
export const pdfToImages = async (pdfBytes: Uint8Array, options: PdfToImagesOptions = {}) => {
const { scale = 2 } = options;
- const task = await pdfjsLib.getDocument({
+ const task = pdfjsLib.getDocument({
data: pdfBytes,
CanvasFactory: SkiaCanvasFactory,
});
diff --git a/packages/lib/server-only/envelope/duplicate-envelope.ts b/packages/lib/server-only/envelope/duplicate-envelope.ts
index c83bc85a2..e949b7941 100644
--- a/packages/lib/server-only/envelope/duplicate-envelope.ts
+++ b/packages/lib/server-only/envelope/duplicate-envelope.ts
@@ -4,6 +4,7 @@ import { omit } from 'remeda';
import { prisma } from '@documenso/prisma';
import { AppError, AppErrorCode } from '../../errors/app-error';
+import { ZFieldMetaSchema } from '../../types/field-meta';
import {
ZWebhookDocumentSchema,
mapEnvelopeToWebhookDocumentPayload,
@@ -158,7 +159,7 @@ export const duplicateEnvelope = async ({ id, userId, teamId }: DuplicateEnvelop
height: field.height,
customText: '',
inserted: false,
- fieldMeta: field.fieldMeta as PrismaJson.FieldMeta,
+ fieldMeta: field.fieldMeta ? ZFieldMetaSchema.parse(field.fieldMeta) : undefined,
})),
},
},
diff --git a/packages/lib/server-only/envelope/get-envelope-for-direct-template-signing.ts b/packages/lib/server-only/envelope/get-envelope-for-direct-template-signing.ts
index d6be78773..6cc0f15f4 100644
--- a/packages/lib/server-only/envelope/get-envelope-for-direct-template-signing.ts
+++ b/packages/lib/server-only/envelope/get-envelope-for-direct-template-signing.ts
@@ -25,7 +25,7 @@ export type GetRecipientEnvelopeByTokenOptions = {
export const getEnvelopeForDirectTemplateSigning = async ({
token,
userId,
- accessAuth,
+ accessAuth: _accessAuth,
}: GetRecipientEnvelopeByTokenOptions): Promise => {
if (!token) {
throw new AppError(AppErrorCode.NOT_FOUND, {
diff --git a/packages/lib/server-only/envelope/update-envelope.ts b/packages/lib/server-only/envelope/update-envelope.ts
index d2cf256bd..e1709aa9d 100644
--- a/packages/lib/server-only/envelope/update-envelope.ts
+++ b/packages/lib/server-only/envelope/update-envelope.ts
@@ -193,12 +193,12 @@ export const updateEnvelope = async ({
isDeepEqual(documentGlobalActionAuth, newGlobalActionAuth);
const isDocumentVisibilitySame =
data.visibility === undefined || data.visibility === envelope.visibility;
- const isFolderSame = data.folderId === undefined || data.folderId === envelope.folderId;
- const isTemplateTypeSame =
+ const _isFolderSame = data.folderId === undefined || data.folderId === envelope.folderId;
+ const _isTemplateTypeSame =
data.templateType === undefined || data.templateType === envelope.templateType;
- const isPublicDescriptionSame =
+ const _isPublicDescriptionSame =
data.publicDescription === undefined || data.publicDescription === envelope.publicDescription;
- const isPublicTitleSame =
+ const _isPublicTitleSame =
data.publicTitle === undefined || data.publicTitle === envelope.publicTitle;
const auditLogs: CreateDocumentAuditLogDataResponse[] = [];
diff --git a/packages/lib/server-only/konva/skia-backend.ts b/packages/lib/server-only/konva/skia-backend.ts
index bdcd4ec64..57ce2e5c3 100644
--- a/packages/lib/server-only/konva/skia-backend.ts
+++ b/packages/lib/server-only/konva/skia-backend.ts
@@ -27,6 +27,7 @@ Konva.Util['createCanvasElement'] = () => {
get: () => node,
});
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
return node as unknown as HTMLCanvasElement;
};
@@ -34,6 +35,7 @@ Konva.Util.createImageElement = () => {
const node = new Image();
node.toString = () => '[object HTMLImageElement]';
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
return node as unknown as HTMLImageElement;
};
diff --git a/packages/lib/server-only/pdf/add-rejection-stamp-to-pdf.ts b/packages/lib/server-only/pdf/add-rejection-stamp-to-pdf.ts
index b80aa0249..8ed99bc66 100644
--- a/packages/lib/server-only/pdf/add-rejection-stamp-to-pdf.ts
+++ b/packages/lib/server-only/pdf/add-rejection-stamp-to-pdf.ts
@@ -6,7 +6,7 @@ import { NEXT_PRIVATE_INTERNAL_WEBAPP_URL } from '../../constants/app';
* Adds a rejection stamp to each page of a PDF document.
* The stamp is placed in the center of the page.
*/
-export async function addRejectionStampToPdf(pdf: PDF, reason: string): Promise {
+export async function addRejectionStampToPdf(pdf: PDF, _reason: string): Promise {
const pages = pdf.getPages();
const fontBytes = await fetch(`${NEXT_PRIVATE_INTERNAL_WEBAPP_URL()}/fonts/noto-sans.ttf`).then(
diff --git a/packages/lib/server-only/pdf/insert-field-in-pdf-v1.ts b/packages/lib/server-only/pdf/insert-field-in-pdf-v1.ts
index e339c2b68..ef86b91c2 100644
--- a/packages/lib/server-only/pdf/insert-field-in-pdf-v1.ts
+++ b/packages/lib/server-only/pdf/insert-field-in-pdf-v1.ts
@@ -694,10 +694,10 @@ const setTextFieldFontSize = (textField: PDFTextField, font: PDFFont, fontSize:
try {
textField.setFontSize(fontSize);
- } catch (err) {
+ } catch {
let da = textField.acroField.getDefaultAppearance() ?? '';
- da += `\n ${setFontAndSize(font.name, fontSize)}`;
+ da += `\n ${String(setFontAndSize(font.name, fontSize))}`;
textField.acroField.setDefaultAppearance(da);
}
diff --git a/packages/lib/server-only/pdf/render-audit-logs.ts b/packages/lib/server-only/pdf/render-audit-logs.ts
index 53874e96e..f7bc4d759 100644
--- a/packages/lib/server-only/pdf/render-audit-logs.ts
+++ b/packages/lib/server-only/pdf/render-audit-logs.ts
@@ -51,7 +51,7 @@ const parser = new UAParser();
const textMutedForegroundLight = '#929DAE';
const textForeground = '#000';
const textMutedForeground = '#64748B';
-const textBase = 10;
+const _textBase = 10;
const textSm = 9;
const textXs = 8;
const fontMedium = '500';
diff --git a/packages/lib/server-only/pdf/render-certificate.ts b/packages/lib/server-only/pdf/render-certificate.ts
index 9991e447a..bf993de11 100644
--- a/packages/lib/server-only/pdf/render-certificate.ts
+++ b/packages/lib/server-only/pdf/render-certificate.ts
@@ -75,13 +75,13 @@ const getDevice = (userAgent?: string | null): string => {
return `${result.os.name} - ${result.browser.name} ${result.browser.version}`;
};
-const textMutedForegroundLight = '#929DAE';
-const textForeground = '#000';
+const _textMutedForegroundLight = '#929DAE';
+const _textForeground = '#000';
const textMutedForeground = '#64748B';
const textRejectedRed = '#dc2626';
const textBase = 10;
const textSm = 9;
-const textXs = 8;
+const _textXs = 8;
const fontMedium = '500';
const columnWidthPercentages = [30, 30, 40];
diff --git a/packages/lib/server-only/profile/set-avatar-image.ts b/packages/lib/server-only/profile/set-avatar-image.ts
index a67a6fe08..8b4b63c0a 100644
--- a/packages/lib/server-only/profile/set-avatar-image.ts
+++ b/packages/lib/server-only/profile/set-avatar-image.ts
@@ -33,7 +33,7 @@ export const setAvatarImage = async ({
userId,
target,
bytes,
- requestMetadata,
+ requestMetadata: _requestMetadata,
}: SetAvatarImageOptions) => {
let oldAvatarImageId: string | null = null;
diff --git a/packages/lib/server-only/public-api/test-credentials.ts b/packages/lib/server-only/public-api/test-credentials.ts
index 76b5a84a1..692d83445 100644
--- a/packages/lib/server-only/public-api/test-credentials.ts
+++ b/packages/lib/server-only/public-api/test-credentials.ts
@@ -13,7 +13,7 @@ export const testCredentialsHandler = async (req: Request) => {
return Response.json({
name: result.team?.name ?? result.user.name,
});
- } catch (err) {
+ } catch {
return Response.json(
{
message: 'Internal Server Error',
diff --git a/packages/lib/server-only/team/delete-team-email.ts b/packages/lib/server-only/team/delete-team-email.ts
index 4e4b538e5..a50c1f096 100644
--- a/packages/lib/server-only/team/delete-team-email.ts
+++ b/packages/lib/server-only/team/delete-team-email.ts
@@ -99,7 +99,7 @@ export const deleteTeamEmail = async ({ userId, userEmail, teamId }: DeleteTeamE
html,
text,
});
- } catch (e) {
+ } catch {
// Todo: Teams - Alert us.
// We don't want to prevent a user from revoking access because an email could not be sent.
}
diff --git a/packages/lib/server-only/user/service-accounts/deleted-account.ts b/packages/lib/server-only/user/service-accounts/deleted-account.ts
index 38c2b8fcb..9d61febeb 100644
--- a/packages/lib/server-only/user/service-accounts/deleted-account.ts
+++ b/packages/lib/server-only/user/service-accounts/deleted-account.ts
@@ -13,7 +13,7 @@ export const deletedServiceAccountEmail = () => {
const { hostname } = new URL(process.env.NEXT_PUBLIC_WEBAPP_URL || 'http://localhost:3000');
return `deleted-account@${hostname}`;
- } catch (error) {
+ } catch {
return LEGACY_DELETED_ACCOUNT_EMAIL;
}
};
diff --git a/packages/lib/server-only/user/service-accounts/legacy-service-account.ts b/packages/lib/server-only/user/service-accounts/legacy-service-account.ts
index 3299c2a47..9de886ea8 100644
--- a/packages/lib/server-only/user/service-accounts/legacy-service-account.ts
+++ b/packages/lib/server-only/user/service-accounts/legacy-service-account.ts
@@ -13,7 +13,7 @@ export const legacyServiceAccountEmail = () => {
const { hostname } = new URL(process.env.NEXT_PUBLIC_WEBAPP_URL || 'http://localhost:3000');
return `serviceaccount@${hostname}`;
- } catch (error) {
+ } catch {
return LEGACY_SERVICE_ACCOUNT_EMAIL;
}
};
diff --git a/packages/lib/server-only/webhooks/trigger/generate-sample-data.ts b/packages/lib/server-only/webhooks/trigger/generate-sample-data.ts
index 86b63a23f..7bfeba7fb 100644
--- a/packages/lib/server-only/webhooks/trigger/generate-sample-data.ts
+++ b/packages/lib/server-only/webhooks/trigger/generate-sample-data.ts
@@ -545,5 +545,5 @@ export const generateSampleWebhookPayload = (
};
}
- throw new Error(`Unsupported event type: ${event}`);
+ throw new Error('Unsupported event type');
};
diff --git a/packages/lib/server-only/webhooks/zapier/validateApiToken.ts b/packages/lib/server-only/webhooks/zapier/validateApiToken.ts
index 45e2b7522..fec08d06f 100644
--- a/packages/lib/server-only/webhooks/zapier/validateApiToken.ts
+++ b/packages/lib/server-only/webhooks/zapier/validateApiToken.ts
@@ -14,7 +14,7 @@ export const validateApiToken = async ({ authorization }: ValidateApiTokenOption
}
return await getApiTokenByToken({ token });
- } catch (err) {
+ } catch {
throw new Error(`Failed to validate API token`);
}
};
diff --git a/packages/lib/types/field-meta.ts b/packages/lib/types/field-meta.ts
index e4ed9be40..ed9ace692 100644
--- a/packages/lib/types/field-meta.ts
+++ b/packages/lib/types/field-meta.ts
@@ -418,5 +418,3 @@ export const ZEnvelopeFieldAndMetaSchema = z.discriminatedUnion('type', [
fieldMeta: ZDropdownFieldMeta.optional().default(FIELD_DROPDOWN_META_DEFAULT_VALUES),
}),
]);
-
-type TEnvelopeFieldAndMeta = z.infer;
diff --git a/packages/lib/universal/field-renderer/field-renderer.ts b/packages/lib/universal/field-renderer/field-renderer.ts
index 8f66084e2..244853c16 100644
--- a/packages/lib/universal/field-renderer/field-renderer.ts
+++ b/packages/lib/universal/field-renderer/field-renderer.ts
@@ -11,7 +11,7 @@ export const MIN_FIELD_WIDTH_PX = 36;
export type FieldToRender = Pick<
Field,
- 'envelopeItemId' | 'recipientId' | 'type' | 'page' | 'customText' | 'inserted' | 'recipientId'
+ 'envelopeItemId' | 'recipientId' | 'type' | 'page' | 'customText' | 'inserted'
> & {
renderId: string; // A unique ID for the field in the render.
width: number;
diff --git a/packages/lib/universal/field-renderer/render-checkbox-field.ts b/packages/lib/universal/field-renderer/render-checkbox-field.ts
index 00e499c63..b15b74258 100644
--- a/packages/lib/universal/field-renderer/render-checkbox-field.ts
+++ b/packages/lib/universal/field-renderer/render-checkbox-field.ts
@@ -30,7 +30,8 @@ export const renderCheckboxFieldElement = (
const { fieldWidth, fieldHeight } = calculateFieldPosition(field, pageWidth, pageHeight);
- const checkboxMeta: TCheckboxFieldMeta | null = (field.fieldMeta as TCheckboxFieldMeta) || null;
+ const checkboxMeta: TCheckboxFieldMeta | null =
+ field.fieldMeta?.type === 'checkbox' ? field.fieldMeta : null;
const checkboxValues = checkboxMeta?.values || [];
const isFirstRender = !pageLayer.findOne(`#${field.renderId}`);
@@ -131,6 +132,7 @@ export const renderCheckboxFieldElement = (
});
const checkedValues: number[] = field.customText ? parseCheckboxCustomText(field.customText) : [];
+ const isReadOnly = checkboxMeta?.readOnly ?? false;
checkboxValues.forEach(({ value, checked }, index) => {
const isCheckboxChecked = match(mode)
@@ -138,7 +140,7 @@ export const renderCheckboxFieldElement = (
.with('sign', () => checkedValues.includes(index))
.with('export', () => {
// If it's read-only, check the originally checked state.
- if (checkboxMeta.readOnly) {
+ if (isReadOnly) {
return checked;
}
diff --git a/packages/lib/universal/field-renderer/render-dropdown-field.ts b/packages/lib/universal/field-renderer/render-dropdown-field.ts
index 4d8e826f7..4b75fd5d9 100644
--- a/packages/lib/universal/field-renderer/render-dropdown-field.ts
+++ b/packages/lib/universal/field-renderer/render-dropdown-field.ts
@@ -54,7 +54,8 @@ export const renderDropdownFieldElement = (
const { fieldWidth, fieldHeight } = calculateFieldPosition(field, pageWidth, pageHeight);
- const dropdownMeta: TDropdownFieldMeta | null = (field.fieldMeta as TDropdownFieldMeta) || null;
+ const dropdownMeta: TDropdownFieldMeta | null =
+ field.fieldMeta?.type === 'dropdown' ? field.fieldMeta : null;
let selectedValue = translations?.[FieldType.DROPDOWN] || 'Select Option';
diff --git a/packages/lib/universal/field-renderer/render-field.ts b/packages/lib/universal/field-renderer/render-field.ts
index d7000389a..88a20eef1 100644
--- a/packages/lib/universal/field-renderer/render-field.ts
+++ b/packages/lib/universal/field-renderer/render-field.ts
@@ -28,7 +28,7 @@ export type FieldRenderMode = 'edit' | 'sign' | 'export';
export type FieldToRender = Pick<
Field,
- 'envelopeItemId' | 'recipientId' | 'type' | 'page' | 'customText' | 'inserted' | 'recipientId'
+ 'envelopeItemId' | 'recipientId' | 'type' | 'page' | 'customText' | 'inserted'
> & {
renderId: string; // A unique ID for the field in the render.
width: number;
diff --git a/packages/lib/universal/field-renderer/render-generic-text-field.ts b/packages/lib/universal/field-renderer/render-generic-text-field.ts
index 6b90e48da..d977f0d5e 100644
--- a/packages/lib/universal/field-renderer/render-generic-text-field.ts
+++ b/packages/lib/universal/field-renderer/render-generic-text-field.ts
@@ -20,12 +20,29 @@ import { calculateFieldPosition } from './field-renderer';
const DEFAULT_TEXT_X_PADDING = 6;
+const getGenericTextFieldMeta = (field: FieldToRender): GenericTextFieldTypeMetas | undefined => {
+ const fieldMeta = field.fieldMeta;
+
+ if (
+ fieldMeta?.type === 'initials' ||
+ fieldMeta?.type === 'name' ||
+ fieldMeta?.type === 'email' ||
+ fieldMeta?.type === 'date' ||
+ fieldMeta?.type === 'text' ||
+ fieldMeta?.type === 'number'
+ ) {
+ return fieldMeta;
+ }
+
+ return undefined;
+};
+
const upsertFieldText = (field: FieldToRender, options: RenderFieldElementOptions): Konva.Text => {
const { pageWidth, pageHeight, mode = 'edit', pageLayer, translations } = options;
const { fieldWidth, fieldHeight } = calculateFieldPosition(field, pageWidth, pageHeight);
- const fieldMeta = field.fieldMeta as GenericTextFieldTypeMetas | undefined;
+ const fieldMeta = getGenericTextFieldMeta(field);
const fieldTypeName = translations?.[field.type] || field.type;
diff --git a/packages/lib/universal/field-renderer/render-radio-field.ts b/packages/lib/universal/field-renderer/render-radio-field.ts
index ebeaa70cb..067197ad1 100644
--- a/packages/lib/universal/field-renderer/render-radio-field.ts
+++ b/packages/lib/universal/field-renderer/render-radio-field.ts
@@ -27,7 +27,8 @@ export const renderRadioFieldElement = (
) => {
const { pageWidth, pageHeight, pageLayer, mode, color } = options;
- const radioMeta: TRadioFieldMeta | null = (field.fieldMeta as TRadioFieldMeta) || null;
+ const radioMeta: TRadioFieldMeta | null =
+ field.fieldMeta?.type === 'radio' ? field.fieldMeta : null;
const radioValues = radioMeta?.values || [];
const isFirstRender = !pageLayer.findOne(`#${field.renderId}`);
@@ -122,6 +123,7 @@ export const renderRadioFieldElement = (
});
const { fieldWidth, fieldHeight } = calculateFieldPosition(field, pageWidth, pageHeight);
+ const isReadOnly = radioMeta?.readOnly ?? false;
radioValues.forEach(({ value, checked }, index) => {
const isRadioValueChecked = match(mode)
@@ -129,7 +131,7 @@ export const renderRadioFieldElement = (
.with('sign', () => index.toString() === field.customText)
.with('export', () => {
// If it's read-only, check the originally checked state.
- if (radioMeta.readOnly) {
+ if (isReadOnly) {
return checked;
}
diff --git a/packages/lib/universal/upload/get-file.ts b/packages/lib/universal/upload/get-file.ts
index ac62b1744..132e7b6c1 100644
--- a/packages/lib/universal/upload/get-file.ts
+++ b/packages/lib/universal/upload/get-file.ts
@@ -13,7 +13,7 @@ export type GetFileOptions = {
*
* - Lucas, 2025-11-04
*/
-const getFile = async ({ type, data }: GetFileOptions) => {
+const _getFile = async ({ type, data }: GetFileOptions) => {
return await match(type)
.with(DocumentDataType.BYTES, () => getFileFromBytes(data))
.with(DocumentDataType.BYTES_64, () => getFileFromBytes64(data))
diff --git a/packages/lib/utils/envelope-download.ts b/packages/lib/utils/envelope-download.ts
index 82e1dd2cd..e0eed5110 100644
--- a/packages/lib/utils/envelope-download.ts
+++ b/packages/lib/utils/envelope-download.ts
@@ -26,7 +26,7 @@ export const getEnvelopeItemPdfUrl = (options: EnvelopeItemPdfUrlOptions) => {
const version = options.version;
return token
- ? `${NEXT_PUBLIC_WEBAPP_URL()}/api/files/token/${token}/envelopeItem/${id}/download/${version}${presignToken ? `?presignToken=${presignToken}` : ''}`
+ ? `${NEXT_PUBLIC_WEBAPP_URL()}/api/files/token/${token}/envelopeItem/${id}/download/${version}`
: `${NEXT_PUBLIC_WEBAPP_URL()}/api/files/envelope/${envelopeId}/envelopeItem/${id}/download/${version}`;
}
diff --git a/packages/lib/utils/fields.ts b/packages/lib/utils/fields.ts
index ec26192eb..b7888df16 100644
--- a/packages/lib/utils/fields.ts
+++ b/packages/lib/utils/fields.ts
@@ -53,8 +53,8 @@ export const validateFieldsUninserted = (): boolean => {
const innerDiv = element.querySelector('div');
const hasError = innerDiv?.getAttribute('data-error') === 'true';
- if (hasError) {
- errorElements.push(element as HTMLElement);
+ if (hasError && element instanceof HTMLElement) {
+ errorElements.push(element);
} else {
element.removeAttribute('data-error');
}
diff --git a/packages/trpc/server/admin-router/update-organisation-member-role.ts b/packages/trpc/server/admin-router/update-organisation-member-role.ts
index bfb12256b..7338c86c8 100644
--- a/packages/trpc/server/admin-router/update-organisation-member-role.ts
+++ b/packages/trpc/server/admin-router/update-organisation-member-role.ts
@@ -151,7 +151,7 @@ export const updateOrganisationMemberRoleRoute = adminProcedure
return;
}
- const targetRole = role as OrganisationMemberRole;
+ const targetRole: OrganisationMemberRole = role;
if (currentOrganisationRole === targetRole) {
throw new AppError(AppErrorCode.INVALID_REQUEST, {
diff --git a/packages/trpc/server/document-router/access-auth-request-2fa-email.ts b/packages/trpc/server/document-router/access-auth-request-2fa-email.ts
index 986705b98..a35d793cf 100644
--- a/packages/trpc/server/document-router/access-auth-request-2fa-email.ts
+++ b/packages/trpc/server/document-router/access-auth-request-2fa-email.ts
@@ -30,8 +30,6 @@ export const accessAuthRequest2FAEmailRoute = procedure
assertRateLimit(rateLimitResult);
- const user = ctx.user;
-
// Get document and recipient by token
const envelope = await prisma.envelope.findFirst({
where: {
diff --git a/packages/trpc/server/folder-router/router.ts b/packages/trpc/server/folder-router/router.ts
index 755b23452..8af9893b0 100644
--- a/packages/trpc/server/folder-router/router.ts
+++ b/packages/trpc/server/folder-router/router.ts
@@ -174,7 +174,7 @@ export const folderRouter = router({
folderId: parentId,
type,
});
- } catch (error) {
+ } catch {
throw new AppError(AppErrorCode.NOT_FOUND, {
message: 'Parent folder not found',
});
diff --git a/packages/trpc/server/webhook-router/find-webhook-calls.ts b/packages/trpc/server/webhook-router/find-webhook-calls.ts
index fa3bc0966..4b1fb5755 100644
--- a/packages/trpc/server/webhook-router/find-webhook-calls.ts
+++ b/packages/trpc/server/webhook-router/find-webhook-calls.ts
@@ -1,4 +1,4 @@
-import { Prisma, WebhookCallStatus, WebhookTriggerEvents } from '@prisma/client';
+import type { Prisma, WebhookCallStatus, WebhookTriggerEvents } from '@prisma/client';
import { TEAM_MEMBER_ROLE_PERMISSIONS_MAP } from '@documenso/lib/constants/teams';
import { AppError, AppErrorCode } from '@documenso/lib/errors/app-error';
diff --git a/packages/trpc/server/webhook-router/resend-webhook-call.ts b/packages/trpc/server/webhook-router/resend-webhook-call.ts
index abb0ca34e..e016bdfcc 100644
--- a/packages/trpc/server/webhook-router/resend-webhook-call.ts
+++ b/packages/trpc/server/webhook-router/resend-webhook-call.ts
@@ -1,8 +1,7 @@
-import { Prisma, WebhookCallStatus, WebhookTriggerEvents } from '@prisma/client';
+import { Prisma, WebhookCallStatus } from '@prisma/client';
import { TEAM_MEMBER_ROLE_PERMISSIONS_MAP } from '@documenso/lib/constants/teams';
import { AppError, AppErrorCode } from '@documenso/lib/errors/app-error';
-import type { FindResultResponse } from '@documenso/lib/types/search-params';
import { buildTeamWhereQuery } from '@documenso/lib/utils/teams';
import { prisma } from '@documenso/prisma';
@@ -62,7 +61,7 @@ export const resendWebhookCallRoute = authenticatedProcedure
try {
responseBody = JSON.parse(body);
- } catch (err) {
+ } catch {
responseBody = body;
}
diff --git a/packages/trpc/server/webhook-router/resend-webhook-call.types.ts b/packages/trpc/server/webhook-router/resend-webhook-call.types.ts
index f34b9ebc6..d75ba994d 100644
--- a/packages/trpc/server/webhook-router/resend-webhook-call.types.ts
+++ b/packages/trpc/server/webhook-router/resend-webhook-call.types.ts
@@ -1,4 +1,3 @@
-import { WebhookCallStatus, WebhookTriggerEvents } from '@prisma/client';
import { z } from 'zod';
import WebhookCallSchema from '@documenso/prisma/generated/zod/modelSchema/WebhookCallSchema';
diff --git a/packages/ui/components/document/document-global-auth-access-select.tsx b/packages/ui/components/document/document-global-auth-access-select.tsx
index d5e99ba74..e576d19c1 100644
--- a/packages/ui/components/document/document-global-auth-access-select.tsx
+++ b/packages/ui/components/document/document-global-auth-access-select.tsx
@@ -39,17 +39,13 @@ export const DocumentGlobalAuthAccessSelect = ({
})),
];
- // Convert string array to Option array for MultiSelect
- const selectedOptions =
- (value
- ?.map((val) => authOptions.find((option) => option.value === val))
- .filter(Boolean) as Option[]) || [];
+ const getSelectedOptions = (selectedValues?: string[]) =>
+ selectedValues
+ ?.map((selectedValue) => authOptions.find((option) => option.value === selectedValue))
+ .filter((option): option is Option => option !== undefined) ?? [];
- // Convert default value to Option array
- const defaultOptions =
- (defaultValue
- ?.map((val) => authOptions.find((option) => option.value === val))
- .filter(Boolean) as Option[]) || [];
+ const selectedOptions = getSelectedOptions(value);
+ const defaultOptions = getSelectedOptions(defaultValue);
const handleChange = (options: Option[]) => {
const values = options.map((option) => option.value);
@@ -79,7 +75,7 @@ export const DocumentGlobalAuthAccessTooltip = () => (
-
+
Document access
diff --git a/packages/ui/components/document/document-global-auth-action-select.tsx b/packages/ui/components/document/document-global-auth-action-select.tsx
index a2e872fd2..b83d1cc3f 100644
--- a/packages/ui/components/document/document-global-auth-action-select.tsx
+++ b/packages/ui/components/document/document-global-auth-action-select.tsx
@@ -39,17 +39,13 @@ export const DocumentGlobalAuthActionSelect = ({
})),
];
- // Convert string array to Option array for MultiSelect
- const selectedOptions =
- (value
- ?.map((val) => authOptions.find((option) => option.value === val))
- .filter(Boolean) as Option[]) || [];
+ const getSelectedOptions = (selectedValues?: string[]) =>
+ selectedValues
+ ?.map((selectedValue) => authOptions.find((option) => option.value === selectedValue))
+ .filter((option): option is Option => option !== undefined) ?? [];
- // Convert default value to Option array
- const defaultOptions =
- (defaultValue
- ?.map((val) => authOptions.find((option) => option.value === val))
- .filter(Boolean) as Option[]) || [];
+ const selectedOptions = getSelectedOptions(value);
+ const defaultOptions = getSelectedOptions(defaultValue);
const handleChange = (options: Option[]) => {
const values = options.map((option) => option.value);
@@ -79,7 +75,7 @@ export const DocumentGlobalAuthActionTooltip = () => (
-
+
Global recipient action authentication
diff --git a/packages/ui/components/document/envelope-recipient-field-tooltip.tsx b/packages/ui/components/document/envelope-recipient-field-tooltip.tsx
index 721834bc7..0439b5f7e 100644
--- a/packages/ui/components/document/envelope-recipient-field-tooltip.tsx
+++ b/packages/ui/components/document/envelope-recipient-field-tooltip.tsx
@@ -56,7 +56,7 @@ export function EnvelopeRecipientFieldTooltip({
field,
showFieldStatus = false,
showRecipientTooltip = false,
- showRecipientColors = false,
+ showRecipientColors: _showRecipientColors = false,
}: EnvelopeRecipientFieldTooltipProps) {
const { t } = useLingui();
@@ -145,7 +145,7 @@ export function EnvelopeRecipientFieldTooltip({
>
+
{extractInitials(field.recipient.name || field.recipient.email)}
@@ -191,12 +191,12 @@ export function EnvelopeRecipientFieldTooltip({
-
+
{getRecipientDisplayText(field.recipient)}