@beignet/core 0.0.37 → 0.0.39
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/CHANGELOG.md +15 -0
- package/README.md +108 -19
- package/dist/client/client.d.ts.map +1 -1
- package/dist/client/client.js +6 -28
- package/dist/client/client.js.map +1 -1
- package/dist/error-reporting/index.d.ts +42 -1
- package/dist/error-reporting/index.d.ts.map +1 -1
- package/dist/error-reporting/index.js +60 -0
- package/dist/error-reporting/index.js.map +1 -1
- package/dist/error-reporting/internal.d.ts +11 -0
- package/dist/error-reporting/internal.d.ts.map +1 -0
- package/dist/error-reporting/internal.js +36 -0
- package/dist/error-reporting/internal.js.map +1 -0
- package/dist/events/index.d.ts +9 -4
- package/dist/events/index.d.ts.map +1 -1
- package/dist/events/index.js +5 -3
- package/dist/events/index.js.map +1 -1
- package/dist/idempotency/index.d.ts +25 -2
- package/dist/idempotency/index.d.ts.map +1 -1
- package/dist/idempotency/index.js +35 -5
- package/dist/idempotency/index.js.map +1 -1
- package/dist/jobs/index.d.ts +26 -4
- package/dist/jobs/index.d.ts.map +1 -1
- package/dist/jobs/index.js +51 -6
- package/dist/jobs/index.js.map +1 -1
- package/dist/locks/index.d.ts +19 -1
- package/dist/locks/index.d.ts.map +1 -1
- package/dist/locks/index.js +27 -12
- package/dist/locks/index.js.map +1 -1
- package/dist/outbox/index.d.ts +23 -4
- package/dist/outbox/index.d.ts.map +1 -1
- package/dist/outbox/index.js +71 -23
- package/dist/outbox/index.js.map +1 -1
- package/dist/ports/events.d.ts +5 -5
- package/dist/ports/events.d.ts.map +1 -1
- package/dist/ports/index.d.ts +4 -4
- package/dist/ports/unbound.js +1 -1
- package/dist/ports/unbound.js.map +1 -1
- package/dist/ports/unit-of-work.d.ts +4 -1
- package/dist/ports/unit-of-work.d.ts.map +1 -1
- package/dist/ports/unit-of-work.js +4 -3
- package/dist/ports/unit-of-work.js.map +1 -1
- package/dist/query-codec.d.ts +3 -0
- package/dist/query-codec.d.ts.map +1 -0
- package/dist/query-codec.js +110 -0
- package/dist/query-codec.js.map +1 -0
- package/dist/server/hooks/cors.d.ts +3 -2
- package/dist/server/hooks/cors.d.ts.map +1 -1
- package/dist/server/hooks/cors.js +7 -3
- package/dist/server/hooks/cors.js.map +1 -1
- package/dist/server/hooks/error-reporting.d.ts +8 -0
- package/dist/server/hooks/error-reporting.d.ts.map +1 -1
- package/dist/server/hooks/error-reporting.js +55 -25
- package/dist/server/hooks/error-reporting.js.map +1 -1
- package/dist/server/hooks/idempotency.d.ts +1 -1
- package/dist/server/hooks/idempotency.d.ts.map +1 -1
- package/dist/server/hooks/idempotency.js +30 -9
- package/dist/server/hooks/idempotency.js.map +1 -1
- package/dist/server/request-executor.d.ts.map +1 -1
- package/dist/server/request-executor.js +4 -10
- package/dist/server/request-executor.js.map +1 -1
- package/dist/server/request-preparation.d.ts.map +1 -1
- package/dist/server/request-preparation.js +3 -1
- package/dist/server/request-preparation.js.map +1 -1
- package/dist/server/response-finalization.d.ts +3 -1
- package/dist/server/response-finalization.d.ts.map +1 -1
- package/dist/server/response-finalization.js +24 -2
- package/dist/server/response-finalization.js.map +1 -1
- package/dist/server/server.js +1 -1
- package/dist/server/server.js.map +1 -1
- package/dist/testing/index.d.ts +5 -5
- package/dist/testing/index.d.ts.map +1 -1
- package/dist/testing/index.js +9 -4
- package/dist/testing/index.js.map +1 -1
- package/dist/tracing/index.d.ts +27 -0
- package/dist/tracing/index.d.ts.map +1 -1
- package/dist/tracing/index.js +96 -0
- package/dist/tracing/index.js.map +1 -1
- package/dist/uploads/index.d.ts.map +1 -1
- package/dist/uploads/index.js +39 -6
- package/dist/uploads/index.js.map +1 -1
- package/dist/webhooks/index.d.ts +2 -1
- package/dist/webhooks/index.d.ts.map +1 -1
- package/dist/webhooks/index.js +25 -1
- package/dist/webhooks/index.js.map +1 -1
- package/package.json +1 -1
- package/skills/app-architecture/SKILL.md +19 -1
- package/src/client/client.ts +6 -31
- package/src/error-reporting/index.ts +111 -0
- package/src/error-reporting/internal.ts +47 -0
- package/src/events/index.ts +20 -4
- package/src/idempotency/index.ts +81 -7
- package/src/jobs/index.ts +85 -6
- package/src/locks/index.ts +65 -16
- package/src/outbox/index.ts +119 -27
- package/src/ports/events.ts +8 -1
- package/src/ports/index.ts +4 -4
- package/src/ports/unbound.ts +1 -1
- package/src/ports/unit-of-work.ts +10 -3
- package/src/query-codec.ts +130 -0
- package/src/server/hooks/cors.ts +10 -3
- package/src/server/hooks/error-reporting.ts +79 -23
- package/src/server/hooks/idempotency.ts +36 -10
- package/src/server/request-executor.ts +4 -12
- package/src/server/request-preparation.ts +4 -2
- package/src/server/response-finalization.ts +36 -5
- package/src/server/server.ts +1 -1
- package/src/testing/index.ts +25 -14
- package/src/tracing/index.ts +120 -0
- package/src/uploads/index.ts +44 -6
- package/src/webhooks/index.ts +34 -2
package/src/uploads/index.ts
CHANGED
|
@@ -1036,6 +1036,7 @@ export function createUploadRouter<Ctx>(
|
|
|
1036
1036
|
assertFiles(definition, intents, { requireChecksum: false });
|
|
1037
1037
|
|
|
1038
1038
|
const completed: CompletedUploadFile[] = [];
|
|
1039
|
+
const storedKeys: string[] = [];
|
|
1039
1040
|
for (const [index, file] of webFiles.entries()) {
|
|
1040
1041
|
const intent = intents[index];
|
|
1041
1042
|
if (!intent) continue;
|
|
@@ -1072,18 +1073,24 @@ export function createUploadRouter<Ctx>(
|
|
|
1072
1073
|
metadata: storageMetadata,
|
|
1073
1074
|
visibility: definition.file.visibility ?? "private",
|
|
1074
1075
|
});
|
|
1076
|
+
storedKeys.push(key);
|
|
1075
1077
|
const completedFile = {
|
|
1076
1078
|
...verifiedIntent,
|
|
1077
1079
|
uploadId,
|
|
1078
1080
|
key,
|
|
1079
1081
|
object,
|
|
1080
1082
|
};
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1083
|
+
try {
|
|
1084
|
+
await assertVerifiedFile(definition, {
|
|
1085
|
+
ctx,
|
|
1086
|
+
metadata,
|
|
1087
|
+
file: completedFile,
|
|
1088
|
+
storage: options.storage,
|
|
1089
|
+
});
|
|
1090
|
+
} catch (error) {
|
|
1091
|
+
await cleanupRejectedServerUpload(uploadName, storedKeys);
|
|
1092
|
+
throw error;
|
|
1093
|
+
}
|
|
1087
1094
|
completed.push(completedFile);
|
|
1088
1095
|
}
|
|
1089
1096
|
|
|
@@ -1114,6 +1121,37 @@ export function createUploadRouter<Ctx>(
|
|
|
1114
1121
|
}
|
|
1115
1122
|
}
|
|
1116
1123
|
|
|
1124
|
+
async function cleanupRejectedServerUpload(
|
|
1125
|
+
uploadName: string,
|
|
1126
|
+
keys: readonly string[],
|
|
1127
|
+
): Promise<void> {
|
|
1128
|
+
const failures: Array<{ key: string; error: string }> = [];
|
|
1129
|
+
|
|
1130
|
+
await Promise.all(
|
|
1131
|
+
keys.map(async (key) => {
|
|
1132
|
+
try {
|
|
1133
|
+
await options.storage.delete(key);
|
|
1134
|
+
} catch (error) {
|
|
1135
|
+
failures.push({
|
|
1136
|
+
key,
|
|
1137
|
+
error: error instanceof Error ? error.message : String(error),
|
|
1138
|
+
});
|
|
1139
|
+
}
|
|
1140
|
+
}),
|
|
1141
|
+
);
|
|
1142
|
+
|
|
1143
|
+
if (failures.length === 0) return;
|
|
1144
|
+
instrumentation.custom({
|
|
1145
|
+
name: "upload.server.cleanup.failed",
|
|
1146
|
+
label: "Rejected upload cleanup failed",
|
|
1147
|
+
summary: uploadName,
|
|
1148
|
+
details: {
|
|
1149
|
+
uploadName,
|
|
1150
|
+
failures,
|
|
1151
|
+
},
|
|
1152
|
+
});
|
|
1153
|
+
}
|
|
1154
|
+
|
|
1117
1155
|
function recordFailure(
|
|
1118
1156
|
name: string,
|
|
1119
1157
|
uploadName: string,
|
package/src/webhooks/index.ts
CHANGED
|
@@ -133,7 +133,8 @@ export type HmacWebhookTimestampFormat =
|
|
|
133
133
|
export type HmacWebhookTimestampOptions =
|
|
134
134
|
| {
|
|
135
135
|
/**
|
|
136
|
-
* Header that carries the provider event timestamp.
|
|
136
|
+
* Header that carries the provider event timestamp. Header timestamps
|
|
137
|
+
* are authenticated as `<timestamp>.<rawBody>`.
|
|
137
138
|
*/
|
|
138
139
|
header: string;
|
|
139
140
|
payloadPath?: never;
|
|
@@ -461,7 +462,12 @@ export function createHmacWebhookVerifier(
|
|
|
461
462
|
});
|
|
462
463
|
}
|
|
463
464
|
|
|
464
|
-
const
|
|
465
|
+
const signedBody = hmacSignedBody({
|
|
466
|
+
input,
|
|
467
|
+
provider: options.provider,
|
|
468
|
+
timestamp,
|
|
469
|
+
});
|
|
470
|
+
const expected = await hmacHex(algorithm, options.secret, signedBody);
|
|
465
471
|
const actual = normalizeSignature(signature, options.signaturePrefix);
|
|
466
472
|
if (!(await timingSafeStringEqual(actual, expected))) {
|
|
467
473
|
throw new WebhookVerificationError({
|
|
@@ -573,6 +579,32 @@ function rawBodyText(rawBody: WebhookRawBody): string {
|
|
|
573
579
|
return new TextDecoder().decode(rawBodyBytes(rawBody));
|
|
574
580
|
}
|
|
575
581
|
|
|
582
|
+
function hmacSignedBody(args: {
|
|
583
|
+
input: VerifyWebhookInput;
|
|
584
|
+
provider: string | undefined;
|
|
585
|
+
timestamp: NormalizedHmacTimestampOptions | undefined;
|
|
586
|
+
}): WebhookRawBody {
|
|
587
|
+
if (!args.timestamp || args.timestamp.source === "payload") {
|
|
588
|
+
return args.input.rawBody;
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
const value = args.input.headers?.[args.timestamp.key];
|
|
592
|
+
if (value === undefined || value === null || value === "") {
|
|
593
|
+
throw new WebhookVerificationError({
|
|
594
|
+
message: `Missing ${args.timestamp.key} header.`,
|
|
595
|
+
provider: args.provider,
|
|
596
|
+
code: "missing_timestamp",
|
|
597
|
+
});
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
const prefix = new TextEncoder().encode(`${value}.`);
|
|
601
|
+
const body = rawBodyBytes(args.input.rawBody);
|
|
602
|
+
const signed = new Uint8Array(prefix.byteLength + body.byteLength);
|
|
603
|
+
signed.set(prefix);
|
|
604
|
+
signed.set(body, prefix.byteLength);
|
|
605
|
+
return signed;
|
|
606
|
+
}
|
|
607
|
+
|
|
576
608
|
function parseJsonBody(rawBody: WebhookRawBody): unknown {
|
|
577
609
|
try {
|
|
578
610
|
return JSON.parse(rawBodyText(rawBody));
|