signyu 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -63,11 +63,21 @@ const signyu = new SignYu({
63
63
 
64
64
  ## Methods
65
65
 
66
- ### `documents.create({ file, fileName?, name? })`
66
+ ### `documents.create({ file, fileName?, name?, replyTo? })`
67
67
 
68
68
  `POST /api/v1/documents`. Uploads a PDF (at most 10MB) and creates a document in `PENDING` state. `file` can be a `Buffer`, `Uint8Array`, `ArrayBuffer` or `Blob`. It is always sent as `application/pdf`. `fileName` defaults to `document.pdf`, and `name` defaults to the file name.
69
69
 
70
- Returns `{ documentId, name, status }`.
70
+ `replyTo` is an email address that receives signer replies to SignYu's signing emails (signature request, completion). If omitted, SignYu uses your account's reply-to setting (dashboard Settings), then your login email. An invalid address fails with `400 invalid_request`.
71
+
72
+ ```ts
73
+ const doc = await signyu.documents.create({
74
+ file: readFileSync("agreement.pdf"),
75
+ replyTo: "legal@example.com",
76
+ });
77
+ console.log(doc.replyTo); // "legal@example.com"
78
+ ```
79
+
80
+ Returns `{ documentId, name, status, replyTo }`.
71
81
 
72
82
  ### `documents.list({ limit?, offset? })`
73
83
 
@@ -77,7 +87,7 @@ Returns `{ documents: [{ documentId, name, status, createdAt, signers: { total,
77
87
 
78
88
  ### `documents.get(documentId)`
79
89
 
80
- `GET /api/v1/documents/{documentId}`. Status and per-signer progress. Once `COMPLETED`, `downloadUrl` is a temporary presigned link to the signed PDF and `certificateUrl` points at the certificate endpoint. Each signer's `signUrl` is `null` until the document is sent.
90
+ `GET /api/v1/documents/{documentId}`. Status and per-signer progress. Once `COMPLETED`, `downloadUrl` is a temporary presigned link to the signed PDF and `certificateUrl` points at the certificate endpoint. Each signer's `signUrl` is `null` until the document is sent. `replyTo` is the effective reply-to address used for signer emails.
81
91
 
82
92
  ### `documents.addSigners(documentId, signers)`
83
93
 
package/dist/index.cjs CHANGED
@@ -93,7 +93,7 @@ var webhooks = {
93
93
  };
94
94
 
95
95
  // src/version.ts
96
- var VERSION = "0.1.0";
96
+ var VERSION = "0.2.0";
97
97
 
98
98
  // src/client.ts
99
99
  var DEFAULT_BASE_URL = "https://signyu.com";
@@ -124,6 +124,7 @@ var Documents = class {
124
124
  const form = new FormData();
125
125
  form.append("file", toPdfBlob(params.file), params.fileName ?? "document.pdf");
126
126
  if (params.name !== void 0) form.append("name", params.name);
127
+ if (params.replyTo !== void 0) form.append("replyTo", params.replyTo);
127
128
  return this.client._request({
128
129
  method: "POST",
129
130
  path: "/api/v1/documents",
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/errors.ts","../src/webhooks.ts","../src/version.ts","../src/client.ts"],"sourcesContent":["export { SignYu, DEFAULT_BASE_URL } from \"./client\";\nexport type {\n SignYuOptions,\n CreateDocumentParams,\n ListDocumentsParams,\n FileInput,\n Documents,\n} from \"./client\";\nexport { SignYuError, WebhookSignatureError } from \"./errors\";\nexport {\n webhooks,\n verifySignature,\n constructEvent,\n computeSignature,\n SIGNATURE_HEADER,\n EVENT_HEADER,\n} from \"./webhooks\";\nexport type { Webhooks, WebhookPayload } from \"./webhooks\";\nexport { VERSION } from \"./version\";\nexport * from \"./types\";\n","/**\n * Thrown for any non-2xx API response, network failure or timeout.\n *\n * `code` is the API's machine readable `error` field (for example\n * `insufficient_credits`). For responses without a JSON error body it is\n * `rate_limited` (429) or `http_error`; for network failures it is\n * `connection_error` and for timeouts `timeout`, both with `status` 0.\n */\nexport class SignYuError extends Error {\n readonly status: number;\n readonly code: string;\n /** Parsed response body, when there was one. */\n readonly body: unknown;\n\n constructor(opts: {\n status: number;\n code: string;\n message: string;\n body?: unknown;\n cause?: unknown;\n }) {\n super(opts.message);\n this.name = \"SignYuError\";\n this.status = opts.status;\n this.code = opts.code;\n this.body = opts.body;\n if (opts.cause !== undefined) {\n (this as { cause?: unknown }).cause = opts.cause;\n }\n }\n}\n\n/** Thrown by `webhooks.constructEvent` when the signature does not match. */\nexport class WebhookSignatureError extends Error {\n constructor(message = \"Webhook signature verification failed.\") {\n super(message);\n this.name = \"WebhookSignatureError\";\n }\n}\n","import { createHmac, timingSafeEqual } from \"node:crypto\";\nimport { WebhookSignatureError } from \"./errors\";\nimport type { WebhookEvent } from \"./types\";\n\n/** Header carrying the signature, `sha256=<hex>`. */\nexport const SIGNATURE_HEADER = \"X-SignSetu-Signature\";\n/** Header carrying the event type, for example `signer.signed`. */\nexport const EVENT_HEADER = \"X-SignSetu-Event\";\n\nexport type WebhookPayload = string | Uint8Array | ArrayBuffer;\n\nfunction toBuffer(payload: WebhookPayload): Buffer {\n if (typeof payload === \"string\") return Buffer.from(payload, \"utf8\");\n if (payload instanceof ArrayBuffer) return Buffer.from(new Uint8Array(payload));\n return Buffer.from(payload.buffer, payload.byteOffset, payload.byteLength);\n}\n\n/** Computes the `sha256=<hex>` header value SignYu sends for a raw body. */\nexport function computeSignature(payload: WebhookPayload, secret: string): string {\n const hex = createHmac(\"sha256\", secret).update(toBuffer(payload)).digest(\"hex\");\n return `sha256=${hex}`;\n}\n\n/**\n * Returns true when `signatureHeader` (the `X-SignSetu-Signature` value) is a\n * valid HMAC-SHA256 of the raw request body under `secret`. Pass the raw body\n * bytes exactly as received; a re-serialized object will not match.\n * Comparison is constant time.\n */\nexport function verifySignature(\n payload: WebhookPayload,\n signatureHeader: string | null | undefined,\n secret: string\n): boolean {\n if (!signatureHeader || !secret) return false;\n const expected = Buffer.from(computeSignature(payload, secret), \"utf8\");\n const received = Buffer.from(signatureHeader.trim(), \"utf8\");\n if (expected.length !== received.length) return false;\n return timingSafeEqual(expected, received);\n}\n\n/**\n * Verifies the signature and returns the parsed event. Throws\n * `WebhookSignatureError` if the signature is missing or invalid.\n */\nexport function constructEvent(\n payload: WebhookPayload,\n signatureHeader: string | null | undefined,\n secret: string\n): WebhookEvent {\n if (!verifySignature(payload, signatureHeader, secret)) {\n throw new WebhookSignatureError();\n }\n return JSON.parse(toBuffer(payload).toString(\"utf8\")) as WebhookEvent;\n}\n\nexport const webhooks = {\n SIGNATURE_HEADER,\n EVENT_HEADER,\n computeSignature,\n verifySignature,\n constructEvent,\n};\n\nexport type Webhooks = typeof webhooks;\n","// Keep in sync with package.json \"version\".\nexport const VERSION = \"0.1.0\";\n","import { SignYuError } from \"./errors\";\nimport { webhooks, type Webhooks } from \"./webhooks\";\nimport type {\n AddSignersResponse,\n CreatedDocument,\n Document,\n DocumentList,\n SendDocumentResponse,\n SignerInput,\n} from \"./types\";\nimport { VERSION } from \"./version\";\n\nexport const DEFAULT_BASE_URL = \"https://signyu.com\";\n\nexport interface SignYuOptions {\n /** Your secret API key, `sk_live_...`. Keep it server side. */\n apiKey: string;\n /** Defaults to `https://signyu.com`. */\n baseUrl?: string;\n /** Per-request timeout in milliseconds. Defaults to 60000. */\n timeoutMs?: number;\n /** Custom fetch implementation (defaults to the global `fetch`). */\n fetch?: typeof fetch;\n}\n\nexport type FileInput = Blob | Uint8Array | ArrayBuffer;\n\nexport interface CreateDocumentParams {\n /** The PDF to sign, at most 10MB. A Node.js `Buffer` works here. */\n file: FileInput;\n /** File name sent with the upload. Defaults to `document.pdf`. */\n fileName?: string;\n /** Label for the document. Defaults to the file name. */\n name?: string;\n}\n\nexport interface ListDocumentsParams {\n /** 1 to 100, default 20. */\n limit?: number;\n /** Default 0. */\n offset?: number;\n}\n\ninterface RequestOptions {\n method: \"GET\" | \"POST\";\n path: string;\n query?: Record<string, string | number | undefined>;\n body?: BodyInit;\n json?: unknown;\n expect?: \"json\" | \"binary\";\n}\n\nfunction toPdfBlob(file: FileInput): Blob {\n if (typeof Blob !== \"undefined\" && file instanceof Blob) {\n // The API rejects anything whose part type is not application/pdf.\n return file.type === \"application/pdf\"\n ? file\n : new Blob([file], { type: \"application/pdf\" });\n }\n if (file instanceof ArrayBuffer) {\n return new Blob([file], { type: \"application/pdf\" });\n }\n if (file instanceof Uint8Array) {\n // Copy into a plain ArrayBuffer-backed view so Blob accepts it everywhere.\n const copy = new Uint8Array(file.byteLength);\n copy.set(file);\n return new Blob([copy], { type: \"application/pdf\" });\n }\n throw new TypeError(\"file must be a Buffer, Uint8Array, ArrayBuffer or Blob.\");\n}\n\nclass Documents {\n constructor(private readonly client: SignYu) {}\n\n /** `POST /api/v1/documents`: upload a PDF and create a `PENDING` document. */\n create(params: CreateDocumentParams): Promise<CreatedDocument> {\n if (!params || params.file === undefined || params.file === null) {\n throw new TypeError(\"documents.create requires a `file`.\");\n }\n const form = new FormData();\n form.append(\"file\", toPdfBlob(params.file), params.fileName ?? \"document.pdf\");\n if (params.name !== undefined) form.append(\"name\", params.name);\n return this.client._request<CreatedDocument>({\n method: \"POST\",\n path: \"/api/v1/documents\",\n body: form,\n });\n }\n\n /** `GET /api/v1/documents`: your documents, most recent first. */\n list(params: ListDocumentsParams = {}): Promise<DocumentList> {\n return this.client._request<DocumentList>({\n method: \"GET\",\n path: \"/api/v1/documents\",\n query: { limit: params.limit, offset: params.offset },\n });\n }\n\n /** `GET /api/v1/documents/{documentId}`: status and per-signer progress. */\n get(documentId: string): Promise<Document> {\n return this.client._request<Document>({\n method: \"GET\",\n path: `/api/v1/documents/${encodeURIComponent(documentId)}`,\n });\n }\n\n /** `POST /api/v1/documents/{documentId}/signers`: add signers while `PENDING` (max 6 per document). */\n addSigners(documentId: string, signers: SignerInput[]): Promise<AddSignersResponse> {\n return this.client._request<AddSignersResponse>({\n method: \"POST\",\n path: `/api/v1/documents/${encodeURIComponent(documentId)}/signers`,\n json: { signers },\n });\n }\n\n /**\n * `POST /api/v1/documents/{documentId}/send`: deducts one credit per signer,\n * emails signing links and returns them. Not idempotent: call it once.\n */\n send(documentId: string): Promise<SendDocumentResponse> {\n return this.client._request<SendDocumentResponse>({\n method: \"POST\",\n path: `/api/v1/documents/${encodeURIComponent(documentId)}/send`,\n });\n }\n\n /**\n * `GET /api/v1/documents/{documentId}/certificate`: the completion\n * certificate and audit trail PDF as raw bytes. Only available once the\n * document is `COMPLETED` (otherwise `409 invalid_state`).\n */\n getCertificate(documentId: string): Promise<Uint8Array> {\n return this.client._request<Uint8Array>({\n method: \"GET\",\n path: `/api/v1/documents/${encodeURIComponent(documentId)}/certificate`,\n expect: \"binary\",\n });\n }\n}\n\nexport class SignYu {\n readonly documents: Documents;\n readonly webhooks: Webhooks = webhooks;\n readonly baseUrl: string;\n\n private readonly apiKey: string;\n private readonly timeoutMs: number;\n private readonly fetchImpl: typeof fetch;\n\n constructor(options: SignYuOptions) {\n if (!options || !options.apiKey) {\n throw new TypeError(\"SignYu requires an `apiKey`.\");\n }\n this.apiKey = options.apiKey;\n this.baseUrl = (options.baseUrl ?? DEFAULT_BASE_URL).replace(/\\/+$/, \"\");\n this.timeoutMs = options.timeoutMs ?? 60_000;\n const f = options.fetch ?? globalThis.fetch;\n if (typeof f !== \"function\") {\n throw new TypeError(\"No global fetch found. SignYu requires Node.js 18 or newer.\");\n }\n this.fetchImpl = f;\n this.documents = new Documents(this);\n }\n\n /** @internal */\n async _request<T>(opts: RequestOptions): Promise<T> {\n const url = new URL(this.baseUrl + opts.path);\n for (const [k, v] of Object.entries(opts.query ?? {})) {\n if (v !== undefined) url.searchParams.set(k, String(v));\n }\n\n const headers: Record<string, string> = {\n Authorization: `Bearer ${this.apiKey}`,\n Accept: opts.expect === \"binary\" ? \"application/pdf\" : \"application/json\",\n \"User-Agent\": `signyu-node/${VERSION}`,\n };\n let body = opts.body;\n if (opts.json !== undefined) {\n headers[\"Content-Type\"] = \"application/json\";\n body = JSON.stringify(opts.json);\n }\n\n let res: Response;\n try {\n res = await this.fetchImpl(url.toString(), {\n method: opts.method,\n headers,\n body,\n signal: AbortSignal.timeout(this.timeoutMs),\n });\n } catch (err) {\n const isTimeout =\n err instanceof Error && (err.name === \"TimeoutError\" || err.name === \"AbortError\");\n throw new SignYuError({\n status: 0,\n code: isTimeout ? \"timeout\" : \"connection_error\",\n message: isTimeout\n ? `Request timed out after ${this.timeoutMs}ms.`\n : `Could not reach the SignYu API: ${err instanceof Error ? err.message : String(err)}`,\n cause: err,\n });\n }\n\n if (!res.ok) {\n const text = await res.text().catch(() => \"\");\n let parsed: unknown = undefined;\n try {\n parsed = text ? JSON.parse(text) : undefined;\n } catch {\n parsed = text;\n }\n const errBody =\n parsed && typeof parsed === \"object\" ? (parsed as Record<string, unknown>) : {};\n const code =\n typeof errBody.error === \"string\"\n ? errBody.error\n : res.status === 429\n ? \"rate_limited\"\n : \"http_error\";\n const message =\n typeof errBody.message === \"string\"\n ? errBody.message\n : `SignYu API request failed with status ${res.status}.`;\n throw new SignYuError({ status: res.status, code, message, body: parsed });\n }\n\n if (opts.expect === \"binary\") {\n return new Uint8Array(await res.arrayBuffer()) as T;\n }\n return (await res.json()) as T;\n }\n}\n\nexport type { Documents };\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACQO,IAAM,cAAN,cAA0B,MAAM;AAAA,EAC5B;AAAA,EACA;AAAA;AAAA,EAEA;AAAA,EAET,YAAY,MAMT;AACD,UAAM,KAAK,OAAO;AAClB,SAAK,OAAO;AACZ,SAAK,SAAS,KAAK;AACnB,SAAK,OAAO,KAAK;AACjB,SAAK,OAAO,KAAK;AACjB,QAAI,KAAK,UAAU,QAAW;AAC5B,MAAC,KAA6B,QAAQ,KAAK;AAAA,IAC7C;AAAA,EACF;AACF;AAGO,IAAM,wBAAN,cAAoC,MAAM;AAAA,EAC/C,YAAY,UAAU,0CAA0C;AAC9D,UAAM,OAAO;AACb,SAAK,OAAO;AAAA,EACd;AACF;;;ACtCA,yBAA4C;AAKrC,IAAM,mBAAmB;AAEzB,IAAM,eAAe;AAI5B,SAAS,SAAS,SAAiC;AACjD,MAAI,OAAO,YAAY,SAAU,QAAO,OAAO,KAAK,SAAS,MAAM;AACnE,MAAI,mBAAmB,YAAa,QAAO,OAAO,KAAK,IAAI,WAAW,OAAO,CAAC;AAC9E,SAAO,OAAO,KAAK,QAAQ,QAAQ,QAAQ,YAAY,QAAQ,UAAU;AAC3E;AAGO,SAAS,iBAAiB,SAAyB,QAAwB;AAChF,QAAM,UAAM,+BAAW,UAAU,MAAM,EAAE,OAAO,SAAS,OAAO,CAAC,EAAE,OAAO,KAAK;AAC/E,SAAO,UAAU,GAAG;AACtB;AAQO,SAAS,gBACd,SACA,iBACA,QACS;AACT,MAAI,CAAC,mBAAmB,CAAC,OAAQ,QAAO;AACxC,QAAM,WAAW,OAAO,KAAK,iBAAiB,SAAS,MAAM,GAAG,MAAM;AACtE,QAAM,WAAW,OAAO,KAAK,gBAAgB,KAAK,GAAG,MAAM;AAC3D,MAAI,SAAS,WAAW,SAAS,OAAQ,QAAO;AAChD,aAAO,oCAAgB,UAAU,QAAQ;AAC3C;AAMO,SAAS,eACd,SACA,iBACA,QACc;AACd,MAAI,CAAC,gBAAgB,SAAS,iBAAiB,MAAM,GAAG;AACtD,UAAM,IAAI,sBAAsB;AAAA,EAClC;AACA,SAAO,KAAK,MAAM,SAAS,OAAO,EAAE,SAAS,MAAM,CAAC;AACtD;AAEO,IAAM,WAAW;AAAA,EACtB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;;;AC7DO,IAAM,UAAU;;;ACWhB,IAAM,mBAAmB;AAwChC,SAAS,UAAU,MAAuB;AACxC,MAAI,OAAO,SAAS,eAAe,gBAAgB,MAAM;AAEvD,WAAO,KAAK,SAAS,oBACjB,OACA,IAAI,KAAK,CAAC,IAAI,GAAG,EAAE,MAAM,kBAAkB,CAAC;AAAA,EAClD;AACA,MAAI,gBAAgB,aAAa;AAC/B,WAAO,IAAI,KAAK,CAAC,IAAI,GAAG,EAAE,MAAM,kBAAkB,CAAC;AAAA,EACrD;AACA,MAAI,gBAAgB,YAAY;AAE9B,UAAM,OAAO,IAAI,WAAW,KAAK,UAAU;AAC3C,SAAK,IAAI,IAAI;AACb,WAAO,IAAI,KAAK,CAAC,IAAI,GAAG,EAAE,MAAM,kBAAkB,CAAC;AAAA,EACrD;AACA,QAAM,IAAI,UAAU,yDAAyD;AAC/E;AAEA,IAAM,YAAN,MAAgB;AAAA,EACd,YAA6B,QAAgB;AAAhB;AAAA,EAAiB;AAAA,EAAjB;AAAA;AAAA,EAG7B,OAAO,QAAwD;AAC7D,QAAI,CAAC,UAAU,OAAO,SAAS,UAAa,OAAO,SAAS,MAAM;AAChE,YAAM,IAAI,UAAU,qCAAqC;AAAA,IAC3D;AACA,UAAM,OAAO,IAAI,SAAS;AAC1B,SAAK,OAAO,QAAQ,UAAU,OAAO,IAAI,GAAG,OAAO,YAAY,cAAc;AAC7E,QAAI,OAAO,SAAS,OAAW,MAAK,OAAO,QAAQ,OAAO,IAAI;AAC9D,WAAO,KAAK,OAAO,SAA0B;AAAA,MAC3C,QAAQ;AAAA,MACR,MAAM;AAAA,MACN,MAAM;AAAA,IACR,CAAC;AAAA,EACH;AAAA;AAAA,EAGA,KAAK,SAA8B,CAAC,GAA0B;AAC5D,WAAO,KAAK,OAAO,SAAuB;AAAA,MACxC,QAAQ;AAAA,MACR,MAAM;AAAA,MACN,OAAO,EAAE,OAAO,OAAO,OAAO,QAAQ,OAAO,OAAO;AAAA,IACtD,CAAC;AAAA,EACH;AAAA;AAAA,EAGA,IAAI,YAAuC;AACzC,WAAO,KAAK,OAAO,SAAmB;AAAA,MACpC,QAAQ;AAAA,MACR,MAAM,qBAAqB,mBAAmB,UAAU,CAAC;AAAA,IAC3D,CAAC;AAAA,EACH;AAAA;AAAA,EAGA,WAAW,YAAoB,SAAqD;AAClF,WAAO,KAAK,OAAO,SAA6B;AAAA,MAC9C,QAAQ;AAAA,MACR,MAAM,qBAAqB,mBAAmB,UAAU,CAAC;AAAA,MACzD,MAAM,EAAE,QAAQ;AAAA,IAClB,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,KAAK,YAAmD;AACtD,WAAO,KAAK,OAAO,SAA+B;AAAA,MAChD,QAAQ;AAAA,MACR,MAAM,qBAAqB,mBAAmB,UAAU,CAAC;AAAA,IAC3D,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,eAAe,YAAyC;AACtD,WAAO,KAAK,OAAO,SAAqB;AAAA,MACtC,QAAQ;AAAA,MACR,MAAM,qBAAqB,mBAAmB,UAAU,CAAC;AAAA,MACzD,QAAQ;AAAA,IACV,CAAC;AAAA,EACH;AACF;AAEO,IAAM,SAAN,MAAa;AAAA,EACT;AAAA,EACA,WAAqB;AAAA,EACrB;AAAA,EAEQ;AAAA,EACA;AAAA,EACA;AAAA,EAEjB,YAAY,SAAwB;AAClC,QAAI,CAAC,WAAW,CAAC,QAAQ,QAAQ;AAC/B,YAAM,IAAI,UAAU,8BAA8B;AAAA,IACpD;AACA,SAAK,SAAS,QAAQ;AACtB,SAAK,WAAW,QAAQ,WAAW,kBAAkB,QAAQ,QAAQ,EAAE;AACvE,SAAK,YAAY,QAAQ,aAAa;AACtC,UAAM,IAAI,QAAQ,SAAS,WAAW;AACtC,QAAI,OAAO,MAAM,YAAY;AAC3B,YAAM,IAAI,UAAU,6DAA6D;AAAA,IACnF;AACA,SAAK,YAAY;AACjB,SAAK,YAAY,IAAI,UAAU,IAAI;AAAA,EACrC;AAAA;AAAA,EAGA,MAAM,SAAY,MAAkC;AAClD,UAAM,MAAM,IAAI,IAAI,KAAK,UAAU,KAAK,IAAI;AAC5C,eAAW,CAAC,GAAG,CAAC,KAAK,OAAO,QAAQ,KAAK,SAAS,CAAC,CAAC,GAAG;AACrD,UAAI,MAAM,OAAW,KAAI,aAAa,IAAI,GAAG,OAAO,CAAC,CAAC;AAAA,IACxD;AAEA,UAAM,UAAkC;AAAA,MACtC,eAAe,UAAU,KAAK,MAAM;AAAA,MACpC,QAAQ,KAAK,WAAW,WAAW,oBAAoB;AAAA,MACvD,cAAc,eAAe,OAAO;AAAA,IACtC;AACA,QAAI,OAAO,KAAK;AAChB,QAAI,KAAK,SAAS,QAAW;AAC3B,cAAQ,cAAc,IAAI;AAC1B,aAAO,KAAK,UAAU,KAAK,IAAI;AAAA,IACjC;AAEA,QAAI;AACJ,QAAI;AACF,YAAM,MAAM,KAAK,UAAU,IAAI,SAAS,GAAG;AAAA,QACzC,QAAQ,KAAK;AAAA,QACb;AAAA,QACA;AAAA,QACA,QAAQ,YAAY,QAAQ,KAAK,SAAS;AAAA,MAC5C,CAAC;AAAA,IACH,SAAS,KAAK;AACZ,YAAM,YACJ,eAAe,UAAU,IAAI,SAAS,kBAAkB,IAAI,SAAS;AACvE,YAAM,IAAI,YAAY;AAAA,QACpB,QAAQ;AAAA,QACR,MAAM,YAAY,YAAY;AAAA,QAC9B,SAAS,YACL,2BAA2B,KAAK,SAAS,QACzC,mCAAmC,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA,QACvF,OAAO;AAAA,MACT,CAAC;AAAA,IACH;AAEA,QAAI,CAAC,IAAI,IAAI;AACX,YAAM,OAAO,MAAM,IAAI,KAAK,EAAE,MAAM,MAAM,EAAE;AAC5C,UAAI,SAAkB;AACtB,UAAI;AACF,iBAAS,OAAO,KAAK,MAAM,IAAI,IAAI;AAAA,MACrC,QAAQ;AACN,iBAAS;AAAA,MACX;AACA,YAAM,UACJ,UAAU,OAAO,WAAW,WAAY,SAAqC,CAAC;AAChF,YAAM,OACJ,OAAO,QAAQ,UAAU,WACrB,QAAQ,QACR,IAAI,WAAW,MACb,iBACA;AACR,YAAM,UACJ,OAAO,QAAQ,YAAY,WACvB,QAAQ,UACR,yCAAyC,IAAI,MAAM;AACzD,YAAM,IAAI,YAAY,EAAE,QAAQ,IAAI,QAAQ,MAAM,SAAS,MAAM,OAAO,CAAC;AAAA,IAC3E;AAEA,QAAI,KAAK,WAAW,UAAU;AAC5B,aAAO,IAAI,WAAW,MAAM,IAAI,YAAY,CAAC;AAAA,IAC/C;AACA,WAAQ,MAAM,IAAI,KAAK;AAAA,EACzB;AACF;","names":[]}
1
+ {"version":3,"sources":["../src/index.ts","../src/errors.ts","../src/webhooks.ts","../src/version.ts","../src/client.ts"],"sourcesContent":["export { SignYu, DEFAULT_BASE_URL } from \"./client\";\nexport type {\n SignYuOptions,\n CreateDocumentParams,\n ListDocumentsParams,\n FileInput,\n Documents,\n} from \"./client\";\nexport { SignYuError, WebhookSignatureError } from \"./errors\";\nexport {\n webhooks,\n verifySignature,\n constructEvent,\n computeSignature,\n SIGNATURE_HEADER,\n EVENT_HEADER,\n} from \"./webhooks\";\nexport type { Webhooks, WebhookPayload } from \"./webhooks\";\nexport { VERSION } from \"./version\";\nexport * from \"./types\";\n","/**\n * Thrown for any non-2xx API response, network failure or timeout.\n *\n * `code` is the API's machine readable `error` field (for example\n * `insufficient_credits`). For responses without a JSON error body it is\n * `rate_limited` (429) or `http_error`; for network failures it is\n * `connection_error` and for timeouts `timeout`, both with `status` 0.\n */\nexport class SignYuError extends Error {\n readonly status: number;\n readonly code: string;\n /** Parsed response body, when there was one. */\n readonly body: unknown;\n\n constructor(opts: {\n status: number;\n code: string;\n message: string;\n body?: unknown;\n cause?: unknown;\n }) {\n super(opts.message);\n this.name = \"SignYuError\";\n this.status = opts.status;\n this.code = opts.code;\n this.body = opts.body;\n if (opts.cause !== undefined) {\n (this as { cause?: unknown }).cause = opts.cause;\n }\n }\n}\n\n/** Thrown by `webhooks.constructEvent` when the signature does not match. */\nexport class WebhookSignatureError extends Error {\n constructor(message = \"Webhook signature verification failed.\") {\n super(message);\n this.name = \"WebhookSignatureError\";\n }\n}\n","import { createHmac, timingSafeEqual } from \"node:crypto\";\nimport { WebhookSignatureError } from \"./errors\";\nimport type { WebhookEvent } from \"./types\";\n\n/** Header carrying the signature, `sha256=<hex>`. */\nexport const SIGNATURE_HEADER = \"X-SignSetu-Signature\";\n/** Header carrying the event type, for example `signer.signed`. */\nexport const EVENT_HEADER = \"X-SignSetu-Event\";\n\nexport type WebhookPayload = string | Uint8Array | ArrayBuffer;\n\nfunction toBuffer(payload: WebhookPayload): Buffer {\n if (typeof payload === \"string\") return Buffer.from(payload, \"utf8\");\n if (payload instanceof ArrayBuffer) return Buffer.from(new Uint8Array(payload));\n return Buffer.from(payload.buffer, payload.byteOffset, payload.byteLength);\n}\n\n/** Computes the `sha256=<hex>` header value SignYu sends for a raw body. */\nexport function computeSignature(payload: WebhookPayload, secret: string): string {\n const hex = createHmac(\"sha256\", secret).update(toBuffer(payload)).digest(\"hex\");\n return `sha256=${hex}`;\n}\n\n/**\n * Returns true when `signatureHeader` (the `X-SignSetu-Signature` value) is a\n * valid HMAC-SHA256 of the raw request body under `secret`. Pass the raw body\n * bytes exactly as received; a re-serialized object will not match.\n * Comparison is constant time.\n */\nexport function verifySignature(\n payload: WebhookPayload,\n signatureHeader: string | null | undefined,\n secret: string\n): boolean {\n if (!signatureHeader || !secret) return false;\n const expected = Buffer.from(computeSignature(payload, secret), \"utf8\");\n const received = Buffer.from(signatureHeader.trim(), \"utf8\");\n if (expected.length !== received.length) return false;\n return timingSafeEqual(expected, received);\n}\n\n/**\n * Verifies the signature and returns the parsed event. Throws\n * `WebhookSignatureError` if the signature is missing or invalid.\n */\nexport function constructEvent(\n payload: WebhookPayload,\n signatureHeader: string | null | undefined,\n secret: string\n): WebhookEvent {\n if (!verifySignature(payload, signatureHeader, secret)) {\n throw new WebhookSignatureError();\n }\n return JSON.parse(toBuffer(payload).toString(\"utf8\")) as WebhookEvent;\n}\n\nexport const webhooks = {\n SIGNATURE_HEADER,\n EVENT_HEADER,\n computeSignature,\n verifySignature,\n constructEvent,\n};\n\nexport type Webhooks = typeof webhooks;\n","// Keep in sync with package.json \"version\".\nexport const VERSION = \"0.2.0\";\n","import { SignYuError } from \"./errors\";\nimport { webhooks, type Webhooks } from \"./webhooks\";\nimport type {\n AddSignersResponse,\n CreatedDocument,\n Document,\n DocumentList,\n SendDocumentResponse,\n SignerInput,\n} from \"./types\";\nimport { VERSION } from \"./version\";\n\nexport const DEFAULT_BASE_URL = \"https://signyu.com\";\n\nexport interface SignYuOptions {\n /** Your secret API key, `sk_live_...`. Keep it server side. */\n apiKey: string;\n /** Defaults to `https://signyu.com`. */\n baseUrl?: string;\n /** Per-request timeout in milliseconds. Defaults to 60000. */\n timeoutMs?: number;\n /** Custom fetch implementation (defaults to the global `fetch`). */\n fetch?: typeof fetch;\n}\n\nexport type FileInput = Blob | Uint8Array | ArrayBuffer;\n\nexport interface CreateDocumentParams {\n /** The PDF to sign, at most 10MB. A Node.js `Buffer` works here. */\n file: FileInput;\n /** File name sent with the upload. Defaults to `document.pdf`. */\n fileName?: string;\n /** Label for the document. Defaults to the file name. */\n name?: string;\n /**\n * Email address that receives signer replies to SignYu's signing emails.\n * Defaults to your account's reply-to setting, then your login email.\n */\n replyTo?: string;\n}\n\nexport interface ListDocumentsParams {\n /** 1 to 100, default 20. */\n limit?: number;\n /** Default 0. */\n offset?: number;\n}\n\ninterface RequestOptions {\n method: \"GET\" | \"POST\";\n path: string;\n query?: Record<string, string | number | undefined>;\n body?: BodyInit;\n json?: unknown;\n expect?: \"json\" | \"binary\";\n}\n\nfunction toPdfBlob(file: FileInput): Blob {\n if (typeof Blob !== \"undefined\" && file instanceof Blob) {\n // The API rejects anything whose part type is not application/pdf.\n return file.type === \"application/pdf\"\n ? file\n : new Blob([file], { type: \"application/pdf\" });\n }\n if (file instanceof ArrayBuffer) {\n return new Blob([file], { type: \"application/pdf\" });\n }\n if (file instanceof Uint8Array) {\n // Copy into a plain ArrayBuffer-backed view so Blob accepts it everywhere.\n const copy = new Uint8Array(file.byteLength);\n copy.set(file);\n return new Blob([copy], { type: \"application/pdf\" });\n }\n throw new TypeError(\"file must be a Buffer, Uint8Array, ArrayBuffer or Blob.\");\n}\n\nclass Documents {\n constructor(private readonly client: SignYu) {}\n\n /** `POST /api/v1/documents`: upload a PDF and create a `PENDING` document. */\n create(params: CreateDocumentParams): Promise<CreatedDocument> {\n if (!params || params.file === undefined || params.file === null) {\n throw new TypeError(\"documents.create requires a `file`.\");\n }\n const form = new FormData();\n form.append(\"file\", toPdfBlob(params.file), params.fileName ?? \"document.pdf\");\n if (params.name !== undefined) form.append(\"name\", params.name);\n if (params.replyTo !== undefined) form.append(\"replyTo\", params.replyTo);\n return this.client._request<CreatedDocument>({\n method: \"POST\",\n path: \"/api/v1/documents\",\n body: form,\n });\n }\n\n /** `GET /api/v1/documents`: your documents, most recent first. */\n list(params: ListDocumentsParams = {}): Promise<DocumentList> {\n return this.client._request<DocumentList>({\n method: \"GET\",\n path: \"/api/v1/documents\",\n query: { limit: params.limit, offset: params.offset },\n });\n }\n\n /** `GET /api/v1/documents/{documentId}`: status and per-signer progress. */\n get(documentId: string): Promise<Document> {\n return this.client._request<Document>({\n method: \"GET\",\n path: `/api/v1/documents/${encodeURIComponent(documentId)}`,\n });\n }\n\n /** `POST /api/v1/documents/{documentId}/signers`: add signers while `PENDING` (max 6 per document). */\n addSigners(documentId: string, signers: SignerInput[]): Promise<AddSignersResponse> {\n return this.client._request<AddSignersResponse>({\n method: \"POST\",\n path: `/api/v1/documents/${encodeURIComponent(documentId)}/signers`,\n json: { signers },\n });\n }\n\n /**\n * `POST /api/v1/documents/{documentId}/send`: deducts one credit per signer,\n * emails signing links and returns them. Not idempotent: call it once.\n */\n send(documentId: string): Promise<SendDocumentResponse> {\n return this.client._request<SendDocumentResponse>({\n method: \"POST\",\n path: `/api/v1/documents/${encodeURIComponent(documentId)}/send`,\n });\n }\n\n /**\n * `GET /api/v1/documents/{documentId}/certificate`: the completion\n * certificate and audit trail PDF as raw bytes. Only available once the\n * document is `COMPLETED` (otherwise `409 invalid_state`).\n */\n getCertificate(documentId: string): Promise<Uint8Array> {\n return this.client._request<Uint8Array>({\n method: \"GET\",\n path: `/api/v1/documents/${encodeURIComponent(documentId)}/certificate`,\n expect: \"binary\",\n });\n }\n}\n\nexport class SignYu {\n readonly documents: Documents;\n readonly webhooks: Webhooks = webhooks;\n readonly baseUrl: string;\n\n private readonly apiKey: string;\n private readonly timeoutMs: number;\n private readonly fetchImpl: typeof fetch;\n\n constructor(options: SignYuOptions) {\n if (!options || !options.apiKey) {\n throw new TypeError(\"SignYu requires an `apiKey`.\");\n }\n this.apiKey = options.apiKey;\n this.baseUrl = (options.baseUrl ?? DEFAULT_BASE_URL).replace(/\\/+$/, \"\");\n this.timeoutMs = options.timeoutMs ?? 60_000;\n const f = options.fetch ?? globalThis.fetch;\n if (typeof f !== \"function\") {\n throw new TypeError(\"No global fetch found. SignYu requires Node.js 18 or newer.\");\n }\n this.fetchImpl = f;\n this.documents = new Documents(this);\n }\n\n /** @internal */\n async _request<T>(opts: RequestOptions): Promise<T> {\n const url = new URL(this.baseUrl + opts.path);\n for (const [k, v] of Object.entries(opts.query ?? {})) {\n if (v !== undefined) url.searchParams.set(k, String(v));\n }\n\n const headers: Record<string, string> = {\n Authorization: `Bearer ${this.apiKey}`,\n Accept: opts.expect === \"binary\" ? \"application/pdf\" : \"application/json\",\n \"User-Agent\": `signyu-node/${VERSION}`,\n };\n let body = opts.body;\n if (opts.json !== undefined) {\n headers[\"Content-Type\"] = \"application/json\";\n body = JSON.stringify(opts.json);\n }\n\n let res: Response;\n try {\n res = await this.fetchImpl(url.toString(), {\n method: opts.method,\n headers,\n body,\n signal: AbortSignal.timeout(this.timeoutMs),\n });\n } catch (err) {\n const isTimeout =\n err instanceof Error && (err.name === \"TimeoutError\" || err.name === \"AbortError\");\n throw new SignYuError({\n status: 0,\n code: isTimeout ? \"timeout\" : \"connection_error\",\n message: isTimeout\n ? `Request timed out after ${this.timeoutMs}ms.`\n : `Could not reach the SignYu API: ${err instanceof Error ? err.message : String(err)}`,\n cause: err,\n });\n }\n\n if (!res.ok) {\n const text = await res.text().catch(() => \"\");\n let parsed: unknown = undefined;\n try {\n parsed = text ? JSON.parse(text) : undefined;\n } catch {\n parsed = text;\n }\n const errBody =\n parsed && typeof parsed === \"object\" ? (parsed as Record<string, unknown>) : {};\n const code =\n typeof errBody.error === \"string\"\n ? errBody.error\n : res.status === 429\n ? \"rate_limited\"\n : \"http_error\";\n const message =\n typeof errBody.message === \"string\"\n ? errBody.message\n : `SignYu API request failed with status ${res.status}.`;\n throw new SignYuError({ status: res.status, code, message, body: parsed });\n }\n\n if (opts.expect === \"binary\") {\n return new Uint8Array(await res.arrayBuffer()) as T;\n }\n return (await res.json()) as T;\n }\n}\n\nexport type { Documents };\n"],"mappings":"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","names":[]}
package/dist/index.d.cts CHANGED
@@ -39,6 +39,8 @@ interface CreatedDocument {
39
39
  documentId: string;
40
40
  name: string;
41
41
  status: DocumentStatus;
42
+ /** Effective reply-to address used for signer emails. */
43
+ replyTo: string | null;
42
44
  }
43
45
  interface SignerCounts {
44
46
  total: number;
@@ -84,6 +86,8 @@ interface Document {
84
86
  downloadUrl: string | null;
85
87
  /** Bearer-authenticated certificate endpoint, set once `COMPLETED`. */
86
88
  certificateUrl: string | null;
89
+ /** Effective reply-to address used for signer emails. */
90
+ replyTo: string | null;
87
91
  signers: DocumentSigner[];
88
92
  }
89
93
  interface AddedSigner {
@@ -194,6 +198,11 @@ interface CreateDocumentParams {
194
198
  fileName?: string;
195
199
  /** Label for the document. Defaults to the file name. */
196
200
  name?: string;
201
+ /**
202
+ * Email address that receives signer replies to SignYu's signing emails.
203
+ * Defaults to your account's reply-to setting, then your login email.
204
+ */
205
+ replyTo?: string;
197
206
  }
198
207
  interface ListDocumentsParams {
199
208
  /** 1 to 100, default 20. */
@@ -270,6 +279,6 @@ declare class WebhookSignatureError extends Error {
270
279
  constructor(message?: string);
271
280
  }
272
281
 
273
- declare const VERSION = "0.1.0";
282
+ declare const VERSION = "0.2.0";
274
283
 
275
284
  export { type AddSignersResponse, type AddedSigner, type ApiErrorBody, type CreateDocumentParams, type CreatedDocument, DEFAULT_BASE_URL, type Document, type DocumentCompletedEvent, type DocumentList, type DocumentSigner, type DocumentStatus, type DocumentSummary, Documents, EVENT_HEADER, type FileInput, type ListDocumentsParams, SIGNATURE_HEADER, type SendDocumentResponse, type SentSigner, SignYu, SignYuError, type SignYuOptions, type SignaturePlacement, type SignaturePosition, type SignerAdvanced, type SignerCounts, type SignerInput, type SignerSignedEvent, VERSION, type WebhookEvent, type WebhookEventType, type WebhookPayload, WebhookSignatureError, type WebhookSigner, type Webhooks, computeSignature, constructEvent, verifySignature, webhooks };
package/dist/index.d.ts CHANGED
@@ -39,6 +39,8 @@ interface CreatedDocument {
39
39
  documentId: string;
40
40
  name: string;
41
41
  status: DocumentStatus;
42
+ /** Effective reply-to address used for signer emails. */
43
+ replyTo: string | null;
42
44
  }
43
45
  interface SignerCounts {
44
46
  total: number;
@@ -84,6 +86,8 @@ interface Document {
84
86
  downloadUrl: string | null;
85
87
  /** Bearer-authenticated certificate endpoint, set once `COMPLETED`. */
86
88
  certificateUrl: string | null;
89
+ /** Effective reply-to address used for signer emails. */
90
+ replyTo: string | null;
87
91
  signers: DocumentSigner[];
88
92
  }
89
93
  interface AddedSigner {
@@ -194,6 +198,11 @@ interface CreateDocumentParams {
194
198
  fileName?: string;
195
199
  /** Label for the document. Defaults to the file name. */
196
200
  name?: string;
201
+ /**
202
+ * Email address that receives signer replies to SignYu's signing emails.
203
+ * Defaults to your account's reply-to setting, then your login email.
204
+ */
205
+ replyTo?: string;
197
206
  }
198
207
  interface ListDocumentsParams {
199
208
  /** 1 to 100, default 20. */
@@ -270,6 +279,6 @@ declare class WebhookSignatureError extends Error {
270
279
  constructor(message?: string);
271
280
  }
272
281
 
273
- declare const VERSION = "0.1.0";
282
+ declare const VERSION = "0.2.0";
274
283
 
275
284
  export { type AddSignersResponse, type AddedSigner, type ApiErrorBody, type CreateDocumentParams, type CreatedDocument, DEFAULT_BASE_URL, type Document, type DocumentCompletedEvent, type DocumentList, type DocumentSigner, type DocumentStatus, type DocumentSummary, Documents, EVENT_HEADER, type FileInput, type ListDocumentsParams, SIGNATURE_HEADER, type SendDocumentResponse, type SentSigner, SignYu, SignYuError, type SignYuOptions, type SignaturePlacement, type SignaturePosition, type SignerAdvanced, type SignerCounts, type SignerInput, type SignerSignedEvent, VERSION, type WebhookEvent, type WebhookEventType, type WebhookPayload, WebhookSignatureError, type WebhookSigner, type Webhooks, computeSignature, constructEvent, verifySignature, webhooks };
package/dist/index.js CHANGED
@@ -57,7 +57,7 @@ var webhooks = {
57
57
  };
58
58
 
59
59
  // src/version.ts
60
- var VERSION = "0.1.0";
60
+ var VERSION = "0.2.0";
61
61
 
62
62
  // src/client.ts
63
63
  var DEFAULT_BASE_URL = "https://signyu.com";
@@ -88,6 +88,7 @@ var Documents = class {
88
88
  const form = new FormData();
89
89
  form.append("file", toPdfBlob(params.file), params.fileName ?? "document.pdf");
90
90
  if (params.name !== void 0) form.append("name", params.name);
91
+ if (params.replyTo !== void 0) form.append("replyTo", params.replyTo);
91
92
  return this.client._request({
92
93
  method: "POST",
93
94
  path: "/api/v1/documents",
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/errors.ts","../src/webhooks.ts","../src/version.ts","../src/client.ts"],"sourcesContent":["/**\n * Thrown for any non-2xx API response, network failure or timeout.\n *\n * `code` is the API's machine readable `error` field (for example\n * `insufficient_credits`). For responses without a JSON error body it is\n * `rate_limited` (429) or `http_error`; for network failures it is\n * `connection_error` and for timeouts `timeout`, both with `status` 0.\n */\nexport class SignYuError extends Error {\n readonly status: number;\n readonly code: string;\n /** Parsed response body, when there was one. */\n readonly body: unknown;\n\n constructor(opts: {\n status: number;\n code: string;\n message: string;\n body?: unknown;\n cause?: unknown;\n }) {\n super(opts.message);\n this.name = \"SignYuError\";\n this.status = opts.status;\n this.code = opts.code;\n this.body = opts.body;\n if (opts.cause !== undefined) {\n (this as { cause?: unknown }).cause = opts.cause;\n }\n }\n}\n\n/** Thrown by `webhooks.constructEvent` when the signature does not match. */\nexport class WebhookSignatureError extends Error {\n constructor(message = \"Webhook signature verification failed.\") {\n super(message);\n this.name = \"WebhookSignatureError\";\n }\n}\n","import { createHmac, timingSafeEqual } from \"node:crypto\";\nimport { WebhookSignatureError } from \"./errors\";\nimport type { WebhookEvent } from \"./types\";\n\n/** Header carrying the signature, `sha256=<hex>`. */\nexport const SIGNATURE_HEADER = \"X-SignSetu-Signature\";\n/** Header carrying the event type, for example `signer.signed`. */\nexport const EVENT_HEADER = \"X-SignSetu-Event\";\n\nexport type WebhookPayload = string | Uint8Array | ArrayBuffer;\n\nfunction toBuffer(payload: WebhookPayload): Buffer {\n if (typeof payload === \"string\") return Buffer.from(payload, \"utf8\");\n if (payload instanceof ArrayBuffer) return Buffer.from(new Uint8Array(payload));\n return Buffer.from(payload.buffer, payload.byteOffset, payload.byteLength);\n}\n\n/** Computes the `sha256=<hex>` header value SignYu sends for a raw body. */\nexport function computeSignature(payload: WebhookPayload, secret: string): string {\n const hex = createHmac(\"sha256\", secret).update(toBuffer(payload)).digest(\"hex\");\n return `sha256=${hex}`;\n}\n\n/**\n * Returns true when `signatureHeader` (the `X-SignSetu-Signature` value) is a\n * valid HMAC-SHA256 of the raw request body under `secret`. Pass the raw body\n * bytes exactly as received; a re-serialized object will not match.\n * Comparison is constant time.\n */\nexport function verifySignature(\n payload: WebhookPayload,\n signatureHeader: string | null | undefined,\n secret: string\n): boolean {\n if (!signatureHeader || !secret) return false;\n const expected = Buffer.from(computeSignature(payload, secret), \"utf8\");\n const received = Buffer.from(signatureHeader.trim(), \"utf8\");\n if (expected.length !== received.length) return false;\n return timingSafeEqual(expected, received);\n}\n\n/**\n * Verifies the signature and returns the parsed event. Throws\n * `WebhookSignatureError` if the signature is missing or invalid.\n */\nexport function constructEvent(\n payload: WebhookPayload,\n signatureHeader: string | null | undefined,\n secret: string\n): WebhookEvent {\n if (!verifySignature(payload, signatureHeader, secret)) {\n throw new WebhookSignatureError();\n }\n return JSON.parse(toBuffer(payload).toString(\"utf8\")) as WebhookEvent;\n}\n\nexport const webhooks = {\n SIGNATURE_HEADER,\n EVENT_HEADER,\n computeSignature,\n verifySignature,\n constructEvent,\n};\n\nexport type Webhooks = typeof webhooks;\n","// Keep in sync with package.json \"version\".\nexport const VERSION = \"0.1.0\";\n","import { SignYuError } from \"./errors\";\nimport { webhooks, type Webhooks } from \"./webhooks\";\nimport type {\n AddSignersResponse,\n CreatedDocument,\n Document,\n DocumentList,\n SendDocumentResponse,\n SignerInput,\n} from \"./types\";\nimport { VERSION } from \"./version\";\n\nexport const DEFAULT_BASE_URL = \"https://signyu.com\";\n\nexport interface SignYuOptions {\n /** Your secret API key, `sk_live_...`. Keep it server side. */\n apiKey: string;\n /** Defaults to `https://signyu.com`. */\n baseUrl?: string;\n /** Per-request timeout in milliseconds. Defaults to 60000. */\n timeoutMs?: number;\n /** Custom fetch implementation (defaults to the global `fetch`). */\n fetch?: typeof fetch;\n}\n\nexport type FileInput = Blob | Uint8Array | ArrayBuffer;\n\nexport interface CreateDocumentParams {\n /** The PDF to sign, at most 10MB. A Node.js `Buffer` works here. */\n file: FileInput;\n /** File name sent with the upload. Defaults to `document.pdf`. */\n fileName?: string;\n /** Label for the document. Defaults to the file name. */\n name?: string;\n}\n\nexport interface ListDocumentsParams {\n /** 1 to 100, default 20. */\n limit?: number;\n /** Default 0. */\n offset?: number;\n}\n\ninterface RequestOptions {\n method: \"GET\" | \"POST\";\n path: string;\n query?: Record<string, string | number | undefined>;\n body?: BodyInit;\n json?: unknown;\n expect?: \"json\" | \"binary\";\n}\n\nfunction toPdfBlob(file: FileInput): Blob {\n if (typeof Blob !== \"undefined\" && file instanceof Blob) {\n // The API rejects anything whose part type is not application/pdf.\n return file.type === \"application/pdf\"\n ? file\n : new Blob([file], { type: \"application/pdf\" });\n }\n if (file instanceof ArrayBuffer) {\n return new Blob([file], { type: \"application/pdf\" });\n }\n if (file instanceof Uint8Array) {\n // Copy into a plain ArrayBuffer-backed view so Blob accepts it everywhere.\n const copy = new Uint8Array(file.byteLength);\n copy.set(file);\n return new Blob([copy], { type: \"application/pdf\" });\n }\n throw new TypeError(\"file must be a Buffer, Uint8Array, ArrayBuffer or Blob.\");\n}\n\nclass Documents {\n constructor(private readonly client: SignYu) {}\n\n /** `POST /api/v1/documents`: upload a PDF and create a `PENDING` document. */\n create(params: CreateDocumentParams): Promise<CreatedDocument> {\n if (!params || params.file === undefined || params.file === null) {\n throw new TypeError(\"documents.create requires a `file`.\");\n }\n const form = new FormData();\n form.append(\"file\", toPdfBlob(params.file), params.fileName ?? \"document.pdf\");\n if (params.name !== undefined) form.append(\"name\", params.name);\n return this.client._request<CreatedDocument>({\n method: \"POST\",\n path: \"/api/v1/documents\",\n body: form,\n });\n }\n\n /** `GET /api/v1/documents`: your documents, most recent first. */\n list(params: ListDocumentsParams = {}): Promise<DocumentList> {\n return this.client._request<DocumentList>({\n method: \"GET\",\n path: \"/api/v1/documents\",\n query: { limit: params.limit, offset: params.offset },\n });\n }\n\n /** `GET /api/v1/documents/{documentId}`: status and per-signer progress. */\n get(documentId: string): Promise<Document> {\n return this.client._request<Document>({\n method: \"GET\",\n path: `/api/v1/documents/${encodeURIComponent(documentId)}`,\n });\n }\n\n /** `POST /api/v1/documents/{documentId}/signers`: add signers while `PENDING` (max 6 per document). */\n addSigners(documentId: string, signers: SignerInput[]): Promise<AddSignersResponse> {\n return this.client._request<AddSignersResponse>({\n method: \"POST\",\n path: `/api/v1/documents/${encodeURIComponent(documentId)}/signers`,\n json: { signers },\n });\n }\n\n /**\n * `POST /api/v1/documents/{documentId}/send`: deducts one credit per signer,\n * emails signing links and returns them. Not idempotent: call it once.\n */\n send(documentId: string): Promise<SendDocumentResponse> {\n return this.client._request<SendDocumentResponse>({\n method: \"POST\",\n path: `/api/v1/documents/${encodeURIComponent(documentId)}/send`,\n });\n }\n\n /**\n * `GET /api/v1/documents/{documentId}/certificate`: the completion\n * certificate and audit trail PDF as raw bytes. Only available once the\n * document is `COMPLETED` (otherwise `409 invalid_state`).\n */\n getCertificate(documentId: string): Promise<Uint8Array> {\n return this.client._request<Uint8Array>({\n method: \"GET\",\n path: `/api/v1/documents/${encodeURIComponent(documentId)}/certificate`,\n expect: \"binary\",\n });\n }\n}\n\nexport class SignYu {\n readonly documents: Documents;\n readonly webhooks: Webhooks = webhooks;\n readonly baseUrl: string;\n\n private readonly apiKey: string;\n private readonly timeoutMs: number;\n private readonly fetchImpl: typeof fetch;\n\n constructor(options: SignYuOptions) {\n if (!options || !options.apiKey) {\n throw new TypeError(\"SignYu requires an `apiKey`.\");\n }\n this.apiKey = options.apiKey;\n this.baseUrl = (options.baseUrl ?? DEFAULT_BASE_URL).replace(/\\/+$/, \"\");\n this.timeoutMs = options.timeoutMs ?? 60_000;\n const f = options.fetch ?? globalThis.fetch;\n if (typeof f !== \"function\") {\n throw new TypeError(\"No global fetch found. SignYu requires Node.js 18 or newer.\");\n }\n this.fetchImpl = f;\n this.documents = new Documents(this);\n }\n\n /** @internal */\n async _request<T>(opts: RequestOptions): Promise<T> {\n const url = new URL(this.baseUrl + opts.path);\n for (const [k, v] of Object.entries(opts.query ?? {})) {\n if (v !== undefined) url.searchParams.set(k, String(v));\n }\n\n const headers: Record<string, string> = {\n Authorization: `Bearer ${this.apiKey}`,\n Accept: opts.expect === \"binary\" ? \"application/pdf\" : \"application/json\",\n \"User-Agent\": `signyu-node/${VERSION}`,\n };\n let body = opts.body;\n if (opts.json !== undefined) {\n headers[\"Content-Type\"] = \"application/json\";\n body = JSON.stringify(opts.json);\n }\n\n let res: Response;\n try {\n res = await this.fetchImpl(url.toString(), {\n method: opts.method,\n headers,\n body,\n signal: AbortSignal.timeout(this.timeoutMs),\n });\n } catch (err) {\n const isTimeout =\n err instanceof Error && (err.name === \"TimeoutError\" || err.name === \"AbortError\");\n throw new SignYuError({\n status: 0,\n code: isTimeout ? \"timeout\" : \"connection_error\",\n message: isTimeout\n ? `Request timed out after ${this.timeoutMs}ms.`\n : `Could not reach the SignYu API: ${err instanceof Error ? err.message : String(err)}`,\n cause: err,\n });\n }\n\n if (!res.ok) {\n const text = await res.text().catch(() => \"\");\n let parsed: unknown = undefined;\n try {\n parsed = text ? JSON.parse(text) : undefined;\n } catch {\n parsed = text;\n }\n const errBody =\n parsed && typeof parsed === \"object\" ? (parsed as Record<string, unknown>) : {};\n const code =\n typeof errBody.error === \"string\"\n ? errBody.error\n : res.status === 429\n ? \"rate_limited\"\n : \"http_error\";\n const message =\n typeof errBody.message === \"string\"\n ? errBody.message\n : `SignYu API request failed with status ${res.status}.`;\n throw new SignYuError({ status: res.status, code, message, body: parsed });\n }\n\n if (opts.expect === \"binary\") {\n return new Uint8Array(await res.arrayBuffer()) as T;\n }\n return (await res.json()) as T;\n }\n}\n\nexport type { Documents };\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/errors.ts","../src/webhooks.ts","../src/version.ts","../src/client.ts"],"sourcesContent":["/**\n * Thrown for any non-2xx API response, network failure or timeout.\n *\n * `code` is the API's machine readable `error` field (for example\n * `insufficient_credits`). For responses without a JSON error body it is\n * `rate_limited` (429) or `http_error`; for network failures it is\n * `connection_error` and for timeouts `timeout`, both with `status` 0.\n */\nexport class SignYuError extends Error {\n readonly status: number;\n readonly code: string;\n /** Parsed response body, when there was one. */\n readonly body: unknown;\n\n constructor(opts: {\n status: number;\n code: string;\n message: string;\n body?: unknown;\n cause?: unknown;\n }) {\n super(opts.message);\n this.name = \"SignYuError\";\n this.status = opts.status;\n this.code = opts.code;\n this.body = opts.body;\n if (opts.cause !== undefined) {\n (this as { cause?: unknown }).cause = opts.cause;\n }\n }\n}\n\n/** Thrown by `webhooks.constructEvent` when the signature does not match. */\nexport class WebhookSignatureError extends Error {\n constructor(message = \"Webhook signature verification failed.\") {\n super(message);\n this.name = \"WebhookSignatureError\";\n }\n}\n","import { createHmac, timingSafeEqual } from \"node:crypto\";\nimport { WebhookSignatureError } from \"./errors\";\nimport type { WebhookEvent } from \"./types\";\n\n/** Header carrying the signature, `sha256=<hex>`. */\nexport const SIGNATURE_HEADER = \"X-SignSetu-Signature\";\n/** Header carrying the event type, for example `signer.signed`. */\nexport const EVENT_HEADER = \"X-SignSetu-Event\";\n\nexport type WebhookPayload = string | Uint8Array | ArrayBuffer;\n\nfunction toBuffer(payload: WebhookPayload): Buffer {\n if (typeof payload === \"string\") return Buffer.from(payload, \"utf8\");\n if (payload instanceof ArrayBuffer) return Buffer.from(new Uint8Array(payload));\n return Buffer.from(payload.buffer, payload.byteOffset, payload.byteLength);\n}\n\n/** Computes the `sha256=<hex>` header value SignYu sends for a raw body. */\nexport function computeSignature(payload: WebhookPayload, secret: string): string {\n const hex = createHmac(\"sha256\", secret).update(toBuffer(payload)).digest(\"hex\");\n return `sha256=${hex}`;\n}\n\n/**\n * Returns true when `signatureHeader` (the `X-SignSetu-Signature` value) is a\n * valid HMAC-SHA256 of the raw request body under `secret`. Pass the raw body\n * bytes exactly as received; a re-serialized object will not match.\n * Comparison is constant time.\n */\nexport function verifySignature(\n payload: WebhookPayload,\n signatureHeader: string | null | undefined,\n secret: string\n): boolean {\n if (!signatureHeader || !secret) return false;\n const expected = Buffer.from(computeSignature(payload, secret), \"utf8\");\n const received = Buffer.from(signatureHeader.trim(), \"utf8\");\n if (expected.length !== received.length) return false;\n return timingSafeEqual(expected, received);\n}\n\n/**\n * Verifies the signature and returns the parsed event. Throws\n * `WebhookSignatureError` if the signature is missing or invalid.\n */\nexport function constructEvent(\n payload: WebhookPayload,\n signatureHeader: string | null | undefined,\n secret: string\n): WebhookEvent {\n if (!verifySignature(payload, signatureHeader, secret)) {\n throw new WebhookSignatureError();\n }\n return JSON.parse(toBuffer(payload).toString(\"utf8\")) as WebhookEvent;\n}\n\nexport const webhooks = {\n SIGNATURE_HEADER,\n EVENT_HEADER,\n computeSignature,\n verifySignature,\n constructEvent,\n};\n\nexport type Webhooks = typeof webhooks;\n","// Keep in sync with package.json \"version\".\nexport const VERSION = \"0.2.0\";\n","import { SignYuError } from \"./errors\";\nimport { webhooks, type Webhooks } from \"./webhooks\";\nimport type {\n AddSignersResponse,\n CreatedDocument,\n Document,\n DocumentList,\n SendDocumentResponse,\n SignerInput,\n} from \"./types\";\nimport { VERSION } from \"./version\";\n\nexport const DEFAULT_BASE_URL = \"https://signyu.com\";\n\nexport interface SignYuOptions {\n /** Your secret API key, `sk_live_...`. Keep it server side. */\n apiKey: string;\n /** Defaults to `https://signyu.com`. */\n baseUrl?: string;\n /** Per-request timeout in milliseconds. Defaults to 60000. */\n timeoutMs?: number;\n /** Custom fetch implementation (defaults to the global `fetch`). */\n fetch?: typeof fetch;\n}\n\nexport type FileInput = Blob | Uint8Array | ArrayBuffer;\n\nexport interface CreateDocumentParams {\n /** The PDF to sign, at most 10MB. A Node.js `Buffer` works here. */\n file: FileInput;\n /** File name sent with the upload. Defaults to `document.pdf`. */\n fileName?: string;\n /** Label for the document. Defaults to the file name. */\n name?: string;\n /**\n * Email address that receives signer replies to SignYu's signing emails.\n * Defaults to your account's reply-to setting, then your login email.\n */\n replyTo?: string;\n}\n\nexport interface ListDocumentsParams {\n /** 1 to 100, default 20. */\n limit?: number;\n /** Default 0. */\n offset?: number;\n}\n\ninterface RequestOptions {\n method: \"GET\" | \"POST\";\n path: string;\n query?: Record<string, string | number | undefined>;\n body?: BodyInit;\n json?: unknown;\n expect?: \"json\" | \"binary\";\n}\n\nfunction toPdfBlob(file: FileInput): Blob {\n if (typeof Blob !== \"undefined\" && file instanceof Blob) {\n // The API rejects anything whose part type is not application/pdf.\n return file.type === \"application/pdf\"\n ? file\n : new Blob([file], { type: \"application/pdf\" });\n }\n if (file instanceof ArrayBuffer) {\n return new Blob([file], { type: \"application/pdf\" });\n }\n if (file instanceof Uint8Array) {\n // Copy into a plain ArrayBuffer-backed view so Blob accepts it everywhere.\n const copy = new Uint8Array(file.byteLength);\n copy.set(file);\n return new Blob([copy], { type: \"application/pdf\" });\n }\n throw new TypeError(\"file must be a Buffer, Uint8Array, ArrayBuffer or Blob.\");\n}\n\nclass Documents {\n constructor(private readonly client: SignYu) {}\n\n /** `POST /api/v1/documents`: upload a PDF and create a `PENDING` document. */\n create(params: CreateDocumentParams): Promise<CreatedDocument> {\n if (!params || params.file === undefined || params.file === null) {\n throw new TypeError(\"documents.create requires a `file`.\");\n }\n const form = new FormData();\n form.append(\"file\", toPdfBlob(params.file), params.fileName ?? \"document.pdf\");\n if (params.name !== undefined) form.append(\"name\", params.name);\n if (params.replyTo !== undefined) form.append(\"replyTo\", params.replyTo);\n return this.client._request<CreatedDocument>({\n method: \"POST\",\n path: \"/api/v1/documents\",\n body: form,\n });\n }\n\n /** `GET /api/v1/documents`: your documents, most recent first. */\n list(params: ListDocumentsParams = {}): Promise<DocumentList> {\n return this.client._request<DocumentList>({\n method: \"GET\",\n path: \"/api/v1/documents\",\n query: { limit: params.limit, offset: params.offset },\n });\n }\n\n /** `GET /api/v1/documents/{documentId}`: status and per-signer progress. */\n get(documentId: string): Promise<Document> {\n return this.client._request<Document>({\n method: \"GET\",\n path: `/api/v1/documents/${encodeURIComponent(documentId)}`,\n });\n }\n\n /** `POST /api/v1/documents/{documentId}/signers`: add signers while `PENDING` (max 6 per document). */\n addSigners(documentId: string, signers: SignerInput[]): Promise<AddSignersResponse> {\n return this.client._request<AddSignersResponse>({\n method: \"POST\",\n path: `/api/v1/documents/${encodeURIComponent(documentId)}/signers`,\n json: { signers },\n });\n }\n\n /**\n * `POST /api/v1/documents/{documentId}/send`: deducts one credit per signer,\n * emails signing links and returns them. Not idempotent: call it once.\n */\n send(documentId: string): Promise<SendDocumentResponse> {\n return this.client._request<SendDocumentResponse>({\n method: \"POST\",\n path: `/api/v1/documents/${encodeURIComponent(documentId)}/send`,\n });\n }\n\n /**\n * `GET /api/v1/documents/{documentId}/certificate`: the completion\n * certificate and audit trail PDF as raw bytes. Only available once the\n * document is `COMPLETED` (otherwise `409 invalid_state`).\n */\n getCertificate(documentId: string): Promise<Uint8Array> {\n return this.client._request<Uint8Array>({\n method: \"GET\",\n path: `/api/v1/documents/${encodeURIComponent(documentId)}/certificate`,\n expect: \"binary\",\n });\n }\n}\n\nexport class SignYu {\n readonly documents: Documents;\n readonly webhooks: Webhooks = webhooks;\n readonly baseUrl: string;\n\n private readonly apiKey: string;\n private readonly timeoutMs: number;\n private readonly fetchImpl: typeof fetch;\n\n constructor(options: SignYuOptions) {\n if (!options || !options.apiKey) {\n throw new TypeError(\"SignYu requires an `apiKey`.\");\n }\n this.apiKey = options.apiKey;\n this.baseUrl = (options.baseUrl ?? DEFAULT_BASE_URL).replace(/\\/+$/, \"\");\n this.timeoutMs = options.timeoutMs ?? 60_000;\n const f = options.fetch ?? globalThis.fetch;\n if (typeof f !== \"function\") {\n throw new TypeError(\"No global fetch found. SignYu requires Node.js 18 or newer.\");\n }\n this.fetchImpl = f;\n this.documents = new Documents(this);\n }\n\n /** @internal */\n async _request<T>(opts: RequestOptions): Promise<T> {\n const url = new URL(this.baseUrl + opts.path);\n for (const [k, v] of Object.entries(opts.query ?? {})) {\n if (v !== undefined) url.searchParams.set(k, String(v));\n }\n\n const headers: Record<string, string> = {\n Authorization: `Bearer ${this.apiKey}`,\n Accept: opts.expect === \"binary\" ? \"application/pdf\" : \"application/json\",\n \"User-Agent\": `signyu-node/${VERSION}`,\n };\n let body = opts.body;\n if (opts.json !== undefined) {\n headers[\"Content-Type\"] = \"application/json\";\n body = JSON.stringify(opts.json);\n }\n\n let res: Response;\n try {\n res = await this.fetchImpl(url.toString(), {\n method: opts.method,\n headers,\n body,\n signal: AbortSignal.timeout(this.timeoutMs),\n });\n } catch (err) {\n const isTimeout =\n err instanceof Error && (err.name === \"TimeoutError\" || err.name === \"AbortError\");\n throw new SignYuError({\n status: 0,\n code: isTimeout ? \"timeout\" : \"connection_error\",\n message: isTimeout\n ? `Request timed out after ${this.timeoutMs}ms.`\n : `Could not reach the SignYu API: ${err instanceof Error ? err.message : String(err)}`,\n cause: err,\n });\n }\n\n if (!res.ok) {\n const text = await res.text().catch(() => \"\");\n let parsed: unknown = undefined;\n try {\n parsed = text ? JSON.parse(text) : undefined;\n } catch {\n parsed = text;\n }\n const errBody =\n parsed && typeof parsed === \"object\" ? (parsed as Record<string, unknown>) : {};\n const code =\n typeof errBody.error === \"string\"\n ? errBody.error\n : res.status === 429\n ? \"rate_limited\"\n : \"http_error\";\n const message =\n typeof errBody.message === \"string\"\n ? errBody.message\n : `SignYu API request failed with status ${res.status}.`;\n throw new SignYuError({ status: res.status, code, message, body: parsed });\n }\n\n if (opts.expect === \"binary\") {\n return new Uint8Array(await res.arrayBuffer()) as T;\n }\n return (await res.json()) as T;\n }\n}\n\nexport type { Documents };\n"],"mappings":"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","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "signyu",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "Official Node.js SDK for the SignYu Aadhaar eSign API",
5
5
  "keywords": [
6
6
  "aadhaar",