@voidhash/mimic-effect 0.0.9 → 1.0.0-beta.2
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/.turbo/turbo-build.log +136 -90
- package/README.md +385 -0
- package/dist/ColdStorage.cjs +60 -0
- package/dist/ColdStorage.d.cts +53 -0
- package/dist/ColdStorage.d.cts.map +1 -0
- package/dist/ColdStorage.d.mts +53 -0
- package/dist/ColdStorage.d.mts.map +1 -0
- package/dist/ColdStorage.mjs +60 -0
- package/dist/ColdStorage.mjs.map +1 -0
- package/dist/DocumentManager.cjs +263 -82
- package/dist/DocumentManager.d.cts +44 -22
- package/dist/DocumentManager.d.cts.map +1 -1
- package/dist/DocumentManager.d.mts +44 -22
- package/dist/DocumentManager.d.mts.map +1 -1
- package/dist/DocumentManager.mjs +259 -67
- package/dist/DocumentManager.mjs.map +1 -1
- package/dist/Errors.cjs +54 -0
- package/dist/Errors.d.cts +96 -0
- package/dist/Errors.d.cts.map +1 -0
- package/dist/Errors.d.mts +96 -0
- package/dist/Errors.d.mts.map +1 -0
- package/dist/Errors.mjs +48 -0
- package/dist/Errors.mjs.map +1 -0
- package/dist/HotStorage.cjs +100 -0
- package/dist/HotStorage.d.cts +70 -0
- package/dist/HotStorage.d.cts.map +1 -0
- package/dist/HotStorage.d.mts +70 -0
- package/dist/HotStorage.d.mts.map +1 -0
- package/dist/HotStorage.mjs +100 -0
- package/dist/HotStorage.mjs.map +1 -0
- package/dist/Metrics.cjs +143 -0
- package/dist/Metrics.d.cts +31 -0
- package/dist/Metrics.d.cts.map +1 -0
- package/dist/Metrics.d.mts +31 -0
- package/dist/Metrics.d.mts.map +1 -0
- package/dist/Metrics.mjs +126 -0
- package/dist/Metrics.mjs.map +1 -0
- package/dist/MimicAuthService.cjs +61 -45
- package/dist/MimicAuthService.d.cts +61 -48
- package/dist/MimicAuthService.d.cts.map +1 -1
- package/dist/MimicAuthService.d.mts +61 -48
- package/dist/MimicAuthService.d.mts.map +1 -1
- package/dist/MimicAuthService.mjs +60 -36
- package/dist/MimicAuthService.mjs.map +1 -1
- package/dist/MimicClusterServerEngine.cjs +521 -0
- package/dist/MimicClusterServerEngine.d.cts +17 -0
- package/dist/MimicClusterServerEngine.d.cts.map +1 -0
- package/dist/MimicClusterServerEngine.d.mts +17 -0
- package/dist/MimicClusterServerEngine.d.mts.map +1 -0
- package/dist/MimicClusterServerEngine.mjs +523 -0
- package/dist/MimicClusterServerEngine.mjs.map +1 -0
- package/dist/MimicServer.cjs +205 -96
- package/dist/MimicServer.d.cts +9 -110
- package/dist/MimicServer.d.cts.map +1 -1
- package/dist/MimicServer.d.mts +9 -110
- package/dist/MimicServer.d.mts.map +1 -1
- package/dist/MimicServer.mjs +206 -90
- package/dist/MimicServer.mjs.map +1 -1
- package/dist/MimicServerEngine.cjs +97 -0
- package/dist/MimicServerEngine.d.cts +78 -0
- package/dist/MimicServerEngine.d.cts.map +1 -0
- package/dist/MimicServerEngine.d.mts +78 -0
- package/dist/MimicServerEngine.d.mts.map +1 -0
- package/dist/MimicServerEngine.mjs +97 -0
- package/dist/MimicServerEngine.mjs.map +1 -0
- package/dist/PresenceManager.cjs +75 -91
- package/dist/PresenceManager.d.cts +17 -66
- package/dist/PresenceManager.d.cts.map +1 -1
- package/dist/PresenceManager.d.mts +17 -66
- package/dist/PresenceManager.d.mts.map +1 -1
- package/dist/PresenceManager.mjs +74 -78
- package/dist/PresenceManager.mjs.map +1 -1
- package/dist/Protocol.cjs +146 -0
- package/dist/Protocol.d.cts +203 -0
- package/dist/Protocol.d.cts.map +1 -0
- package/dist/Protocol.d.mts +203 -0
- package/dist/Protocol.d.mts.map +1 -0
- package/dist/Protocol.mjs +132 -0
- package/dist/Protocol.mjs.map +1 -0
- package/dist/Types.d.cts +172 -0
- package/dist/Types.d.cts.map +1 -0
- package/dist/Types.d.mts +172 -0
- package/dist/Types.d.mts.map +1 -0
- package/dist/_virtual/rolldown_runtime.cjs +1 -25
- package/dist/_virtual/rolldown_runtime.mjs +4 -1
- package/dist/index.cjs +37 -75
- package/dist/index.d.cts +13 -12
- package/dist/index.d.mts +13 -12
- package/dist/index.mjs +12 -12
- package/dist/testing/ColdStorageTestSuite.cjs +508 -0
- package/dist/testing/ColdStorageTestSuite.d.cts +36 -0
- package/dist/testing/ColdStorageTestSuite.d.cts.map +1 -0
- package/dist/testing/ColdStorageTestSuite.d.mts +36 -0
- package/dist/testing/ColdStorageTestSuite.d.mts.map +1 -0
- package/dist/testing/ColdStorageTestSuite.mjs +508 -0
- package/dist/testing/ColdStorageTestSuite.mjs.map +1 -0
- package/dist/testing/FailingStorage.cjs +135 -0
- package/dist/testing/FailingStorage.d.cts +43 -0
- package/dist/testing/FailingStorage.d.cts.map +1 -0
- package/dist/testing/FailingStorage.d.mts +43 -0
- package/dist/testing/FailingStorage.d.mts.map +1 -0
- package/dist/testing/FailingStorage.mjs +136 -0
- package/dist/testing/FailingStorage.mjs.map +1 -0
- package/dist/testing/HotStorageTestSuite.cjs +585 -0
- package/dist/testing/HotStorageTestSuite.d.cts +40 -0
- package/dist/testing/HotStorageTestSuite.d.cts.map +1 -0
- package/dist/testing/HotStorageTestSuite.d.mts +40 -0
- package/dist/testing/HotStorageTestSuite.d.mts.map +1 -0
- package/dist/testing/HotStorageTestSuite.mjs +585 -0
- package/dist/testing/HotStorageTestSuite.mjs.map +1 -0
- package/dist/testing/StorageIntegrationTestSuite.cjs +349 -0
- package/dist/testing/StorageIntegrationTestSuite.d.cts +35 -0
- package/dist/testing/StorageIntegrationTestSuite.d.cts.map +1 -0
- package/dist/testing/StorageIntegrationTestSuite.d.mts +35 -0
- package/dist/testing/StorageIntegrationTestSuite.d.mts.map +1 -0
- package/dist/testing/StorageIntegrationTestSuite.mjs +349 -0
- package/dist/testing/StorageIntegrationTestSuite.mjs.map +1 -0
- package/dist/testing/assertions.cjs +114 -0
- package/dist/testing/assertions.mjs +109 -0
- package/dist/testing/assertions.mjs.map +1 -0
- package/dist/testing/index.cjs +14 -0
- package/dist/testing/index.d.cts +6 -0
- package/dist/testing/index.d.mts +6 -0
- package/dist/testing/index.mjs +7 -0
- package/dist/testing/types.cjs +15 -0
- package/dist/testing/types.d.cts +90 -0
- package/dist/testing/types.d.cts.map +1 -0
- package/dist/testing/types.d.mts +90 -0
- package/dist/testing/types.d.mts.map +1 -0
- package/dist/testing/types.mjs +16 -0
- package/dist/testing/types.mjs.map +1 -0
- package/package.json +18 -3
- package/src/ColdStorage.ts +136 -0
- package/src/DocumentManager.ts +550 -190
- package/src/Errors.ts +114 -0
- package/src/HotStorage.ts +239 -0
- package/src/Metrics.ts +187 -0
- package/src/MimicAuthService.ts +126 -64
- package/src/MimicClusterServerEngine.ts +946 -0
- package/src/MimicServer.ts +448 -195
- package/src/MimicServerEngine.ts +276 -0
- package/src/PresenceManager.ts +169 -240
- package/src/Protocol.ts +350 -0
- package/src/Types.ts +231 -0
- package/src/index.ts +57 -23
- package/src/testing/ColdStorageTestSuite.ts +589 -0
- package/src/testing/FailingStorage.ts +286 -0
- package/src/testing/HotStorageTestSuite.ts +762 -0
- package/src/testing/StorageIntegrationTestSuite.ts +504 -0
- package/src/testing/assertions.ts +181 -0
- package/src/testing/index.ts +83 -0
- package/src/testing/types.ts +100 -0
- package/tests/ColdStorage.test.ts +24 -0
- package/tests/DocumentManager.test.ts +158 -287
- package/tests/HotStorage.test.ts +24 -0
- package/tests/MimicAuthService.test.ts +102 -134
- package/tests/MimicClusterServerEngine.test.ts +587 -0
- package/tests/MimicServer.test.ts +90 -226
- package/tests/MimicServerEngine.test.ts +521 -0
- package/tests/PresenceManager.test.ts +22 -63
- package/tests/Protocol.test.ts +190 -0
- package/tests/StorageIntegration.test.ts +259 -0
- package/tsconfig.json +1 -1
- package/tsdown.config.ts +1 -1
- package/dist/DocumentProtocol.cjs +0 -94
- package/dist/DocumentProtocol.d.cts +0 -113
- package/dist/DocumentProtocol.d.cts.map +0 -1
- package/dist/DocumentProtocol.d.mts +0 -113
- package/dist/DocumentProtocol.d.mts.map +0 -1
- package/dist/DocumentProtocol.mjs +0 -89
- package/dist/DocumentProtocol.mjs.map +0 -1
- package/dist/MimicConfig.cjs +0 -60
- package/dist/MimicConfig.d.cts +0 -141
- package/dist/MimicConfig.d.cts.map +0 -1
- package/dist/MimicConfig.d.mts +0 -141
- package/dist/MimicConfig.d.mts.map +0 -1
- package/dist/MimicConfig.mjs +0 -50
- package/dist/MimicConfig.mjs.map +0 -1
- package/dist/MimicDataStorage.cjs +0 -83
- package/dist/MimicDataStorage.d.cts +0 -113
- package/dist/MimicDataStorage.d.cts.map +0 -1
- package/dist/MimicDataStorage.d.mts +0 -113
- package/dist/MimicDataStorage.d.mts.map +0 -1
- package/dist/MimicDataStorage.mjs +0 -74
- package/dist/MimicDataStorage.mjs.map +0 -1
- package/dist/WebSocketHandler.cjs +0 -365
- package/dist/WebSocketHandler.d.cts +0 -34
- package/dist/WebSocketHandler.d.cts.map +0 -1
- package/dist/WebSocketHandler.d.mts +0 -34
- package/dist/WebSocketHandler.d.mts.map +0 -1
- package/dist/WebSocketHandler.mjs +0 -355
- package/dist/WebSocketHandler.mjs.map +0 -1
- package/dist/auth/NoAuth.cjs +0 -43
- package/dist/auth/NoAuth.d.cts +0 -22
- package/dist/auth/NoAuth.d.cts.map +0 -1
- package/dist/auth/NoAuth.d.mts +0 -22
- package/dist/auth/NoAuth.d.mts.map +0 -1
- package/dist/auth/NoAuth.mjs +0 -36
- package/dist/auth/NoAuth.mjs.map +0 -1
- package/dist/errors.cjs +0 -74
- package/dist/errors.d.cts +0 -89
- package/dist/errors.d.cts.map +0 -1
- package/dist/errors.d.mts +0 -89
- package/dist/errors.d.mts.map +0 -1
- package/dist/errors.mjs +0 -67
- package/dist/errors.mjs.map +0 -1
- package/dist/storage/InMemoryDataStorage.cjs +0 -57
- package/dist/storage/InMemoryDataStorage.d.cts +0 -19
- package/dist/storage/InMemoryDataStorage.d.cts.map +0 -1
- package/dist/storage/InMemoryDataStorage.d.mts +0 -19
- package/dist/storage/InMemoryDataStorage.d.mts.map +0 -1
- package/dist/storage/InMemoryDataStorage.mjs +0 -48
- package/dist/storage/InMemoryDataStorage.mjs.map +0 -1
- package/src/DocumentProtocol.ts +0 -112
- package/src/MimicConfig.ts +0 -211
- package/src/MimicDataStorage.ts +0 -157
- package/src/WebSocketHandler.ts +0 -735
- package/src/auth/NoAuth.ts +0 -46
- package/src/errors.ts +0 -113
- package/src/storage/InMemoryDataStorage.ts +0 -66
- package/tests/DocumentProtocol.test.ts +0 -113
- package/tests/InMemoryDataStorage.test.ts +0 -190
- package/tests/MimicConfig.test.ts +0 -290
- package/tests/MimicDataStorage.test.ts +0 -190
- package/tests/NoAuth.test.ts +0 -94
- package/tests/WebSocketHandler.test.ts +0 -321
- package/tests/errors.test.ts +0 -77
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { TestError } from "./types.mjs";
|
|
2
|
+
import { Categories, ColdStorageTestSuite } from "./ColdStorageTestSuite.mjs";
|
|
3
|
+
import { Categories as Categories$1, HotStorageTestSuite } from "./HotStorageTestSuite.mjs";
|
|
4
|
+
import { Categories as Categories$2, StorageIntegrationTestSuite } from "./StorageIntegrationTestSuite.mjs";
|
|
5
|
+
import { FailingStorage } from "./FailingStorage.mjs";
|
|
6
|
+
|
|
7
|
+
export { Categories as ColdStorageCategories, ColdStorageTestSuite, FailingStorage, Categories$1 as HotStorageCategories, HotStorageTestSuite, Categories$2 as IntegrationCategories, StorageIntegrationTestSuite, TestError };
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
let effect = require("effect");
|
|
2
|
+
|
|
3
|
+
//#region src/testing/types.ts
|
|
4
|
+
/**
|
|
5
|
+
* @voidhash/mimic-effect/testing - Core Types
|
|
6
|
+
*
|
|
7
|
+
* Types used by the storage adapter test utilities.
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Error thrown when a test assertion fails.
|
|
11
|
+
*/
|
|
12
|
+
var TestError = class extends effect.Data.TaggedError("TestError") {};
|
|
13
|
+
|
|
14
|
+
//#endregion
|
|
15
|
+
exports.TestError = TestError;
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { Effect } from "effect";
|
|
2
|
+
import * as effect_Types7 from "effect/Types";
|
|
3
|
+
import * as effect_Cause7 from "effect/Cause";
|
|
4
|
+
|
|
5
|
+
//#region src/testing/types.d.ts
|
|
6
|
+
|
|
7
|
+
declare const TestError_base: new <A extends Record<string, any> = {}>(args: effect_Types7.Equals<A, {}> extends true ? void : { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P] }) => effect_Cause7.YieldableError & {
|
|
8
|
+
readonly _tag: "TestError";
|
|
9
|
+
} & Readonly<A>;
|
|
10
|
+
/**
|
|
11
|
+
* Error thrown when a test assertion fails.
|
|
12
|
+
*/
|
|
13
|
+
declare class TestError extends TestError_base<{
|
|
14
|
+
/** Description of what failed */
|
|
15
|
+
readonly message: string;
|
|
16
|
+
/** Expected value (if applicable) */
|
|
17
|
+
readonly expected?: unknown;
|
|
18
|
+
/** Actual value received (if applicable) */
|
|
19
|
+
readonly actual?: unknown;
|
|
20
|
+
}> {}
|
|
21
|
+
/**
|
|
22
|
+
* A single storage adapter test case.
|
|
23
|
+
*
|
|
24
|
+
* Test cases are framework-agnostic Effects that can be run with any test runner.
|
|
25
|
+
*
|
|
26
|
+
* @template E - The error type for this test case
|
|
27
|
+
* @template R - The Effect requirements (e.g., ColdStorageTag or HotStorageTag)
|
|
28
|
+
*
|
|
29
|
+
* @example
|
|
30
|
+
* ```typescript
|
|
31
|
+
* // Using with vitest
|
|
32
|
+
* const tests = ColdStorageTestSuite.makeTests();
|
|
33
|
+
*
|
|
34
|
+
* describe("MyAdapter", () => {
|
|
35
|
+
* for (const test of tests) {
|
|
36
|
+
* it(test.name, () =>
|
|
37
|
+
* Effect.runPromise(test.run.pipe(Effect.provide(myAdapterLayer)))
|
|
38
|
+
* );
|
|
39
|
+
* }
|
|
40
|
+
* });
|
|
41
|
+
* ```
|
|
42
|
+
*/
|
|
43
|
+
interface StorageTestCase<E, R> {
|
|
44
|
+
/** Human-readable test name */
|
|
45
|
+
readonly name: string;
|
|
46
|
+
/** Category for grouping (e.g., "Basic Operations", "Data Integrity") */
|
|
47
|
+
readonly category: string;
|
|
48
|
+
/** The test as an Effect - succeeds if test passes, fails with error if not */
|
|
49
|
+
readonly run: Effect.Effect<void, E, R>;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Result of a failed test.
|
|
53
|
+
*/
|
|
54
|
+
interface FailedTest<E, R> {
|
|
55
|
+
/** The test case that failed */
|
|
56
|
+
readonly test: StorageTestCase<E, R>;
|
|
57
|
+
/** The error that caused the failure */
|
|
58
|
+
readonly error: E;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Results from running all tests in a suite.
|
|
62
|
+
*
|
|
63
|
+
* @example
|
|
64
|
+
* ```typescript
|
|
65
|
+
* const results = await Effect.runPromise(
|
|
66
|
+
* ColdStorageTestSuite.runAll().pipe(Effect.provide(myAdapterLayer))
|
|
67
|
+
* );
|
|
68
|
+
*
|
|
69
|
+
* console.log(`Passed: ${results.passCount}/${results.total}`);
|
|
70
|
+
*
|
|
71
|
+
* for (const { test, error } of results.failed) {
|
|
72
|
+
* console.error(`FAIL: ${test.name} - ${error._tag}`);
|
|
73
|
+
* }
|
|
74
|
+
* ```
|
|
75
|
+
*/
|
|
76
|
+
interface TestResults<E, R> {
|
|
77
|
+
/** Tests that passed */
|
|
78
|
+
readonly passed: StorageTestCase<E, R>[];
|
|
79
|
+
/** Tests that failed with their errors */
|
|
80
|
+
readonly failed: FailedTest<E, R>[];
|
|
81
|
+
/** Total number of tests run */
|
|
82
|
+
readonly total: number;
|
|
83
|
+
/** Number of tests that passed */
|
|
84
|
+
readonly passCount: number;
|
|
85
|
+
/** Number of tests that failed */
|
|
86
|
+
readonly failCount: number;
|
|
87
|
+
}
|
|
88
|
+
//#endregion
|
|
89
|
+
export { FailedTest, StorageTestCase, TestError, TestResults };
|
|
90
|
+
//# sourceMappingURL=types.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.cts","names":[],"sources":["../../src/testing/types.ts"],"sourcesContent":[],"mappings":";;;;;;cAKsC;;;;;;cASzB,SAAA,SAAkB;;;;;;EAAlB,SAAA,MAAU,CAAA,EAAA,OAAQ;AAmC/B,CAAA,CAAA,CAAA;;;;AAgBA;;;;;;AAuBA;;;;;;;;;;;;;UAvCiB;;;;;;gBAMD,MAAA,CAAO,aAAa,GAAG;;;;;UAUtB;;iBAEA,gBAAgB,GAAG;;kBAElB;;;;;;;;;;;;;;;;;;UAmBD;;mBAEE,gBAAgB,GAAG;;mBAEnB,WAAW,GAAG"}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { Effect } from "effect";
|
|
2
|
+
import * as effect_Types0 from "effect/Types";
|
|
3
|
+
import * as effect_Cause0 from "effect/Cause";
|
|
4
|
+
|
|
5
|
+
//#region src/testing/types.d.ts
|
|
6
|
+
|
|
7
|
+
declare const TestError_base: new <A extends Record<string, any> = {}>(args: effect_Types0.Equals<A, {}> extends true ? void : { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P] }) => effect_Cause0.YieldableError & {
|
|
8
|
+
readonly _tag: "TestError";
|
|
9
|
+
} & Readonly<A>;
|
|
10
|
+
/**
|
|
11
|
+
* Error thrown when a test assertion fails.
|
|
12
|
+
*/
|
|
13
|
+
declare class TestError extends TestError_base<{
|
|
14
|
+
/** Description of what failed */
|
|
15
|
+
readonly message: string;
|
|
16
|
+
/** Expected value (if applicable) */
|
|
17
|
+
readonly expected?: unknown;
|
|
18
|
+
/** Actual value received (if applicable) */
|
|
19
|
+
readonly actual?: unknown;
|
|
20
|
+
}> {}
|
|
21
|
+
/**
|
|
22
|
+
* A single storage adapter test case.
|
|
23
|
+
*
|
|
24
|
+
* Test cases are framework-agnostic Effects that can be run with any test runner.
|
|
25
|
+
*
|
|
26
|
+
* @template E - The error type for this test case
|
|
27
|
+
* @template R - The Effect requirements (e.g., ColdStorageTag or HotStorageTag)
|
|
28
|
+
*
|
|
29
|
+
* @example
|
|
30
|
+
* ```typescript
|
|
31
|
+
* // Using with vitest
|
|
32
|
+
* const tests = ColdStorageTestSuite.makeTests();
|
|
33
|
+
*
|
|
34
|
+
* describe("MyAdapter", () => {
|
|
35
|
+
* for (const test of tests) {
|
|
36
|
+
* it(test.name, () =>
|
|
37
|
+
* Effect.runPromise(test.run.pipe(Effect.provide(myAdapterLayer)))
|
|
38
|
+
* );
|
|
39
|
+
* }
|
|
40
|
+
* });
|
|
41
|
+
* ```
|
|
42
|
+
*/
|
|
43
|
+
interface StorageTestCase<E, R> {
|
|
44
|
+
/** Human-readable test name */
|
|
45
|
+
readonly name: string;
|
|
46
|
+
/** Category for grouping (e.g., "Basic Operations", "Data Integrity") */
|
|
47
|
+
readonly category: string;
|
|
48
|
+
/** The test as an Effect - succeeds if test passes, fails with error if not */
|
|
49
|
+
readonly run: Effect.Effect<void, E, R>;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Result of a failed test.
|
|
53
|
+
*/
|
|
54
|
+
interface FailedTest<E, R> {
|
|
55
|
+
/** The test case that failed */
|
|
56
|
+
readonly test: StorageTestCase<E, R>;
|
|
57
|
+
/** The error that caused the failure */
|
|
58
|
+
readonly error: E;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Results from running all tests in a suite.
|
|
62
|
+
*
|
|
63
|
+
* @example
|
|
64
|
+
* ```typescript
|
|
65
|
+
* const results = await Effect.runPromise(
|
|
66
|
+
* ColdStorageTestSuite.runAll().pipe(Effect.provide(myAdapterLayer))
|
|
67
|
+
* );
|
|
68
|
+
*
|
|
69
|
+
* console.log(`Passed: ${results.passCount}/${results.total}`);
|
|
70
|
+
*
|
|
71
|
+
* for (const { test, error } of results.failed) {
|
|
72
|
+
* console.error(`FAIL: ${test.name} - ${error._tag}`);
|
|
73
|
+
* }
|
|
74
|
+
* ```
|
|
75
|
+
*/
|
|
76
|
+
interface TestResults<E, R> {
|
|
77
|
+
/** Tests that passed */
|
|
78
|
+
readonly passed: StorageTestCase<E, R>[];
|
|
79
|
+
/** Tests that failed with their errors */
|
|
80
|
+
readonly failed: FailedTest<E, R>[];
|
|
81
|
+
/** Total number of tests run */
|
|
82
|
+
readonly total: number;
|
|
83
|
+
/** Number of tests that passed */
|
|
84
|
+
readonly passCount: number;
|
|
85
|
+
/** Number of tests that failed */
|
|
86
|
+
readonly failCount: number;
|
|
87
|
+
}
|
|
88
|
+
//#endregion
|
|
89
|
+
export { FailedTest, StorageTestCase, TestError, TestResults };
|
|
90
|
+
//# sourceMappingURL=types.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.mts","names":[],"sources":["../../src/testing/types.ts"],"sourcesContent":[],"mappings":";;;;;;cAKsC;;;;;;cASzB,SAAA,SAAkB;;;;;;EAAlB,SAAA,MAAU,CAAA,EAAA,OAAQ;AAmC/B,CAAA,CAAA,CAAA;;;;AAgBA;;;;;;AAuBA;;;;;;;;;;;;;UAvCiB;;;;;;gBAMD,MAAA,CAAO,aAAa,GAAG;;;;;UAUtB;;iBAEA,gBAAgB,GAAG;;kBAElB;;;;;;;;;;;;;;;;;;UAmBD;;mBAEE,gBAAgB,GAAG;;mBAEnB,WAAW,GAAG"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { Data } from "effect";
|
|
2
|
+
|
|
3
|
+
//#region src/testing/types.ts
|
|
4
|
+
/**
|
|
5
|
+
* @voidhash/mimic-effect/testing - Core Types
|
|
6
|
+
*
|
|
7
|
+
* Types used by the storage adapter test utilities.
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Error thrown when a test assertion fails.
|
|
11
|
+
*/
|
|
12
|
+
var TestError = class extends Data.TaggedError("TestError") {};
|
|
13
|
+
|
|
14
|
+
//#endregion
|
|
15
|
+
export { TestError };
|
|
16
|
+
//# sourceMappingURL=types.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.mjs","names":[],"sources":["../../src/testing/types.ts"],"sourcesContent":["/**\n * @voidhash/mimic-effect/testing - Core Types\n *\n * Types used by the storage adapter test utilities.\n */\nimport { Data, Effect } from \"effect\";\n\n// =============================================================================\n// Error Types\n// =============================================================================\n\n/**\n * Error thrown when a test assertion fails.\n */\nexport class TestError extends Data.TaggedError(\"TestError\")<{\n /** Description of what failed */\n readonly message: string;\n /** Expected value (if applicable) */\n readonly expected?: unknown;\n /** Actual value received (if applicable) */\n readonly actual?: unknown;\n}> {}\n\n// =============================================================================\n// Test Case Types\n// =============================================================================\n\n/**\n * A single storage adapter test case.\n *\n * Test cases are framework-agnostic Effects that can be run with any test runner.\n *\n * @template E - The error type for this test case\n * @template R - The Effect requirements (e.g., ColdStorageTag or HotStorageTag)\n *\n * @example\n * ```typescript\n * // Using with vitest\n * const tests = ColdStorageTestSuite.makeTests();\n *\n * describe(\"MyAdapter\", () => {\n * for (const test of tests) {\n * it(test.name, () =>\n * Effect.runPromise(test.run.pipe(Effect.provide(myAdapterLayer)))\n * );\n * }\n * });\n * ```\n */\nexport interface StorageTestCase<E, R> {\n /** Human-readable test name */\n readonly name: string;\n /** Category for grouping (e.g., \"Basic Operations\", \"Data Integrity\") */\n readonly category: string;\n /** The test as an Effect - succeeds if test passes, fails with error if not */\n readonly run: Effect.Effect<void, E, R>;\n}\n\n// =============================================================================\n// Test Results Types\n// =============================================================================\n\n/**\n * Result of a failed test.\n */\nexport interface FailedTest<E, R> {\n /** The test case that failed */\n readonly test: StorageTestCase<E, R>;\n /** The error that caused the failure */\n readonly error: E;\n}\n\n/**\n * Results from running all tests in a suite.\n *\n * @example\n * ```typescript\n * const results = await Effect.runPromise(\n * ColdStorageTestSuite.runAll().pipe(Effect.provide(myAdapterLayer))\n * );\n *\n * console.log(`Passed: ${results.passCount}/${results.total}`);\n *\n * for (const { test, error } of results.failed) {\n * console.error(`FAIL: ${test.name} - ${error._tag}`);\n * }\n * ```\n */\nexport interface TestResults<E, R> {\n /** Tests that passed */\n readonly passed: StorageTestCase<E, R>[];\n /** Tests that failed with their errors */\n readonly failed: FailedTest<E, R>[];\n /** Total number of tests run */\n readonly total: number;\n /** Number of tests that passed */\n readonly passCount: number;\n /** Number of tests that failed */\n readonly failCount: number;\n}\n"],"mappings":";;;;;;;;;;;AAcA,IAAa,YAAb,cAA+B,KAAK,YAAY,YAAY,CAOzD"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@voidhash/mimic-effect",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "1.0.0-beta.2",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -13,6 +13,11 @@
|
|
|
13
13
|
"types": "./dist/index.d.mts",
|
|
14
14
|
"import": "./dist/index.mjs",
|
|
15
15
|
"require": "./dist/index.cjs"
|
|
16
|
+
},
|
|
17
|
+
"./testing": {
|
|
18
|
+
"types": "./dist/testing/index.d.mts",
|
|
19
|
+
"import": "./dist/testing/index.mjs",
|
|
20
|
+
"require": "./dist/testing/index.cjs"
|
|
16
21
|
}
|
|
17
22
|
},
|
|
18
23
|
"devDependencies": {
|
|
@@ -21,12 +26,22 @@
|
|
|
21
26
|
"typescript": "5.8.3",
|
|
22
27
|
"vite-tsconfig-paths": "^5.1.4",
|
|
23
28
|
"vitest": "^3.2.4",
|
|
24
|
-
"@voidhash/tsconfig": "0.0.
|
|
29
|
+
"@voidhash/tsconfig": "1.0.0-beta.2"
|
|
25
30
|
},
|
|
26
31
|
"peerDependencies": {
|
|
27
32
|
"@effect/platform": "^0.93.8",
|
|
33
|
+
"@effect/cluster": "^0.55.0",
|
|
34
|
+
"@effect/rpc": "^0.72.2",
|
|
28
35
|
"effect": "^3.19.12",
|
|
29
|
-
"@voidhash/mimic": "0.0.
|
|
36
|
+
"@voidhash/mimic": "1.0.0-beta.2"
|
|
37
|
+
},
|
|
38
|
+
"peerDependenciesMeta": {
|
|
39
|
+
"@effect/cluster": {
|
|
40
|
+
"optional": true
|
|
41
|
+
},
|
|
42
|
+
"@effect/rpc": {
|
|
43
|
+
"optional": true
|
|
44
|
+
}
|
|
30
45
|
},
|
|
31
46
|
"scripts": {
|
|
32
47
|
"build": "tsdown",
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @voidhash/mimic-effect - ColdStorage
|
|
3
|
+
*
|
|
4
|
+
* Interface and implementations for document snapshot storage.
|
|
5
|
+
*/
|
|
6
|
+
import { Context, Effect, HashMap, Layer, Ref } from "effect";
|
|
7
|
+
import type { StoredDocument } from "./Types";
|
|
8
|
+
import { ColdStorageError } from "./Errors";
|
|
9
|
+
|
|
10
|
+
// =============================================================================
|
|
11
|
+
// ColdStorage Interface
|
|
12
|
+
// =============================================================================
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* ColdStorage interface for storing document snapshots.
|
|
16
|
+
*
|
|
17
|
+
* This is the "cold" tier of the two-tier storage system.
|
|
18
|
+
* It stores complete document snapshots less frequently (on periodic intervals
|
|
19
|
+
* or after a threshold of transactions).
|
|
20
|
+
*/
|
|
21
|
+
export interface ColdStorage {
|
|
22
|
+
/**
|
|
23
|
+
* Load a document snapshot.
|
|
24
|
+
* Returns undefined if the document doesn't exist.
|
|
25
|
+
*/
|
|
26
|
+
readonly load: (
|
|
27
|
+
documentId: string
|
|
28
|
+
) => Effect.Effect<StoredDocument | undefined, ColdStorageError>;
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Save a document snapshot.
|
|
32
|
+
*/
|
|
33
|
+
readonly save: (
|
|
34
|
+
documentId: string,
|
|
35
|
+
document: StoredDocument
|
|
36
|
+
) => Effect.Effect<void, ColdStorageError>;
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Delete a document snapshot.
|
|
40
|
+
*/
|
|
41
|
+
readonly delete: (
|
|
42
|
+
documentId: string
|
|
43
|
+
) => Effect.Effect<void, ColdStorageError>;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// =============================================================================
|
|
47
|
+
// Context Tag
|
|
48
|
+
// =============================================================================
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Context tag for ColdStorage service
|
|
52
|
+
*/
|
|
53
|
+
export class ColdStorageTag extends Context.Tag("@voidhash/mimic-effect/ColdStorage")<
|
|
54
|
+
ColdStorageTag,
|
|
55
|
+
ColdStorage
|
|
56
|
+
>() {}
|
|
57
|
+
|
|
58
|
+
// =============================================================================
|
|
59
|
+
// Factory
|
|
60
|
+
// =============================================================================
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Create a ColdStorage layer from an Effect that produces a ColdStorage service.
|
|
64
|
+
*
|
|
65
|
+
* This allows you to access other Effect services when implementing custom storage.
|
|
66
|
+
*
|
|
67
|
+
* @example
|
|
68
|
+
* ```typescript
|
|
69
|
+
* const Cold = ColdStorage.make(
|
|
70
|
+
* Effect.gen(function*() {
|
|
71
|
+
* const redis = yield* RedisService
|
|
72
|
+
*
|
|
73
|
+
* return {
|
|
74
|
+
* load: (documentId) => redis.get(`doc:${documentId}`).pipe(
|
|
75
|
+
* Effect.map(data => data ? JSON.parse(data) : undefined)
|
|
76
|
+
* ),
|
|
77
|
+
* save: (documentId, document) =>
|
|
78
|
+
* redis.set(`doc:${documentId}`, JSON.stringify(document)),
|
|
79
|
+
* delete: (documentId) => redis.del(`doc:${documentId}`),
|
|
80
|
+
* }
|
|
81
|
+
* })
|
|
82
|
+
* )
|
|
83
|
+
* ```
|
|
84
|
+
*/
|
|
85
|
+
export const make = <E, R>(
|
|
86
|
+
effect: Effect.Effect<ColdStorage, E, R>
|
|
87
|
+
): Layer.Layer<ColdStorageTag, E, R> =>
|
|
88
|
+
Layer.effect(ColdStorageTag, effect);
|
|
89
|
+
|
|
90
|
+
// =============================================================================
|
|
91
|
+
// InMemory Implementation
|
|
92
|
+
// =============================================================================
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* In-memory ColdStorage implementation.
|
|
96
|
+
*
|
|
97
|
+
* Useful for testing and development. Not suitable for production
|
|
98
|
+
* as data is lost when the process restarts.
|
|
99
|
+
*/
|
|
100
|
+
export namespace InMemory {
|
|
101
|
+
/**
|
|
102
|
+
* Create an in-memory ColdStorage layer.
|
|
103
|
+
*/
|
|
104
|
+
export const make = (): Layer.Layer<ColdStorageTag> =>
|
|
105
|
+
Layer.effect(
|
|
106
|
+
ColdStorageTag,
|
|
107
|
+
Effect.gen(function* () {
|
|
108
|
+
const store = yield* Ref.make(HashMap.empty<string, StoredDocument>());
|
|
109
|
+
|
|
110
|
+
return {
|
|
111
|
+
load: (documentId) =>
|
|
112
|
+
Effect.gen(function* () {
|
|
113
|
+
const current = yield* Ref.get(store);
|
|
114
|
+
const result = HashMap.get(current, documentId);
|
|
115
|
+
return result._tag === "Some" ? result.value : undefined;
|
|
116
|
+
}),
|
|
117
|
+
|
|
118
|
+
save: (documentId, document) =>
|
|
119
|
+
Ref.update(store, (map) => HashMap.set(map, documentId, document)),
|
|
120
|
+
|
|
121
|
+
delete: (documentId) =>
|
|
122
|
+
Ref.update(store, (map) => HashMap.remove(map, documentId)),
|
|
123
|
+
};
|
|
124
|
+
})
|
|
125
|
+
);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// =============================================================================
|
|
129
|
+
// Re-export namespace
|
|
130
|
+
// =============================================================================
|
|
131
|
+
|
|
132
|
+
export const ColdStorage = {
|
|
133
|
+
Tag: ColdStorageTag,
|
|
134
|
+
make,
|
|
135
|
+
InMemory,
|
|
136
|
+
};
|