import {z} from 'zod' export type NonPerson = {type: 'NON_PERSON', identification?: string | undefined, externalIdentifier?: string | undefined, name: string}; export type Person = {type: 'PERSON', identification?: string | undefined, externalIdentifier?: string | undefined, firstName?: string | undefined, lastName?: string | undefined, email?: string | undefined, mobile?: string | undefined}; export type Verification = {processId?: string | undefined, verifiedOn?: string | undefined, rejectedOn?: string | undefined, payload?: string | undefined, files?: Array | undefined, residentPermit?: (boolean | null) | undefined}; export type IdentifiedPerson = {firstName?: string | undefined, lastName?: string | undefined, birthName?: string | undefined, dateOfBirth?: string | undefined, placeOfBirth?: string | undefined, nationality?: string | undefined, gender?: string | undefined, title?: string | undefined}; export type IdentificationDocument = {type?: string | undefined, number?: string | undefined, issuingCountry?: string | undefined, issuingAuthority?: string | undefined, dateOfIssue?: string | undefined, dateOfExpiry?: string | undefined}; export type IdentAttempt = {type?: 'ONLINE' | undefined, provider?: string | undefined, status?: ('PENDING' | 'COMPLETED') | undefined, startedOn?: string | undefined, completedOn?: (string | null) | undefined, result?: string | undefined, reason?: (string | null) | undefined, nameMatch?: ('UNCHECKED' | 'MATCH' | 'MISMATCH') | undefined, identifiedPerson?: IdentifiedPerson | undefined, identificationDocument?: IdentificationDocument | undefined, files?: Array | undefined}; export type Ident = {status?: ('CREATED' | 'PENDING' | 'APPROVED' | 'REJECTED') | undefined, required?: (boolean | null) | undefined, requiredResidenceCountry?: ('CHE' | null) | undefined, attempts?: Array | undefined}; export type Signer = {type: 'SIGNER', identification?: string | undefined, externalIdentifier?: string | undefined, firstName: string, lastName: string, email?: string | undefined, mobile?: string | undefined, role?: string | undefined, signingIndex?: (number | null) | undefined, verification?: Verification | undefined, ident?: Ident | undefined, status?: ('WAITING' | 'PENDING' | 'SIGNED' | 'CANCELED' | 'DECLINED' | 'REMOVED' | 'REPLACED' | 'DELEGATED') | undefined, signedOn?: (string | null) | undefined, discontinuedOn?: (string | null) | undefined, canceledOn?: (string | null) | undefined, declinedOn?: (string | null) | undefined, declinedReason?: (string | null) | undefined, removedOn?: (string | null) | undefined, replacedOn?: (string | null) | undefined, replacedBy?: (string | null) | undefined, replaces?: (string | null) | undefined, delegatedOn?: (string | null) | undefined, delegatedTo?: (string | null) | undefined, delegatedFrom?: (string | null) | undefined, delegatedReason?: (string | null) | undefined, certificateName?: (string | null) | undefined, certificateFirstName?: (string | null) | undefined, certificateLastName?: (string | null) | undefined, certificateMatch?: ('UNCHECKED' | 'MATCH' | 'MISMATCH' | null) | undefined, placeOfSignature?: (string | null) | undefined}; export type Invitees = {personalMessage?: string | undefined, signers?: Array | undefined}; export type Property = {key: string, value: string}; export type FileSignaturePosition = {signer: string, pageNumber: number, positionX: number, positionY: number, stickerProvider?: ('VISUAL_SIGNATURE_PROVIDER' | 'CUSTOM_VISUAL_SIGNATURE_PROVIDER') | undefined}; export type FileReference = {externalIdentifier?: string | undefined, initialFileId?: string | undefined, lastSignedFileId?: string | undefined, signaturePositions?: Array | undefined}; export type Process = {id?: string | undefined, status?: ('CREATED' | 'PENDING' | 'COMPLETED' | 'EXPIRED') | undefined, signatureLevel?: ('SIMPLE' | 'ADVANCED' | 'ADVANCED_EU' | 'QUALIFIED' | 'QUALIFIED_EU') | undefined, initiator: NonPerson | Person | Signer, invitees?: Invitees | undefined, teamId?: (string | null) | undefined, properties?: Array | undefined, payload?: string | undefined, validUntil?: string | undefined, createdDate?: string | undefined, lastModifiedDate?: string | undefined, archiveOn?: string | undefined, archivedOn?: string | undefined, fileReferences?: Array | undefined, partnerId?: (string | null) | undefined, authorization?: ('CODE' | 'ACCOUNT') | undefined, signingOrder?: ('PARALLEL' | 'SERIAL' | null) | undefined}; export type CreateApiApiProcessArgs = {body: Process}; export type CreateApiApiProcessOptions = {baseUrl?: string | undefined, SwisscomSignOAuth2?: string | undefined, fetch?: typeof fetch | undefined}; export const nonPerson = z.object({type: z.literal("NON_PERSON"), identification: z.string().optional(), externalIdentifier: z.string().max(50).optional(), name: z.string().max(50)}); export const person = z.object({type: z.literal("PERSON"), identification: z.string().optional(), externalIdentifier: z.string().max(50).optional(), firstName: z.string().max(64).optional(), lastName: z.string().max(64).optional(), email: z.string().max(254).optional(), mobile: z.string().max(17).optional()}); export const verification = z.object({processId: z.string().max(36).optional(), verifiedOn: z.string().optional(), rejectedOn: z.string().optional(), payload: z.string().max(20000).optional(), files: z.array(z.string()).optional(), residentPermit: z.boolean().nullable().optional()}); export const identifiedPerson = z.object({firstName: z.string().optional(), lastName: z.string().optional(), birthName: z.string().optional(), dateOfBirth: z.string().optional(), placeOfBirth: z.string().optional(), nationality: z.string().optional(), gender: z.string().optional(), title: z.string().optional()}); export const identificationDocument = z.object({type: z.string().optional(), number: z.string().optional(), issuingCountry: z.string().optional(), issuingAuthority: z.string().optional(), dateOfIssue: z.string().optional(), dateOfExpiry: z.string().optional()}); export const identAttempt = z.object({type: z.literal("ONLINE").optional(), provider: z.string().optional(), status: z.enum(["PENDING", "COMPLETED"]).optional(), startedOn: z.string().optional(), completedOn: z.string().nullable().optional(), result: z.string().optional(), reason: z.string().nullable().optional(), nameMatch: z.enum(["UNCHECKED", "MATCH", "MISMATCH"]).optional(), identifiedPerson: identifiedPerson.optional(), identificationDocument: identificationDocument.optional(), files: z.array(z.string()).optional()}); export const ident = z.object({status: z.enum(["CREATED", "PENDING", "APPROVED", "REJECTED"]).optional(), required: z.boolean().nullable().optional(), requiredResidenceCountry: z.literal("CHE").nullable().optional(), attempts: z.array(identAttempt).optional()}); export const signer = z.object({type: z.literal("SIGNER"), identification: z.string().optional(), externalIdentifier: z.string().max(50).optional(), firstName: z.string().max(64), lastName: z.string().max(64), email: z.string().max(254).optional(), mobile: z.string().max(17).optional(), role: z.string().max(256).optional(), signingIndex: z.number().int().gte(0).nullable().optional(), verification: verification.optional(), ident: ident.optional(), status: z.enum(["WAITING", "PENDING", "SIGNED", "CANCELED", "DECLINED", "REMOVED", "REPLACED", "DELEGATED"]).optional(), signedOn: z.string().nullable().optional(), discontinuedOn: z.string().nullable().optional(), canceledOn: z.string().nullable().optional(), declinedOn: z.string().nullable().optional(), declinedReason: z.string().nullable().optional(), removedOn: z.string().nullable().optional(), replacedOn: z.string().nullable().optional(), replacedBy: z.string().nullable().optional(), replaces: z.string().nullable().optional(), delegatedOn: z.string().nullable().optional(), delegatedTo: z.string().nullable().optional(), delegatedFrom: z.string().nullable().optional(), delegatedReason: z.string().nullable().optional(), certificateName: z.string().nullable().optional(), certificateFirstName: z.string().nullable().optional(), certificateLastName: z.string().nullable().optional(), certificateMatch: z.enum(["UNCHECKED", "MATCH", "MISMATCH"]).nullable().optional(), placeOfSignature: z.string().nullable().optional()}); export const invitees = z.object({personalMessage: z.string().max(8192).optional(), signers: z.array(signer).optional()}); export const property = z.object({key: z.string().max(64), value: z.string().max(64)}); export const fileSignaturePosition = z.object({signer: z.string().max(128), pageNumber: z.number().int(), positionX: z.number().int().gte(0), positionY: z.number().int().gte(0), stickerProvider: z.enum(["VISUAL_SIGNATURE_PROVIDER", "CUSTOM_VISUAL_SIGNATURE_PROVIDER"]).optional()}); export const fileReference = z.object({externalIdentifier: z.string().max(50).optional(), initialFileId: z.string().optional(), lastSignedFileId: z.string().optional(), signaturePositions: z.array(fileSignaturePosition).optional()}); export const process = z.object({id: z.string().optional(), status: z.enum(["CREATED", "PENDING", "COMPLETED", "EXPIRED"]).optional(), signatureLevel: z.enum(["SIMPLE", "ADVANCED", "ADVANCED_EU", "QUALIFIED", "QUALIFIED_EU"]).optional(), initiator: z.union([nonPerson, person, signer]), invitees: invitees.optional(), teamId: z.string().nullable().optional(), properties: z.array(property).optional(), payload: z.string().max(8192).optional(), validUntil: z.string().optional(), createdDate: z.string().optional(), lastModifiedDate: z.string().optional(), archiveOn: z.string().optional(), archivedOn: z.string().optional(), fileReferences: z.array(fileReference).optional(), partnerId: z.string().nullable().optional(), authorization: z.enum(["CODE", "ACCOUNT"]).optional(), signingOrder: z.enum(["PARALLEL", "SERIAL"]).nullable().optional()}); export const validateResponse = async ( schema: { readonly '~standard': { readonly validate: (value: unknown) => ({ readonly value: Output; readonly issues?: undefined } | { readonly issues: ReadonlyArray<{ readonly message: string; readonly path?: ReadonlyArray | undefined }> }) | Promise<{ readonly value: Output; readonly issues?: undefined } | { readonly issues: ReadonlyArray<{ readonly message: string; readonly path?: ReadonlyArray | undefined }> }> } }, value: unknown ): Promise => { const result = await schema['~standard'].validate(value) if (result.issues !== undefined) { const detail = result.issues .map(({ message, path }) => path?.length ? `${path.map((segment) => String(typeof segment === 'object' ? segment.key : segment)).join('.')}: ${message}` : message ) .join('; ') throw new Error(`Response does not match the schema: ${detail}`, { cause: { issues: result.issues } }) } return result.value }; /** * Create a process * * POST /api/process */ export const createApiApiProcess = async (args: CreateApiApiProcessArgs, options?: CreateApiApiProcessOptions) => { const {baseUrl = "https://sign.swisscom.ch/system", fetch: fetchFn = fetch, SwisscomSignOAuth2} = options ?? {} const query = new URLSearchParams() const headers = new Headers() headers.set('content-type', "application/json") headers.set('accept', "application/json") if (SwisscomSignOAuth2 !== undefined) headers.set('authorization', `Bearer ${SwisscomSignOAuth2}`) const url = `${baseUrl.replace(/\/+$/, '')}/api/process${query.size > 0 ? `?${query}` : ''}` const res = await fetchFn(url, {method: "POST", headers, body: JSON.stringify(args.body)}) if (!res.ok) throw new Error(`Request failed with status ${res.status}`, {cause: {status: res.status, body: await res.text()}}) return validateResponse(process, await res.json()) };