@palantir/pack.state.core 0.0.1-beta.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/.turbo/turbo-lint.log +4 -0
- package/.turbo/turbo-transpileBrowser.log +5 -0
- package/.turbo/turbo-transpileCjs.log +5 -0
- package/.turbo/turbo-transpileEsm.log +5 -0
- package/.turbo/turbo-transpileTypes.log +5 -0
- package/.turbo/turbo-typecheck.log +4 -0
- package/LICENSE.txt +13 -0
- package/README.md +55 -0
- package/build/browser/index.js +1257 -0
- package/build/browser/index.js.map +1 -0
- package/build/cjs/index.cjs +1298 -0
- package/build/cjs/index.cjs.map +1 -0
- package/build/cjs/index.d.cts +272 -0
- package/build/esm/index.js +1257 -0
- package/build/esm/index.js.map +1 -0
- package/build/types/DocumentServiceModule.d.ts +6 -0
- package/build/types/DocumentServiceModule.d.ts.map +1 -0
- package/build/types/__tests__/DocumentStatusTracking.test.d.ts +1 -0
- package/build/types/__tests__/DocumentStatusTracking.test.d.ts.map +1 -0
- package/build/types/__tests__/RefStability.test.d.ts +1 -0
- package/build/types/__tests__/RefStability.test.d.ts.map +1 -0
- package/build/types/__tests__/StateModule.integration.test.d.ts +1 -0
- package/build/types/__tests__/StateModule.integration.test.d.ts.map +1 -0
- package/build/types/__tests__/testUtils.d.ts +7 -0
- package/build/types/__tests__/testUtils.d.ts.map +1 -0
- package/build/types/index.d.ts +11 -0
- package/build/types/index.d.ts.map +1 -0
- package/build/types/service/BaseYjsDocumentService.d.ts +155 -0
- package/build/types/service/BaseYjsDocumentService.d.ts.map +1 -0
- package/build/types/service/InMemoryDocumentService.d.ts +12 -0
- package/build/types/service/InMemoryDocumentService.d.ts.map +1 -0
- package/build/types/service/YjsSchemaMapper.d.ts +9 -0
- package/build/types/service/YjsSchemaMapper.d.ts.map +1 -0
- package/build/types/types/DocumentRefImpl.d.ts +5 -0
- package/build/types/types/DocumentRefImpl.d.ts.map +1 -0
- package/build/types/types/DocumentService.d.ts +62 -0
- package/build/types/types/DocumentService.d.ts.map +1 -0
- package/build/types/types/DocumentServiceConfig.d.ts +5 -0
- package/build/types/types/DocumentServiceConfig.d.ts.map +1 -0
- package/build/types/types/RecordCollectionRefImpl.d.ts +5 -0
- package/build/types/types/RecordCollectionRefImpl.d.ts.map +1 -0
- package/build/types/types/RecordRefImpl.d.ts +5 -0
- package/build/types/types/RecordRefImpl.d.ts.map +1 -0
- package/build/types/types/StateModule.d.ts +59 -0
- package/build/types/types/StateModule.d.ts.map +1 -0
- package/package.json +71 -0
- package/src/DocumentServiceModule.ts +53 -0
- package/src/__tests__/DocumentStatusTracking.test.ts +229 -0
- package/src/__tests__/RefStability.test.ts +441 -0
- package/src/__tests__/StateModule.integration.test.ts +1187 -0
- package/src/__tests__/testUtils.ts +106 -0
- package/src/index.ts +38 -0
- package/src/service/BaseYjsDocumentService.ts +1277 -0
- package/src/service/InMemoryDocumentService.ts +162 -0
- package/src/service/YjsSchemaMapper.ts +194 -0
- package/src/types/DocumentRefImpl.ts +98 -0
- package/src/types/DocumentService.ts +210 -0
- package/src/types/DocumentServiceConfig.ts +22 -0
- package/src/types/RecordCollectionRefImpl.ts +124 -0
- package/src/types/RecordRefImpl.ts +106 -0
- package/src/types/StateModule.ts +329 -0
- package/tsconfig.json +21 -0
- package/vitest.config.mjs +26 -0
|
@@ -0,0 +1,441 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright 2025 Palantir Technologies, Inc. All rights reserved.
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this file except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
import type { PackAppInternal } from "@palantir/pack.core";
|
|
18
|
+
import type {
|
|
19
|
+
DocumentId,
|
|
20
|
+
DocumentMetadata,
|
|
21
|
+
DocumentSchema,
|
|
22
|
+
Model,
|
|
23
|
+
RecordId,
|
|
24
|
+
} from "@palantir/pack.document-schema.model-types";
|
|
25
|
+
import { Metadata } from "@palantir/pack.document-schema.model-types";
|
|
26
|
+
import { beforeEach, describe, expect, it } from "vitest";
|
|
27
|
+
import { z } from "zod";
|
|
28
|
+
import { createDocRef, invalidDocRef, isValidDocRef } from "../types/DocumentRefImpl.js";
|
|
29
|
+
import {
|
|
30
|
+
invalidRecordCollectionRef,
|
|
31
|
+
isValidRecordCollectionRef,
|
|
32
|
+
} from "../types/RecordCollectionRefImpl.js";
|
|
33
|
+
import { invalidRecordRef, isValidRecordRef } from "../types/RecordRefImpl.js";
|
|
34
|
+
import { getStateModule } from "../types/StateModule.js";
|
|
35
|
+
import { createTestApp } from "./testUtils.js";
|
|
36
|
+
|
|
37
|
+
const TEST_SECURITY = {
|
|
38
|
+
mandatory: {
|
|
39
|
+
classification: ["MU"],
|
|
40
|
+
markings: [],
|
|
41
|
+
},
|
|
42
|
+
discretionary: {
|
|
43
|
+
owners: [],
|
|
44
|
+
editors: [],
|
|
45
|
+
viewers: [],
|
|
46
|
+
},
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
// Test schema with User and Post models
|
|
50
|
+
const createTestSchema = () => {
|
|
51
|
+
const userSchema = z.object({
|
|
52
|
+
id: z.string(),
|
|
53
|
+
name: z.string(),
|
|
54
|
+
email: z.string(),
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
const postSchema = z.object({
|
|
58
|
+
id: z.string(),
|
|
59
|
+
title: z.string(),
|
|
60
|
+
content: z.string(),
|
|
61
|
+
authorId: z.string(),
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
type User = { id: string; name: string; email: string };
|
|
65
|
+
type Post = { id: string; title: string; content: string; authorId: string };
|
|
66
|
+
|
|
67
|
+
const User: Model<User, typeof userSchema> = {
|
|
68
|
+
__type: {} as User,
|
|
69
|
+
zodSchema: userSchema,
|
|
70
|
+
[Metadata]: { name: "User" },
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
const Post: Model<Post, typeof postSchema> = {
|
|
74
|
+
__type: {} as Post,
|
|
75
|
+
zodSchema: postSchema,
|
|
76
|
+
[Metadata]: { name: "Post" },
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
const schema: DocumentSchema = {
|
|
80
|
+
[Metadata]: { version: 1 },
|
|
81
|
+
User,
|
|
82
|
+
Post,
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
return { schema, User, Post };
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
describe("Ref Stability Tests", () => {
|
|
89
|
+
let app: PackAppInternal;
|
|
90
|
+
const { schema, User, Post } = createTestSchema();
|
|
91
|
+
|
|
92
|
+
beforeEach(() => {
|
|
93
|
+
app = createTestApp();
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
describe("DocumentRef Stability", () => {
|
|
97
|
+
it("should return the same DocumentRef instance for identical parameters", () => {
|
|
98
|
+
const stateModule = getStateModule(app);
|
|
99
|
+
const docId = "test-doc-1" as DocumentId;
|
|
100
|
+
|
|
101
|
+
// Create multiple refs with same parameters
|
|
102
|
+
const ref1 = stateModule.createDocRef(docId, schema);
|
|
103
|
+
const ref2 = stateModule.createDocRef(docId, schema);
|
|
104
|
+
const ref3 = stateModule.createDocRef(docId, schema);
|
|
105
|
+
|
|
106
|
+
// Should be the exact same instance (reference equality)
|
|
107
|
+
expect(ref1).toBe(ref2);
|
|
108
|
+
expect(ref2).toBe(ref3);
|
|
109
|
+
expect(ref1).toBe(ref3);
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
it("should return different instances for different document IDs", () => {
|
|
113
|
+
const stateModule = getStateModule(app);
|
|
114
|
+
const docId1 = "test-doc-1" as DocumentId;
|
|
115
|
+
const docId2 = "test-doc-2" as DocumentId;
|
|
116
|
+
|
|
117
|
+
const ref1 = stateModule.createDocRef(docId1, schema);
|
|
118
|
+
const ref2 = stateModule.createDocRef(docId2, schema);
|
|
119
|
+
|
|
120
|
+
// Should be different instances
|
|
121
|
+
expect(ref1).not.toBe(ref2);
|
|
122
|
+
expect(ref1.id).toBe(docId1);
|
|
123
|
+
expect(ref2.id).toBe(docId2);
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
it("should work with invalid refs", () => {
|
|
127
|
+
const invalidRef = invalidDocRef();
|
|
128
|
+
expect(isValidDocRef(invalidRef)).toBe(false);
|
|
129
|
+
|
|
130
|
+
const validRef = createDocRef(app, "valid-doc" as DocumentId, schema);
|
|
131
|
+
expect(isValidDocRef(validRef)).toBe(true);
|
|
132
|
+
});
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
describe("RecordCollectionRef Stability", () => {
|
|
136
|
+
it("should return the same RecordCollectionRef instance for identical parameters", async () => {
|
|
137
|
+
const stateModule = getStateModule(app);
|
|
138
|
+
|
|
139
|
+
// Create a document first
|
|
140
|
+
const metadata: DocumentMetadata = {
|
|
141
|
+
name: "Test Document",
|
|
142
|
+
documentTypeName: "TestType",
|
|
143
|
+
ontologyRid: "test-ontology-rid",
|
|
144
|
+
security: TEST_SECURITY,
|
|
145
|
+
};
|
|
146
|
+
const docRef = await stateModule.createDocument(metadata, schema);
|
|
147
|
+
|
|
148
|
+
// Get collection refs multiple times
|
|
149
|
+
const collection1 = docRef.getRecords(User);
|
|
150
|
+
const collection2 = docRef.getRecords(User);
|
|
151
|
+
const collection3 = docRef.getRecords(User);
|
|
152
|
+
|
|
153
|
+
// Should be the exact same instance (reference equality)
|
|
154
|
+
expect(collection1).toBe(collection2);
|
|
155
|
+
expect(collection2).toBe(collection3);
|
|
156
|
+
expect(collection1).toBe(collection3);
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
it("should return different instances for different models", async () => {
|
|
160
|
+
const stateModule = getStateModule(app);
|
|
161
|
+
|
|
162
|
+
const metadata: DocumentMetadata = {
|
|
163
|
+
name: "Test Document",
|
|
164
|
+
documentTypeName: "TestType",
|
|
165
|
+
ontologyRid: "test-ontology-rid",
|
|
166
|
+
security: TEST_SECURITY,
|
|
167
|
+
};
|
|
168
|
+
const docRef = await stateModule.createDocument(metadata, schema);
|
|
169
|
+
|
|
170
|
+
const userCollection = docRef.getRecords(User);
|
|
171
|
+
const postCollection = docRef.getRecords(Post);
|
|
172
|
+
|
|
173
|
+
// Should be different instances
|
|
174
|
+
expect(userCollection).not.toBe(postCollection);
|
|
175
|
+
expect(userCollection.model).toBe(User);
|
|
176
|
+
expect(postCollection.model).toBe(Post);
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
it("should return different instances for different documents", async () => {
|
|
180
|
+
const stateModule = getStateModule(app);
|
|
181
|
+
|
|
182
|
+
const metadata1: DocumentMetadata = {
|
|
183
|
+
name: "Test Document 1",
|
|
184
|
+
documentTypeName: "TestType",
|
|
185
|
+
ontologyRid: "test-ontology-rid",
|
|
186
|
+
security: TEST_SECURITY,
|
|
187
|
+
};
|
|
188
|
+
const metadata2: DocumentMetadata = {
|
|
189
|
+
name: "Test Document 2",
|
|
190
|
+
documentTypeName: "TestType",
|
|
191
|
+
ontologyRid: "test-ontology-rid",
|
|
192
|
+
security: TEST_SECURITY,
|
|
193
|
+
};
|
|
194
|
+
|
|
195
|
+
const docRef1 = await stateModule.createDocument(metadata1, schema);
|
|
196
|
+
const docRef2 = await stateModule.createDocument(metadata2, schema);
|
|
197
|
+
|
|
198
|
+
const collection1 = docRef1.getRecords(User);
|
|
199
|
+
const collection2 = docRef2.getRecords(User);
|
|
200
|
+
|
|
201
|
+
// Should be different instances
|
|
202
|
+
expect(collection1).not.toBe(collection2);
|
|
203
|
+
expect(collection1.docRef).toBe(docRef1);
|
|
204
|
+
expect(collection2.docRef).toBe(docRef2);
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
it("should work with invalid refs", async () => {
|
|
208
|
+
const invalidRef = invalidRecordCollectionRef();
|
|
209
|
+
expect(isValidRecordCollectionRef(invalidRef)).toBe(false);
|
|
210
|
+
|
|
211
|
+
// All methods should be safe to call
|
|
212
|
+
expect(invalidRef.get("any-id" as RecordId)).toBeUndefined();
|
|
213
|
+
expect(invalidRef.has("any-id" as RecordId)).toBe(false);
|
|
214
|
+
expect(invalidRef.size).toBe(0);
|
|
215
|
+
|
|
216
|
+
// Async methods should reject
|
|
217
|
+
await expect(invalidRef.set("id" as RecordId, {})).rejects.toThrow();
|
|
218
|
+
await expect(invalidRef.delete("id" as RecordId)).rejects.toThrow();
|
|
219
|
+
|
|
220
|
+
// Iterator should be empty
|
|
221
|
+
const iterator = invalidRef[Symbol.iterator]();
|
|
222
|
+
const result = iterator.next();
|
|
223
|
+
expect(result.done).toBe(true);
|
|
224
|
+
});
|
|
225
|
+
});
|
|
226
|
+
|
|
227
|
+
describe("RecordRef Stability", () => {
|
|
228
|
+
it("should return the same RecordRef instance for identical parameters", async () => {
|
|
229
|
+
const stateModule = getStateModule(app);
|
|
230
|
+
|
|
231
|
+
const metadata: DocumentMetadata = {
|
|
232
|
+
name: "Test Document",
|
|
233
|
+
documentTypeName: "TestType",
|
|
234
|
+
ontologyRid: "test-ontology-rid",
|
|
235
|
+
security: TEST_SECURITY,
|
|
236
|
+
};
|
|
237
|
+
const docRef = await stateModule.createDocument(metadata, schema);
|
|
238
|
+
const userCollection = docRef.getRecords(User);
|
|
239
|
+
const userId = "user-1" as RecordId;
|
|
240
|
+
|
|
241
|
+
// Create the record first
|
|
242
|
+
await userCollection.set(userId, {
|
|
243
|
+
id: "user-1",
|
|
244
|
+
name: "Test User",
|
|
245
|
+
email: "test@example.com",
|
|
246
|
+
});
|
|
247
|
+
|
|
248
|
+
// Get record refs multiple times
|
|
249
|
+
const record1 = userCollection.get(userId);
|
|
250
|
+
const record2 = userCollection.get(userId);
|
|
251
|
+
const record3 = userCollection.get(userId);
|
|
252
|
+
|
|
253
|
+
// Should be the exact same instance (reference equality)
|
|
254
|
+
expect(record1).toBe(record2);
|
|
255
|
+
expect(record2).toBe(record3);
|
|
256
|
+
expect(record1).toBe(record3);
|
|
257
|
+
});
|
|
258
|
+
|
|
259
|
+
it("should return stable refs even for non-existent records", async () => {
|
|
260
|
+
const stateModule = getStateModule(app);
|
|
261
|
+
|
|
262
|
+
const metadata: DocumentMetadata = {
|
|
263
|
+
name: "Test Document",
|
|
264
|
+
documentTypeName: "TestType",
|
|
265
|
+
ontologyRid: "test-ontology-rid",
|
|
266
|
+
security: TEST_SECURITY,
|
|
267
|
+
};
|
|
268
|
+
const docRef = await stateModule.createDocument(metadata, schema);
|
|
269
|
+
|
|
270
|
+
const nonExistentId = "non-existent" as RecordId;
|
|
271
|
+
|
|
272
|
+
const ref1 = stateModule.createRecordRef(docRef, nonExistentId, User);
|
|
273
|
+
const ref2 = stateModule.createRecordRef(docRef, nonExistentId, User);
|
|
274
|
+
|
|
275
|
+
expect(ref1).toBe(ref2);
|
|
276
|
+
});
|
|
277
|
+
|
|
278
|
+
it("should return different instances for different record IDs", async () => {
|
|
279
|
+
const stateModule = getStateModule(app);
|
|
280
|
+
|
|
281
|
+
const metadata: DocumentMetadata = {
|
|
282
|
+
name: "Test Document",
|
|
283
|
+
documentTypeName: "TestType",
|
|
284
|
+
ontologyRid: "test-ontology-rid",
|
|
285
|
+
security: TEST_SECURITY,
|
|
286
|
+
};
|
|
287
|
+
const docRef = await stateModule.createDocument(metadata, schema);
|
|
288
|
+
const userCollection = docRef.getRecords(User);
|
|
289
|
+
|
|
290
|
+
const userId1 = "user-1" as RecordId;
|
|
291
|
+
const userId2 = "user-2" as RecordId;
|
|
292
|
+
|
|
293
|
+
// Create both records
|
|
294
|
+
await userCollection.set(userId1, {
|
|
295
|
+
id: "user-1",
|
|
296
|
+
name: "User 1",
|
|
297
|
+
email: "user1@example.com",
|
|
298
|
+
});
|
|
299
|
+
await userCollection.set(userId2, {
|
|
300
|
+
id: "user-2",
|
|
301
|
+
name: "User 2",
|
|
302
|
+
email: "user2@example.com",
|
|
303
|
+
});
|
|
304
|
+
|
|
305
|
+
const record1 = userCollection.get(userId1);
|
|
306
|
+
const record2 = userCollection.get(userId2);
|
|
307
|
+
|
|
308
|
+
// Should be different instances
|
|
309
|
+
expect(record1).not.toBe(record2);
|
|
310
|
+
expect(record1?.id).toBe(userId1);
|
|
311
|
+
expect(record2?.id).toBe(userId2);
|
|
312
|
+
});
|
|
313
|
+
|
|
314
|
+
it("should return different instances for different models", async () => {
|
|
315
|
+
const stateModule = getStateModule(app);
|
|
316
|
+
|
|
317
|
+
const metadata: DocumentMetadata = {
|
|
318
|
+
name: "Test Document",
|
|
319
|
+
documentTypeName: "TestType",
|
|
320
|
+
ontologyRid: "test-ontology-rid",
|
|
321
|
+
security: TEST_SECURITY,
|
|
322
|
+
};
|
|
323
|
+
const docRef = await stateModule.createDocument(metadata, schema);
|
|
324
|
+
|
|
325
|
+
const userCollection = docRef.getRecords(User);
|
|
326
|
+
const postCollection = docRef.getRecords(Post);
|
|
327
|
+
|
|
328
|
+
const recordId = "same-id" as RecordId;
|
|
329
|
+
|
|
330
|
+
// Create records with same ID but different models
|
|
331
|
+
await userCollection.set(recordId, {
|
|
332
|
+
id: "same-id",
|
|
333
|
+
name: "Test User",
|
|
334
|
+
email: "test@example.com",
|
|
335
|
+
});
|
|
336
|
+
await postCollection.set(recordId, {
|
|
337
|
+
id: "same-id",
|
|
338
|
+
title: "Test Post",
|
|
339
|
+
content: "Test content",
|
|
340
|
+
authorId: "user-1",
|
|
341
|
+
});
|
|
342
|
+
|
|
343
|
+
const userRecord = userCollection.get(recordId);
|
|
344
|
+
const postRecord = postCollection.get(recordId);
|
|
345
|
+
|
|
346
|
+
// Should be different instances
|
|
347
|
+
expect(userRecord).not.toBe(postRecord);
|
|
348
|
+
expect(userRecord?.model).toBe(User);
|
|
349
|
+
expect(postRecord?.model).toBe(Post);
|
|
350
|
+
});
|
|
351
|
+
|
|
352
|
+
it("should work with invalid refs", async () => {
|
|
353
|
+
const invalidRef = invalidRecordRef();
|
|
354
|
+
expect(isValidRecordRef(invalidRef)).toBe(false);
|
|
355
|
+
|
|
356
|
+
// Async methods should reject
|
|
357
|
+
await expect(invalidRef.getSnapshot()).rejects.toThrow();
|
|
358
|
+
await expect(invalidRef.set({})).rejects.toThrow();
|
|
359
|
+
|
|
360
|
+
// Subscription methods should be safe
|
|
361
|
+
const unsubscribe1 = invalidRef.onChange(() => {});
|
|
362
|
+
const unsubscribe2 = invalidRef.onDeleted(() => {});
|
|
363
|
+
|
|
364
|
+
expect(typeof unsubscribe1).toBe("function");
|
|
365
|
+
expect(typeof unsubscribe2).toBe("function");
|
|
366
|
+
|
|
367
|
+
// Should be safe to call
|
|
368
|
+
unsubscribe1();
|
|
369
|
+
unsubscribe2();
|
|
370
|
+
});
|
|
371
|
+
});
|
|
372
|
+
|
|
373
|
+
describe("Cross-reference Stability", () => {
|
|
374
|
+
it("should maintain stable refs across collection iterations", async () => {
|
|
375
|
+
const stateModule = getStateModule(app);
|
|
376
|
+
|
|
377
|
+
const metadata: DocumentMetadata = {
|
|
378
|
+
name: "Test Document",
|
|
379
|
+
documentTypeName: "TestType",
|
|
380
|
+
ontologyRid: "test-ontology-rid",
|
|
381
|
+
security: TEST_SECURITY,
|
|
382
|
+
};
|
|
383
|
+
const docRef = await stateModule.createDocument(metadata, schema);
|
|
384
|
+
const userCollection = docRef.getRecords(User);
|
|
385
|
+
|
|
386
|
+
// Create multiple users
|
|
387
|
+
const userIds = ["user-1", "user-2", "user-3"] as RecordId[];
|
|
388
|
+
for (const userId of userIds) {
|
|
389
|
+
await userCollection.set(userId, {
|
|
390
|
+
id: userId,
|
|
391
|
+
name: `User ${userId}`,
|
|
392
|
+
email: `${userId}@example.com`,
|
|
393
|
+
});
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
// Get refs through iteration
|
|
397
|
+
const iterationRefs = Array.from(userCollection);
|
|
398
|
+
|
|
399
|
+
// Get refs through direct access
|
|
400
|
+
const directRefs = userIds.map(id => userCollection.get(id)!);
|
|
401
|
+
|
|
402
|
+
// Should be the same instances
|
|
403
|
+
expect(iterationRefs).toHaveLength(3);
|
|
404
|
+
expect(directRefs).toHaveLength(3);
|
|
405
|
+
|
|
406
|
+
for (let i = 0; i < userIds.length; i++) {
|
|
407
|
+
const iterationRef = iterationRefs.find(ref => ref.id === userIds[i]);
|
|
408
|
+
const directRef = directRefs[i];
|
|
409
|
+
|
|
410
|
+
expect(iterationRef).toBeDefined();
|
|
411
|
+
expect(iterationRef).toBe(directRef);
|
|
412
|
+
}
|
|
413
|
+
});
|
|
414
|
+
|
|
415
|
+
it("should maintain stable document refs when accessed through different paths", async () => {
|
|
416
|
+
const stateModule = getStateModule(app);
|
|
417
|
+
|
|
418
|
+
const metadata: DocumentMetadata = {
|
|
419
|
+
name: "Test Document",
|
|
420
|
+
documentTypeName: "TestType",
|
|
421
|
+
ontologyRid: "test-ontology-rid",
|
|
422
|
+
security: TEST_SECURITY,
|
|
423
|
+
};
|
|
424
|
+
|
|
425
|
+
// Create doc through state module
|
|
426
|
+
const docRef1 = await stateModule.createDocument(metadata, schema);
|
|
427
|
+
|
|
428
|
+
// Get doc through createDocRef using the actual document ID
|
|
429
|
+
const docRef2 = stateModule.createDocRef(docRef1.id, schema);
|
|
430
|
+
|
|
431
|
+
// Get doc through collection's docRef
|
|
432
|
+
const collection = docRef1.getRecords(User);
|
|
433
|
+
const docRef3 = collection.docRef;
|
|
434
|
+
|
|
435
|
+
// Should be the same instances
|
|
436
|
+
expect(docRef1).toBe(docRef2);
|
|
437
|
+
expect(docRef2).toBe(docRef3);
|
|
438
|
+
expect(docRef1).toBe(docRef3);
|
|
439
|
+
});
|
|
440
|
+
});
|
|
441
|
+
});
|