@streetjs/storage 1.0.0 → 1.0.1
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/dist/drivers/local.d.ts +8 -0
- package/dist/drivers/local.d.ts.map +1 -1
- package/dist/drivers/local.js +18 -3
- package/dist/drivers/local.js.map +1 -1
- package/package.json +12 -6
- package/dist/tests/access.test.d.ts +0 -2
- package/dist/tests/access.test.d.ts.map +0 -1
- package/dist/tests/access.test.js +0 -270
- package/dist/tests/access.test.js.map +0 -1
- package/dist/tests/azure-driver.test.d.ts +0 -2
- package/dist/tests/azure-driver.test.d.ts.map +0 -1
- package/dist/tests/azure-driver.test.js +0 -183
- package/dist/tests/azure-driver.test.js.map +0 -1
- package/dist/tests/backblaze-driver.test.d.ts +0 -2
- package/dist/tests/backblaze-driver.test.d.ts.map +0 -1
- package/dist/tests/backblaze-driver.test.js +0 -185
- package/dist/tests/backblaze-driver.test.js.map +0 -1
- package/dist/tests/bridge-degradation.test.d.ts +0 -2
- package/dist/tests/bridge-degradation.test.d.ts.map +0 -1
- package/dist/tests/bridge-degradation.test.js +0 -138
- package/dist/tests/bridge-degradation.test.js.map +0 -1
- package/dist/tests/cli.test.d.ts +0 -2
- package/dist/tests/cli.test.d.ts.map +0 -1
- package/dist/tests/cli.test.js +0 -127
- package/dist/tests/cli.test.js.map +0 -1
- package/dist/tests/contract.d.ts +0 -131
- package/dist/tests/contract.d.ts.map +0 -1
- package/dist/tests/contract.js +0 -222
- package/dist/tests/contract.js.map +0 -1
- package/dist/tests/contract.test.d.ts +0 -2
- package/dist/tests/contract.test.d.ts.map +0 -1
- package/dist/tests/contract.test.js +0 -110
- package/dist/tests/contract.test.js.map +0 -1
- package/dist/tests/directory.test.d.ts +0 -2
- package/dist/tests/directory.test.d.ts.map +0 -1
- package/dist/tests/directory.test.js +0 -125
- package/dist/tests/directory.test.js.map +0 -1
- package/dist/tests/errors.test.d.ts +0 -2
- package/dist/tests/errors.test.d.ts.map +0 -1
- package/dist/tests/errors.test.js +0 -93
- package/dist/tests/errors.test.js.map +0 -1
- package/dist/tests/events-bridge.test.d.ts +0 -2
- package/dist/tests/events-bridge.test.d.ts.map +0 -1
- package/dist/tests/events-bridge.test.js +0 -228
- package/dist/tests/events-bridge.test.js.map +0 -1
- package/dist/tests/example-smoke.test.d.ts +0 -2
- package/dist/tests/example-smoke.test.d.ts.map +0 -1
- package/dist/tests/example-smoke.test.js +0 -34
- package/dist/tests/example-smoke.test.js.map +0 -1
- package/dist/tests/gcs-driver.test.d.ts +0 -2
- package/dist/tests/gcs-driver.test.d.ts.map +0 -1
- package/dist/tests/gcs-driver.test.js +0 -197
- package/dist/tests/gcs-driver.test.js.map +0 -1
- package/dist/tests/image.test.d.ts +0 -2
- package/dist/tests/image.test.d.ts.map +0 -1
- package/dist/tests/image.test.js +0 -102
- package/dist/tests/image.test.js.map +0 -1
- package/dist/tests/lifecycle.test.d.ts +0 -2
- package/dist/tests/lifecycle.test.d.ts.map +0 -1
- package/dist/tests/lifecycle.test.js +0 -171
- package/dist/tests/lifecycle.test.js.map +0 -1
- package/dist/tests/local-driver.test.d.ts +0 -2
- package/dist/tests/local-driver.test.d.ts.map +0 -1
- package/dist/tests/local-driver.test.js +0 -153
- package/dist/tests/local-driver.test.js.map +0 -1
- package/dist/tests/local-streaming.test.d.ts +0 -2
- package/dist/tests/local-streaming.test.d.ts.map +0 -1
- package/dist/tests/local-streaming.test.js +0 -121
- package/dist/tests/local-streaming.test.js.map +0 -1
- package/dist/tests/memory-driver.test.d.ts +0 -2
- package/dist/tests/memory-driver.test.d.ts.map +0 -1
- package/dist/tests/memory-driver.test.js +0 -180
- package/dist/tests/memory-driver.test.js.map +0 -1
- package/dist/tests/memory-streaming.test.d.ts +0 -2
- package/dist/tests/memory-streaming.test.d.ts.map +0 -1
- package/dist/tests/memory-streaming.test.js +0 -92
- package/dist/tests/memory-streaming.test.js.map +0 -1
- package/dist/tests/minio-driver.test.d.ts +0 -2
- package/dist/tests/minio-driver.test.d.ts.map +0 -1
- package/dist/tests/minio-driver.test.js +0 -146
- package/dist/tests/minio-driver.test.js.map +0 -1
- package/dist/tests/non-s3-integration.test.d.ts +0 -2
- package/dist/tests/non-s3-integration.test.d.ts.map +0 -1
- package/dist/tests/non-s3-integration.test.js +0 -201
- package/dist/tests/non-s3-integration.test.js.map +0 -1
- package/dist/tests/observability.registration.test.d.ts +0 -2
- package/dist/tests/observability.registration.test.d.ts.map +0 -1
- package/dist/tests/observability.registration.test.js +0 -103
- package/dist/tests/observability.registration.test.js.map +0 -1
- package/dist/tests/observability.test.d.ts +0 -2
- package/dist/tests/observability.test.d.ts.map +0 -1
- package/dist/tests/observability.test.js +0 -240
- package/dist/tests/observability.test.js.map +0 -1
- package/dist/tests/plugin.test.d.ts +0 -2
- package/dist/tests/plugin.test.d.ts.map +0 -1
- package/dist/tests/plugin.test.js +0 -112
- package/dist/tests/plugin.test.js.map +0 -1
- package/dist/tests/prop-concurrent.test.d.ts +0 -2
- package/dist/tests/prop-concurrent.test.d.ts.map +0 -1
- package/dist/tests/prop-concurrent.test.js +0 -59
- package/dist/tests/prop-concurrent.test.js.map +0 -1
- package/dist/tests/prop-copy.test.d.ts +0 -2
- package/dist/tests/prop-copy.test.d.ts.map +0 -1
- package/dist/tests/prop-copy.test.js +0 -63
- package/dist/tests/prop-copy.test.js.map +0 -1
- package/dist/tests/prop-delete.test.d.ts +0 -2
- package/dist/tests/prop-delete.test.d.ts.map +0 -1
- package/dist/tests/prop-delete.test.js +0 -35
- package/dist/tests/prop-delete.test.js.map +0 -1
- package/dist/tests/prop-directory.test.d.ts +0 -2
- package/dist/tests/prop-directory.test.d.ts.map +0 -1
- package/dist/tests/prop-directory.test.js +0 -118
- package/dist/tests/prop-directory.test.js.map +0 -1
- package/dist/tests/prop-driver-conformance.test.d.ts +0 -2
- package/dist/tests/prop-driver-conformance.test.d.ts.map +0 -1
- package/dist/tests/prop-driver-conformance.test.js +0 -110
- package/dist/tests/prop-driver-conformance.test.js.map +0 -1
- package/dist/tests/prop-driver-equivalence.test.d.ts +0 -2
- package/dist/tests/prop-driver-equivalence.test.d.ts.map +0 -1
- package/dist/tests/prop-driver-equivalence.test.js +0 -163
- package/dist/tests/prop-driver-equivalence.test.js.map +0 -1
- package/dist/tests/prop-lifecycle.test.d.ts +0 -2
- package/dist/tests/prop-lifecycle.test.d.ts.map +0 -1
- package/dist/tests/prop-lifecycle.test.js +0 -83
- package/dist/tests/prop-lifecycle.test.js.map +0 -1
- package/dist/tests/prop-list.test.d.ts +0 -2
- package/dist/tests/prop-list.test.d.ts.map +0 -1
- package/dist/tests/prop-list.test.js +0 -53
- package/dist/tests/prop-list.test.js.map +0 -1
- package/dist/tests/prop-metadata.test.d.ts +0 -2
- package/dist/tests/prop-metadata.test.d.ts.map +0 -1
- package/dist/tests/prop-metadata.test.js +0 -87
- package/dist/tests/prop-metadata.test.js.map +0 -1
- package/dist/tests/prop-move.test.d.ts +0 -2
- package/dist/tests/prop-move.test.d.ts.map +0 -1
- package/dist/tests/prop-move.test.js +0 -67
- package/dist/tests/prop-move.test.js.map +0 -1
- package/dist/tests/prop-multipart-abort.test.d.ts +0 -2
- package/dist/tests/prop-multipart-abort.test.d.ts.map +0 -1
- package/dist/tests/prop-multipart-abort.test.js +0 -48
- package/dist/tests/prop-multipart-abort.test.js.map +0 -1
- package/dist/tests/prop-multipart.test.d.ts +0 -2
- package/dist/tests/prop-multipart.test.d.ts.map +0 -1
- package/dist/tests/prop-multipart.test.js +0 -65
- package/dist/tests/prop-multipart.test.js.map +0 -1
- package/dist/tests/prop-resumable.test.d.ts +0 -2
- package/dist/tests/prop-resumable.test.d.ts.map +0 -1
- package/dist/tests/prop-resumable.test.js +0 -78
- package/dist/tests/prop-resumable.test.js.map +0 -1
- package/dist/tests/prop-search.test.d.ts +0 -2
- package/dist/tests/prop-search.test.d.ts.map +0 -1
- package/dist/tests/prop-search.test.js +0 -120
- package/dist/tests/prop-search.test.js.map +0 -1
- package/dist/tests/prop-signed-url.test.d.ts +0 -2
- package/dist/tests/prop-signed-url.test.d.ts.map +0 -1
- package/dist/tests/prop-signed-url.test.js +0 -74
- package/dist/tests/prop-signed-url.test.js.map +0 -1
- package/dist/tests/prop-streaming.test.d.ts +0 -2
- package/dist/tests/prop-streaming.test.d.ts.map +0 -1
- package/dist/tests/prop-streaming.test.js +0 -34
- package/dist/tests/prop-streaming.test.js.map +0 -1
- package/dist/tests/prop-upload-download.test.d.ts +0 -2
- package/dist/tests/prop-upload-download.test.d.ts.map +0 -1
- package/dist/tests/prop-upload-download.test.js +0 -30
- package/dist/tests/prop-upload-download.test.js.map +0 -1
- package/dist/tests/prop-validation.test.d.ts +0 -2
- package/dist/tests/prop-validation.test.d.ts.map +0 -1
- package/dist/tests/prop-validation.test.js +0 -50
- package/dist/tests/prop-validation.test.js.map +0 -1
- package/dist/tests/prop-versioning.test.d.ts +0 -2
- package/dist/tests/prop-versioning.test.d.ts.map +0 -1
- package/dist/tests/prop-versioning.test.js +0 -74
- package/dist/tests/prop-versioning.test.js.map +0 -1
- package/dist/tests/queue-bridge.test.d.ts +0 -2
- package/dist/tests/queue-bridge.test.d.ts.map +0 -1
- package/dist/tests/queue-bridge.test.js +0 -111
- package/dist/tests/queue-bridge.test.js.map +0 -1
- package/dist/tests/r2-driver.test.d.ts +0 -2
- package/dist/tests/r2-driver.test.d.ts.map +0 -1
- package/dist/tests/r2-driver.test.js +0 -143
- package/dist/tests/r2-driver.test.js.map +0 -1
- package/dist/tests/realtime-bridge.test.d.ts +0 -2
- package/dist/tests/realtime-bridge.test.d.ts.map +0 -1
- package/dist/tests/realtime-bridge.test.js +0 -106
- package/dist/tests/realtime-bridge.test.js.map +0 -1
- package/dist/tests/resumable.test.d.ts +0 -2
- package/dist/tests/resumable.test.d.ts.map +0 -1
- package/dist/tests/resumable.test.js +0 -104
- package/dist/tests/resumable.test.js.map +0 -1
- package/dist/tests/s3-base.test.d.ts +0 -2
- package/dist/tests/s3-base.test.d.ts.map +0 -1
- package/dist/tests/s3-base.test.js +0 -289
- package/dist/tests/s3-base.test.js.map +0 -1
- package/dist/tests/s3-integration.test.d.ts +0 -2
- package/dist/tests/s3-integration.test.d.ts.map +0 -1
- package/dist/tests/s3-integration.test.js +0 -270
- package/dist/tests/s3-integration.test.js.map +0 -1
- package/dist/tests/s3.test.d.ts +0 -2
- package/dist/tests/s3.test.d.ts.map +0 -1
- package/dist/tests/s3.test.js +0 -203
- package/dist/tests/s3.test.js.map +0 -1
- package/dist/tests/scaffold.test.d.ts +0 -2
- package/dist/tests/scaffold.test.d.ts.map +0 -1
- package/dist/tests/scaffold.test.js +0 -13
- package/dist/tests/scaffold.test.js.map +0 -1
- package/dist/tests/search.test.d.ts +0 -2
- package/dist/tests/search.test.d.ts.map +0 -1
- package/dist/tests/search.test.js +0 -106
- package/dist/tests/search.test.js.map +0 -1
- package/dist/tests/supabase-driver.test.d.ts +0 -2
- package/dist/tests/supabase-driver.test.d.ts.map +0 -1
- package/dist/tests/supabase-driver.test.js +0 -196
- package/dist/tests/supabase-driver.test.js.map +0 -1
- package/dist/tests/testing-utilities.test.d.ts +0 -2
- package/dist/tests/testing-utilities.test.d.ts.map +0 -1
- package/dist/tests/testing-utilities.test.js +0 -138
- package/dist/tests/testing-utilities.test.js.map +0 -1
- package/dist/tests/validation.test.d.ts +0 -2
- package/dist/tests/validation.test.d.ts.map +0 -1
- package/dist/tests/validation.test.js +0 -135
- package/dist/tests/validation.test.js.map +0 -1
- package/dist/tests/versioning.test.d.ts +0 -2
- package/dist/tests/versioning.test.d.ts.map +0 -1
- package/dist/tests/versioning.test.js +0 -128
- package/dist/tests/versioning.test.js.map +0 -1
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
// Property-based test for the storage facade's signed URL expiry guarantee.
|
|
2
|
-
//
|
|
3
|
-
// Property 11 (Signed URL expiry is honored): for an arbitrary key, operation
|
|
4
|
-
// (GET/PUT/DELETE), and expiry window, a signed URL minted at time T with
|
|
5
|
-
// `expiresInMs = E` verifies as VALID for its authorized operation when checked
|
|
6
|
-
// at any instant strictly before `T + E`, and verifies as INVALID with reason
|
|
7
|
-
// `'expired'` when checked at any instant at or after `T + E`.
|
|
8
|
-
//
|
|
9
|
-
// Time is made deterministic with an injected, controllable clock passed to
|
|
10
|
-
// `createStorage({ provider: 'memory', signingSecret, clock })`. The facade
|
|
11
|
-
// mints the URL over the zero-dependency memory provider (which has no native
|
|
12
|
-
// signed-URL capability, so the HMAC simulation path runs). A second
|
|
13
|
-
// `SignedUrlService` constructed with the SAME signing secret verifies the URL
|
|
14
|
-
// at an explicit check time via its `verify(url, op, now)` path, exercising the
|
|
15
|
-
// same code every provider shares (Requirements 8.1, 8.3, 8.4, 26.6).
|
|
16
|
-
//
|
|
17
|
-
// Uses the Node.js built-in test runner (node:test) with fast-check for input
|
|
18
|
-
// generation, executed via `node --test dist/tests/*.test.js`, configured with
|
|
19
|
-
// { numRuns: 100 } per the design's property-testing contract.
|
|
20
|
-
//
|
|
21
|
-
// Feature: unified-storage-framework, Property 11: Signed URL expiry is honored
|
|
22
|
-
//
|
|
23
|
-
// Validates: Requirements 8.1, 8.3, 8.4, 26.6
|
|
24
|
-
import test from "node:test";
|
|
25
|
-
import assert from "node:assert/strict";
|
|
26
|
-
import fc from "fast-check";
|
|
27
|
-
import { createStorage } from "../facade.js";
|
|
28
|
-
import { SignedUrlService } from "../signed-url.js";
|
|
29
|
-
const SIGNING_SECRET = "prop-11-signing-secret";
|
|
30
|
-
test("Feature: unified-storage-framework, Property 11: Signed URL expiry is honored", async () => {
|
|
31
|
-
await fc.assert(fc.asyncProperty(
|
|
32
|
-
// An arbitrary object key.
|
|
33
|
-
fc.string(),
|
|
34
|
-
// The single operation the URL authorizes (Requirement 8.1).
|
|
35
|
-
fc.constantFrom("GET", "PUT", "DELETE"),
|
|
36
|
-
// The mint instant T as epoch milliseconds.
|
|
37
|
-
fc.integer({ min: 0, max: 2 ** 40 }),
|
|
38
|
-
// A strictly-positive expiry window E, so the URL is valid at mint time.
|
|
39
|
-
fc.integer({ min: 1, max: 2 ** 32 }),
|
|
40
|
-
// An offset relative to the expiry instant (T + E). A negative offset
|
|
41
|
-
// lands strictly before expiry (must be VALID); a non-negative offset
|
|
42
|
-
// lands at or after expiry (must be 'expired'). The range straddles zero
|
|
43
|
-
// so both branches are exercised across the 100 runs.
|
|
44
|
-
fc.integer({ min: -(2 ** 20), max: 2 ** 20 }), async (key, op, mintTime, expiresInMs, offsetFromExpiry) => {
|
|
45
|
-
// A controllable clock so minting stamps expiry as T + E deterministically.
|
|
46
|
-
let now = mintTime;
|
|
47
|
-
const clock = () => now;
|
|
48
|
-
const storage = createStorage({
|
|
49
|
-
provider: "memory",
|
|
50
|
-
signingSecret: SIGNING_SECRET,
|
|
51
|
-
clock,
|
|
52
|
-
});
|
|
53
|
-
// Mint through the facade at time T; expiry = T + E.
|
|
54
|
-
const url = await storage.signedUrl(key, op, { expiresInMs });
|
|
55
|
-
const expiry = mintTime + expiresInMs;
|
|
56
|
-
// Independent verifier sharing only the secret; the check time is
|
|
57
|
-
// supplied explicitly so expiry is driven deterministically.
|
|
58
|
-
const verifier = new SignedUrlService({ signingSecret: SIGNING_SECRET });
|
|
59
|
-
const checkTime = expiry + offsetFromExpiry;
|
|
60
|
-
const verification = verifier.verify(url, op, checkTime);
|
|
61
|
-
if (checkTime < expiry) {
|
|
62
|
-
// Strictly before T + E: the URL is valid for its authorized op.
|
|
63
|
-
assert.equal(verification.valid, true);
|
|
64
|
-
assert.equal(verification.key, key);
|
|
65
|
-
assert.equal(verification.op, op);
|
|
66
|
-
}
|
|
67
|
-
else {
|
|
68
|
-
// At or after T + E: the URL is invalid, specifically 'expired'.
|
|
69
|
-
assert.equal(verification.valid, false);
|
|
70
|
-
assert.equal(verification.reason, "expired");
|
|
71
|
-
}
|
|
72
|
-
}), { numRuns: 100 });
|
|
73
|
-
});
|
|
74
|
-
//# sourceMappingURL=prop-signed-url.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"prop-signed-url.test.js","sourceRoot":"","sources":["../../src/tests/prop-signed-url.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"prop-streaming.test.d.ts","sourceRoot":"","sources":["../../src/tests/prop-streaming.test.ts"],"names":[],"mappings":""}
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
// Property-based test for the storage facade streaming round-trip guarantee.
|
|
2
|
-
//
|
|
3
|
-
// Property 7 (Streaming preserves bytes): for arbitrary keys and byte contents,
|
|
4
|
-
// persisting bytes with `putStream(key, Readable.from([bytes]))` and then
|
|
5
|
-
// reading them back with `getStream(key)` (collecting every emitted chunk)
|
|
6
|
-
// yields content bytes exactly equal to the original input. This exercises the
|
|
7
|
-
// facade over the zero-dependency `memory` provider, driving the identical
|
|
8
|
-
// streaming code path every provider shares (Requirement 5.1, 5.2, 5.4).
|
|
9
|
-
//
|
|
10
|
-
// Uses the Node.js built-in test runner (node:test) with fast-check for input
|
|
11
|
-
// generation, executed via `node --test dist/tests/*.test.js`. fast-check is
|
|
12
|
-
// configured with { numRuns: 100 } per the design's property-testing contract.
|
|
13
|
-
//
|
|
14
|
-
// Feature: unified-storage-framework, Property 7: Streaming preserves bytes
|
|
15
|
-
//
|
|
16
|
-
// Validates: Requirements 5.1, 5.2, 5.4
|
|
17
|
-
import test from "node:test";
|
|
18
|
-
import assert from "node:assert/strict";
|
|
19
|
-
import { Readable } from "node:stream";
|
|
20
|
-
import { buffer as streamToBuffer } from "node:stream/consumers";
|
|
21
|
-
import fc from "fast-check";
|
|
22
|
-
import { createStorage } from "../facade.js";
|
|
23
|
-
test("Feature: unified-storage-framework, Property 7: Streaming preserves bytes", async () => {
|
|
24
|
-
await fc.assert(fc.asyncProperty(fc.string(), fc.uint8Array(), async (key, content) => {
|
|
25
|
-
// A fresh store per run keeps each key/content pair independent.
|
|
26
|
-
const storage = createStorage({ provider: "memory" });
|
|
27
|
-
// Build the source stream from the raw bytes and stream it in.
|
|
28
|
-
await storage.putStream(key, Readable.from([Buffer.from(content)]));
|
|
29
|
-
// Collect all emitted chunks from the readable back into a buffer.
|
|
30
|
-
const out = await streamToBuffer(await storage.getStream(key));
|
|
31
|
-
assert.deepEqual(new Uint8Array(out), content);
|
|
32
|
-
}), { numRuns: 100 });
|
|
33
|
-
});
|
|
34
|
-
//# sourceMappingURL=prop-streaming.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"prop-streaming.test.js","sourceRoot":"","sources":["../../src/tests/prop-streaming.test.ts"],"names":[],"mappings":"AAAA,6EAA6E;AAC7E,EAAE;AACF,gFAAgF;AAChF,0EAA0E;AAC1E,2EAA2E;AAC3E,+EAA+E;AAC/E,2EAA2E;AAC3E,yEAAyE;AACzE,EAAE;AACF,8EAA8E;AAC9E,6EAA6E;AAC7E,+EAA+E;AAC/E,EAAE;AACF,4EAA4E;AAC5E,EAAE;AACF,wCAAwC;AAExC,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,MAAM,MAAM,oBAAoB,CAAC;AACxC,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACvC,OAAO,EAAE,MAAM,IAAI,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAEjE,OAAO,EAAE,MAAM,YAAY,CAAC;AAE5B,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAE7C,IAAI,CACF,2EAA2E,EAC3E,KAAK,IAAI,EAAE;IACT,MAAM,EAAE,CAAC,MAAM,CACb,EAAE,CAAC,aAAa,CACd,EAAE,CAAC,MAAM,EAAE,EACX,EAAE,CAAC,UAAU,EAAE,EACf,KAAK,EAAE,GAAG,EAAE,OAAO,EAAE,EAAE;QACrB,iEAAiE;QACjE,MAAM,OAAO,GAAG,aAAa,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC,CAAC;QAEtD,+DAA+D;QAC/D,MAAM,OAAO,CAAC,SAAS,CAAC,GAAG,EAAE,QAAQ,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;QAEpE,mEAAmE;QACnE,MAAM,GAAG,GAAG,MAAM,cAAc,CAAC,MAAM,OAAO,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC;QAE/D,MAAM,CAAC,SAAS,CAAC,IAAI,UAAU,CAAC,GAAG,CAAC,EAAE,OAAO,CAAC,CAAC;IACjD,CAAC,CACF,EACD,EAAE,OAAO,EAAE,GAAG,EAAE,CACjB,CAAC;AACJ,CAAC,CACF,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"prop-upload-download.test.d.ts","sourceRoot":"","sources":["../../src/tests/prop-upload-download.test.ts"],"names":[],"mappings":""}
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
// Property-based test for the storage facade round-trip guarantee.
|
|
2
|
-
//
|
|
3
|
-
// Property 1 (Upload/download preserves bytes): for arbitrary keys and byte
|
|
4
|
-
// contents, persisting bytes with `put(key, bytes)` and then reading them back
|
|
5
|
-
// with `get(key)` yields `found: true` and content bytes exactly equal to the
|
|
6
|
-
// original input. This exercises the facade over the zero-dependency `memory`
|
|
7
|
-
// provider, driving the identical code path every provider shares.
|
|
8
|
-
//
|
|
9
|
-
// Uses the Node.js built-in test runner (node:test) with fast-check for input
|
|
10
|
-
// generation, executed via `node --test dist/tests/*.test.js`. fast-check is
|
|
11
|
-
// configured with { numRuns: 100 } per the design's property-testing contract.
|
|
12
|
-
//
|
|
13
|
-
// Feature: unified-storage-framework, Property 1: Upload/download preserves bytes
|
|
14
|
-
//
|
|
15
|
-
// Validates: Requirements 4.1, 4.2, 26.2
|
|
16
|
-
import test from "node:test";
|
|
17
|
-
import assert from "node:assert/strict";
|
|
18
|
-
import fc from "fast-check";
|
|
19
|
-
import { createStorage } from "../facade.js";
|
|
20
|
-
test("Feature: unified-storage-framework, Property 1: Upload/download preserves bytes", async () => {
|
|
21
|
-
await fc.assert(fc.asyncProperty(fc.string(), fc.uint8Array(), async (key, content) => {
|
|
22
|
-
// A fresh store per run keeps each key/content pair independent.
|
|
23
|
-
const storage = createStorage({ provider: "memory" });
|
|
24
|
-
await storage.put(key, content);
|
|
25
|
-
const result = await storage.get(key);
|
|
26
|
-
assert.equal(result.found, true);
|
|
27
|
-
assert.deepEqual(result.bytes, content);
|
|
28
|
-
}), { numRuns: 100 });
|
|
29
|
-
});
|
|
30
|
-
//# sourceMappingURL=prop-upload-download.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"prop-upload-download.test.js","sourceRoot":"","sources":["../../src/tests/prop-upload-download.test.ts"],"names":[],"mappings":"AAAA,mEAAmE;AACnE,EAAE;AACF,4EAA4E;AAC5E,+EAA+E;AAC/E,8EAA8E;AAC9E,8EAA8E;AAC9E,mEAAmE;AACnE,EAAE;AACF,8EAA8E;AAC9E,6EAA6E;AAC7E,+EAA+E;AAC/E,EAAE;AACF,kFAAkF;AAClF,EAAE;AACF,yCAAyC;AAEzC,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,MAAM,MAAM,oBAAoB,CAAC;AAExC,OAAO,EAAE,MAAM,YAAY,CAAC;AAE5B,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAE7C,IAAI,CACF,iFAAiF,EACjF,KAAK,IAAI,EAAE;IACT,MAAM,EAAE,CAAC,MAAM,CACb,EAAE,CAAC,aAAa,CACd,EAAE,CAAC,MAAM,EAAE,EACX,EAAE,CAAC,UAAU,EAAE,EACf,KAAK,EAAE,GAAG,EAAE,OAAO,EAAE,EAAE;QACrB,iEAAiE;QACjE,MAAM,OAAO,GAAG,aAAa,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC,CAAC;QAEtD,MAAM,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;QAChC,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAEtC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;QACjC,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;IAC1C,CAAC,CACF,EACD,EAAE,OAAO,EAAE,GAAG,EAAE,CACjB,CAAC;AACJ,CAAC,CACF,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"prop-validation.test.d.ts","sourceRoot":"","sources":["../../src/tests/prop-validation.test.ts"],"names":[],"mappings":""}
|
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
// Property-based test for the storage facade's validation pipeline guarantee.
|
|
2
|
-
//
|
|
3
|
-
// Property 12 (Validation rejects leave no partial object): a Storage instance
|
|
4
|
-
// configured with a size validator (`validation: { maxSize: N }`) must, for any
|
|
5
|
-
// upload whose byte length exceeds `N`, reject the `put` with a `ValidationError`
|
|
6
|
-
// AND leave no partial object behind (`exists(key)` is false afterward). For any
|
|
7
|
-
// upload within the limit, `put` succeeds and the object then exists. Because the
|
|
8
|
-
// facade runs the validation pipeline before any bytes reach the driver, a
|
|
9
|
-
// rejection can never persist content (Requirements 9.3, 9.4).
|
|
10
|
-
//
|
|
11
|
-
// Backed by the zero-dependency in-memory provider via `createStorage({
|
|
12
|
-
// provider: 'memory', validation: { maxSize } })`, exercised across arbitrary
|
|
13
|
-
// keys, byte contents, and size limits with fast-check at { numRuns: 100 }.
|
|
14
|
-
// Executed via the Node.js built-in test runner (`node --test dist/tests/*.test.js`).
|
|
15
|
-
//
|
|
16
|
-
// Feature: unified-storage-framework, Property 12
|
|
17
|
-
// Validates: Requirements 9.3, 9.4
|
|
18
|
-
import test from "node:test";
|
|
19
|
-
import assert from "node:assert/strict";
|
|
20
|
-
import fc from "fast-check";
|
|
21
|
-
import { createStorage } from "../index.js";
|
|
22
|
-
import { ValidationError } from "../errors.js";
|
|
23
|
-
test("Feature: unified-storage-framework, Property 12 — validation rejects leave no partial object", async () => {
|
|
24
|
-
await fc.assert(fc.asyncProperty(
|
|
25
|
-
// Arbitrary non-empty keys and arbitrary byte contents.
|
|
26
|
-
fc.string({ minLength: 1 }), fc.uint8Array(),
|
|
27
|
-
// A non-negative size limit; chosen from a range that straddles typical
|
|
28
|
-
// fast-check byte-array lengths so both accepted and rejected inputs are
|
|
29
|
-
// generated across the 100 runs.
|
|
30
|
-
fc.nat({ max: 16 }), async (key, content, maxSize) => {
|
|
31
|
-
// A fresh store per run keeps each key/content pair independent.
|
|
32
|
-
const storage = createStorage({
|
|
33
|
-
provider: "memory",
|
|
34
|
-
validation: { maxSize },
|
|
35
|
-
});
|
|
36
|
-
const violatesLimit = content.byteLength > maxSize;
|
|
37
|
-
if (violatesLimit) {
|
|
38
|
-
// The oversized upload must be rejected with a ValidationError...
|
|
39
|
-
await assert.rejects(() => storage.put(key, content), (error) => error instanceof ValidationError);
|
|
40
|
-
// ...and must leave no partial object stored.
|
|
41
|
-
assert.equal(await storage.exists(key), false);
|
|
42
|
-
}
|
|
43
|
-
else {
|
|
44
|
-
// A within-limit upload succeeds and the object then exists.
|
|
45
|
-
await storage.put(key, content);
|
|
46
|
-
assert.equal(await storage.exists(key), true);
|
|
47
|
-
}
|
|
48
|
-
}), { numRuns: 100 });
|
|
49
|
-
});
|
|
50
|
-
//# sourceMappingURL=prop-validation.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"prop-validation.test.js","sourceRoot":"","sources":["../../src/tests/prop-validation.test.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,EAAE;AACF,+EAA+E;AAC/E,gFAAgF;AAChF,kFAAkF;AAClF,iFAAiF;AACjF,kFAAkF;AAClF,2EAA2E;AAC3E,+DAA+D;AAC/D,EAAE;AACF,wEAAwE;AACxE,8EAA8E;AAC9E,4EAA4E;AAC5E,sFAAsF;AACtF,EAAE;AACF,kDAAkD;AAClD,mCAAmC;AAEnC,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,MAAM,MAAM,oBAAoB,CAAC;AAExC,OAAO,EAAE,MAAM,YAAY,CAAC;AAE5B,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAE/C,IAAI,CACF,8FAA8F,EAC9F,KAAK,IAAI,EAAE;IACT,MAAM,EAAE,CAAC,MAAM,CACb,EAAE,CAAC,aAAa;IACd,wDAAwD;IACxD,EAAE,CAAC,MAAM,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,CAAC,EAC3B,EAAE,CAAC,UAAU,EAAE;IACf,wEAAwE;IACxE,yEAAyE;IACzE,iCAAiC;IACjC,EAAE,CAAC,GAAG,CAAC,EAAE,GAAG,EAAE,EAAE,EAAE,CAAC,EACnB,KAAK,EAAE,GAAG,EAAE,OAAO,EAAE,OAAO,EAAE,EAAE;QAC9B,iEAAiE;QACjE,MAAM,OAAO,GAAG,aAAa,CAAC;YAC5B,QAAQ,EAAE,QAAQ;YAClB,UAAU,EAAE,EAAE,OAAO,EAAE;SACxB,CAAC,CAAC;QAEH,MAAM,aAAa,GAAG,OAAO,CAAC,UAAU,GAAG,OAAO,CAAC;QAEnD,IAAI,aAAa,EAAE,CAAC;YAClB,kEAAkE;YAClE,MAAM,MAAM,CAAC,OAAO,CAClB,GAAG,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,OAAO,CAAC,EAC/B,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,YAAY,eAAe,CAC5C,CAAC;YACF,8CAA8C;YAC9C,MAAM,CAAC,KAAK,CAAC,MAAM,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,KAAK,CAAC,CAAC;QACjD,CAAC;aAAM,CAAC;YACN,6DAA6D;YAC7D,MAAM,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;YAChC,MAAM,CAAC,KAAK,CAAC,MAAM,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,CAAC;QAChD,CAAC;IACH,CAAC,CACF,EACD,EAAE,OAAO,EAAE,GAAG,EAAE,CACjB,CAAC;AACJ,CAAC,CACF,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"prop-versioning.test.d.ts","sourceRoot":"","sources":["../../src/tests/prop-versioning.test.ts"],"names":[],"mappings":""}
|
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
// Property-based test for the storage facade's versioning restore semantics.
|
|
2
|
-
//
|
|
3
|
-
// Feature: unified-storage-framework, Property 13: Version restore reproduces
|
|
4
|
-
// prior state. With versioning enabled (`createStorage({ provider: 'memory',
|
|
5
|
-
// versioning: true, clock })`), for an arbitrary sequence of contents written
|
|
6
|
-
// to a single key, each overwrite snapshots the prior content as a retained
|
|
7
|
-
// Version. Restoring a listed Version makes exactly that Version's prior
|
|
8
|
-
// content current again (bytes equal).
|
|
9
|
-
//
|
|
10
|
-
// The listed Versions are ordered oldest-first by creation time, so with a
|
|
11
|
-
// strictly-increasing clock the i-th listed Version corresponds to the i-th
|
|
12
|
-
// written content (each of the N writes after the first snapshots the content
|
|
13
|
-
// that preceded it, yielding N-1 Versions for contents[0..N-2]).
|
|
14
|
-
//
|
|
15
|
-
// Backed by the zero-dependency in-memory provider, exercised across arbitrary
|
|
16
|
-
// keys and content sequences with fast-check at { numRuns: 100 }. Executed via
|
|
17
|
-
// the Node.js built-in test runner (`node --test dist/tests/*.test.js`).
|
|
18
|
-
//
|
|
19
|
-
// Validates: Requirements 12.1, 12.2, 12.3, 12.4, 26.5
|
|
20
|
-
import test from "node:test";
|
|
21
|
-
import assert from "node:assert/strict";
|
|
22
|
-
import fc from "fast-check";
|
|
23
|
-
import { createStorage } from "../index.js";
|
|
24
|
-
/**
|
|
25
|
-
* A strictly-increasing clock. Each successive write therefore stamps a larger
|
|
26
|
-
* creation time, so the retained Versions enumerate oldest-first in the same
|
|
27
|
-
* order they were written — letting the i-th Version be matched to the i-th
|
|
28
|
-
* written content.
|
|
29
|
-
*/
|
|
30
|
-
function makeIncrementingClock() {
|
|
31
|
-
let now = 1_700_000_000_000;
|
|
32
|
-
return () => now++;
|
|
33
|
-
}
|
|
34
|
-
/** Arbitrary object content: byte arrays (including empty) as Uint8Array. */
|
|
35
|
-
const contentArb = fc.uint8Array({ minLength: 0, maxLength: 128 });
|
|
36
|
-
/**
|
|
37
|
-
* A sequence of at least two contents written to the same key, so at least one
|
|
38
|
-
* overwrite (and therefore at least one retained Version) occurs.
|
|
39
|
-
*/
|
|
40
|
-
const contentSequenceArb = fc.array(contentArb, { minLength: 2, maxLength: 6 });
|
|
41
|
-
test("Feature: unified-storage-framework, Property 13 — version restore reproduces prior state", async () => {
|
|
42
|
-
await fc.assert(fc.asyncProperty(fc.string({ minLength: 1, maxLength: 40 }), contentSequenceArb, async (key, contents) => {
|
|
43
|
-
// A fresh, versioned storage instance per case keeps runs independent.
|
|
44
|
-
const storage = createStorage({
|
|
45
|
-
provider: "memory",
|
|
46
|
-
versioning: true,
|
|
47
|
-
clock: makeIncrementingClock(),
|
|
48
|
-
});
|
|
49
|
-
// Write the full sequence to the same key; each write after the first
|
|
50
|
-
// overwrites the prior content and snapshots it as a Version (12.1).
|
|
51
|
-
for (const content of contents) {
|
|
52
|
-
await storage.put(key, content);
|
|
53
|
-
}
|
|
54
|
-
// Each of the N writes after the first produces exactly one Version,
|
|
55
|
-
// enumerated oldest-first (12.2).
|
|
56
|
-
const versions = await storage.listVersions(key);
|
|
57
|
-
assert.equal(versions.length, contents.length - 1, "one retained Version per overwrite");
|
|
58
|
-
// Restoring the i-th listed Version reproduces exactly contents[i],
|
|
59
|
-
// the content that preceded the (i+1)-th write (12.3). Restoring does
|
|
60
|
-
// not itself create a new Version, so the Version set is stable and
|
|
61
|
-
// every listed Version remains restorable (12.4).
|
|
62
|
-
for (let i = 0; i < versions.length; i++) {
|
|
63
|
-
const meta = await storage.restoreVersion(key, versions[i].versionId);
|
|
64
|
-
assert.equal(meta.key, key, "restore returns metadata for the key");
|
|
65
|
-
const got = await storage.get(key);
|
|
66
|
-
assert.equal(got.found, true, "restored object is readable");
|
|
67
|
-
assert.deepEqual(got.bytes, contents[i], "restored content equals the Version's prior content (bytes equal)");
|
|
68
|
-
// The Version set is unchanged by a restore.
|
|
69
|
-
assert.equal((await storage.listVersions(key)).length, versions.length, "restore does not add or remove Versions");
|
|
70
|
-
}
|
|
71
|
-
await storage.close();
|
|
72
|
-
}), { numRuns: 100 });
|
|
73
|
-
});
|
|
74
|
-
//# sourceMappingURL=prop-versioning.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"prop-versioning.test.js","sourceRoot":"","sources":["../../src/tests/prop-versioning.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"queue-bridge.test.d.ts","sourceRoot":"","sources":["../../src/tests/queue-bridge.test.ts"],"names":[],"mappings":""}
|
|
@@ -1,111 +0,0 @@
|
|
|
1
|
-
// Unit tests for the Queue integration bridge wired into the storage facade
|
|
2
|
-
// (task 21.2).
|
|
3
|
-
//
|
|
4
|
-
// Verifies the Requirement 17 / 28.3 graceful-degradation semantics over the
|
|
5
|
-
// zero-dependency `memory` provider:
|
|
6
|
-
//
|
|
7
|
-
// - bridgeStorageQueue dispatches the correct typed job name + payload through
|
|
8
|
-
// the structural QueueLike bridge (17.1).
|
|
9
|
-
// - a synchronous throw from the queue is fully isolated — never propagates
|
|
10
|
-
// into the caller (17.4).
|
|
11
|
-
// - an asynchronous rejection from the queue is fully isolated (17.4).
|
|
12
|
-
// - with no queue bridge configured, storage operations proceed unaffected
|
|
13
|
-
// (17.3).
|
|
14
|
-
// - configuring a queue bridge (present, throwing, or absent) never breaks the
|
|
15
|
-
// storage operation path.
|
|
16
|
-
//
|
|
17
|
-
// Uses the Node.js built-in test runner (node:test); executed via
|
|
18
|
-
// `node --test dist/tests/*.test.js`.
|
|
19
|
-
//
|
|
20
|
-
// Requirements: 17.1, 17.2, 17.3, 17.4, 28.3
|
|
21
|
-
import test from "node:test";
|
|
22
|
-
import assert from "node:assert/strict";
|
|
23
|
-
import { createStorage, bridgeStorageQueue } from "../index.js";
|
|
24
|
-
/** A recording QueueLike double capturing every dispatched (job, payload). */
|
|
25
|
-
function recordingQueue() {
|
|
26
|
-
const dispatched = [];
|
|
27
|
-
return {
|
|
28
|
-
dispatched,
|
|
29
|
-
dispatch(job, payload) {
|
|
30
|
-
dispatched.push({ job, payload: payload });
|
|
31
|
-
},
|
|
32
|
-
};
|
|
33
|
-
}
|
|
34
|
-
test("bridgeStorageQueue dispatches typed job names with key + options (Req 17.1)", () => {
|
|
35
|
-
const queue = recordingQueue();
|
|
36
|
-
const publisher = bridgeStorageQueue(queue);
|
|
37
|
-
publisher.thumbnail("photo.png", { size: 128 });
|
|
38
|
-
publisher.virusScan("upload.bin");
|
|
39
|
-
publisher.ocr("scan.tiff");
|
|
40
|
-
publisher.pdfProcess("doc.pdf");
|
|
41
|
-
publisher.transcode("video.mov");
|
|
42
|
-
publisher.imageOptimize("photo.png");
|
|
43
|
-
publisher.archive("report.csv");
|
|
44
|
-
assert.deepEqual(queue.dispatched.map((d) => d.job), [
|
|
45
|
-
"storage.thumbnail",
|
|
46
|
-
"storage.virus-scan",
|
|
47
|
-
"storage.ocr",
|
|
48
|
-
"storage.pdf-process",
|
|
49
|
-
"storage.transcode",
|
|
50
|
-
"storage.image-optimize",
|
|
51
|
-
"storage.archive",
|
|
52
|
-
]);
|
|
53
|
-
assert.equal(queue.dispatched[0].payload.key, "photo.png");
|
|
54
|
-
assert.deepEqual(queue.dispatched[0].payload.options, { size: 128 });
|
|
55
|
-
assert.equal(queue.dispatched[1].payload.key, "upload.bin");
|
|
56
|
-
});
|
|
57
|
-
test("dispatch() passes an already-named job straight through (Req 17.1)", () => {
|
|
58
|
-
const queue = recordingQueue();
|
|
59
|
-
const publisher = bridgeStorageQueue(queue);
|
|
60
|
-
publisher.dispatch("storage.archive", { key: "k" });
|
|
61
|
-
assert.equal(queue.dispatched.length, 1);
|
|
62
|
-
assert.equal(queue.dispatched[0].job, "storage.archive");
|
|
63
|
-
assert.equal(queue.dispatched[0].payload.key, "k");
|
|
64
|
-
});
|
|
65
|
-
test("a synchronous dispatch failure never throws into the caller (Req 17.4)", () => {
|
|
66
|
-
const publisher = bridgeStorageQueue({
|
|
67
|
-
dispatch() {
|
|
68
|
-
throw new Error("queue down");
|
|
69
|
-
},
|
|
70
|
-
});
|
|
71
|
-
assert.doesNotThrow(() => publisher.thumbnail("photo.png"));
|
|
72
|
-
assert.doesNotThrow(() => publisher.dispatch("storage.archive", { key: "k" }));
|
|
73
|
-
});
|
|
74
|
-
test("an asynchronous dispatch rejection never throws into the caller (Req 17.4)", async () => {
|
|
75
|
-
const publisher = bridgeStorageQueue({
|
|
76
|
-
dispatch() {
|
|
77
|
-
return Promise.reject(new Error("async queue down"));
|
|
78
|
-
},
|
|
79
|
-
});
|
|
80
|
-
assert.doesNotThrow(() => publisher.transcode("video.mov"));
|
|
81
|
-
// Give any swallowed rejection a tick to settle without an unhandled error.
|
|
82
|
-
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
83
|
-
});
|
|
84
|
-
test("facade wires a queue publisher when config.bridges.queue is present (Req 17.1)", async () => {
|
|
85
|
-
const queue = recordingQueue();
|
|
86
|
-
const storage = createStorage({ provider: "memory", bridges: { queue } });
|
|
87
|
-
// The bridge is constructed and held; storage operations remain unaffected.
|
|
88
|
-
const metadata = await storage.put("photo.png", "bytes", { contentType: "image/png" });
|
|
89
|
-
assert.equal(metadata.key, "photo.png");
|
|
90
|
-
assert.equal(await storage.exists("photo.png"), true);
|
|
91
|
-
});
|
|
92
|
-
test("a throwing queue never breaks storage operations (Req 17.4)", async () => {
|
|
93
|
-
const throwingQueue = {
|
|
94
|
-
dispatch() {
|
|
95
|
-
throw new Error("queue down");
|
|
96
|
-
},
|
|
97
|
-
};
|
|
98
|
-
const storage = createStorage({ provider: "memory", bridges: { queue: throwingQueue } });
|
|
99
|
-
const metadata = await storage.put("k", "v");
|
|
100
|
-
assert.equal(metadata.key, "k");
|
|
101
|
-
await storage.delete("k");
|
|
102
|
-
assert.equal(await storage.exists("k"), false);
|
|
103
|
-
});
|
|
104
|
-
test("with no queue bridge configured, operations proceed unaffected (Req 17.3)", async () => {
|
|
105
|
-
const storage = createStorage({ provider: "memory" });
|
|
106
|
-
const metadata = await storage.put("k", "v");
|
|
107
|
-
assert.equal(metadata.key, "k");
|
|
108
|
-
await storage.delete("k");
|
|
109
|
-
assert.equal(await storage.exists("k"), false);
|
|
110
|
-
});
|
|
111
|
-
//# sourceMappingURL=queue-bridge.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"queue-bridge.test.js","sourceRoot":"","sources":["../../src/tests/queue-bridge.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"r2-driver.test.d.ts","sourceRoot":"","sources":["../../src/tests/r2-driver.test.ts"],"names":[],"mappings":""}
|
|
@@ -1,143 +0,0 @@
|
|
|
1
|
-
// Unit tests for the CloudflareR2Driver submodule (task 28.3). R2 is the shared
|
|
2
|
-
// S3-style base pinned to the "r2" provider name with an R2 endpoint/credential
|
|
3
|
-
// specialization for the build-its-own-client path. A fake in-memory
|
|
4
|
-
// S3ClientLike stands in for the provider SDK so the driver is exercised with no
|
|
5
|
-
// external service and no SDK dependency.
|
|
6
|
-
//
|
|
7
|
-
// Coverage:
|
|
8
|
-
// - createCloudflareR2Driver wraps an injected S3ClientLike, name === "r2"
|
|
9
|
-
// - the CloudflareR2Driver class is constructible and pinned to "r2"
|
|
10
|
-
// - primitives round-trip typed metadata across the client boundary
|
|
11
|
-
// - the shared driver contract-conformance suite passes against the driver
|
|
12
|
-
// - connectCloudflareR2Driver validates required config (StorageConfigError)
|
|
13
|
-
// - connectCloudflareR2Driver throws StorageConfigError when the S3 SDK is
|
|
14
|
-
// absent and no client was injected (the SDK is not installed here)
|
|
15
|
-
//
|
|
16
|
-
// Requirements: 2.1, 2.3, 3.3
|
|
17
|
-
import test from "node:test";
|
|
18
|
-
import assert from "node:assert/strict";
|
|
19
|
-
import { CloudflareR2Driver, createCloudflareR2Driver, connectCloudflareR2Driver, } from "../drivers/r2.js";
|
|
20
|
-
import { StorageConfigError } from "../errors.js";
|
|
21
|
-
import { registerStorageDriverContractTests } from "./contract.js";
|
|
22
|
-
const FIXED_NOW = 1_700_000_000_000;
|
|
23
|
-
const fixedClock = () => FIXED_NOW;
|
|
24
|
-
function bytes(str) {
|
|
25
|
-
return new TextEncoder().encode(str);
|
|
26
|
-
}
|
|
27
|
-
/** A minimal in-memory S3ClientLike standing in for the R2 (S3-API) client. */
|
|
28
|
-
function makeFakeClient() {
|
|
29
|
-
const objects = new Map(); // key -> { body, contentType, metadata }
|
|
30
|
-
return {
|
|
31
|
-
async putObject({ key, body, contentType, metadata }) {
|
|
32
|
-
objects.set(key, {
|
|
33
|
-
body: body.slice(),
|
|
34
|
-
contentType,
|
|
35
|
-
metadata: metadata ? { ...metadata } : undefined,
|
|
36
|
-
});
|
|
37
|
-
return { etag: `"${key}-etag"` };
|
|
38
|
-
},
|
|
39
|
-
async getObject({ key }) {
|
|
40
|
-
const obj = objects.get(key);
|
|
41
|
-
if (obj === undefined) {
|
|
42
|
-
return null;
|
|
43
|
-
}
|
|
44
|
-
return {
|
|
45
|
-
body: obj.body.slice(),
|
|
46
|
-
contentType: obj.contentType,
|
|
47
|
-
etag: `"${key}-etag"`,
|
|
48
|
-
size: obj.body.byteLength,
|
|
49
|
-
lastModified: FIXED_NOW,
|
|
50
|
-
metadata: obj.metadata,
|
|
51
|
-
};
|
|
52
|
-
},
|
|
53
|
-
async headObject({ key }) {
|
|
54
|
-
const obj = objects.get(key);
|
|
55
|
-
if (obj === undefined) {
|
|
56
|
-
return null;
|
|
57
|
-
}
|
|
58
|
-
return {
|
|
59
|
-
contentType: obj.contentType,
|
|
60
|
-
etag: `"${key}-etag"`,
|
|
61
|
-
size: obj.body.byteLength,
|
|
62
|
-
lastModified: FIXED_NOW,
|
|
63
|
-
metadata: obj.metadata,
|
|
64
|
-
};
|
|
65
|
-
},
|
|
66
|
-
async deleteObject({ key }) {
|
|
67
|
-
objects.delete(key);
|
|
68
|
-
},
|
|
69
|
-
async listObjects({ prefix }) {
|
|
70
|
-
return [...objects.entries()]
|
|
71
|
-
.filter(([key]) => key.startsWith(prefix))
|
|
72
|
-
.sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0))
|
|
73
|
-
.map(([key, obj]) => ({ key, size: obj.body.byteLength, updatedAt: FIXED_NOW }));
|
|
74
|
-
},
|
|
75
|
-
};
|
|
76
|
-
}
|
|
77
|
-
// ── name / construction ─────────────────────────────────────────────────────────
|
|
78
|
-
test("createCloudflareR2Driver wraps an injected client and names it r2", () => {
|
|
79
|
-
const driver = createCloudflareR2Driver(makeFakeClient(), { clock: fixedClock });
|
|
80
|
-
assert.equal(driver.name, "r2");
|
|
81
|
-
});
|
|
82
|
-
test("CloudflareR2Driver class is constructible and pinned to r2", async () => {
|
|
83
|
-
const driver = new CloudflareR2Driver(makeFakeClient(), { clock: fixedClock });
|
|
84
|
-
assert.equal(driver.name, "r2");
|
|
85
|
-
const meta = await driver.put("k", bytes("v"), {});
|
|
86
|
-
assert.equal(meta.key, "k");
|
|
87
|
-
});
|
|
88
|
-
// ── primitives round-trip across the client boundary ─────────────────────────────
|
|
89
|
-
test("put/get round-trips bytes and typed metadata", async () => {
|
|
90
|
-
const driver = createCloudflareR2Driver(makeFakeClient(), { clock: fixedClock });
|
|
91
|
-
const content = bytes("cloudflare r2 payload");
|
|
92
|
-
await driver.put("docs/r2.txt", content, {
|
|
93
|
-
contentType: "text/plain",
|
|
94
|
-
owner: "user-9",
|
|
95
|
-
tenant: "tenant-z",
|
|
96
|
-
accessLevel: "public",
|
|
97
|
-
custom: { region: "auto" },
|
|
98
|
-
});
|
|
99
|
-
const result = await driver.get("docs/r2.txt");
|
|
100
|
-
assert.equal(result.found, true);
|
|
101
|
-
assert.deepEqual(result.bytes, content);
|
|
102
|
-
assert.equal(result.metadata.contentType, "text/plain");
|
|
103
|
-
assert.equal(result.metadata.owner, "user-9");
|
|
104
|
-
assert.equal(result.metadata.tenant, "tenant-z");
|
|
105
|
-
assert.equal(result.metadata.accessLevel, "public");
|
|
106
|
-
assert.deepEqual(result.metadata.custom, { region: "auto" });
|
|
107
|
-
});
|
|
108
|
-
test("get on a missing key reports found:false (not an error)", async () => {
|
|
109
|
-
const driver = createCloudflareR2Driver(makeFakeClient(), { clock: fixedClock });
|
|
110
|
-
const result = await driver.get("missing");
|
|
111
|
-
assert.equal(result.found, false);
|
|
112
|
-
});
|
|
113
|
-
// ── build-its-own-client path (SDK isolation) ────────────────────────────────────
|
|
114
|
-
test("connectCloudflareR2Driver validates required config", async () => {
|
|
115
|
-
await assert.rejects(() => connectCloudflareR2Driver({
|
|
116
|
-
accountId: "",
|
|
117
|
-
bucket: "media",
|
|
118
|
-
accessKeyId: "AK",
|
|
119
|
-
secretAccessKey: "SK",
|
|
120
|
-
}), (error) => {
|
|
121
|
-
assert.ok(error instanceof StorageConfigError);
|
|
122
|
-
assert.equal(error.provider, "r2");
|
|
123
|
-
return true;
|
|
124
|
-
});
|
|
125
|
-
});
|
|
126
|
-
test("connectCloudflareR2Driver throws StorageConfigError when the S3 SDK is absent", async () => {
|
|
127
|
-
// The optional @aws-sdk/client-s3 peer is not installed in this workspace, so
|
|
128
|
-
// the lazy dynamic import must fail and surface a StorageConfigError rather
|
|
129
|
-
// than an unhandled module-resolution error.
|
|
130
|
-
await assert.rejects(() => connectCloudflareR2Driver({
|
|
131
|
-
accountId: "acct-123",
|
|
132
|
-
bucket: "media",
|
|
133
|
-
accessKeyId: "AK",
|
|
134
|
-
secretAccessKey: "SK",
|
|
135
|
-
}), (error) => {
|
|
136
|
-
assert.ok(error instanceof StorageConfigError);
|
|
137
|
-
assert.equal(error.provider, "r2");
|
|
138
|
-
return true;
|
|
139
|
-
});
|
|
140
|
-
});
|
|
141
|
-
// ── shared contract-conformance suite ────────────────────────────────────────────
|
|
142
|
-
registerStorageDriverContractTests("r2", () => createCloudflareR2Driver(makeFakeClient(), { clock: fixedClock }), test);
|
|
143
|
-
//# sourceMappingURL=r2-driver.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"r2-driver.test.js","sourceRoot":"","sources":["../../src/tests/r2-driver.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"realtime-bridge.test.d.ts","sourceRoot":"","sources":["../../src/tests/realtime-bridge.test.ts"],"names":[],"mappings":""}
|