signyu 0.2.0 → 0.3.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 +12 -2
- package/dist/index.cjs +7 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +20 -1
- package/dist/index.d.ts +20 -1
- package/dist/index.js +7 -1
- package/dist/index.js.map +1 -1
- package/package.json +6 -2
package/README.md
CHANGED
|
@@ -63,7 +63,7 @@ const signyu = new SignYu({
|
|
|
63
63
|
|
|
64
64
|
## Methods
|
|
65
65
|
|
|
66
|
-
### `documents.create({ file, fileName?, name?, replyTo? })`
|
|
66
|
+
### `documents.create({ file, fileName?, name?, replyTo?, notifySigners?, notifyOwner? })`
|
|
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
|
|
|
@@ -77,7 +77,17 @@ const doc = await signyu.documents.create({
|
|
|
77
77
|
console.log(doc.replyTo); // "legal@example.com"
|
|
78
78
|
```
|
|
79
79
|
|
|
80
|
-
|
|
80
|
+
`notifySigners: false` stops SignYu emailing signers for this document: no signing-request email and no completion email. Send each signer the `signUrl` (returned by `documents.send` and `documents.get`) from your own system instead. Signers can still download their signed copy on the signing page. `notifyOwner: false` stops the completion email to you, the account owner; use webhooks or `documents.get` instead. Both default to `true`.
|
|
81
|
+
|
|
82
|
+
```ts
|
|
83
|
+
const doc = await signyu.documents.create({
|
|
84
|
+
file: readFileSync("agreement.pdf"),
|
|
85
|
+
notifySigners: false,
|
|
86
|
+
notifyOwner: false,
|
|
87
|
+
});
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
Returns `{ documentId, name, status, replyTo, notifySigners, notifyOwner }`.
|
|
81
91
|
|
|
82
92
|
### `documents.list({ limit?, offset? })`
|
|
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.
|
|
96
|
+
var VERSION = "0.3.0";
|
|
97
97
|
|
|
98
98
|
// src/client.ts
|
|
99
99
|
var DEFAULT_BASE_URL = "https://signyu.com";
|
|
@@ -125,6 +125,12 @@ var Documents = class {
|
|
|
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
127
|
if (params.replyTo !== void 0) form.append("replyTo", params.replyTo);
|
|
128
|
+
if (params.notifySigners !== void 0) {
|
|
129
|
+
form.append("notifySigners", params.notifySigners ? "true" : "false");
|
|
130
|
+
}
|
|
131
|
+
if (params.notifyOwner !== void 0) {
|
|
132
|
+
form.append("notifyOwner", params.notifyOwner ? "true" : "false");
|
|
133
|
+
}
|
|
128
134
|
return this.client._request({
|
|
129
135
|
method: "POST",
|
|
130
136
|
path: "/api/v1/documents",
|
package/dist/index.cjs.map
CHANGED
|
@@ -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.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":[]}
|
|
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.3.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 * Set to `false` to stop SignYu emailing signers for this document: no\n * signing-request email and no completion email. Send each signer the\n * `signUrl` from your own system instead. Default `true`.\n */\n notifySigners?: boolean;\n /**\n * Set to `false` to stop SignYu emailing you (the account owner) when the\n * document is completed. Use webhooks or `documents.get` instead. Default `true`.\n */\n notifyOwner?: boolean;\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 if (params.notifySigners !== undefined) {\n form.append(\"notifySigners\", params.notifySigners ? \"true\" : \"false\");\n }\n if (params.notifyOwner !== undefined) {\n form.append(\"notifyOwner\", params.notifyOwner ? \"true\" : \"false\");\n }\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
|
@@ -41,6 +41,10 @@ interface CreatedDocument {
|
|
|
41
41
|
status: DocumentStatus;
|
|
42
42
|
/** Effective reply-to address used for signer emails. */
|
|
43
43
|
replyTo: string | null;
|
|
44
|
+
/** `false` when SignYu sends no emails to signers for this document. */
|
|
45
|
+
notifySigners: boolean;
|
|
46
|
+
/** `false` when SignYu sends no completion email to the account owner. */
|
|
47
|
+
notifyOwner: boolean;
|
|
44
48
|
}
|
|
45
49
|
interface SignerCounts {
|
|
46
50
|
total: number;
|
|
@@ -88,6 +92,10 @@ interface Document {
|
|
|
88
92
|
certificateUrl: string | null;
|
|
89
93
|
/** Effective reply-to address used for signer emails. */
|
|
90
94
|
replyTo: string | null;
|
|
95
|
+
/** `false` when SignYu sends no emails to signers for this document. */
|
|
96
|
+
notifySigners: boolean;
|
|
97
|
+
/** `false` when SignYu sends no completion email to the account owner. */
|
|
98
|
+
notifyOwner: boolean;
|
|
91
99
|
signers: DocumentSigner[];
|
|
92
100
|
}
|
|
93
101
|
interface AddedSigner {
|
|
@@ -203,6 +211,17 @@ interface CreateDocumentParams {
|
|
|
203
211
|
* Defaults to your account's reply-to setting, then your login email.
|
|
204
212
|
*/
|
|
205
213
|
replyTo?: string;
|
|
214
|
+
/**
|
|
215
|
+
* Set to `false` to stop SignYu emailing signers for this document: no
|
|
216
|
+
* signing-request email and no completion email. Send each signer the
|
|
217
|
+
* `signUrl` from your own system instead. Default `true`.
|
|
218
|
+
*/
|
|
219
|
+
notifySigners?: boolean;
|
|
220
|
+
/**
|
|
221
|
+
* Set to `false` to stop SignYu emailing you (the account owner) when the
|
|
222
|
+
* document is completed. Use webhooks or `documents.get` instead. Default `true`.
|
|
223
|
+
*/
|
|
224
|
+
notifyOwner?: boolean;
|
|
206
225
|
}
|
|
207
226
|
interface ListDocumentsParams {
|
|
208
227
|
/** 1 to 100, default 20. */
|
|
@@ -279,6 +298,6 @@ declare class WebhookSignatureError extends Error {
|
|
|
279
298
|
constructor(message?: string);
|
|
280
299
|
}
|
|
281
300
|
|
|
282
|
-
declare const VERSION = "0.
|
|
301
|
+
declare const VERSION = "0.3.0";
|
|
283
302
|
|
|
284
303
|
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
|
@@ -41,6 +41,10 @@ interface CreatedDocument {
|
|
|
41
41
|
status: DocumentStatus;
|
|
42
42
|
/** Effective reply-to address used for signer emails. */
|
|
43
43
|
replyTo: string | null;
|
|
44
|
+
/** `false` when SignYu sends no emails to signers for this document. */
|
|
45
|
+
notifySigners: boolean;
|
|
46
|
+
/** `false` when SignYu sends no completion email to the account owner. */
|
|
47
|
+
notifyOwner: boolean;
|
|
44
48
|
}
|
|
45
49
|
interface SignerCounts {
|
|
46
50
|
total: number;
|
|
@@ -88,6 +92,10 @@ interface Document {
|
|
|
88
92
|
certificateUrl: string | null;
|
|
89
93
|
/** Effective reply-to address used for signer emails. */
|
|
90
94
|
replyTo: string | null;
|
|
95
|
+
/** `false` when SignYu sends no emails to signers for this document. */
|
|
96
|
+
notifySigners: boolean;
|
|
97
|
+
/** `false` when SignYu sends no completion email to the account owner. */
|
|
98
|
+
notifyOwner: boolean;
|
|
91
99
|
signers: DocumentSigner[];
|
|
92
100
|
}
|
|
93
101
|
interface AddedSigner {
|
|
@@ -203,6 +211,17 @@ interface CreateDocumentParams {
|
|
|
203
211
|
* Defaults to your account's reply-to setting, then your login email.
|
|
204
212
|
*/
|
|
205
213
|
replyTo?: string;
|
|
214
|
+
/**
|
|
215
|
+
* Set to `false` to stop SignYu emailing signers for this document: no
|
|
216
|
+
* signing-request email and no completion email. Send each signer the
|
|
217
|
+
* `signUrl` from your own system instead. Default `true`.
|
|
218
|
+
*/
|
|
219
|
+
notifySigners?: boolean;
|
|
220
|
+
/**
|
|
221
|
+
* Set to `false` to stop SignYu emailing you (the account owner) when the
|
|
222
|
+
* document is completed. Use webhooks or `documents.get` instead. Default `true`.
|
|
223
|
+
*/
|
|
224
|
+
notifyOwner?: boolean;
|
|
206
225
|
}
|
|
207
226
|
interface ListDocumentsParams {
|
|
208
227
|
/** 1 to 100, default 20. */
|
|
@@ -279,6 +298,6 @@ declare class WebhookSignatureError extends Error {
|
|
|
279
298
|
constructor(message?: string);
|
|
280
299
|
}
|
|
281
300
|
|
|
282
|
-
declare const VERSION = "0.
|
|
301
|
+
declare const VERSION = "0.3.0";
|
|
283
302
|
|
|
284
303
|
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.
|
|
60
|
+
var VERSION = "0.3.0";
|
|
61
61
|
|
|
62
62
|
// src/client.ts
|
|
63
63
|
var DEFAULT_BASE_URL = "https://signyu.com";
|
|
@@ -89,6 +89,12 @@ var Documents = class {
|
|
|
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
91
|
if (params.replyTo !== void 0) form.append("replyTo", params.replyTo);
|
|
92
|
+
if (params.notifySigners !== void 0) {
|
|
93
|
+
form.append("notifySigners", params.notifySigners ? "true" : "false");
|
|
94
|
+
}
|
|
95
|
+
if (params.notifyOwner !== void 0) {
|
|
96
|
+
form.append("notifyOwner", params.notifyOwner ? "true" : "false");
|
|
97
|
+
}
|
|
92
98
|
return this.client._request({
|
|
93
99
|
method: "POST",
|
|
94
100
|
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.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":";AAQO,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,SAAS,YAAY,uBAAuB;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,MAAM,WAAW,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,SAAO,gBAAgB,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;AA6ChC,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,QAAI,OAAO,YAAY,OAAW,MAAK,OAAO,WAAW,OAAO,OAAO;AACvE,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/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.3.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 * Set to `false` to stop SignYu emailing signers for this document: no\n * signing-request email and no completion email. Send each signer the\n * `signUrl` from your own system instead. Default `true`.\n */\n notifySigners?: boolean;\n /**\n * Set to `false` to stop SignYu emailing you (the account owner) when the\n * document is completed. Use webhooks or `documents.get` instead. Default `true`.\n */\n notifyOwner?: boolean;\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 if (params.notifySigners !== undefined) {\n form.append(\"notifySigners\", params.notifySigners ? \"true\" : \"false\");\n }\n if (params.notifyOwner !== undefined) {\n form.append(\"notifyOwner\", params.notifyOwner ? \"true\" : \"false\");\n }\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.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "Official Node.js SDK for the SignYu Aadhaar eSign API",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"aadhaar",
|
|
@@ -13,8 +13,12 @@
|
|
|
13
13
|
"signyu"
|
|
14
14
|
],
|
|
15
15
|
"homepage": "https://signyu.com/api",
|
|
16
|
+
"repository": {
|
|
17
|
+
"type": "git",
|
|
18
|
+
"url": "git+https://github.com/signyu/signyu-node.git"
|
|
19
|
+
},
|
|
16
20
|
"bugs": {
|
|
17
|
-
"url": "https://
|
|
21
|
+
"url": "https://github.com/signyu/signyu-node/issues",
|
|
18
22
|
"email": "contact@mail.signyu.com"
|
|
19
23
|
},
|
|
20
24
|
"author": "SignYu <contact@mail.signyu.com> (https://signyu.com)",
|