mirror of
https://github.com/documenso/documenso.git
synced 2026-07-15 23:39:35 +10:00
chore: merge main, resolve biome formatting conflicts
Merge origin/main into feat/external-2fa-codes. Resolve formatting conflicts caused by biome rollout; preserve both feature streams: PR's external 2FA token + signing-session 2FA proof additions plus main's RateLimit/RecipientExpired/signingReminders/date-auto-insert. In complete-document-with-token.ts, drop the duplicate early field-fetching block introduced when main moved that logic later with date auto-insert support; keep the EXTERNAL_TWO_FACTOR_AUTH check using derivedRecipientActionAuth.
This commit is contained in:
@@ -12,6 +12,7 @@ export async function GET(request: Request) {
|
||||
status: 200,
|
||||
headers: {
|
||||
'content-type': 'application/json',
|
||||
'Cache-Control': 'public, s-maxage=3600, stale-while-revalidate=7200',
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
@@ -12,6 +12,7 @@ export async function GET(request: Request) {
|
||||
status: 200,
|
||||
headers: {
|
||||
'content-type': 'application/json',
|
||||
'Cache-Control': 'public, s-maxage=3600, stale-while-revalidate=7200',
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
@@ -12,6 +12,7 @@ export async function GET(request: Request) {
|
||||
status: 200,
|
||||
headers: {
|
||||
'content-type': 'application/json',
|
||||
'Cache-Control': 'public, s-maxage=3600, stale-while-revalidate=7200',
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
@@ -12,6 +12,7 @@ export async function GET(request: Request) {
|
||||
status: 200,
|
||||
headers: {
|
||||
'content-type': 'application/json',
|
||||
'Cache-Control': 'public, s-maxage=3600, stale-while-revalidate=7200',
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
@@ -10,6 +10,7 @@ export async function GET(request: Request) {
|
||||
status: 200,
|
||||
headers: {
|
||||
'content-type': 'application/json',
|
||||
'Cache-Control': 'public, s-maxage=3600, stale-while-revalidate=7200',
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
@@ -12,6 +12,7 @@ export async function GET(request: Request) {
|
||||
status: 200,
|
||||
headers: {
|
||||
'content-type': 'application/json',
|
||||
'Cache-Control': 'public, s-maxage=3600, stale-while-revalidate=7200',
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
@@ -12,6 +12,7 @@ export async function GET(request: Request) {
|
||||
status: 200,
|
||||
headers: {
|
||||
'content-type': 'application/json',
|
||||
'Cache-Control': 'public, s-maxage=3600, stale-while-revalidate=7200',
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
@@ -10,6 +10,7 @@ export async function GET(request: Request) {
|
||||
status: 200,
|
||||
headers: {
|
||||
'content-type': 'application/json',
|
||||
'Cache-Control': 'public, s-maxage=3600, stale-while-revalidate=7200',
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
@@ -10,6 +10,7 @@ export async function GET(request: Request) {
|
||||
status: 200,
|
||||
headers: {
|
||||
'content-type': 'application/json',
|
||||
'Cache-Control': 'public, s-maxage=3600, stale-while-revalidate=7200',
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
@@ -10,6 +10,7 @@ export async function GET(request: Request) {
|
||||
status: 200,
|
||||
headers: {
|
||||
'content-type': 'application/json',
|
||||
'Cache-Control': 'public, s-maxage=3600, stale-while-revalidate=7200',
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
@@ -10,6 +10,7 @@ export async function GET(request: Request) {
|
||||
status: 200,
|
||||
headers: {
|
||||
'content-type': 'application/json',
|
||||
'Cache-Control': 'public, s-maxage=3600, stale-while-revalidate=7200',
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
@@ -10,6 +10,7 @@ export async function GET(request: Request) {
|
||||
status: 200,
|
||||
headers: {
|
||||
'content-type': 'application/json',
|
||||
'Cache-Control': 'public, s-maxage=3600, stale-while-revalidate=7200',
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
@@ -16,6 +16,7 @@ export async function GET(request: Request) {
|
||||
status: 200,
|
||||
headers: {
|
||||
'content-type': 'application/json',
|
||||
'Cache-Control': 'public, s-maxage=3600, stale-while-revalidate=7200',
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
@@ -10,6 +10,7 @@ export async function GET(request: Request) {
|
||||
status: 200,
|
||||
headers: {
|
||||
'content-type': 'application/json',
|
||||
'Cache-Control': 'public, s-maxage=3600, stale-while-revalidate=7200',
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
@@ -10,6 +10,7 @@ export async function GET(request: Request) {
|
||||
status: 200,
|
||||
headers: {
|
||||
'content-type': 'application/json',
|
||||
'Cache-Control': 'public, s-maxage=3600, stale-while-revalidate=7200',
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
@@ -1,15 +1,17 @@
|
||||
import { DateTime } from 'luxon';
|
||||
|
||||
export interface TransformedData {
|
||||
export type TransformedData = {
|
||||
labels: string[];
|
||||
datasets: Array<{
|
||||
label: string;
|
||||
data: number[];
|
||||
}>;
|
||||
}
|
||||
};
|
||||
|
||||
export function addZeroMonth(transformedData: TransformedData): TransformedData {
|
||||
const result = {
|
||||
const FORMAT = 'MMM yyyy';
|
||||
|
||||
export const addZeroMonth = (transformedData: TransformedData, isCumulative = false): TransformedData => {
|
||||
const result: TransformedData = {
|
||||
labels: [...transformedData.labels],
|
||||
datasets: transformedData.datasets.map((dataset) => ({
|
||||
label: dataset.label,
|
||||
@@ -21,34 +23,28 @@ export function addZeroMonth(transformedData: TransformedData): TransformedData
|
||||
return result;
|
||||
}
|
||||
|
||||
if (result.datasets.every((dataset) => dataset.data[0] === 0)) {
|
||||
return result;
|
||||
}
|
||||
|
||||
try {
|
||||
let firstMonth = DateTime.fromFormat(result.labels[0], 'MMM yyyy');
|
||||
if (!result.datasets.every((dataset) => dataset.data[0] === 0)) {
|
||||
const firstMonth = DateTime.fromFormat(result.labels[0], FORMAT);
|
||||
if (!firstMonth.isValid) {
|
||||
const formats = ['MMM yyyy', 'MMMM yyyy', 'MM/yyyy', 'yyyy-MM'];
|
||||
|
||||
for (const format of formats) {
|
||||
firstMonth = DateTime.fromFormat(result.labels[0], format);
|
||||
if (firstMonth.isValid) break;
|
||||
}
|
||||
|
||||
if (!firstMonth.isValid) {
|
||||
console.warn(`Could not parse date: "${result.labels[0]}"`);
|
||||
return transformedData;
|
||||
}
|
||||
console.warn(`Could not parse date: "${result.labels[0]}"`);
|
||||
return transformedData;
|
||||
}
|
||||
|
||||
const zeroMonth = firstMonth.minus({ months: 1 }).toFormat('MMM yyyy');
|
||||
result.labels.unshift(zeroMonth);
|
||||
result.labels.unshift(firstMonth.minus({ months: 1 }).toFormat(FORMAT));
|
||||
result.datasets.forEach((dataset) => {
|
||||
dataset.data.unshift(0);
|
||||
});
|
||||
|
||||
return result;
|
||||
} catch (error) {
|
||||
return transformedData;
|
||||
}
|
||||
}
|
||||
|
||||
const now = DateTime.now().startOf('month');
|
||||
const lastMonth = DateTime.fromFormat(result.labels[result.labels.length - 1], FORMAT);
|
||||
|
||||
if (lastMonth.isValid && lastMonth.startOf('month') < now) {
|
||||
result.labels.push(now.toFormat(FORMAT));
|
||||
result.datasets.forEach((dataset) => {
|
||||
dataset.data.push(isCumulative ? dataset.data[dataset.data.length - 1] : 0);
|
||||
});
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
@@ -60,7 +60,9 @@ async function originHeadersFromReq(req: Request, origin: StaticOrigin | OriginF
|
||||
const reqOrigin = req.headers.get('Origin') || undefined;
|
||||
const value = typeof origin === 'function' ? await origin(reqOrigin, req) : origin;
|
||||
|
||||
if (!value) return;
|
||||
if (!value) {
|
||||
return;
|
||||
}
|
||||
return getOriginHeaders(reqOrigin, value);
|
||||
}
|
||||
|
||||
@@ -85,12 +87,17 @@ export default async function cors(req: Request, res: Response, options?: CorsOp
|
||||
const { headers } = res;
|
||||
const originHeaders = await originHeadersFromReq(req, opts.origin ?? false);
|
||||
const mergeHeaders = (v: string, k: string) => {
|
||||
if (k === 'Vary') headers.append(k, v);
|
||||
else headers.set(k, v);
|
||||
if (k === 'Vary') {
|
||||
headers.append(k, v);
|
||||
} else {
|
||||
headers.set(k, v);
|
||||
}
|
||||
};
|
||||
|
||||
// If there's no origin we won't touch the response
|
||||
if (!originHeaders) return res;
|
||||
if (!originHeaders) {
|
||||
return res;
|
||||
}
|
||||
|
||||
originHeaders.forEach(mergeHeaders);
|
||||
|
||||
@@ -98,9 +105,7 @@ export default async function cors(req: Request, res: Response, options?: CorsOp
|
||||
headers.set('Access-Control-Allow-Credentials', 'true');
|
||||
}
|
||||
|
||||
const exposed = Array.isArray(opts.exposedHeaders)
|
||||
? opts.exposedHeaders.join(',')
|
||||
: opts.exposedHeaders;
|
||||
const exposed = Array.isArray(opts.exposedHeaders) ? opts.exposedHeaders.join(',') : opts.exposedHeaders;
|
||||
|
||||
if (exposed) {
|
||||
headers.set('Access-Control-Expose-Headers', exposed);
|
||||
@@ -120,7 +125,9 @@ export default async function cors(req: Request, res: Response, options?: CorsOp
|
||||
headers.set('Access-Control-Max-Age', String(opts.maxAge));
|
||||
}
|
||||
|
||||
if (opts.preflightContinue) return res;
|
||||
if (opts.preflightContinue) {
|
||||
return res;
|
||||
}
|
||||
|
||||
headers.set('Content-Length', '0');
|
||||
return new Response(null, { status: opts.optionsSuccessStatus, headers });
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import { kyselyPrisma, sql } from '@documenso/prisma';
|
||||
import { DocumentStatus, EnvelopeType } from '@prisma/client';
|
||||
import { DateTime } from 'luxon';
|
||||
|
||||
import { kyselyPrisma, sql } from '@documenso/prisma';
|
||||
|
||||
import { addZeroMonth } from '../add-zero-month';
|
||||
|
||||
export const getCompletedDocumentsMonthly = async (type: 'count' | 'cumulative' = 'count') => {
|
||||
@@ -21,8 +20,7 @@ export const getCompletedDocumentsMonthly = async (type: 'count' | 'cumulative'
|
||||
.where(() => sql`"Envelope"."status" = ${DocumentStatus.COMPLETED}::"DocumentStatus"`)
|
||||
.where(() => sql`"Envelope"."type" = ${EnvelopeType.DOCUMENT}::"EnvelopeType"`)
|
||||
.groupBy('month')
|
||||
.orderBy('month', 'desc')
|
||||
.limit(12);
|
||||
.orderBy('month', 'desc');
|
||||
|
||||
const result = await qb.execute();
|
||||
|
||||
@@ -31,16 +29,12 @@ export const getCompletedDocumentsMonthly = async (type: 'count' | 'cumulative'
|
||||
datasets: [
|
||||
{
|
||||
label: type === 'count' ? 'Completed Documents per Month' : 'Total Completed Documents',
|
||||
data: result
|
||||
.map((row) => (type === 'count' ? Number(row.count) : Number(row.cume_count)))
|
||||
.reverse(),
|
||||
data: result.map((row) => (type === 'count' ? Number(row.count) : Number(row.cume_count))).reverse(),
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
return addZeroMonth(transformedData);
|
||||
return addZeroMonth(transformedData, type === 'cumulative');
|
||||
};
|
||||
|
||||
export type GetCompletedDocumentsMonthlyResult = Awaited<
|
||||
ReturnType<typeof getCompletedDocumentsMonthly>
|
||||
>;
|
||||
export type GetCompletedDocumentsMonthlyResult = Awaited<ReturnType<typeof getCompletedDocumentsMonthly>>;
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { DateTime } from 'luxon';
|
||||
|
||||
import { kyselyPrisma, sql } from '@documenso/prisma';
|
||||
import { DateTime } from 'luxon';
|
||||
|
||||
import { addZeroMonth } from '../add-zero-month';
|
||||
|
||||
@@ -29,16 +28,12 @@ export const getSignerConversionMonthly = async (type: 'count' | 'cumulative' =
|
||||
datasets: [
|
||||
{
|
||||
label: type === 'count' ? 'Signers That Signed Up' : 'Total Signers That Signed Up',
|
||||
data: result
|
||||
.map((row) => (type === 'count' ? Number(row.count) : Number(row.cume_count)))
|
||||
.reverse(),
|
||||
data: result.map((row) => (type === 'count' ? Number(row.count) : Number(row.cume_count))).reverse(),
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
return addZeroMonth(transformedData);
|
||||
return addZeroMonth(transformedData, type === 'cumulative');
|
||||
};
|
||||
|
||||
export type GetSignerConversionMonthlyResult = Awaited<
|
||||
ReturnType<typeof getSignerConversionMonthly>
|
||||
>;
|
||||
export type GetSignerConversionMonthlyResult = Awaited<ReturnType<typeof getSignerConversionMonthly>>;
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { DateTime } from 'luxon';
|
||||
|
||||
import { kyselyPrisma, sql } from '@documenso/prisma';
|
||||
import { DateTime } from 'luxon';
|
||||
|
||||
import { addZeroMonth } from '../add-zero-month';
|
||||
|
||||
@@ -17,8 +16,7 @@ export const getUserMonthlyGrowth = async (type: 'count' | 'cumulative' = 'count
|
||||
.as('cume_count'),
|
||||
])
|
||||
.groupBy('month')
|
||||
.orderBy('month', 'desc')
|
||||
.limit(12);
|
||||
.orderBy('month', 'desc');
|
||||
|
||||
const result = await qb.execute();
|
||||
|
||||
@@ -27,14 +25,12 @@ export const getUserMonthlyGrowth = async (type: 'count' | 'cumulative' = 'count
|
||||
datasets: [
|
||||
{
|
||||
label: type === 'count' ? 'New Users' : 'Total Users',
|
||||
data: result
|
||||
.map((row) => (type === 'count' ? Number(row.count) : Number(row.cume_count)))
|
||||
.reverse(),
|
||||
data: result.map((row) => (type === 'count' ? Number(row.count) : Number(row.cume_count))).reverse(),
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
return addZeroMonth(transformedData);
|
||||
return addZeroMonth(transformedData, type === 'cumulative');
|
||||
};
|
||||
|
||||
export type GetUserMonthlyGrowthResult = Awaited<ReturnType<typeof getUserMonthlyGrowth>>;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { DateTime } from 'luxon';
|
||||
|
||||
import { addZeroMonth } from './add-zero-month';
|
||||
import { addZeroMonth, type TransformedData } from './add-zero-month';
|
||||
|
||||
type MetricKeys = {
|
||||
stars: number;
|
||||
@@ -14,14 +14,6 @@ type DataEntry = {
|
||||
[key: string]: MetricKeys;
|
||||
};
|
||||
|
||||
type TransformData = {
|
||||
labels: string[];
|
||||
datasets: {
|
||||
label: string;
|
||||
data: number[];
|
||||
}[];
|
||||
};
|
||||
|
||||
type MetricKey = keyof MetricKeys;
|
||||
|
||||
const FRIENDLY_METRIC_NAMES: { [key in MetricKey]: string } = {
|
||||
@@ -32,13 +24,7 @@ const FRIENDLY_METRIC_NAMES: { [key in MetricKey]: string } = {
|
||||
earlyAdopters: 'Customers',
|
||||
};
|
||||
|
||||
export function transformData({
|
||||
data,
|
||||
metric,
|
||||
}: {
|
||||
data: DataEntry;
|
||||
metric: MetricKey;
|
||||
}): TransformData {
|
||||
export function transformData({ data, metric }: { data: DataEntry; metric: MetricKey }): TransformedData {
|
||||
try {
|
||||
if (!data || Object.keys(data).length === 0) {
|
||||
return {
|
||||
@@ -103,7 +89,7 @@ export function transformData({
|
||||
],
|
||||
};
|
||||
|
||||
return addZeroMonth(transformedData);
|
||||
return addZeroMonth(transformedData, true);
|
||||
} catch (error) {
|
||||
return {
|
||||
labels: [],
|
||||
@@ -111,6 +97,3 @@ export function transformData({
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// To be on the safer side
|
||||
export const transformRepoStats = transformData;
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
"dependencies": {
|
||||
"@documenso/prisma": "*",
|
||||
"luxon": "^3.7.2",
|
||||
"next": "15.5.9"
|
||||
"next": "16.2.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^20",
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
"moduleResolution": "bundler",
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
"jsx": "preserve",
|
||||
"jsx": "react-jsx",
|
||||
"incremental": true,
|
||||
"plugins": [
|
||||
{
|
||||
@@ -22,6 +22,6 @@
|
||||
"@/*": ["./*"]
|
||||
}
|
||||
},
|
||||
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
|
||||
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts", ".next/dev/types/**/*.ts"],
|
||||
"exclude": ["node_modules"]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user