@timbro/invoices 0.7.0-next.30
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 +308 -0
- package/dist/artifact-headers.d.ts +9 -0
- package/dist/artifact-headers.d.ts.map +1 -0
- package/dist/artifact-headers.js +43 -0
- package/dist/certificate-custody-import.d.ts +13 -0
- package/dist/certificate-custody-import.d.ts.map +1 -0
- package/dist/certificate-custody-import.js +30 -0
- package/dist/certificate-custody-readiness.d.ts +6 -0
- package/dist/certificate-custody-readiness.d.ts.map +1 -0
- package/dist/certificate-custody-readiness.js +13 -0
- package/dist/collection.d.ts +13 -0
- package/dist/collection.d.ts.map +1 -0
- package/dist/collection.js +21 -0
- package/dist/direct-connection.d.ts +74 -0
- package/dist/direct-connection.d.ts.map +1 -0
- package/dist/direct-connection.js +192 -0
- package/dist/document-node.d.ts +15 -0
- package/dist/document-node.d.ts.map +1 -0
- package/dist/document-node.js +67 -0
- package/dist/document-worker-protocol.d.ts +30 -0
- package/dist/document-worker-protocol.d.ts.map +1 -0
- package/dist/document-worker-protocol.js +103 -0
- package/dist/document-worker.d.ts +2 -0
- package/dist/document-worker.d.ts.map +1 -0
- package/dist/document-worker.js +71 -0
- package/dist/document.d.ts +38 -0
- package/dist/document.d.ts.map +1 -0
- package/dist/document.js +204 -0
- package/dist/fiscal-delivery.d.ts +12 -0
- package/dist/fiscal-delivery.d.ts.map +1 -0
- package/dist/fiscal-delivery.js +45 -0
- package/dist/fiscal-engine-runtime.manifest.json +637 -0
- package/dist/fiscal-engine-runtime.provenance.json +1010 -0
- package/dist/fiscal-error.d.ts +23 -0
- package/dist/fiscal-error.d.ts.map +1 -0
- package/dist/fiscal-error.js +36 -0
- package/dist/fiscal-numbering-readiness.d.ts +6 -0
- package/dist/fiscal-numbering-readiness.d.ts.map +1 -0
- package/dist/fiscal-numbering-readiness.js +13 -0
- package/dist/fiscal-operation-timing.d.ts +9 -0
- package/dist/fiscal-operation-timing.d.ts.map +1 -0
- package/dist/fiscal-operation-timing.js +22 -0
- package/dist/fiscal-operation.d.ts +112 -0
- package/dist/fiscal-operation.d.ts.map +1 -0
- package/dist/fiscal-operation.js +193 -0
- package/dist/fiscal-receipt.d.ts +19 -0
- package/dist/fiscal-receipt.d.ts.map +1 -0
- package/dist/fiscal-receipt.js +66 -0
- package/dist/generated/index.d.ts +5 -0
- package/dist/generated/index.d.ts.map +1 -0
- package/dist/generated/index.js +4 -0
- package/dist/generated/problem-catalog.d.ts +7 -0
- package/dist/generated/problem-catalog.d.ts.map +1 -0
- package/dist/generated/problem-catalog.js +198 -0
- package/dist/generated/sdk.gen.d.ts +240 -0
- package/dist/generated/sdk.gen.d.ts.map +1 -0
- package/dist/generated/sdk.gen.js +4486 -0
- package/dist/generated/types.gen.d.ts +6906 -0
- package/dist/generated/types.gen.d.ts.map +1 -0
- package/dist/generated/types.gen.js +2 -0
- package/dist/generated/zod.gen.d.ts +146666 -0
- package/dist/generated/zod.gen.d.ts.map +1 -0
- package/dist/generated/zod.gen.js +25077 -0
- package/dist/generated-operation-client.d.ts +47 -0
- package/dist/generated-operation-client.d.ts.map +1 -0
- package/dist/generated-operation-client.js +112 -0
- package/dist/generated-problem.d.ts +12 -0
- package/dist/generated-problem.d.ts.map +1 -0
- package/dist/generated-problem.js +37 -0
- package/dist/hosted-tenant.d.ts +38 -0
- package/dist/hosted-tenant.d.ts.map +1 -0
- package/dist/hosted-tenant.js +67 -0
- package/dist/hosted-workspace-transport.d.ts +15 -0
- package/dist/hosted-workspace-transport.d.ts.map +1 -0
- package/dist/hosted-workspace-transport.js +15 -0
- package/dist/idempotency-key.d.ts +3 -0
- package/dist/idempotency-key.d.ts.map +1 -0
- package/dist/idempotency-key.js +11 -0
- package/dist/index.d.ts +42 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +14 -0
- package/dist/printed-representation.d.ts +23 -0
- package/dist/printed-representation.d.ts.map +1 -0
- package/dist/printed-representation.js +135 -0
- package/dist/problem-contract.d.ts +265 -0
- package/dist/problem-contract.d.ts.map +1 -0
- package/dist/problem-contract.js +25 -0
- package/dist/public-case.d.ts +15 -0
- package/dist/public-case.d.ts.map +1 -0
- package/dist/public-case.js +26 -0
- package/dist/received-documents.d.ts +35 -0
- package/dist/received-documents.d.ts.map +1 -0
- package/dist/received-documents.js +83 -0
- package/dist/sha256.d.ts +2 -0
- package/dist/sha256.d.ts.map +1 -0
- package/dist/sha256.js +6 -0
- package/dist/signed-document.d.ts +15 -0
- package/dist/signed-document.d.ts.map +1 -0
- package/dist/signed-document.js +57 -0
- package/dist/source-command-validation.d.ts +3 -0
- package/dist/source-command-validation.d.ts.map +1 -0
- package/dist/source-command-validation.js +14 -0
- package/dist/source-connection-activation.d.ts +18 -0
- package/dist/source-connection-activation.d.ts.map +1 -0
- package/dist/source-connection-activation.js +41 -0
- package/dist/source-connection-transport.d.ts +8 -0
- package/dist/source-connection-transport.d.ts.map +1 -0
- package/dist/source-connection-transport.js +8 -0
- package/dist/source-connection.d.ts +18 -0
- package/dist/source-connection.d.ts.map +1 -0
- package/dist/source-connection.js +35 -0
- package/dist/stamp-server-http-transport.d.ts +23 -0
- package/dist/stamp-server-http-transport.d.ts.map +1 -0
- package/dist/stamp-server-http-transport.js +179 -0
- package/dist/timbro-client.d.ts +124 -0
- package/dist/timbro-client.d.ts.map +1 -0
- package/dist/timbro-client.js +72 -0
- package/dist/timbro_fiscal_engine.js +239 -0
- package/dist/timbro_fiscal_engine_bg.wasm +0 -0
- package/dist/transport-contract.d.ts +16 -0
- package/dist/transport-contract.d.ts.map +1 -0
- package/dist/transport-contract.js +1 -0
- package/dist/webhook-delivery.d.ts +14 -0
- package/dist/webhook-delivery.d.ts.map +1 -0
- package/dist/webhook-delivery.js +32 -0
- package/dist/webhook-event.d.ts +2711 -0
- package/dist/webhook-event.d.ts.map +1 -0
- package/dist/webhook-event.js +15 -0
- package/dist/webhook-registration.d.ts +12 -0
- package/dist/webhook-registration.d.ts.map +1 -0
- package/dist/webhook-registration.js +37 -0
- package/dist/webhook-replay.d.ts +12 -0
- package/dist/webhook-replay.d.ts.map +1 -0
- package/dist/webhook-replay.js +27 -0
- package/dist/webhook-verification.d.ts +25 -0
- package/dist/webhook-verification.d.ts.map +1 -0
- package/dist/webhook-verification.js +53 -0
- package/dist/workspace-session-transport.d.ts +8 -0
- package/dist/workspace-session-transport.d.ts.map +1 -0
- package/dist/workspace-session-transport.js +11 -0
- package/dist/workspace.d.ts +74 -0
- package/dist/workspace.d.ts.map +1 -0
- package/dist/workspace.js +278 -0
- package/package.json +73 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"webhook-event.d.ts","sourceRoot":"","sources":["../src/webhook-event.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;oBAAwB,CAAC;AAExD,eAAO,MAAM,2BAA2B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;oBAAiC,CAAC;AAE1E,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAE9D,MAAM,MAAM,qBAAqB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,2BAA2B,CAAC,CAAC;AAEhF,iFAAiF;AACjF,eAAO,MAAM,2BAA2B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;sBAGtC,CAAC;AAEH,MAAM,MAAM,qBAAqB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,2BAA2B,CAAC,CAAC;AAEhF,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,OAAO,GAAG,YAAY,CAEhE;AAED,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,OAAO,GAAG,qBAAqB,CAIlF"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { zReceptionWebhookEventEnvelope, zWebhookEventEnvelope } from "./generated/index.js";
|
|
3
|
+
export const webhookEventSchema = zWebhookEventEnvelope;
|
|
4
|
+
export const receptionWebhookEventSchema = zReceptionWebhookEventEnvelope;
|
|
5
|
+
/** Every notification an endpoint is delivered, told apart by its event type. */
|
|
6
|
+
export const deliveredWebhookEventSchema = z.union([
|
|
7
|
+
webhookEventSchema,
|
|
8
|
+
receptionWebhookEventSchema,
|
|
9
|
+
]);
|
|
10
|
+
export function parseWebhookEvent(payload) {
|
|
11
|
+
return webhookEventSchema.parse(typeof payload === "string" ? JSON.parse(payload) : payload);
|
|
12
|
+
}
|
|
13
|
+
export function parseDeliveredWebhookEvent(payload) {
|
|
14
|
+
return deliveredWebhookEventSchema.parse(typeof payload === "string" ? JSON.parse(payload) : payload);
|
|
15
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { type WebhookEndpointRegistration as GeneratedWebhookEndpointRegistration } from "./generated/index.ts";
|
|
2
|
+
import type { Client } from "./generated-operation-client.ts";
|
|
3
|
+
import { type ReadonlyCamelCase } from "./public-case.ts";
|
|
4
|
+
export type WebhookRegistrationCommand = {
|
|
5
|
+
readonly url: string;
|
|
6
|
+
readonly idempotencyKey: string;
|
|
7
|
+
readonly description?: string;
|
|
8
|
+
readonly signal?: AbortSignal;
|
|
9
|
+
};
|
|
10
|
+
export type WebhookRegistration = ReadonlyCamelCase<GeneratedWebhookEndpointRegistration>;
|
|
11
|
+
export declare function registerWebhookResource(client: Client, command: WebhookRegistrationCommand): Promise<WebhookRegistration>;
|
|
12
|
+
//# sourceMappingURL=webhook-registration.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"webhook-registration.d.ts","sourceRoot":"","sources":["../src/webhook-registration.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,2BAA2B,IAAI,oCAAoC,EAEzE,MAAM,sBAAsB,CAAC;AAC9B,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,iCAAiC,CAAC;AAE9D,OAAO,EAAE,KAAK,iBAAiB,EAAgB,MAAM,kBAAkB,CAAC;AAExE,MAAM,MAAM,0BAA0B,GAAG;IACvC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,CAAC;CAC/B,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG,iBAAiB,CAAC,oCAAoC,CAAC,CAAC;AAE1F,wBAAsB,uBAAuB,CAC3C,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,0BAA0B,GAClC,OAAO,CAAC,mBAAmB,CAAC,CAyC9B"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { registerWebhookEndpoint, } from "./generated/index.js";
|
|
2
|
+
import { throwGeneratedProblem } from "./generated-problem.js";
|
|
3
|
+
import { toPublicCase } from "./public-case.js";
|
|
4
|
+
export async function registerWebhookResource(client, command) {
|
|
5
|
+
if (!/^[A-Za-z0-9._:-]{16,255}$/u.test(command.idempotencyKey)) {
|
|
6
|
+
throw new TypeError("idempotencyKey must contain 16–255 letters, digits, dots, underscores, colons, or hyphens");
|
|
7
|
+
}
|
|
8
|
+
const destination = URL.parse(command.url);
|
|
9
|
+
if (destination === null ||
|
|
10
|
+
destination.protocol !== "https:" ||
|
|
11
|
+
destination.username !== "" ||
|
|
12
|
+
destination.password !== "" ||
|
|
13
|
+
destination.hash !== "" ||
|
|
14
|
+
/\s/u.test(command.url) ||
|
|
15
|
+
[...command.url].length > 2048) {
|
|
16
|
+
throw new TypeError("url must be an HTTPS callback without credentials, a fragment, or whitespace");
|
|
17
|
+
}
|
|
18
|
+
if (command.description !== undefined &&
|
|
19
|
+
(command.description.trim() !== command.description ||
|
|
20
|
+
command.description === "" ||
|
|
21
|
+
[...command.description].length > 200)) {
|
|
22
|
+
throw new TypeError("description must contain 1–200 characters without surrounding whitespace");
|
|
23
|
+
}
|
|
24
|
+
const response = await registerWebhookEndpoint({
|
|
25
|
+
client,
|
|
26
|
+
headers: { "Idempotency-Key": command.idempotencyKey },
|
|
27
|
+
body: {
|
|
28
|
+
url: command.url,
|
|
29
|
+
...(command.description === undefined ? {} : { description: command.description }),
|
|
30
|
+
},
|
|
31
|
+
...(command.signal === undefined ? {} : { signal: command.signal }),
|
|
32
|
+
});
|
|
33
|
+
if (response.status !== 200 && response.status !== 201) {
|
|
34
|
+
throwGeneratedProblem(response, "Webhook registration failed");
|
|
35
|
+
}
|
|
36
|
+
return toPublicCase(response.body);
|
|
37
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { type WebhookReplayResource as GeneratedWebhookReplayResource } from "./generated/index.ts";
|
|
2
|
+
import type { Client } from "./generated-operation-client.ts";
|
|
3
|
+
import { type ReadonlyCamelCase } from "./public-case.ts";
|
|
4
|
+
export type WebhookReplayCommand = {
|
|
5
|
+
readonly webhookEndpointId: string;
|
|
6
|
+
readonly eventIds: readonly string[];
|
|
7
|
+
readonly idempotencyKey: string;
|
|
8
|
+
readonly signal?: AbortSignal;
|
|
9
|
+
};
|
|
10
|
+
export type WebhookReplay = ReadonlyCamelCase<GeneratedWebhookReplayResource>;
|
|
11
|
+
export declare function replayWebhookResource(client: Client, command: WebhookReplayCommand): Promise<WebhookReplay>;
|
|
12
|
+
//# sourceMappingURL=webhook-replay.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"webhook-replay.d.ts","sourceRoot":"","sources":["../src/webhook-replay.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,qBAAqB,IAAI,8BAA8B,EAI7D,MAAM,sBAAsB,CAAC;AAC9B,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,iCAAiC,CAAC;AAG9D,OAAO,EAAE,KAAK,iBAAiB,EAAgB,MAAM,kBAAkB,CAAC;AAExE,MAAM,MAAM,oBAAoB,GAAG;IACjC,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAC;IACnC,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;IACrC,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,CAAC;CAC/B,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG,iBAAiB,CAAC,8BAA8B,CAAC,CAAC;AAE9E,wBAAsB,qBAAqB,CACzC,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,oBAAoB,GAC5B,OAAO,CAAC,aAAa,CAAC,CA4BxB"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { replayWebhookEvents, zRegisteredWebhookEndpoint, zReplayEventIdsScope, } from "./generated/index.js";
|
|
2
|
+
import { throwGeneratedProblem } from "./generated-problem.js";
|
|
3
|
+
import { isValidIdempotencyKey } from "./idempotency-key.js";
|
|
4
|
+
import { toPublicCase } from "./public-case.js";
|
|
5
|
+
export async function replayWebhookResource(client, command) {
|
|
6
|
+
if (!isValidIdempotencyKey(command.idempotencyKey)) {
|
|
7
|
+
throw new TypeError("idempotencyKey must contain 16–255 letters, digits, dots, underscores, colons, or hyphens");
|
|
8
|
+
}
|
|
9
|
+
const request = {
|
|
10
|
+
path: { webhook_endpoint_id: command.webhookEndpointId },
|
|
11
|
+
headers: { "Idempotency-Key": command.idempotencyKey },
|
|
12
|
+
body: { webhook_event_ids: [...command.eventIds] },
|
|
13
|
+
};
|
|
14
|
+
if (!(zRegisteredWebhookEndpoint.shape.id.safeParse(command.webhookEndpointId).success &&
|
|
15
|
+
zReplayEventIdsScope.safeParse(request.body).success)) {
|
|
16
|
+
throw new TypeError("webhookEndpointId must be a UUID; eventIds must contain 1–100 UUIDs");
|
|
17
|
+
}
|
|
18
|
+
const response = await replayWebhookEvents({
|
|
19
|
+
client,
|
|
20
|
+
...request,
|
|
21
|
+
...(command.signal === undefined ? {} : { signal: command.signal }),
|
|
22
|
+
});
|
|
23
|
+
if (response.status !== 200 && response.status !== 201) {
|
|
24
|
+
throwGeneratedProblem(response, "Webhook replay failed");
|
|
25
|
+
}
|
|
26
|
+
return toPublicCase(response.body);
|
|
27
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { type DeliveredWebhookEvent } from "./webhook-event.ts";
|
|
2
|
+
export type WebhookVerificationRejection = "invalid_secret" | "missing_header" | "malformed_header" | "stale_timestamp" | "future_timestamp" | "signature_mismatch" | "unreadable_envelope" | "id_mismatch";
|
|
3
|
+
export type WebhookVerificationErrorDetail = ErrorOptions & {
|
|
4
|
+
readonly rejection: WebhookVerificationRejection;
|
|
5
|
+
};
|
|
6
|
+
export declare class WebhookVerificationError extends Error {
|
|
7
|
+
readonly rejection: WebhookVerificationRejection;
|
|
8
|
+
constructor(message: string, detail: WebhookVerificationErrorDetail);
|
|
9
|
+
}
|
|
10
|
+
export type WebhookDeliveryHeaders = Readonly<Record<string, string | readonly string[] | undefined>>;
|
|
11
|
+
export type WebhookVerificationCommand = {
|
|
12
|
+
readonly body: string;
|
|
13
|
+
readonly headers: WebhookDeliveryHeaders;
|
|
14
|
+
readonly nowSeconds?: number | undefined;
|
|
15
|
+
} & ({
|
|
16
|
+
readonly secret: string;
|
|
17
|
+
} | {
|
|
18
|
+
readonly secrets: readonly string[];
|
|
19
|
+
});
|
|
20
|
+
/**
|
|
21
|
+
* Verifies a Standard Webhooks delivery over the exact bytes the receiver was sent.
|
|
22
|
+
* Re-serializing a parsed body before verifying changes those bytes and always rejects.
|
|
23
|
+
*/
|
|
24
|
+
export declare function verifyWebhookDelivery(command: WebhookVerificationCommand): Promise<DeliveredWebhookEvent>;
|
|
25
|
+
//# sourceMappingURL=webhook-verification.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"webhook-verification.d.ts","sourceRoot":"","sources":["../src/webhook-verification.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,qBAAqB,EAA8B,MAAM,oBAAoB,CAAC;AAE5F,MAAM,MAAM,4BAA4B,GACpC,gBAAgB,GAChB,gBAAgB,GAChB,kBAAkB,GAClB,iBAAiB,GACjB,kBAAkB,GAClB,oBAAoB,GACpB,qBAAqB,GACrB,aAAa,CAAC;AAElB,MAAM,MAAM,8BAA8B,GAAG,YAAY,GAAG;IAC1D,QAAQ,CAAC,SAAS,EAAE,4BAA4B,CAAC;CAClD,CAAC;AAEF,qBAAa,wBAAyB,SAAQ,KAAK;IACjD,QAAQ,CAAC,SAAS,EAAE,4BAA4B,CAAC;IAEjD,YAAY,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,8BAA8B,EAIlE;CACF;AAED,MAAM,MAAM,sBAAsB,GAAG,QAAQ,CAC3C,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,MAAM,EAAE,GAAG,SAAS,CAAC,CACvD,CAAC;AAEF,MAAM,MAAM,0BAA0B,GAAG;IACvC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,sBAAsB,CAAC;IACzC,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC1C,GAAG,CAAC;IAAE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAA;CAAE,CAAC,CAAC;AAE5E;;;GAGG;AACH,wBAAsB,qBAAqB,CACzC,OAAO,EAAE,0BAA0B,GAClC,OAAO,CAAC,qBAAqB,CAAC,CA6BhC"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { StandardWebhookVerificationError, verifyStandardWebhookSignature } from "@timbro/protocol";
|
|
2
|
+
import { parseDeliveredWebhookEvent } from "./webhook-event.js";
|
|
3
|
+
export class WebhookVerificationError extends Error {
|
|
4
|
+
rejection;
|
|
5
|
+
constructor(message, detail) {
|
|
6
|
+
super(message, detail);
|
|
7
|
+
this.name = "WebhookVerificationError";
|
|
8
|
+
this.rejection = detail.rejection;
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Verifies a Standard Webhooks delivery over the exact bytes the receiver was sent.
|
|
13
|
+
* Re-serializing a parsed body before verifying changes those bytes and always rejects.
|
|
14
|
+
*/
|
|
15
|
+
export async function verifyWebhookDelivery(command) {
|
|
16
|
+
const secrets = "secret" in command ? [command.secret] : command.secrets;
|
|
17
|
+
let webhookId;
|
|
18
|
+
try {
|
|
19
|
+
({ webhookId } = await verifyStandardWebhookSignature({
|
|
20
|
+
body: new TextEncoder().encode(command.body),
|
|
21
|
+
headers: command.headers,
|
|
22
|
+
secrets,
|
|
23
|
+
nowSeconds: command.nowSeconds,
|
|
24
|
+
}));
|
|
25
|
+
}
|
|
26
|
+
catch (cause) {
|
|
27
|
+
if (cause instanceof StandardWebhookVerificationError) {
|
|
28
|
+
throw new WebhookVerificationError(cause.message, {
|
|
29
|
+
rejection: cause.rejection,
|
|
30
|
+
cause,
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
throw cause;
|
|
34
|
+
}
|
|
35
|
+
const event = readEnvelope(command.body);
|
|
36
|
+
if (event.id !== webhookId) {
|
|
37
|
+
throw new WebhookVerificationError("webhook-id does not carry the envelope id", {
|
|
38
|
+
rejection: "id_mismatch",
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
return event;
|
|
42
|
+
}
|
|
43
|
+
function readEnvelope(body) {
|
|
44
|
+
try {
|
|
45
|
+
return parseDeliveredWebhookEvent(body);
|
|
46
|
+
}
|
|
47
|
+
catch (cause) {
|
|
48
|
+
throw new WebhookVerificationError("the signed body is not a Timbro webhook event", {
|
|
49
|
+
rejection: "unreadable_envelope",
|
|
50
|
+
cause,
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { TimbroTransport } from "./transport-contract.ts";
|
|
2
|
+
export type WorkspaceSessionTransportOptions = {
|
|
3
|
+
readonly stampServerOrigin: string;
|
|
4
|
+
readonly fetch?: typeof globalThis.fetch;
|
|
5
|
+
readonly maxBinaryResponseBytes?: number;
|
|
6
|
+
};
|
|
7
|
+
export declare function createWorkspaceSessionTransport(options: WorkspaceSessionTransportOptions): TimbroTransport;
|
|
8
|
+
//# sourceMappingURL=workspace-session-transport.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workspace-session-transport.d.ts","sourceRoot":"","sources":["../src/workspace-session-transport.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAE/D,MAAM,MAAM,gCAAgC,GAAG;IAC7C,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAC;IACnC,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,UAAU,CAAC,KAAK,CAAC;IACzC,QAAQ,CAAC,sBAAsB,CAAC,EAAE,MAAM,CAAC;CAC1C,CAAC;AAEF,wBAAgB,+BAA+B,CAC7C,OAAO,EAAE,gCAAgC,GACxC,eAAe,CASjB"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { createStampServerHttpTransport } from "./stamp-server-http-transport.js";
|
|
2
|
+
export function createWorkspaceSessionTransport(options) {
|
|
3
|
+
return createStampServerHttpTransport({
|
|
4
|
+
stampServerOrigin: options.stampServerOrigin,
|
|
5
|
+
authentication: { mode: "workspace_session" },
|
|
6
|
+
...(options.fetch === undefined ? {} : { fetch: options.fetch }),
|
|
7
|
+
...(options.maxBinaryResponseBytes === undefined
|
|
8
|
+
? {}
|
|
9
|
+
: { maxBinaryResponseBytes: options.maxBinaryResponseBytes }),
|
|
10
|
+
});
|
|
11
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { type DirectConnectionWorkspaceOperations } from "./direct-connection.ts";
|
|
2
|
+
import { type ElectronicFiscalDocumentType, type FiscalArtifactKind, type PrintedRepresentationA4ProfileVersion, type PrintedRepresentationProfile, type PrintedRepresentationReceiptProfileVersion, type WorkspaceFiscalOperationPage, type WorkspaceFiscalOperationResource } from "./generated/index.ts";
|
|
3
|
+
/** Workspace artifact safety ceiling; larger artifacts are rejected before buffering. */
|
|
4
|
+
export declare const WORKSPACE_ARTIFACT_MAX_BYTES: number;
|
|
5
|
+
/** Options for a Workspace client. The default is the current browser origin. */
|
|
6
|
+
export type WorkspaceClientOptions = {
|
|
7
|
+
/** An explicit Timbro origin for dedicated deployments and tests. */
|
|
8
|
+
readonly baseUrl?: string;
|
|
9
|
+
/** A fetch implementation for tests or a dedicated runtime. */
|
|
10
|
+
readonly fetch?: typeof globalThis.fetch;
|
|
11
|
+
};
|
|
12
|
+
export type WorkspaceFiscalOperationListCommand = {
|
|
13
|
+
readonly organizationId: string;
|
|
14
|
+
readonly cursor?: string;
|
|
15
|
+
readonly limit?: number;
|
|
16
|
+
readonly signal?: AbortSignal;
|
|
17
|
+
/** Maximum number of pages read by listAll; list ignores this traversal-only option. */
|
|
18
|
+
readonly maxPages?: number;
|
|
19
|
+
};
|
|
20
|
+
export type WorkspaceFiscalOperationIdentity = {
|
|
21
|
+
readonly organizationId: string;
|
|
22
|
+
readonly fiscalOperationId: string;
|
|
23
|
+
};
|
|
24
|
+
export type WorkspaceFiscalOperationCommand = WorkspaceFiscalOperationIdentity & {
|
|
25
|
+
/** Cursor and limit page the operation's timeline. */
|
|
26
|
+
readonly cursor?: string;
|
|
27
|
+
readonly limit?: number;
|
|
28
|
+
readonly signal?: AbortSignal;
|
|
29
|
+
};
|
|
30
|
+
export type WorkspaceFiscalArtifactCommand = WorkspaceFiscalOperationIdentity & {
|
|
31
|
+
readonly kind: FiscalArtifactKind;
|
|
32
|
+
readonly signal?: AbortSignal;
|
|
33
|
+
};
|
|
34
|
+
/** Verified bytes and identity metadata returned by a Workspace artifact retrieval. */
|
|
35
|
+
export type WorkspaceFiscalArtifact = {
|
|
36
|
+
readonly artifactId: string;
|
|
37
|
+
readonly artifactKind: FiscalArtifactKind;
|
|
38
|
+
readonly bytes: Uint8Array;
|
|
39
|
+
readonly byteLength: number;
|
|
40
|
+
readonly contentSha256: string;
|
|
41
|
+
readonly contentDisposition: string;
|
|
42
|
+
readonly cacheControl: string;
|
|
43
|
+
readonly createdAt: string;
|
|
44
|
+
readonly fiscalOperationId: string;
|
|
45
|
+
readonly mediaType: "application/pdf" | "application/xml";
|
|
46
|
+
readonly signedSourceSha256?: string;
|
|
47
|
+
readonly printedRepresentation?: {
|
|
48
|
+
readonly fiscalDocumentType: ElectronicFiscalDocumentType;
|
|
49
|
+
readonly fiscalNumber: string;
|
|
50
|
+
readonly paginationPlanSha256: string;
|
|
51
|
+
readonly profile: PrintedRepresentationProfile;
|
|
52
|
+
readonly profileVersion: PrintedRepresentationA4ProfileVersion | PrintedRepresentationReceiptProfileVersion;
|
|
53
|
+
readonly rendererIdentity: string;
|
|
54
|
+
readonly pageCount: number;
|
|
55
|
+
};
|
|
56
|
+
};
|
|
57
|
+
export type WorkspaceFiscalOperations = {
|
|
58
|
+
readonly list: (command: WorkspaceFiscalOperationListCommand) => Promise<WorkspaceFiscalOperationPage>;
|
|
59
|
+
readonly listAll: (command: WorkspaceFiscalOperationListCommand) => AsyncIterable<WorkspaceFiscalOperationPage["data"][number]>;
|
|
60
|
+
readonly get: (command: WorkspaceFiscalOperationCommand) => Promise<WorkspaceFiscalOperationResource>;
|
|
61
|
+
readonly artifacts: {
|
|
62
|
+
readonly retrieve: (command: WorkspaceFiscalArtifactCommand) => Promise<WorkspaceFiscalArtifact>;
|
|
63
|
+
};
|
|
64
|
+
};
|
|
65
|
+
export type WorkspaceClient = {
|
|
66
|
+
readonly fiscalOperations: WorkspaceFiscalOperations;
|
|
67
|
+
readonly directConnections: DirectConnectionWorkspaceOperations;
|
|
68
|
+
};
|
|
69
|
+
/**
|
|
70
|
+
* Creates a Workspace client authenticated by the browser's same-origin session cookie.
|
|
71
|
+
* Importing this module does not load the document evaluator or any Wasm asset.
|
|
72
|
+
*/
|
|
73
|
+
export declare function createWorkspaceClient(options?: WorkspaceClientOptions): WorkspaceClient;
|
|
74
|
+
//# sourceMappingURL=workspace.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workspace.d.ts","sourceRoot":"","sources":["../src/workspace.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,278 @@
|
|
|
1
|
+
// biome-ignore-all lint/correctness/useQwikValidLexicalScope: this module is a plain SDK client, not a Qwik component.
|
|
2
|
+
import { walkCollectionPages } from "./collection.js";
|
|
3
|
+
import { createDirectConnectionWorkspaceOperations, } from "./direct-connection.js";
|
|
4
|
+
import { FiscalError } from "./fiscal-error.js";
|
|
5
|
+
import { listOrganizationFiscalOperations, readOrganizationFiscalOperation, retrieveWorkspaceFiscalArtifact, zElectronicFiscalDocumentType, } from "./generated/index.js";
|
|
6
|
+
import { createGeneratedOperationClient } from "./generated-operation-client.js";
|
|
7
|
+
import { throwGeneratedProblem } from "./generated-problem.js";
|
|
8
|
+
import { isCanonicalRfc3339MillisecondUtc } from "./printed-representation.js";
|
|
9
|
+
import { digestSha256Hex } from "./sha256.js";
|
|
10
|
+
import { createWorkspaceSessionTransport } from "./workspace-session-transport.js";
|
|
11
|
+
const SHA256_PATTERN = /^[0-9a-f]{64}$/;
|
|
12
|
+
const UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
|
13
|
+
const FISCAL_NUMBER_PATTERN = /^E(?:31|32|33|34|41|43|44|45|46|47)[0-9]{10}$/;
|
|
14
|
+
const POSITIVE_INTEGER_PATTERN = /^[0-9]+$/;
|
|
15
|
+
const MAX_SAFE_INT = Number.MAX_SAFE_INTEGER;
|
|
16
|
+
/** Workspace artifact safety ceiling; larger artifacts are rejected before buffering. */
|
|
17
|
+
export const WORKSPACE_ARTIFACT_MAX_BYTES = 16 * 1024 * 1024;
|
|
18
|
+
/**
|
|
19
|
+
* Creates a Workspace client authenticated by the browser's same-origin session cookie.
|
|
20
|
+
* Importing this module does not load the document evaluator or any Wasm asset.
|
|
21
|
+
*/
|
|
22
|
+
export function createWorkspaceClient(options = {}) {
|
|
23
|
+
const baseUrl = options.baseUrl ?? readBrowserOrigin();
|
|
24
|
+
if (baseUrl === undefined) {
|
|
25
|
+
throw new TypeError("a Workspace client needs a browser origin or an explicit baseUrl");
|
|
26
|
+
}
|
|
27
|
+
const client = createGeneratedOperationClient(createWorkspaceSessionTransport({
|
|
28
|
+
stampServerOrigin: baseUrl,
|
|
29
|
+
maxBinaryResponseBytes: WORKSPACE_ARTIFACT_MAX_BYTES,
|
|
30
|
+
...(options.fetch === undefined ? {} : { fetch: options.fetch }),
|
|
31
|
+
}));
|
|
32
|
+
return createWorkspaceClientFromGeneratedClient(client);
|
|
33
|
+
}
|
|
34
|
+
function createWorkspaceClientFromGeneratedClient(client) {
|
|
35
|
+
const list = (command) => readWorkspaceFiscalOperationPage(client, command);
|
|
36
|
+
return {
|
|
37
|
+
fiscalOperations: {
|
|
38
|
+
list,
|
|
39
|
+
listAll: (command) => walkCollectionPages((cursor, signal) => list({
|
|
40
|
+
...command,
|
|
41
|
+
...(cursor === undefined ? {} : { cursor }),
|
|
42
|
+
...(signal === undefined ? {} : { signal }),
|
|
43
|
+
}), {
|
|
44
|
+
...(command.maxPages === undefined ? {} : { maxPages: command.maxPages }),
|
|
45
|
+
...(command.signal === undefined ? {} : { signal: command.signal }),
|
|
46
|
+
}),
|
|
47
|
+
get: (command) => readWorkspaceFiscalOperation(client, command),
|
|
48
|
+
artifacts: {
|
|
49
|
+
retrieve: (command) => readWorkspaceFiscalArtifact(client, command),
|
|
50
|
+
},
|
|
51
|
+
},
|
|
52
|
+
directConnections: createDirectConnectionWorkspaceOperations(client),
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
async function readWorkspaceFiscalOperationPage(client, command) {
|
|
56
|
+
validateIdentity(command.organizationId, "organizationId");
|
|
57
|
+
const response = await listOrganizationFiscalOperations({
|
|
58
|
+
client,
|
|
59
|
+
path: { organization_id: command.organizationId },
|
|
60
|
+
...workspacePaginationQuery(command),
|
|
61
|
+
...(command.signal === undefined ? {} : { signal: command.signal }),
|
|
62
|
+
});
|
|
63
|
+
if (response.status !== 200) {
|
|
64
|
+
throwGeneratedProblem(response, "Workspace Fiscal operation listing failed");
|
|
65
|
+
}
|
|
66
|
+
return response.body;
|
|
67
|
+
}
|
|
68
|
+
async function readWorkspaceFiscalOperation(client, command) {
|
|
69
|
+
validateIdentity(command.organizationId, "organizationId");
|
|
70
|
+
validateIdentity(command.fiscalOperationId, "fiscalOperationId");
|
|
71
|
+
const response = await readOrganizationFiscalOperation({
|
|
72
|
+
client,
|
|
73
|
+
path: {
|
|
74
|
+
organization_id: command.organizationId,
|
|
75
|
+
fiscal_operation_id: command.fiscalOperationId,
|
|
76
|
+
},
|
|
77
|
+
...workspacePaginationQuery(command),
|
|
78
|
+
...(command.signal === undefined ? {} : { signal: command.signal }),
|
|
79
|
+
});
|
|
80
|
+
if (response.status !== 200) {
|
|
81
|
+
throwGeneratedProblem(response, "Workspace Fiscal operation lookup failed");
|
|
82
|
+
}
|
|
83
|
+
return response.body;
|
|
84
|
+
}
|
|
85
|
+
function workspacePaginationQuery(command) {
|
|
86
|
+
return command.cursor === undefined && command.limit === undefined
|
|
87
|
+
? {}
|
|
88
|
+
: {
|
|
89
|
+
query: {
|
|
90
|
+
...(command.cursor === undefined ? {} : { cursor: command.cursor }),
|
|
91
|
+
...(command.limit === undefined ? {} : { limit: command.limit }),
|
|
92
|
+
},
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
async function readWorkspaceFiscalArtifact(client, command) {
|
|
96
|
+
validateIdentity(command.organizationId, "organizationId");
|
|
97
|
+
validateIdentity(command.fiscalOperationId, "fiscalOperationId");
|
|
98
|
+
const response = await retrieveWorkspaceFiscalArtifact({
|
|
99
|
+
client,
|
|
100
|
+
path: {
|
|
101
|
+
organization_id: command.organizationId,
|
|
102
|
+
fiscal_operation_id: command.fiscalOperationId,
|
|
103
|
+
artifact_kind: command.kind,
|
|
104
|
+
},
|
|
105
|
+
...(command.signal === undefined ? {} : { signal: command.signal }),
|
|
106
|
+
});
|
|
107
|
+
if (response.status !== 200) {
|
|
108
|
+
throwGeneratedProblem(response, "Workspace Fiscal artifact retrieval failed");
|
|
109
|
+
}
|
|
110
|
+
return verifyWorkspaceFiscalArtifact(response.body, response.headers, command);
|
|
111
|
+
}
|
|
112
|
+
async function verifyWorkspaceFiscalArtifact(body, headers, command) {
|
|
113
|
+
if (!(body instanceof Uint8Array)) {
|
|
114
|
+
throwArtifactFailure("Timbro returned a non-binary Workspace Fiscal artifact");
|
|
115
|
+
}
|
|
116
|
+
const contentSha256 = requiredDigestHeader(headers, "timbro-artifact-sha256");
|
|
117
|
+
if ((await digestSha256Hex(body)) !== contentSha256) {
|
|
118
|
+
throwArtifactFailure("the Workspace Fiscal artifact bytes do not match their SHA-256");
|
|
119
|
+
}
|
|
120
|
+
const byteLength = body.byteLength;
|
|
121
|
+
const artifactId = requiredUuidHeader(headers, "timbro-artifact-id");
|
|
122
|
+
const fiscalOperationId = requiredUuidHeader(headers, "timbro-fiscal-operation-id");
|
|
123
|
+
if (fiscalOperationId.toLowerCase() !== command.fiscalOperationId.toLowerCase()) {
|
|
124
|
+
throwArtifactFailure("the Workspace Fiscal artifact belongs to another Fiscal operation");
|
|
125
|
+
}
|
|
126
|
+
const mediaType = requiredHeader(headers, "content-type");
|
|
127
|
+
if (mediaType !== expectedMediaType(command.kind)) {
|
|
128
|
+
throwArtifactFailure("Timbro returned an unexpected Workspace Fiscal artifact media type");
|
|
129
|
+
}
|
|
130
|
+
const contentDisposition = requiredHeader(headers, "content-disposition");
|
|
131
|
+
const cacheControl = requiredHeader(headers, "cache-control");
|
|
132
|
+
if (cacheControl !== "private, no-store, no-transform") {
|
|
133
|
+
throwArtifactFailure("Timbro returned an unexpected Workspace Fiscal artifact cache policy");
|
|
134
|
+
}
|
|
135
|
+
const createdAt = requiredHeader(headers, "timbro-artifact-created-at");
|
|
136
|
+
if (!isCanonicalRfc3339MillisecondUtc(createdAt)) {
|
|
137
|
+
throwArtifactFailure("Timbro returned an invalid Workspace Fiscal artifact creation time");
|
|
138
|
+
}
|
|
139
|
+
const signedSourceSha256 = optionalDigestHeader(headers, "timbro-signed-source-sha256");
|
|
140
|
+
const printedRepresentation = command.kind === "printed_representation"
|
|
141
|
+
? readPrintedRepresentationHeaders(headers, signedSourceSha256, contentSha256)
|
|
142
|
+
: undefined;
|
|
143
|
+
return {
|
|
144
|
+
artifactId,
|
|
145
|
+
artifactKind: command.kind,
|
|
146
|
+
bytes: body,
|
|
147
|
+
byteLength,
|
|
148
|
+
contentSha256,
|
|
149
|
+
contentDisposition,
|
|
150
|
+
cacheControl,
|
|
151
|
+
createdAt,
|
|
152
|
+
fiscalOperationId,
|
|
153
|
+
mediaType,
|
|
154
|
+
...(signedSourceSha256 === undefined ? {} : { signedSourceSha256 }),
|
|
155
|
+
...(printedRepresentation === undefined ? {} : { printedRepresentation }),
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
function expectedMediaType(kind) {
|
|
159
|
+
return kind === "printed_representation" ? "application/pdf" : "application/xml";
|
|
160
|
+
}
|
|
161
|
+
function readPrintedRepresentationHeaders(headers, signedSourceSha256, contentSha256) {
|
|
162
|
+
if (signedSourceSha256 === undefined) {
|
|
163
|
+
throwArtifactFailure("Timbro omitted required printed-representation source digest");
|
|
164
|
+
}
|
|
165
|
+
const fiscalDocumentType = requiredDocumentTypeHeader(headers);
|
|
166
|
+
const fiscalNumber = requiredHeader(headers, "timbro-fiscal-number");
|
|
167
|
+
if (!FISCAL_NUMBER_PATTERN.test(fiscalNumber)) {
|
|
168
|
+
throwArtifactFailure("Timbro returned an invalid fiscal number header");
|
|
169
|
+
}
|
|
170
|
+
if (fiscalNumber.slice(1, 3) !== fiscalDocumentType) {
|
|
171
|
+
throwArtifactFailure("Timbro returned a fiscal number for another document type");
|
|
172
|
+
}
|
|
173
|
+
if (requiredDigestHeader(headers, "timbro-pdf-sha256") !== contentSha256) {
|
|
174
|
+
throwArtifactFailure("Timbro returned mismatched artifact and PDF digests");
|
|
175
|
+
}
|
|
176
|
+
const rendererIdentity = requiredHeader(headers, "timbro-renderer-identity");
|
|
177
|
+
if (rendererIdentity.length > 200 || rendererIdentity !== rendererIdentity.trim()) {
|
|
178
|
+
throwArtifactFailure("Timbro returned an invalid renderer identity header");
|
|
179
|
+
}
|
|
180
|
+
const pageCount = requiredPositiveIntegerHeader(headers, "timbro-page-count");
|
|
181
|
+
if (pageCount > 100) {
|
|
182
|
+
throwArtifactFailure("Timbro returned a page count above the supported bound");
|
|
183
|
+
}
|
|
184
|
+
return {
|
|
185
|
+
fiscalDocumentType,
|
|
186
|
+
fiscalNumber,
|
|
187
|
+
paginationPlanSha256: requiredDigestHeader(headers, "timbro-pagination-plan-sha256"),
|
|
188
|
+
profile: requiredProfileHeader(headers),
|
|
189
|
+
profileVersion: requiredProfileVersionHeader(headers),
|
|
190
|
+
rendererIdentity,
|
|
191
|
+
pageCount,
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
function requiredDocumentTypeHeader(headers) {
|
|
195
|
+
const parsed = zElectronicFiscalDocumentType.safeParse(requiredHeader(headers, "timbro-fiscal-document-type"));
|
|
196
|
+
if (!parsed.success) {
|
|
197
|
+
throwArtifactFailure("Timbro returned an unsupported fiscal document type header");
|
|
198
|
+
}
|
|
199
|
+
return parsed.data;
|
|
200
|
+
}
|
|
201
|
+
function requiredProfileHeader(headers) {
|
|
202
|
+
const profile = requiredHeader(headers, "timbro-printed-representation-profile");
|
|
203
|
+
if (profile !== "a4" && profile !== "receipt_80mm") {
|
|
204
|
+
throwArtifactFailure("Timbro returned an unsupported printed representation profile");
|
|
205
|
+
}
|
|
206
|
+
return profile;
|
|
207
|
+
}
|
|
208
|
+
function requiredProfileVersionHeader(headers) {
|
|
209
|
+
const profile = requiredProfileHeader(headers);
|
|
210
|
+
const version = requiredHeader(headers, "timbro-printed-representation-profile-version");
|
|
211
|
+
if ((profile === "a4" && version === "a4.v1") ||
|
|
212
|
+
(profile === "receipt_80mm" && version === "receipt_80mm.v1")) {
|
|
213
|
+
return version;
|
|
214
|
+
}
|
|
215
|
+
throwArtifactFailure("Timbro returned a profile version that does not match its profile");
|
|
216
|
+
}
|
|
217
|
+
function requiredHeader(headers, name) {
|
|
218
|
+
const value = headerValue(headers, name);
|
|
219
|
+
if (value === undefined || value.trim() === "") {
|
|
220
|
+
throwArtifactFailure(`Timbro omitted required artifact header ${name}`);
|
|
221
|
+
}
|
|
222
|
+
return value;
|
|
223
|
+
}
|
|
224
|
+
function requiredDigestHeader(headers, name) {
|
|
225
|
+
const digest = requiredHeader(headers, name);
|
|
226
|
+
if (!SHA256_PATTERN.test(digest)) {
|
|
227
|
+
throwArtifactFailure(`Timbro returned an invalid digest header ${name}`);
|
|
228
|
+
}
|
|
229
|
+
return digest;
|
|
230
|
+
}
|
|
231
|
+
function optionalDigestHeader(headers, name) {
|
|
232
|
+
const value = headerValue(headers, name);
|
|
233
|
+
if (value === undefined) {
|
|
234
|
+
return;
|
|
235
|
+
}
|
|
236
|
+
if (!SHA256_PATTERN.test(value)) {
|
|
237
|
+
throwArtifactFailure(`Timbro returned an invalid digest header ${name}`);
|
|
238
|
+
}
|
|
239
|
+
return value;
|
|
240
|
+
}
|
|
241
|
+
function requiredUuidHeader(headers, name) {
|
|
242
|
+
const identity = requiredHeader(headers, name);
|
|
243
|
+
if (!UUID_PATTERN.test(identity)) {
|
|
244
|
+
throwArtifactFailure(`Timbro returned an invalid UUID header ${name}`);
|
|
245
|
+
}
|
|
246
|
+
return identity;
|
|
247
|
+
}
|
|
248
|
+
function requiredPositiveIntegerHeader(headers, name) {
|
|
249
|
+
const raw = requiredHeader(headers, name);
|
|
250
|
+
if (!POSITIVE_INTEGER_PATTERN.test(raw)) {
|
|
251
|
+
throwArtifactFailure(`Timbro returned a non-integer header ${name}`);
|
|
252
|
+
}
|
|
253
|
+
const value = Number(raw);
|
|
254
|
+
if (!Number.isSafeInteger(value) || value < 1 || value > MAX_SAFE_INT) {
|
|
255
|
+
throwArtifactFailure(`Timbro returned an out-of-range header ${name}`);
|
|
256
|
+
}
|
|
257
|
+
return value;
|
|
258
|
+
}
|
|
259
|
+
function headerValue(headers, name) {
|
|
260
|
+
const direct = headers.get(name);
|
|
261
|
+
if (direct !== undefined) {
|
|
262
|
+
return direct;
|
|
263
|
+
}
|
|
264
|
+
const lowerName = name.toLowerCase();
|
|
265
|
+
return Array.from(headers).find(([headerName]) => headerName.toLowerCase() === lowerName)?.[1];
|
|
266
|
+
}
|
|
267
|
+
function validateIdentity(identity, name) {
|
|
268
|
+
if (identity.trim() === "") {
|
|
269
|
+
throw new TypeError(`${name} must not be blank`);
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
function readBrowserOrigin() {
|
|
273
|
+
const browserGlobal = globalThis;
|
|
274
|
+
return typeof browserGlobal.location === "object" ? browserGlobal.location.origin : undefined;
|
|
275
|
+
}
|
|
276
|
+
function throwArtifactFailure(message) {
|
|
277
|
+
throw new FiscalError(message, { failure: "server_processing" });
|
|
278
|
+
}
|