mirror of
https://github.com/documenso/documenso.git
synced 2026-07-26 09:54:51 +10:00
feat: get many endpoints (#2226)
Co-authored-by: Lucas Smith <me@lucasjamessmith.me>
This commit is contained in:
@@ -18,6 +18,8 @@ const ZDocumentIdSchema = z.string().regex(/^document_\d+$/);
|
||||
const ZTemplateIdSchema = z.string().regex(/^template_\d+$/);
|
||||
const ZEnvelopeIdSchema = z.string().regex(/^envelope_.{2,}$/);
|
||||
|
||||
const MAX_ENVELOPE_IDS_PER_REQUEST = 20;
|
||||
|
||||
export type EnvelopeIdOptions =
|
||||
| {
|
||||
type: 'envelopeId';
|
||||
@@ -32,6 +34,20 @@ export type EnvelopeIdOptions =
|
||||
id: number;
|
||||
};
|
||||
|
||||
export type EnvelopeIdsOptions =
|
||||
| {
|
||||
type: 'envelopeId';
|
||||
ids: string[];
|
||||
}
|
||||
| {
|
||||
type: 'documentId';
|
||||
ids: number[];
|
||||
}
|
||||
| {
|
||||
type: 'templateId';
|
||||
ids: number[];
|
||||
};
|
||||
|
||||
/**
|
||||
* Parses an unknown document or template ID.
|
||||
*
|
||||
@@ -89,6 +105,87 @@ export const unsafeBuildEnvelopeIdQuery = (
|
||||
.exhaustive();
|
||||
};
|
||||
|
||||
/**
|
||||
* Parses multiple document or template IDs and builds a query filter.
|
||||
*
|
||||
* This is UNSAFE because it does not validate access, it only validates ID format and builds the query.
|
||||
*
|
||||
* @throws AppError if any ID is invalid or if the array exceeds the maximum limit
|
||||
*/
|
||||
export const unsafeBuildEnvelopeIdsQuery = (
|
||||
options: EnvelopeIdsOptions,
|
||||
expectedEnvelopeType: EnvelopeType | null,
|
||||
) => {
|
||||
if (!options.ids || options.ids.length === 0) {
|
||||
throw new AppError(AppErrorCode.INVALID_BODY, {
|
||||
message: 'At least one ID is required',
|
||||
});
|
||||
}
|
||||
|
||||
if (options.ids.length > MAX_ENVELOPE_IDS_PER_REQUEST) {
|
||||
throw new AppError(AppErrorCode.INVALID_BODY, {
|
||||
message: `Cannot request more than ${MAX_ENVELOPE_IDS_PER_REQUEST} envelopes at once`,
|
||||
});
|
||||
}
|
||||
|
||||
return match(options)
|
||||
.with({ type: 'envelopeId' }, (value) => {
|
||||
const validatedIds: string[] = [];
|
||||
|
||||
for (const id of value.ids) {
|
||||
const parsed = ZEnvelopeIdSchema.safeParse(id);
|
||||
|
||||
if (!parsed.success) {
|
||||
throw new AppError(AppErrorCode.INVALID_BODY, {
|
||||
message: `Invalid envelope ID: ${id}`,
|
||||
});
|
||||
}
|
||||
|
||||
validatedIds.push(parsed.data);
|
||||
}
|
||||
|
||||
if (expectedEnvelopeType) {
|
||||
return {
|
||||
id: { in: validatedIds },
|
||||
type: expectedEnvelopeType,
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
id: { in: validatedIds },
|
||||
};
|
||||
})
|
||||
.with({ type: 'documentId' }, (value) => {
|
||||
if (expectedEnvelopeType && expectedEnvelopeType !== EnvelopeType.DOCUMENT) {
|
||||
throw new AppError(AppErrorCode.INVALID_BODY, {
|
||||
message: 'Invalid document ID type',
|
||||
});
|
||||
}
|
||||
|
||||
const secondaryIds = value.ids.map((id) => mapDocumentIdToSecondaryId(id));
|
||||
|
||||
return {
|
||||
type: EnvelopeType.DOCUMENT,
|
||||
secondaryId: { in: secondaryIds },
|
||||
};
|
||||
})
|
||||
.with({ type: 'templateId' }, (value) => {
|
||||
if (expectedEnvelopeType && expectedEnvelopeType !== EnvelopeType.TEMPLATE) {
|
||||
throw new AppError(AppErrorCode.INVALID_BODY, {
|
||||
message: 'Invalid template ID type',
|
||||
});
|
||||
}
|
||||
|
||||
const secondaryIds = value.ids.map((id) => mapTemplateIdToSecondaryId(id));
|
||||
|
||||
return {
|
||||
type: EnvelopeType.TEMPLATE,
|
||||
secondaryId: { in: secondaryIds },
|
||||
};
|
||||
})
|
||||
.exhaustive();
|
||||
};
|
||||
|
||||
/**
|
||||
* Maps a legacy document ID number to an envelope secondary ID.
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user