@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
|
@@ -1,290 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect } from "vitest";
|
|
2
|
-
import * as Effect from "effect/Effect";
|
|
3
|
-
import * as Duration from "effect/Duration";
|
|
4
|
-
import * as Schema from "effect/Schema";
|
|
5
|
-
import { Primitive, Presence } from "@voidhash/mimic";
|
|
6
|
-
import * as MimicConfig from "../src/MimicConfig";
|
|
7
|
-
|
|
8
|
-
// =============================================================================
|
|
9
|
-
// Test Schema
|
|
10
|
-
// =============================================================================
|
|
11
|
-
|
|
12
|
-
const TestSchema = Primitive.Struct({
|
|
13
|
-
title: Primitive.String().default(""),
|
|
14
|
-
count: Primitive.Number().default(0),
|
|
15
|
-
});
|
|
16
|
-
|
|
17
|
-
// =============================================================================
|
|
18
|
-
// MimicConfig Tests
|
|
19
|
-
// =============================================================================
|
|
20
|
-
|
|
21
|
-
describe("MimicConfig", () => {
|
|
22
|
-
describe("make", () => {
|
|
23
|
-
it("should create config with default values", () => {
|
|
24
|
-
const config = MimicConfig.make({
|
|
25
|
-
schema: TestSchema,
|
|
26
|
-
});
|
|
27
|
-
|
|
28
|
-
expect(config.schema).toBe(TestSchema);
|
|
29
|
-
expect(Duration.toMillis(config.maxIdleTime)).toBe(5 * 60 * 1000); // 5 minutes
|
|
30
|
-
expect(config.maxTransactionHistory).toBe(1000);
|
|
31
|
-
expect(Duration.toMillis(config.heartbeatInterval)).toBe(30 * 1000); // 30 seconds
|
|
32
|
-
expect(Duration.toMillis(config.heartbeatTimeout)).toBe(10 * 1000); // 10 seconds
|
|
33
|
-
});
|
|
34
|
-
|
|
35
|
-
it("should accept custom maxIdleTime", () => {
|
|
36
|
-
const config = MimicConfig.make({
|
|
37
|
-
schema: TestSchema,
|
|
38
|
-
maxIdleTime: "10 minutes",
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
expect(Duration.toMillis(config.maxIdleTime)).toBe(10 * 60 * 1000);
|
|
42
|
-
});
|
|
43
|
-
|
|
44
|
-
it("should accept custom maxTransactionHistory", () => {
|
|
45
|
-
const config = MimicConfig.make({
|
|
46
|
-
schema: TestSchema,
|
|
47
|
-
maxTransactionHistory: 500,
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
expect(config.maxTransactionHistory).toBe(500);
|
|
51
|
-
});
|
|
52
|
-
|
|
53
|
-
it("should accept custom heartbeatInterval", () => {
|
|
54
|
-
const config = MimicConfig.make({
|
|
55
|
-
schema: TestSchema,
|
|
56
|
-
heartbeatInterval: "1 minute",
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
expect(Duration.toMillis(config.heartbeatInterval)).toBe(60 * 1000);
|
|
60
|
-
});
|
|
61
|
-
|
|
62
|
-
it("should accept custom heartbeatTimeout", () => {
|
|
63
|
-
const config = MimicConfig.make({
|
|
64
|
-
schema: TestSchema,
|
|
65
|
-
heartbeatTimeout: "30 seconds",
|
|
66
|
-
});
|
|
67
|
-
|
|
68
|
-
expect(Duration.toMillis(config.heartbeatTimeout)).toBe(30 * 1000);
|
|
69
|
-
});
|
|
70
|
-
|
|
71
|
-
it("should accept all custom values", () => {
|
|
72
|
-
const config = MimicConfig.make({
|
|
73
|
-
schema: TestSchema,
|
|
74
|
-
maxIdleTime: "15 minutes",
|
|
75
|
-
maxTransactionHistory: 2000,
|
|
76
|
-
heartbeatInterval: "45 seconds",
|
|
77
|
-
heartbeatTimeout: "15 seconds",
|
|
78
|
-
});
|
|
79
|
-
|
|
80
|
-
expect(config.schema).toBe(TestSchema);
|
|
81
|
-
expect(Duration.toMillis(config.maxIdleTime)).toBe(15 * 60 * 1000);
|
|
82
|
-
expect(config.maxTransactionHistory).toBe(2000);
|
|
83
|
-
expect(Duration.toMillis(config.heartbeatInterval)).toBe(45 * 1000);
|
|
84
|
-
expect(Duration.toMillis(config.heartbeatTimeout)).toBe(15 * 1000);
|
|
85
|
-
});
|
|
86
|
-
});
|
|
87
|
-
|
|
88
|
-
describe("layer", () => {
|
|
89
|
-
it("should create a layer that provides MimicServerConfigTag", async () => {
|
|
90
|
-
const testLayer = MimicConfig.layer({
|
|
91
|
-
schema: TestSchema,
|
|
92
|
-
maxTransactionHistory: 100,
|
|
93
|
-
});
|
|
94
|
-
|
|
95
|
-
const result = await Effect.runPromise(
|
|
96
|
-
Effect.gen(function* () {
|
|
97
|
-
const config = yield* MimicConfig.MimicServerConfigTag;
|
|
98
|
-
return config;
|
|
99
|
-
}).pipe(Effect.provide(testLayer))
|
|
100
|
-
);
|
|
101
|
-
|
|
102
|
-
expect(result.schema).toBe(TestSchema);
|
|
103
|
-
expect(result.maxTransactionHistory).toBe(100);
|
|
104
|
-
});
|
|
105
|
-
});
|
|
106
|
-
|
|
107
|
-
describe("MimicServerConfigTag", () => {
|
|
108
|
-
it("should have the correct tag identifier", () => {
|
|
109
|
-
expect(MimicConfig.MimicServerConfigTag.key).toBe(
|
|
110
|
-
"@voidhash/mimic-server-effect/MimicServerConfig"
|
|
111
|
-
);
|
|
112
|
-
});
|
|
113
|
-
});
|
|
114
|
-
|
|
115
|
-
describe("presence configuration", () => {
|
|
116
|
-
const CursorPresence = Presence.make({
|
|
117
|
-
schema: Schema.Struct({
|
|
118
|
-
x: Schema.Number,
|
|
119
|
-
y: Schema.Number,
|
|
120
|
-
name: Schema.optional(Schema.String),
|
|
121
|
-
}),
|
|
122
|
-
});
|
|
123
|
-
|
|
124
|
-
it("should have undefined presence by default", () => {
|
|
125
|
-
const config = MimicConfig.make({
|
|
126
|
-
schema: TestSchema,
|
|
127
|
-
});
|
|
128
|
-
|
|
129
|
-
expect(config.presence).toBeUndefined();
|
|
130
|
-
});
|
|
131
|
-
|
|
132
|
-
it("should accept presence schema option", () => {
|
|
133
|
-
const config = MimicConfig.make({
|
|
134
|
-
schema: TestSchema,
|
|
135
|
-
presence: CursorPresence,
|
|
136
|
-
});
|
|
137
|
-
|
|
138
|
-
expect(config.presence).toBe(CursorPresence);
|
|
139
|
-
});
|
|
140
|
-
|
|
141
|
-
it("should provide presence through layer", async () => {
|
|
142
|
-
const testLayer = MimicConfig.layer({
|
|
143
|
-
schema: TestSchema,
|
|
144
|
-
presence: CursorPresence,
|
|
145
|
-
});
|
|
146
|
-
|
|
147
|
-
const result = await Effect.runPromise(
|
|
148
|
-
Effect.gen(function* () {
|
|
149
|
-
const config = yield* MimicConfig.MimicServerConfigTag;
|
|
150
|
-
return config.presence;
|
|
151
|
-
}).pipe(Effect.provide(testLayer))
|
|
152
|
-
);
|
|
153
|
-
|
|
154
|
-
expect(result).toBe(CursorPresence);
|
|
155
|
-
});
|
|
156
|
-
|
|
157
|
-
it("should work with all options including presence", () => {
|
|
158
|
-
const config = MimicConfig.make({
|
|
159
|
-
schema: TestSchema,
|
|
160
|
-
maxIdleTime: "10 minutes",
|
|
161
|
-
maxTransactionHistory: 500,
|
|
162
|
-
heartbeatInterval: "1 minute",
|
|
163
|
-
heartbeatTimeout: "20 seconds",
|
|
164
|
-
presence: CursorPresence,
|
|
165
|
-
});
|
|
166
|
-
|
|
167
|
-
expect(config.schema).toBe(TestSchema);
|
|
168
|
-
expect(Duration.toMillis(config.maxIdleTime)).toBe(10 * 60 * 1000);
|
|
169
|
-
expect(config.maxTransactionHistory).toBe(500);
|
|
170
|
-
expect(Duration.toMillis(config.heartbeatInterval)).toBe(60 * 1000);
|
|
171
|
-
expect(Duration.toMillis(config.heartbeatTimeout)).toBe(20 * 1000);
|
|
172
|
-
expect(config.presence).toBe(CursorPresence);
|
|
173
|
-
});
|
|
174
|
-
});
|
|
175
|
-
|
|
176
|
-
describe("initial state configuration", () => {
|
|
177
|
-
it("should have undefined initial state by default", () => {
|
|
178
|
-
const config = MimicConfig.make({
|
|
179
|
-
schema: TestSchema,
|
|
180
|
-
});
|
|
181
|
-
|
|
182
|
-
expect(config.initial).toBeUndefined();
|
|
183
|
-
});
|
|
184
|
-
|
|
185
|
-
it("should accept initial state object and convert to function", async () => {
|
|
186
|
-
const config = MimicConfig.make({
|
|
187
|
-
schema: TestSchema,
|
|
188
|
-
initial: { title: "My Document", count: 42 },
|
|
189
|
-
});
|
|
190
|
-
|
|
191
|
-
expect(typeof config.initial).toBe("function");
|
|
192
|
-
// The function should return the initial state when called
|
|
193
|
-
const result = await Effect.runPromise(config.initial!({ documentId: "test-doc" }));
|
|
194
|
-
expect(result).toEqual({ title: "My Document", count: 42 });
|
|
195
|
-
});
|
|
196
|
-
|
|
197
|
-
it("should apply defaults for omitted fields in initial state object", async () => {
|
|
198
|
-
const config = MimicConfig.make({
|
|
199
|
-
schema: TestSchema,
|
|
200
|
-
initial: { title: "My Document" }, // count has default of 0
|
|
201
|
-
});
|
|
202
|
-
|
|
203
|
-
const result = await Effect.runPromise(config.initial!({ documentId: "test-doc" }));
|
|
204
|
-
expect(result).toEqual({ title: "My Document", count: 0 });
|
|
205
|
-
});
|
|
206
|
-
|
|
207
|
-
it("should accept initial state function", async () => {
|
|
208
|
-
const config = MimicConfig.make({
|
|
209
|
-
schema: TestSchema,
|
|
210
|
-
initial: ({ documentId }) => Effect.succeed({ title: `Doc ${documentId}`, count: 123 }),
|
|
211
|
-
});
|
|
212
|
-
|
|
213
|
-
expect(typeof config.initial).toBe("function");
|
|
214
|
-
const result = await Effect.runPromise(config.initial!({ documentId: "my-doc-id" }));
|
|
215
|
-
expect(result).toEqual({ title: "Doc my-doc-id", count: 123 });
|
|
216
|
-
});
|
|
217
|
-
|
|
218
|
-
it("should apply defaults to initial state function result", async () => {
|
|
219
|
-
const config = MimicConfig.make({
|
|
220
|
-
schema: TestSchema,
|
|
221
|
-
initial: ({ documentId }) => Effect.succeed({ title: documentId }), // count omitted
|
|
222
|
-
});
|
|
223
|
-
|
|
224
|
-
const result = await Effect.runPromise(config.initial!({ documentId: "test" }));
|
|
225
|
-
expect(result).toEqual({ title: "test", count: 0 });
|
|
226
|
-
});
|
|
227
|
-
|
|
228
|
-
it("should provide initial function through layer", async () => {
|
|
229
|
-
const testLayer = MimicConfig.layer({
|
|
230
|
-
schema: TestSchema,
|
|
231
|
-
initial: { title: "From Layer", count: 100 },
|
|
232
|
-
});
|
|
233
|
-
|
|
234
|
-
const result = await Effect.runPromise(
|
|
235
|
-
Effect.gen(function* () {
|
|
236
|
-
const config = yield* MimicConfig.MimicServerConfigTag;
|
|
237
|
-
return yield* config.initial!({ documentId: "layer-doc" });
|
|
238
|
-
}).pipe(Effect.provide(testLayer))
|
|
239
|
-
);
|
|
240
|
-
|
|
241
|
-
expect(result).toEqual({ title: "From Layer", count: 100 });
|
|
242
|
-
});
|
|
243
|
-
|
|
244
|
-
it("should work with schema that has required fields without defaults", async () => {
|
|
245
|
-
const SchemaWithRequired = Primitive.Struct({
|
|
246
|
-
name: Primitive.String().required(),
|
|
247
|
-
optional: Primitive.String().default("default"),
|
|
248
|
-
});
|
|
249
|
-
|
|
250
|
-
const config = MimicConfig.make({
|
|
251
|
-
schema: SchemaWithRequired,
|
|
252
|
-
initial: { name: "Required Name" },
|
|
253
|
-
});
|
|
254
|
-
|
|
255
|
-
const result = await Effect.runPromise(config.initial!({ documentId: "test" }));
|
|
256
|
-
expect(result).toEqual({ name: "Required Name", optional: "default" });
|
|
257
|
-
});
|
|
258
|
-
|
|
259
|
-
it("should work with all options including initial object", async () => {
|
|
260
|
-
const config = MimicConfig.make({
|
|
261
|
-
schema: TestSchema,
|
|
262
|
-
maxIdleTime: "10 minutes",
|
|
263
|
-
maxTransactionHistory: 500,
|
|
264
|
-
initial: { title: "Full Options", count: 999 },
|
|
265
|
-
});
|
|
266
|
-
|
|
267
|
-
expect(config.schema).toBe(TestSchema);
|
|
268
|
-
expect(Duration.toMillis(config.maxIdleTime)).toBe(10 * 60 * 1000);
|
|
269
|
-
expect(config.maxTransactionHistory).toBe(500);
|
|
270
|
-
const result = await Effect.runPromise(config.initial!({ documentId: "test" }));
|
|
271
|
-
expect(result).toEqual({ title: "Full Options", count: 999 });
|
|
272
|
-
});
|
|
273
|
-
|
|
274
|
-
it("should work with initial function that uses documentId", async () => {
|
|
275
|
-
const config = MimicConfig.make({
|
|
276
|
-
schema: TestSchema,
|
|
277
|
-
initial: ({ documentId }) => Effect.succeed({
|
|
278
|
-
title: `Document: ${documentId}`,
|
|
279
|
-
count: documentId.length,
|
|
280
|
-
}),
|
|
281
|
-
});
|
|
282
|
-
|
|
283
|
-
const result1 = await Effect.runPromise(config.initial!({ documentId: "short" }));
|
|
284
|
-
expect(result1).toEqual({ title: "Document: short", count: 5 });
|
|
285
|
-
|
|
286
|
-
const result2 = await Effect.runPromise(config.initial!({ documentId: "longer-id" }));
|
|
287
|
-
expect(result2).toEqual({ title: "Document: longer-id", count: 9 });
|
|
288
|
-
});
|
|
289
|
-
});
|
|
290
|
-
});
|
|
@@ -1,190 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect } from "vitest";
|
|
2
|
-
import * as Effect from "effect/Effect";
|
|
3
|
-
import * as MimicDataStorage from "../src/MimicDataStorage";
|
|
4
|
-
|
|
5
|
-
// =============================================================================
|
|
6
|
-
// Error Tests
|
|
7
|
-
// =============================================================================
|
|
8
|
-
|
|
9
|
-
describe("MimicDataStorage", () => {
|
|
10
|
-
describe("StorageLoadError", () => {
|
|
11
|
-
it("should have correct message", () => {
|
|
12
|
-
const error = new MimicDataStorage.StorageLoadError({
|
|
13
|
-
documentId: "doc-123",
|
|
14
|
-
cause: new Error("Connection failed"),
|
|
15
|
-
});
|
|
16
|
-
expect(error.message).toBe(
|
|
17
|
-
"Failed to load document doc-123: Error: Connection failed"
|
|
18
|
-
);
|
|
19
|
-
expect(error._tag).toBe("StorageLoadError");
|
|
20
|
-
expect(error.documentId).toBe("doc-123");
|
|
21
|
-
});
|
|
22
|
-
});
|
|
23
|
-
|
|
24
|
-
describe("StorageSaveError", () => {
|
|
25
|
-
it("should have correct message", () => {
|
|
26
|
-
const error = new MimicDataStorage.StorageSaveError({
|
|
27
|
-
documentId: "doc-456",
|
|
28
|
-
cause: new Error("Disk full"),
|
|
29
|
-
});
|
|
30
|
-
expect(error.message).toBe(
|
|
31
|
-
"Failed to save document doc-456: Error: Disk full"
|
|
32
|
-
);
|
|
33
|
-
expect(error._tag).toBe("StorageSaveError");
|
|
34
|
-
expect(error.documentId).toBe("doc-456");
|
|
35
|
-
});
|
|
36
|
-
});
|
|
37
|
-
|
|
38
|
-
describe("StorageDeleteError", () => {
|
|
39
|
-
it("should have correct message", () => {
|
|
40
|
-
const error = new MimicDataStorage.StorageDeleteError({
|
|
41
|
-
documentId: "doc-789",
|
|
42
|
-
cause: new Error("Permission denied"),
|
|
43
|
-
});
|
|
44
|
-
expect(error.message).toBe(
|
|
45
|
-
"Failed to delete document doc-789: Error: Permission denied"
|
|
46
|
-
);
|
|
47
|
-
expect(error._tag).toBe("StorageDeleteError");
|
|
48
|
-
expect(error.documentId).toBe("doc-789");
|
|
49
|
-
});
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
describe("make", () => {
|
|
53
|
-
it("should create storage with required functions", async () => {
|
|
54
|
-
const storage = MimicDataStorage.make({
|
|
55
|
-
load: (documentId) => Effect.succeed({ id: documentId, data: "test" }),
|
|
56
|
-
save: (_documentId, _state) => Effect.void,
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
const loaded = await Effect.runPromise(storage.load("doc-1"));
|
|
60
|
-
expect(loaded).toEqual({ id: "doc-1", data: "test" });
|
|
61
|
-
|
|
62
|
-
await Effect.runPromise(storage.save("doc-1", { data: "new" }));
|
|
63
|
-
});
|
|
64
|
-
|
|
65
|
-
it("should provide default delete implementation", async () => {
|
|
66
|
-
const storage = MimicDataStorage.make({
|
|
67
|
-
load: (_documentId) => Effect.succeed(undefined),
|
|
68
|
-
save: (_documentId, _state) => Effect.void,
|
|
69
|
-
});
|
|
70
|
-
|
|
71
|
-
// Default delete should be a no-op
|
|
72
|
-
await Effect.runPromise(storage.delete("doc-1"));
|
|
73
|
-
});
|
|
74
|
-
|
|
75
|
-
it("should provide default onLoad implementation (pass-through)", async () => {
|
|
76
|
-
const storage = MimicDataStorage.make({
|
|
77
|
-
load: (_documentId) => Effect.succeed(undefined),
|
|
78
|
-
save: (_documentId, _state) => Effect.void,
|
|
79
|
-
});
|
|
80
|
-
|
|
81
|
-
const state = { title: "Test" };
|
|
82
|
-
const result = await Effect.runPromise(storage.onLoad(state));
|
|
83
|
-
expect(result).toBe(state);
|
|
84
|
-
});
|
|
85
|
-
|
|
86
|
-
it("should provide default onSave implementation (pass-through)", async () => {
|
|
87
|
-
const storage = MimicDataStorage.make({
|
|
88
|
-
load: (_documentId) => Effect.succeed(undefined),
|
|
89
|
-
save: (_documentId, _state) => Effect.void,
|
|
90
|
-
});
|
|
91
|
-
|
|
92
|
-
const state = { title: "Test" };
|
|
93
|
-
const result = await Effect.runPromise(storage.onSave(state));
|
|
94
|
-
expect(result).toBe(state);
|
|
95
|
-
});
|
|
96
|
-
|
|
97
|
-
it("should accept custom delete implementation", async () => {
|
|
98
|
-
let deletedId: string | null = null;
|
|
99
|
-
const storage = MimicDataStorage.make({
|
|
100
|
-
load: (_documentId) => Effect.succeed(undefined),
|
|
101
|
-
save: (_documentId, _state) => Effect.void,
|
|
102
|
-
delete: (documentId) => {
|
|
103
|
-
deletedId = documentId;
|
|
104
|
-
return Effect.void;
|
|
105
|
-
},
|
|
106
|
-
});
|
|
107
|
-
|
|
108
|
-
await Effect.runPromise(storage.delete("doc-to-delete"));
|
|
109
|
-
expect(deletedId).toBe("doc-to-delete");
|
|
110
|
-
});
|
|
111
|
-
|
|
112
|
-
it("should accept custom onLoad implementation", async () => {
|
|
113
|
-
const storage = MimicDataStorage.make({
|
|
114
|
-
load: (_documentId) => Effect.succeed(undefined),
|
|
115
|
-
save: (_documentId, _state) => Effect.void,
|
|
116
|
-
onLoad: (state) =>
|
|
117
|
-
Effect.succeed({ ...(state as object), loaded: true }),
|
|
118
|
-
});
|
|
119
|
-
|
|
120
|
-
const result = await Effect.runPromise(
|
|
121
|
-
storage.onLoad({ title: "Test" })
|
|
122
|
-
);
|
|
123
|
-
expect(result).toEqual({ title: "Test", loaded: true });
|
|
124
|
-
});
|
|
125
|
-
|
|
126
|
-
it("should accept custom onSave implementation", async () => {
|
|
127
|
-
const storage = MimicDataStorage.make({
|
|
128
|
-
load: (_documentId) => Effect.succeed(undefined),
|
|
129
|
-
save: (_documentId, _state) => Effect.void,
|
|
130
|
-
onSave: (state) =>
|
|
131
|
-
Effect.succeed({ ...(state as object), savedAt: "now" }),
|
|
132
|
-
});
|
|
133
|
-
|
|
134
|
-
const result = await Effect.runPromise(
|
|
135
|
-
storage.onSave({ title: "Test" })
|
|
136
|
-
);
|
|
137
|
-
expect(result).toEqual({ title: "Test", savedAt: "now" });
|
|
138
|
-
});
|
|
139
|
-
});
|
|
140
|
-
|
|
141
|
-
describe("layer", () => {
|
|
142
|
-
it("should create a layer that provides MimicDataStorageTag", async () => {
|
|
143
|
-
const testStorage = MimicDataStorage.make({
|
|
144
|
-
load: (_documentId) => Effect.succeed({ test: true }),
|
|
145
|
-
save: (_documentId, _state) => Effect.void,
|
|
146
|
-
});
|
|
147
|
-
|
|
148
|
-
const testLayer = MimicDataStorage.layer(testStorage);
|
|
149
|
-
|
|
150
|
-
const result = await Effect.runPromise(
|
|
151
|
-
Effect.gen(function* () {
|
|
152
|
-
const storage = yield* MimicDataStorage.MimicDataStorageTag;
|
|
153
|
-
return yield* storage.load("doc-1");
|
|
154
|
-
}).pipe(Effect.provide(testLayer))
|
|
155
|
-
);
|
|
156
|
-
|
|
157
|
-
expect(result).toEqual({ test: true });
|
|
158
|
-
});
|
|
159
|
-
});
|
|
160
|
-
|
|
161
|
-
describe("layerEffect", () => {
|
|
162
|
-
it("should create a layer from an Effect", async () => {
|
|
163
|
-
const testLayer = MimicDataStorage.layerEffect(
|
|
164
|
-
Effect.succeed(
|
|
165
|
-
MimicDataStorage.make({
|
|
166
|
-
load: (_documentId) => Effect.succeed({ fromEffect: true }),
|
|
167
|
-
save: (_documentId, _state) => Effect.void,
|
|
168
|
-
})
|
|
169
|
-
)
|
|
170
|
-
);
|
|
171
|
-
|
|
172
|
-
const result = await Effect.runPromise(
|
|
173
|
-
Effect.gen(function* () {
|
|
174
|
-
const storage = yield* MimicDataStorage.MimicDataStorageTag;
|
|
175
|
-
return yield* storage.load("doc-1");
|
|
176
|
-
}).pipe(Effect.provide(testLayer))
|
|
177
|
-
);
|
|
178
|
-
|
|
179
|
-
expect(result).toEqual({ fromEffect: true });
|
|
180
|
-
});
|
|
181
|
-
});
|
|
182
|
-
|
|
183
|
-
describe("MimicDataStorageTag", () => {
|
|
184
|
-
it("should have the correct tag identifier", () => {
|
|
185
|
-
expect(MimicDataStorage.MimicDataStorageTag.key).toBe(
|
|
186
|
-
"@voidhash/mimic-server-effect/MimicDataStorage"
|
|
187
|
-
);
|
|
188
|
-
});
|
|
189
|
-
});
|
|
190
|
-
});
|
package/tests/NoAuth.test.ts
DELETED
|
@@ -1,94 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect } from "vitest";
|
|
2
|
-
import * as Effect from "effect/Effect";
|
|
3
|
-
import * as NoAuth from "../src/auth/NoAuth";
|
|
4
|
-
import { MimicAuthServiceTag } from "../src/MimicAuthService";
|
|
5
|
-
|
|
6
|
-
// =============================================================================
|
|
7
|
-
// NoAuth Tests
|
|
8
|
-
// =============================================================================
|
|
9
|
-
|
|
10
|
-
describe("NoAuth", () => {
|
|
11
|
-
describe("authenticate", () => {
|
|
12
|
-
it("should always return success: true", async () => {
|
|
13
|
-
const result = await Effect.runPromise(
|
|
14
|
-
Effect.gen(function* () {
|
|
15
|
-
const authService = yield* MimicAuthServiceTag;
|
|
16
|
-
return yield* authService.authenticate("any-token");
|
|
17
|
-
}).pipe(Effect.provide(NoAuth.layer))
|
|
18
|
-
);
|
|
19
|
-
|
|
20
|
-
expect(result).toEqual({ success: true });
|
|
21
|
-
});
|
|
22
|
-
|
|
23
|
-
it("should succeed with empty token", async () => {
|
|
24
|
-
const result = await Effect.runPromise(
|
|
25
|
-
Effect.gen(function* () {
|
|
26
|
-
const authService = yield* MimicAuthServiceTag;
|
|
27
|
-
return yield* authService.authenticate("");
|
|
28
|
-
}).pipe(Effect.provide(NoAuth.layer))
|
|
29
|
-
);
|
|
30
|
-
|
|
31
|
-
expect(result.success).toBe(true);
|
|
32
|
-
});
|
|
33
|
-
|
|
34
|
-
it("should succeed with any arbitrary token", async () => {
|
|
35
|
-
const tokens = [
|
|
36
|
-
"valid-token-123",
|
|
37
|
-
"invalid-token",
|
|
38
|
-
"abc123xyz",
|
|
39
|
-
"special!@#$%^&*()",
|
|
40
|
-
"very-long-token-" + "x".repeat(1000),
|
|
41
|
-
];
|
|
42
|
-
|
|
43
|
-
for (const token of tokens) {
|
|
44
|
-
const result = await Effect.runPromise(
|
|
45
|
-
Effect.gen(function* () {
|
|
46
|
-
const authService = yield* MimicAuthServiceTag;
|
|
47
|
-
return yield* authService.authenticate(token);
|
|
48
|
-
}).pipe(Effect.provide(NoAuth.layer))
|
|
49
|
-
);
|
|
50
|
-
|
|
51
|
-
expect(result.success).toBe(true);
|
|
52
|
-
}
|
|
53
|
-
});
|
|
54
|
-
|
|
55
|
-
it("should not include userId in result", async () => {
|
|
56
|
-
const result = await Effect.runPromise(
|
|
57
|
-
Effect.gen(function* () {
|
|
58
|
-
const authService = yield* MimicAuthServiceTag;
|
|
59
|
-
return yield* authService.authenticate("test-token");
|
|
60
|
-
}).pipe(Effect.provide(NoAuth.layer))
|
|
61
|
-
);
|
|
62
|
-
|
|
63
|
-
expect(result.success).toBe(true);
|
|
64
|
-
if (result.success) {
|
|
65
|
-
expect(result.userId).toBeUndefined();
|
|
66
|
-
}
|
|
67
|
-
});
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
describe("layer aliases", () => {
|
|
71
|
-
it("should have layerDefault as an alias for layer", () => {
|
|
72
|
-
expect(NoAuth.layerDefault).toBe(NoAuth.layer);
|
|
73
|
-
});
|
|
74
|
-
});
|
|
75
|
-
|
|
76
|
-
describe("multiple authentications", () => {
|
|
77
|
-
it("should handle multiple sequential authentications", async () => {
|
|
78
|
-
const results = await Effect.runPromise(
|
|
79
|
-
Effect.gen(function* () {
|
|
80
|
-
const authService = yield* MimicAuthServiceTag;
|
|
81
|
-
const result1 = yield* authService.authenticate("token-1");
|
|
82
|
-
const result2 = yield* authService.authenticate("token-2");
|
|
83
|
-
const result3 = yield* authService.authenticate("token-3");
|
|
84
|
-
return [result1, result2, result3];
|
|
85
|
-
}).pipe(Effect.provide(NoAuth.layer))
|
|
86
|
-
);
|
|
87
|
-
|
|
88
|
-
expect(results).toHaveLength(3);
|
|
89
|
-
for (const result of results) {
|
|
90
|
-
expect(result.success).toBe(true);
|
|
91
|
-
}
|
|
92
|
-
});
|
|
93
|
-
});
|
|
94
|
-
});
|