@roc-db/in-memory 0.2.0-pre.1 → 0.2.0-pre.100

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/index.js CHANGED
@@ -10,85 +10,157 @@ var __export = (target, all) => {
10
10
  };
11
11
 
12
12
  // src/createInMemoryAdapter.ts
13
- import { createAdapter, Snowflake } from "roc-db";
13
+ import {
14
+ createAdapter,
15
+ Snowflake
16
+ } from "roc-db";
14
17
 
15
18
  // src/functions/index.ts
16
19
  var exports_functions = {};
17
20
  __export(exports_functions, {
18
- updateEntity: () => updateEntity,
19
21
  saveMutation: () => saveMutation,
22
+ refByUniqueField: () => refByUniqueField,
20
23
  readMutation: () => readMutation,
21
24
  readEntity: () => readEntity,
22
- patchEntity: () => patchEntity,
23
25
  pageMutations: () => pageMutations,
26
+ pageEntitiesByIndex: () => pageEntitiesByIndex,
27
+ pageEntities: () => pageEntities,
24
28
  getChangeSetMutations: () => getChangeSetMutations,
25
29
  findDebounceMutation: () => findDebounceMutation,
26
- deleteEntity: () => deleteEntity,
27
- createEntity: () => createEntity,
28
- begin: () => begin
30
+ commit: () => commit,
31
+ batchReadEntities: () => batchReadEntities
29
32
  });
30
33
 
31
- // src/functions/begin.ts
32
- var begin = (request, engineOpts) => {
33
- return {
34
- ...engineOpts,
35
- changeSet: request.changeSetRef ? {
36
- entities: new Map([]),
37
- mutations: new Map([])
38
- } : null
39
- };
34
+ // src/functions/readEntity.ts
35
+ var readEntity = (txn, ref) => txn.engineOpts.entities.get(ref);
36
+
37
+ // src/functions/batchReadEntities.ts
38
+ var batchReadEntities = (txn, refs) => {
39
+ return refs.map((ref) => readEntity(txn, ref));
40
40
  };
41
- // src/functions/createEntity.ts
42
- import { entityFromRef } from "roc-db";
43
- var createEntity = (txn, ref, {
44
- data = {},
45
- indexedData = {},
46
- children = {},
47
- parents = {},
48
- ancestors = {}
49
- }) => {
50
- const entity = entityFromRef(ref);
51
- const document = {
52
- ref,
53
- entity,
54
- created: {
55
- timestamp: txn.mutation.timestamp,
56
- mutationRef: txn.mutation.ref
57
- },
58
- updated: {
59
- timestamp: txn.mutation.timestamp,
60
- mutationRef: txn.mutation.ref
61
- },
62
- data: {
63
- ...data,
64
- ...indexedData
65
- },
66
- children,
67
- parents,
68
- ancestors
69
- };
70
- if (txn.request.changeSetRef) {
71
- if (txn.engineOpts.changeSet.entities.has(ref)) {
72
- throw new Error("Entity already exists in changeSet");
41
+ // src/functions/commit.ts
42
+ import {
43
+ createUniqueConstraintConflictError
44
+ } from "roc-db";
45
+
46
+ // src/functions/saveMutation.ts
47
+ var saveMutation = (txn, finalizedMutation) => {
48
+ txn.engineOpts.mutations.set(finalizedMutation.ref, finalizedMutation);
49
+ return finalizedMutation;
50
+ };
51
+
52
+ // src/functions/commit.ts
53
+ var findAddedAndRemovedEntries = (oldArr, newArr) => {
54
+ const removed = newArr?.filter(([k1, v1]) => !oldArr.some(([k2, v2]) => k1 === k2 && v1 === v2));
55
+ const added = oldArr?.filter(([k1, v1]) => !newArr.some(([k2, v2]) => k1 === k2 && v1 === v2));
56
+ return [added, removed];
57
+ };
58
+ var commit = (txn, mutation, { created, updated, deleted }) => {
59
+ const { mutations } = txn.engineOpts;
60
+ const currentMutation = mutations.get(txn.mutation.ref);
61
+ if (currentMutation) {
62
+ if (currentMutation && mutation.appliedAt === txn.timestamp) {
63
+ saveMutation(txn, mutation);
64
+ } else if (currentMutation && mutation.debounceCount > currentMutation.debounceCount) {
65
+ saveMutation(txn, mutation);
73
66
  } else {
74
- txn.engineOpts.changeSet.entities.set(ref, document);
75
- return document;
67
+ throw new Error("Mutation already exists");
76
68
  }
77
69
  } else {
78
- txn.engineOpts.entities.set(ref, document);
79
- return document;
70
+ saveMutation(txn, mutation);
80
71
  }
81
- };
82
- // src/functions/deleteEntity.ts
83
- import { DELETED_IN_CHANGE_SET_SYMBOL } from "roc-db";
84
- var deleteEntity = (txn, ref) => {
85
- if (txn.request.changeSetRef) {
86
- txn.engineOpts.changeSet.entities.set(ref, DELETED_IN_CHANGE_SET_SYMBOL);
87
- return true;
88
- } else {
89
- txn.engineOpts.entities.delete(ref);
90
- return true;
72
+ if (txn.request.changeSetRef)
73
+ return mutation;
74
+ for (const doc of created) {
75
+ if (txn.adapter.models?.[doc.entity]?.singleton && txn.engineOpts.entities.has(doc.ref)) {
76
+ throw createUniqueConstraintConflictError(doc.entity);
77
+ }
78
+ if (doc.__.unique?.length) {
79
+ doc.__.unique.forEach(([key, value]) => {
80
+ const uniqueKey = `${doc.entity}:${key}:${JSON.stringify(value)}`;
81
+ if (txn.engineOpts.entitiesUnique.has(uniqueKey))
82
+ throw createUniqueConstraintConflictError(doc.entity);
83
+ txn.engineOpts.entitiesUnique.set(uniqueKey, doc.ref);
84
+ });
85
+ }
86
+ if (doc.__.index?.length) {
87
+ doc.__.index.forEach(([key, value]) => {
88
+ const indexKey = `${doc.entity}:${key}:${JSON.stringify(value)}`;
89
+ const arr = txn.engineOpts.entitiesIndex.get(indexKey) ?? [];
90
+ txn.engineOpts.entitiesIndex.set(indexKey, [...arr, doc.ref]);
91
+ });
92
+ }
93
+ txn.engineOpts.entities.set(doc.ref, doc);
94
+ }
95
+ for (const updatedDocument of updated) {
96
+ const existingDocument = txn.engineOpts.entities.get(updatedDocument.ref);
97
+ if (updatedDocument.__.unique?.length || existingDocument.__.unique?.length) {
98
+ const { ref, entity } = updatedDocument;
99
+ const [added, removed] = findAddedAndRemovedEntries(updatedDocument.__.unique, existingDocument.__.unique);
100
+ removed.forEach(([key, value]) => {
101
+ const uniqueKey = `${updatedDocument.entity}:${key}:${JSON.stringify(value)}`;
102
+ txn.engineOpts.entitiesUnique.delete(uniqueKey);
103
+ });
104
+ added.forEach(([key, value]) => {
105
+ const uniqueKey = `${updatedDocument.entity}:${key}:${JSON.stringify(value)}`;
106
+ if (txn.engineOpts.entitiesUnique.has(uniqueKey))
107
+ throw createUniqueConstraintConflictError(entity);
108
+ txn.engineOpts.entitiesUnique.set(uniqueKey, ref);
109
+ });
110
+ }
111
+ if (updatedDocument.__.index?.length || existingDocument.__.index?.length) {
112
+ const { ref, entity } = updatedDocument;
113
+ const [added, removed] = findAddedAndRemovedEntries(updatedDocument.__.index, existingDocument.__.index);
114
+ removed.forEach(([key, value]) => {
115
+ const indexKey = `${updatedDocument.entity}:${key}:${JSON.stringify(value)}`;
116
+ const arr = txn.engineOpts.entitiesIndex.get(indexKey);
117
+ txn.engineOpts.entitiesIndex.set(indexKey, arr.filter((ref2) => ref2 !== updatedDocument.ref));
118
+ });
119
+ added.forEach(([key, value]) => {
120
+ const indexKey = `${updatedDocument.entity}:${key}:${JSON.stringify(value)}`;
121
+ const arr = txn.engineOpts.entitiesIndex.get(indexKey) ?? [];
122
+ txn.engineOpts.entitiesIndex.set(indexKey, [
123
+ ...arr,
124
+ updatedDocument.ref
125
+ ]);
126
+ });
127
+ }
128
+ txn.engineOpts.entities.set(updatedDocument.ref, updatedDocument);
129
+ }
130
+ for (const ref of deleted) {
131
+ if (ref.startsWith("Mutation/")) {
132
+ txn.engineOpts.mutations.delete(ref);
133
+ } else {
134
+ const existingDocument = txn.engineOpts.entities.get(ref);
135
+ if (existingDocument.__.unique?.length) {
136
+ existingDocument.__.unique.forEach(([key, value]) => {
137
+ const uniqueKey = `${existingDocument.entity}:${key}:${JSON.stringify(value)}`;
138
+ txn.engineOpts.entitiesUnique.delete(uniqueKey);
139
+ });
140
+ }
141
+ if (existingDocument.__.index?.length) {
142
+ existingDocument.__.index.forEach(([key, value]) => {
143
+ const indexKey = `${existingDocument.entity}:${key}:${JSON.stringify(value)}`;
144
+ const arr = txn.engineOpts.entitiesIndex.get(indexKey) ?? [];
145
+ txn.engineOpts.entitiesIndex.set(indexKey, arr.filter((ref2) => ref2 !== existingDocument.ref));
146
+ });
147
+ }
148
+ txn.engineOpts.entities.delete(ref);
149
+ }
91
150
  }
151
+ return mutation;
152
+ };
153
+ // src/functions/findDebounceMutation.ts
154
+ var findDebounceMutation = (request, engine, now, mutationName, identityRef) => {
155
+ const debounceTime = request.operation.debounce;
156
+ const thresholdTime = new Date(now.getTime() - debounceTime * 1000).toISOString();
157
+ const payloadRef = request.payload?.ref;
158
+ const res = engine.mutations.values().find((mutation) => {
159
+ if (mutation.operation.name === mutationName && mutation.timestamp > thresholdTime && mutation.payload?.ref === payloadRef && (mutation.changeSetRef ?? null) === (request.changeSetRef ?? null) && mutation.identityRef === identityRef) {
160
+ return true;
161
+ }
162
+ });
163
+ return res;
92
164
  };
93
165
  // src/functions/getChangeSetMutations.ts
94
166
  var getChangeSetMutations = (txn, changeSetRef) => {
@@ -102,110 +174,85 @@ var getChangeSetMutations = (txn, changeSetRef) => {
102
174
  });
103
175
  return res;
104
176
  };
105
- // src/functions/findDebounceMutation.ts
106
- var findDebounceMutation = (request, engine, now) => {
107
- const debounceTime = request.settings.debounce;
108
- const mutationName = request.schema.shape.name.value;
109
- const thresholdTime = new Date(now - debounceTime * 1000).toISOString();
110
- const res = engine.mutations.values().find((mutation) => {
111
- if (mutation.name === mutationName && mutation.timestamp > thresholdTime && mutation.payload.ref === request.payload.ref) {
112
- return true;
177
+ // src/functions/pageEntities.ts
178
+ var pageEntities = (txn, args) => {
179
+ const { size, entities, childrenOf } = args;
180
+ const result = [];
181
+ for (const [, doc] of txn.engineOpts.entities) {
182
+ if (size && result.length >= size) {
183
+ break;
184
+ }
185
+ if (entities && entities !== "*" && !entities.includes(doc.entity)) {
186
+ continue;
187
+ } else {
188
+ if (childrenOf && childrenOf.length > 0) {
189
+ if (!childrenOf.some((childRef) => doc.__?.parentRefs?.includes(childRef))) {
190
+ continue;
191
+ }
192
+ }
193
+ result.push(doc);
113
194
  }
114
- });
115
- return res;
116
- };
117
- // src/functions/pageMutations.ts
118
- var pageMutations = (txn, { size = 30, skip = 0 } = {}) => {
119
- return txn.engineOpts.mutations.values().drop(skip).take(size).toArray();
120
- };
121
- // src/functions/patchEntity.ts
122
- import { deepPatch, NotFoundError } from "roc-db";
123
-
124
- // src/functions/readEntity.ts
125
- import { DELETED_IN_CHANGE_SET_SYMBOL as DELETED_IN_CHANGE_SET_SYMBOL2 } from "roc-db";
126
- var readEntity = (txn, ref) => {
127
- if (txn.request.changeSetRef) {
128
- const doc = txn.engineOpts.changeSet.entities.get(ref);
129
- if (doc === DELETED_IN_CHANGE_SET_SYMBOL2)
130
- return;
131
- if (doc)
132
- return doc;
133
195
  }
134
- return txn.engineOpts.entities.get(ref);
196
+ return result;
135
197
  };
136
-
137
- // src/functions/patchEntity.ts
138
- var patchEntity = (txn, ref, { data = {}, children = {}, parents = {}, ancestors = {} }) => {
139
- const existingDocument = readEntity(txn, ref);
140
- if (!existingDocument)
141
- throw new NotFoundError(ref);
142
- const updatedDocument = {
143
- ...existingDocument,
144
- updated: {
145
- timestamp: txn.mutation.timestamp,
146
- mutationRef: txn.mutation.ref
147
- },
148
- data: deepPatch(existingDocument.data, data),
149
- children: deepPatch(existingDocument.children, children),
150
- parents: deepPatch(existingDocument.parents, parents),
151
- ancestors: deepPatch(existingDocument.ancestors, ancestors)
152
- };
153
- if (txn.request.changeSetRef) {
154
- txn.engineOpts.changeSet.entities.set(ref, updatedDocument);
155
- return updatedDocument;
156
- } else {
157
- txn.engineOpts.entities.set(ref, updatedDocument);
158
- return updatedDocument;
198
+ // src/functions/pageEntitiesByIndex.ts
199
+ var pageEntitiesByIndex = (txn, entity, field, value) => {
200
+ const { entitiesIndex } = txn.engineOpts;
201
+ const indexKey = `${entity}:${field}:${JSON.stringify(value)}`;
202
+ const refs = entitiesIndex.get(indexKey) ?? [];
203
+ return refs.map((ref) => txn.engineOpts.entities.get(ref));
204
+ };
205
+ // src/functions/pageMutations.ts
206
+ var pageMutations = (txn, { size = 30, skip = 0, changeSetRef } = {}) => {
207
+ const res = [];
208
+ const iterator = txn.engineOpts.mutations.values().drop(skip);
209
+ let next = iterator.next();
210
+ while (!next.done && res.length < size) {
211
+ if (changeSetRef) {
212
+ if (next.value.changeSetRef === changeSetRef) {
213
+ res.push(next.value);
214
+ }
215
+ } else {
216
+ res.push(next.value);
217
+ }
218
+ next = iterator.next();
159
219
  }
220
+ return res;
160
221
  };
161
222
  // src/functions/readMutation.ts
162
223
  var readMutation = (engineOpts, ref) => {
163
224
  return engineOpts.mutations.get(ref);
164
225
  };
165
- // src/functions/saveMutation.ts
166
- var saveMutation = (txn, finalizedMutation) => {
167
- txn.engineOpts.mutations.set(finalizedMutation.ref, finalizedMutation);
168
- return finalizedMutation;
169
- };
170
- // src/functions/updateEntity.ts
171
- import { NotFoundError as NotFoundError2 } from "roc-db";
172
- var updateEntity = (txn, ref, { data = {}, children = {}, parents = {}, ancestors = {} }) => {
173
- const currentEntity = readEntity(txn, ref);
174
- if (!currentEntity)
175
- throw new NotFoundError2(ref);
176
- const document = {
177
- ...currentEntity,
178
- updated: {
179
- mutationRef: txn.mutation.ref,
180
- timestamp: txn.mutation.timestamp
181
- },
182
- data,
183
- children,
184
- parents,
185
- ancestors
186
- };
187
- if (txn.request.changeSetRef) {
188
- throw new Error("TODO support changeSetRef");
189
- } else {
190
- txn.engineOpts.entities.set(ref, document);
191
- return document;
226
+ // src/functions/refByUniqueField.ts
227
+ var refByUniqueField = (txn, entity, field, fieldIndex, value) => {
228
+ const key = `${entity}:${field}:${JSON.stringify(value)}`;
229
+ const { entitiesUnique } = txn.engineOpts;
230
+ if (entitiesUnique.has(key)) {
231
+ return entitiesUnique.get(key);
192
232
  }
193
233
  };
194
234
  // src/createInMemoryAdapter.ts
195
235
  var createInMemoryAdapter = ({
196
236
  operations,
197
237
  entities,
198
- snowflake = new Snowflake(1, 1)
238
+ snowflake = new Snowflake(1, 1),
239
+ optimistic = true,
240
+ session,
241
+ engine
199
242
  }) => {
200
243
  return createAdapter({
201
244
  name: "in-memory",
202
245
  operations,
203
246
  entities,
204
247
  functions: exports_functions,
205
- snowflake
206
- }, {
248
+ snowflake,
249
+ optimistic,
250
+ session
251
+ }, engine ?? {
207
252
  entities: new Map,
208
- mutations: new Map
253
+ mutations: new Map,
254
+ entitiesUnique: new Map,
255
+ entitiesIndex: new Map
209
256
  });
210
257
  };
211
258
  export {
@@ -0,0 +1,14 @@
1
+ import { Snowflake, type Adapter, type Entity, type Operation, type Session } from "roc-db";
2
+ export declare const createInMemoryAdapter: <const Name extends string, const Operations extends readonly Operation[], const Entities extends readonly Entity<any>[]>({ operations, entities, snowflake, optimistic, session, engine, }: {
3
+ operations: Operations;
4
+ entities: Entities;
5
+ snowflake?: Snowflake;
6
+ optimistic?: boolean;
7
+ session: Session;
8
+ engine?: {
9
+ entities: Map<string, any>;
10
+ mutations: Map<string, any>;
11
+ entitiesUnique: Map<string, any>;
12
+ entitiesIndex: Map<string, any>;
13
+ };
14
+ }) => Adapter;
@@ -0,0 +1,3 @@
1
+ import type { Ref, Transaction } from "roc-db";
2
+ import type { InMemoryEngine } from "../types/InMemoryEngine";
3
+ export declare const batchReadEntities: (txn: Transaction<InMemoryEngine>, refs: Ref[]) => any[];
@@ -0,0 +1,3 @@
1
+ import { type CommitFunction } from "roc-db";
2
+ import type { InMemoryEngine } from "../types/InMemoryEngine";
3
+ export declare const commit: CommitFunction<InMemoryEngine>;
@@ -0,0 +1,3 @@
1
+ import type { FindDebounceMutationFunction } from "roc-db";
2
+ import type { InMemoryEngine } from "../types/InMemoryEngine";
3
+ export declare const findDebounceMutation: FindDebounceMutationFunction<InMemoryEngine>;
@@ -0,0 +1,3 @@
1
+ import type { GetChangeSetMutationsFunction } from "roc-db";
2
+ import type { InMemoryEngine } from "../types/InMemoryEngine";
3
+ export declare const getChangeSetMutations: GetChangeSetMutationsFunction<InMemoryEngine>;
@@ -0,0 +1,11 @@
1
+ export { batchReadEntities } from "./batchReadEntities";
2
+ export { commit } from "./commit";
3
+ export { findDebounceMutation } from "./findDebounceMutation";
4
+ export { getChangeSetMutations } from "./getChangeSetMutations";
5
+ export { pageEntities } from "./pageEntities";
6
+ export { pageEntitiesByIndex } from "./pageEntitiesByIndex";
7
+ export { pageMutations } from "./pageMutations";
8
+ export { readEntity } from "./readEntity";
9
+ export { readMutation } from "./readMutation";
10
+ export { refByUniqueField } from "./refByUniqueField";
11
+ export { saveMutation } from "./saveMutation";
@@ -0,0 +1,3 @@
1
+ import type { PageEntitiesFunction } from "roc-db";
2
+ import type { InMemoryEngine } from "../types/InMemoryEngine";
3
+ export declare const pageEntities: PageEntitiesFunction<InMemoryEngine>;
@@ -0,0 +1,3 @@
1
+ import type { PageEntitiesByIndexFunction } from "roc-db";
2
+ import type { InMemoryEngine } from "../types/InMemoryEngine";
3
+ export declare const pageEntitiesByIndex: PageEntitiesByIndexFunction<InMemoryEngine>;
@@ -0,0 +1,3 @@
1
+ import type { PageMutationsFunction } from "roc-db";
2
+ import type { InMemoryEngine } from "../types/InMemoryEngine";
3
+ export declare const pageMutations: PageMutationsFunction<InMemoryEngine>;
@@ -0,0 +1,3 @@
1
+ import type { ReadEntityFunctiun } from "roc-db";
2
+ import type { InMemoryEngine } from "../types/InMemoryEngine";
3
+ export declare const readEntity: ReadEntityFunctiun<InMemoryEngine>;
@@ -0,0 +1,3 @@
1
+ import type { ReadMutationFunction } from "roc-db";
2
+ import type { InMemoryEngine } from "../types/InMemoryEngine";
3
+ export declare const readMutation: ReadMutationFunction<InMemoryEngine>;
@@ -0,0 +1,3 @@
1
+ import type { RefByUniqueFieldFunction } from "roc-db";
2
+ import type { InMemoryEngine } from "../types/InMemoryEngine";
3
+ export declare const refByUniqueField: RefByUniqueFieldFunction<InMemoryEngine>;
@@ -0,0 +1,3 @@
1
+ import type { SaveMutationFunction } from "roc-db";
2
+ import type { InMemoryEngine } from "../types/InMemoryEngine";
3
+ export declare const saveMutation: SaveMutationFunction<InMemoryEngine>;
@@ -0,0 +1 @@
1
+ export { createInMemoryAdapter } from "./createInMemoryAdapter";
@@ -0,0 +1,7 @@
1
+ import type { EntityDocument, Mutation, Ref } from "roc-db";
2
+ export type InMemoryEngine = {
3
+ entities: Map<Ref, EntityDocument>;
4
+ mutations: Map<Ref, Mutation>;
5
+ entitiesUnique: Map<string, Ref>;
6
+ entitiesIndex: Map<string, Ref[]>;
7
+ };
package/package.json CHANGED
@@ -1,27 +1,20 @@
1
1
  {
2
2
  "name": "@roc-db/in-memory",
3
- "version": "0.2.0-pre.1",
3
+ "version": "0.2.0-pre.100",
4
4
  "type": "module",
5
5
  "exports": {
6
- ".": "./src/index.ts"
6
+ ".": {
7
+ "import": "./dist/index.js",
8
+ "types": "./dist/types/index.d.ts"
9
+ }
7
10
  },
8
11
  "files": [
9
12
  "dist"
10
13
  ],
11
14
  "sideEffects": false,
12
- "scripts": {
13
- "build": "NODE_ENV=production bun run scripts/build.ts",
14
- "build:types": "rm -rf dist/types && bun run tsc --noCheck",
15
- "test": "bun test"
16
- },
17
- "devDependencies": {
18
- "@roc-db/test-utils": "0.2.0-pre.1",
19
- "roc-db": "0.2.0-pre.1",
20
- "zod": "3.24.2"
21
- },
22
15
  "peerDependencies": {
23
- "roc-db": "0.2.0-pre.1",
24
- "zod": "3.24.2"
16
+ "roc-db": ">=0.2.0-pre.98 <1.0.0",
17
+ "zod": ">=4.0.0"
25
18
  },
26
19
  "keywords": [],
27
20
  "author": "Eigil Sagafos",
@@ -29,5 +22,9 @@
29
22
  "type": "git",
30
23
  "url": "git+https://github.com/eigilsagafos/roc-db.git"
31
24
  },
32
- "license": "MIT"
25
+ "license": "MIT",
26
+ "publishConfig": {
27
+ "access": "public",
28
+ "registry": "https://registry.npmjs.org/"
29
+ }
33
30
  }