@twin.org/entity-storage-connector-memory 0.0.1-next.2 → 0.0.1-next.21

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.
@@ -36,7 +36,6 @@ class MemoryEntityStorageConnector {
36
36
  /**
37
37
  * Create a new instance of MemoryEntityStorageConnector.
38
38
  * @param options The options for the connector.
39
- * @param options.entitySchema The schema for the entity.
40
39
  */
41
40
  constructor(options) {
42
41
  core.Guards.object(this.CLASS_NAME, "options", options);
@@ -45,25 +44,34 @@ class MemoryEntityStorageConnector {
45
44
  this._primaryKey = entity.EntitySchemaHelper.getPrimaryKey(this._entitySchema);
46
45
  this._store = [];
47
46
  }
47
+ /**
48
+ * Get the schema for the entities.
49
+ * @returns The schema for the entities.
50
+ */
51
+ getSchema() {
52
+ return this._entitySchema;
53
+ }
48
54
  /**
49
55
  * Get an entity.
50
56
  * @param id The id of the entity to get, or the index value if secondaryIndex is set.
51
57
  * @param secondaryIndex Get the item using a secondary index.
58
+ * @param conditions The optional conditions to match for the entities.
52
59
  * @returns The object if it can be found or undefined.
53
60
  */
54
- async get(id, secondaryIndex) {
61
+ async get(id, secondaryIndex, conditions) {
55
62
  core.Guards.stringValue(this.CLASS_NAME, "id", id);
56
- const lookupKey = secondaryIndex ?? this._primaryKey.property;
57
- return this._store.find(entity => entity[lookupKey] === id);
63
+ const index = this.findItem(id, secondaryIndex, conditions);
64
+ return index >= 0 ? this._store[index] : undefined;
58
65
  }
59
66
  /**
60
67
  * Set an entity.
61
68
  * @param entity The entity to set.
69
+ * @param conditions The optional conditions to match for the entities.
62
70
  * @returns The id of the entity.
63
71
  */
64
- async set(entity) {
72
+ async set(entity, conditions) {
65
73
  core.Guards.object(this.CLASS_NAME, "entity", entity);
66
- const existingIndex = this._store.findIndex(e => e[this._primaryKey.property] === entity[this._primaryKey.property]);
74
+ const existingIndex = this.findItem(entity[this._primaryKey.property], undefined, conditions);
67
75
  if (existingIndex >= 0) {
68
76
  this._store[existingIndex] = entity;
69
77
  }
@@ -74,11 +82,12 @@ class MemoryEntityStorageConnector {
74
82
  /**
75
83
  * Remove the entity.
76
84
  * @param id The id of the entity to remove.
85
+ * @param conditions The optional conditions to match for the entities.
77
86
  * @returns Nothing.
78
87
  */
79
- async remove(id) {
88
+ async remove(id, conditions) {
80
89
  core.Guards.stringValue(this.CLASS_NAME, "id", id);
81
- const index = this._store.findIndex(e => e[this._primaryKey.property] === id) ?? -1;
90
+ const index = this.findItem(id, undefined, conditions);
82
91
  if (index >= 0) {
83
92
  this._store.splice(index, 1);
84
93
  }
@@ -106,7 +115,10 @@ class MemoryEntityStorageConnector {
106
115
  if (entity.EntityConditions.check(allEntities[i], conditions) && entities.length < finalPageSize) {
107
116
  entities.push(core.ObjectHelper.pick(allEntities[i], properties));
108
117
  if (entities.length >= finalPageSize) {
109
- nextCursor = (i + 1).toString();
118
+ if (i < allEntities.length - 1) {
119
+ nextCursor = (i + 1).toString();
120
+ }
121
+ break;
110
122
  }
111
123
  }
112
124
  }
@@ -123,6 +135,50 @@ class MemoryEntityStorageConnector {
123
135
  getStore() {
124
136
  return this._store;
125
137
  }
138
+ /**
139
+ * Find the item in the store.
140
+ * @param id The id to search for.
141
+ * @param secondaryIndex The secondary index to search for.
142
+ * @param conditions The optional conditions to match for the entities.
143
+ * @returns The index of the item if found or -1.
144
+ * @internal
145
+ */
146
+ findItem(id, secondaryIndex, conditions) {
147
+ const finalConditions = [];
148
+ if (!core.Is.empty(secondaryIndex)) {
149
+ finalConditions.push({
150
+ property: secondaryIndex,
151
+ comparison: entity.ComparisonOperator.Equals,
152
+ value: id
153
+ });
154
+ }
155
+ if (core.Is.arrayValue(conditions)) {
156
+ // If we haven't added a secondary index condition we need to add the primary key condition.
157
+ if (finalConditions.length === 0) {
158
+ finalConditions.push({
159
+ property: this._primaryKey.property,
160
+ comparison: entity.ComparisonOperator.Equals,
161
+ value: id
162
+ });
163
+ }
164
+ finalConditions.push(...conditions.map(c => ({
165
+ property: c.property,
166
+ comparison: entity.ComparisonOperator.Equals,
167
+ value: c.value
168
+ })));
169
+ }
170
+ if (finalConditions.length > 0) {
171
+ for (let i = 0; i < this._store.length; i++) {
172
+ if (entity.EntityConditions.check(this._store[i], { conditions: finalConditions })) {
173
+ return i;
174
+ }
175
+ }
176
+ }
177
+ else {
178
+ return this._store.findIndex(e => e[this._primaryKey.property] === id);
179
+ }
180
+ return -1;
181
+ }
126
182
  }
127
183
 
128
184
  exports.MemoryEntityStorageConnector = MemoryEntityStorageConnector;
@@ -1,5 +1,5 @@
1
- import { Guards, Coerce, ObjectHelper } from '@twin.org/core';
2
- import { EntitySchemaFactory, EntitySchemaHelper, EntitySorter, EntityConditions } from '@twin.org/entity';
1
+ import { Guards, Coerce, ObjectHelper, Is } from '@twin.org/core';
2
+ import { EntitySchemaFactory, EntitySchemaHelper, EntitySorter, EntityConditions, ComparisonOperator } from '@twin.org/entity';
3
3
 
4
4
  // Copyright 2024 IOTA Stiftung.
5
5
  // SPDX-License-Identifier: Apache-2.0.
@@ -34,7 +34,6 @@ class MemoryEntityStorageConnector {
34
34
  /**
35
35
  * Create a new instance of MemoryEntityStorageConnector.
36
36
  * @param options The options for the connector.
37
- * @param options.entitySchema The schema for the entity.
38
37
  */
39
38
  constructor(options) {
40
39
  Guards.object(this.CLASS_NAME, "options", options);
@@ -43,25 +42,34 @@ class MemoryEntityStorageConnector {
43
42
  this._primaryKey = EntitySchemaHelper.getPrimaryKey(this._entitySchema);
44
43
  this._store = [];
45
44
  }
45
+ /**
46
+ * Get the schema for the entities.
47
+ * @returns The schema for the entities.
48
+ */
49
+ getSchema() {
50
+ return this._entitySchema;
51
+ }
46
52
  /**
47
53
  * Get an entity.
48
54
  * @param id The id of the entity to get, or the index value if secondaryIndex is set.
49
55
  * @param secondaryIndex Get the item using a secondary index.
56
+ * @param conditions The optional conditions to match for the entities.
50
57
  * @returns The object if it can be found or undefined.
51
58
  */
52
- async get(id, secondaryIndex) {
59
+ async get(id, secondaryIndex, conditions) {
53
60
  Guards.stringValue(this.CLASS_NAME, "id", id);
54
- const lookupKey = secondaryIndex ?? this._primaryKey.property;
55
- return this._store.find(entity => entity[lookupKey] === id);
61
+ const index = this.findItem(id, secondaryIndex, conditions);
62
+ return index >= 0 ? this._store[index] : undefined;
56
63
  }
57
64
  /**
58
65
  * Set an entity.
59
66
  * @param entity The entity to set.
67
+ * @param conditions The optional conditions to match for the entities.
60
68
  * @returns The id of the entity.
61
69
  */
62
- async set(entity) {
70
+ async set(entity, conditions) {
63
71
  Guards.object(this.CLASS_NAME, "entity", entity);
64
- const existingIndex = this._store.findIndex(e => e[this._primaryKey.property] === entity[this._primaryKey.property]);
72
+ const existingIndex = this.findItem(entity[this._primaryKey.property], undefined, conditions);
65
73
  if (existingIndex >= 0) {
66
74
  this._store[existingIndex] = entity;
67
75
  }
@@ -72,11 +80,12 @@ class MemoryEntityStorageConnector {
72
80
  /**
73
81
  * Remove the entity.
74
82
  * @param id The id of the entity to remove.
83
+ * @param conditions The optional conditions to match for the entities.
75
84
  * @returns Nothing.
76
85
  */
77
- async remove(id) {
86
+ async remove(id, conditions) {
78
87
  Guards.stringValue(this.CLASS_NAME, "id", id);
79
- const index = this._store.findIndex(e => e[this._primaryKey.property] === id) ?? -1;
88
+ const index = this.findItem(id, undefined, conditions);
80
89
  if (index >= 0) {
81
90
  this._store.splice(index, 1);
82
91
  }
@@ -104,7 +113,10 @@ class MemoryEntityStorageConnector {
104
113
  if (EntityConditions.check(allEntities[i], conditions) && entities.length < finalPageSize) {
105
114
  entities.push(ObjectHelper.pick(allEntities[i], properties));
106
115
  if (entities.length >= finalPageSize) {
107
- nextCursor = (i + 1).toString();
116
+ if (i < allEntities.length - 1) {
117
+ nextCursor = (i + 1).toString();
118
+ }
119
+ break;
108
120
  }
109
121
  }
110
122
  }
@@ -121,6 +133,50 @@ class MemoryEntityStorageConnector {
121
133
  getStore() {
122
134
  return this._store;
123
135
  }
136
+ /**
137
+ * Find the item in the store.
138
+ * @param id The id to search for.
139
+ * @param secondaryIndex The secondary index to search for.
140
+ * @param conditions The optional conditions to match for the entities.
141
+ * @returns The index of the item if found or -1.
142
+ * @internal
143
+ */
144
+ findItem(id, secondaryIndex, conditions) {
145
+ const finalConditions = [];
146
+ if (!Is.empty(secondaryIndex)) {
147
+ finalConditions.push({
148
+ property: secondaryIndex,
149
+ comparison: ComparisonOperator.Equals,
150
+ value: id
151
+ });
152
+ }
153
+ if (Is.arrayValue(conditions)) {
154
+ // If we haven't added a secondary index condition we need to add the primary key condition.
155
+ if (finalConditions.length === 0) {
156
+ finalConditions.push({
157
+ property: this._primaryKey.property,
158
+ comparison: ComparisonOperator.Equals,
159
+ value: id
160
+ });
161
+ }
162
+ finalConditions.push(...conditions.map(c => ({
163
+ property: c.property,
164
+ comparison: ComparisonOperator.Equals,
165
+ value: c.value
166
+ })));
167
+ }
168
+ if (finalConditions.length > 0) {
169
+ for (let i = 0; i < this._store.length; i++) {
170
+ if (EntityConditions.check(this._store[i], { conditions: finalConditions })) {
171
+ return i;
172
+ }
173
+ }
174
+ }
175
+ else {
176
+ return this._store.findIndex(e => e[this._primaryKey.property] === id);
177
+ }
178
+ return -1;
179
+ }
124
180
  }
125
181
 
126
182
  export { MemoryEntityStorageConnector };
@@ -1 +1,2 @@
1
1
  export * from "./memoryEntityStorageConnector";
2
+ export * from "./models/IMemoryEntityStorageConnectorConstructorOptions";
@@ -1,5 +1,6 @@
1
- import { type EntityCondition, type SortDirection } from "@twin.org/entity";
1
+ import { type EntityCondition, type IEntitySchema, type SortDirection } from "@twin.org/entity";
2
2
  import type { IEntityStorageConnector } from "@twin.org/entity-storage-models";
3
+ import type { IMemoryEntityStorageConnectorConstructorOptions } from "./models/IMemoryEntityStorageConnectorConstructorOptions";
3
4
  /**
4
5
  * Class for performing entity storage operations in-memory.
5
6
  */
@@ -11,30 +12,44 @@ export declare class MemoryEntityStorageConnector<T = unknown> implements IEntit
11
12
  /**
12
13
  * Create a new instance of MemoryEntityStorageConnector.
13
14
  * @param options The options for the connector.
14
- * @param options.entitySchema The schema for the entity.
15
15
  */
16
- constructor(options: {
17
- entitySchema: string;
18
- });
16
+ constructor(options: IMemoryEntityStorageConnectorConstructorOptions);
17
+ /**
18
+ * Get the schema for the entities.
19
+ * @returns The schema for the entities.
20
+ */
21
+ getSchema(): IEntitySchema;
19
22
  /**
20
23
  * Get an entity.
21
24
  * @param id The id of the entity to get, or the index value if secondaryIndex is set.
22
25
  * @param secondaryIndex Get the item using a secondary index.
26
+ * @param conditions The optional conditions to match for the entities.
23
27
  * @returns The object if it can be found or undefined.
24
28
  */
25
- get(id: string, secondaryIndex?: keyof T): Promise<T | undefined>;
29
+ get(id: string, secondaryIndex?: keyof T, conditions?: {
30
+ property: keyof T;
31
+ value: unknown;
32
+ }[]): Promise<T | undefined>;
26
33
  /**
27
34
  * Set an entity.
28
35
  * @param entity The entity to set.
36
+ * @param conditions The optional conditions to match for the entities.
29
37
  * @returns The id of the entity.
30
38
  */
31
- set(entity: T): Promise<void>;
39
+ set(entity: T, conditions?: {
40
+ property: keyof T;
41
+ value: unknown;
42
+ }[]): Promise<void>;
32
43
  /**
33
44
  * Remove the entity.
34
45
  * @param id The id of the entity to remove.
46
+ * @param conditions The optional conditions to match for the entities.
35
47
  * @returns Nothing.
36
48
  */
37
- remove(id: string): Promise<void>;
49
+ remove(id: string, conditions?: {
50
+ property: keyof T;
51
+ value: unknown;
52
+ }[]): Promise<void>;
38
53
  /**
39
54
  * Find all the entities which match the conditions.
40
55
  * @param conditions The conditions to match for the entities.
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Options for the Memory Entity Storage Connector constructor.
3
+ */
4
+ export interface IMemoryEntityStorageConnectorConstructorOptions {
5
+ /**
6
+ * The schema for the entity.
7
+ */
8
+ entitySchema: string;
9
+ }
package/docs/changelog.md CHANGED
@@ -1,5 +1,5 @@
1
1
  # @twin.org/entity-storage-connector-memory - Changelog
2
2
 
3
- ## v0.0.1-next.2
3
+ ## v0.0.1-next.21
4
4
 
5
5
  - Initial Release
@@ -20,13 +20,11 @@ Create a new instance of MemoryEntityStorageConnector.
20
20
 
21
21
  #### Parameters
22
22
 
23
- **options**
23
+ ##### options
24
24
 
25
- The options for the connector.
26
-
27
- • **options.entitySchema**: `string`
25
+ [`IMemoryEntityStorageConnectorConstructorOptions`](../interfaces/IMemoryEntityStorageConnectorConstructorOptions.md)
28
26
 
29
- The schema for the entity.
27
+ The options for the connector.
30
28
 
31
29
  #### Returns
32
30
 
@@ -46,22 +44,50 @@ Runtime name for the class.
46
44
 
47
45
  ## Methods
48
46
 
47
+ ### getSchema()
48
+
49
+ > **getSchema**(): `IEntitySchema`
50
+
51
+ Get the schema for the entities.
52
+
53
+ #### Returns
54
+
55
+ `IEntitySchema`
56
+
57
+ The schema for the entities.
58
+
59
+ #### Implementation of
60
+
61
+ `IEntityStorageConnector.getSchema`
62
+
63
+ ***
64
+
49
65
  ### get()
50
66
 
51
- > **get**(`id`, `secondaryIndex`?): `Promise`\<`undefined` \| `T`\>
67
+ > **get**(`id`, `secondaryIndex`?, `conditions`?): `Promise`\<`undefined` \| `T`\>
52
68
 
53
69
  Get an entity.
54
70
 
55
71
  #### Parameters
56
72
 
57
- **id**: `string`
73
+ ##### id
74
+
75
+ `string`
58
76
 
59
77
  The id of the entity to get, or the index value if secondaryIndex is set.
60
78
 
61
- **secondaryIndex?**: keyof `T`
79
+ ##### secondaryIndex?
80
+
81
+ keyof `T`
62
82
 
63
83
  Get the item using a secondary index.
64
84
 
85
+ ##### conditions?
86
+
87
+ `object`[]
88
+
89
+ The optional conditions to match for the entities.
90
+
65
91
  #### Returns
66
92
 
67
93
  `Promise`\<`undefined` \| `T`\>
@@ -76,16 +102,24 @@ The object if it can be found or undefined.
76
102
 
77
103
  ### set()
78
104
 
79
- > **set**(`entity`): `Promise`\<`void`\>
105
+ > **set**(`entity`, `conditions`?): `Promise`\<`void`\>
80
106
 
81
107
  Set an entity.
82
108
 
83
109
  #### Parameters
84
110
 
85
- **entity**: `T`
111
+ ##### entity
112
+
113
+ `T`
86
114
 
87
115
  The entity to set.
88
116
 
117
+ ##### conditions?
118
+
119
+ `object`[]
120
+
121
+ The optional conditions to match for the entities.
122
+
89
123
  #### Returns
90
124
 
91
125
  `Promise`\<`void`\>
@@ -100,16 +134,24 @@ The id of the entity.
100
134
 
101
135
  ### remove()
102
136
 
103
- > **remove**(`id`): `Promise`\<`void`\>
137
+ > **remove**(`id`, `conditions`?): `Promise`\<`void`\>
104
138
 
105
139
  Remove the entity.
106
140
 
107
141
  #### Parameters
108
142
 
109
- **id**: `string`
143
+ ##### id
144
+
145
+ `string`
110
146
 
111
147
  The id of the entity to remove.
112
148
 
149
+ ##### conditions?
150
+
151
+ `object`[]
152
+
153
+ The optional conditions to match for the entities.
154
+
113
155
  #### Returns
114
156
 
115
157
  `Promise`\<`void`\>
@@ -124,51 +166,49 @@ Nothing.
124
166
 
125
167
  ### query()
126
168
 
127
- > **query**(`conditions`?, `sortProperties`?, `properties`?, `cursor`?, `pageSize`?): `Promise`\<`object`\>
169
+ > **query**(`conditions`?, `sortProperties`?, `properties`?, `cursor`?, `pageSize`?): `Promise`\<\{ `entities`: `Partial`\<`T`\>[]; `cursor`: `string`; \}\>
128
170
 
129
171
  Find all the entities which match the conditions.
130
172
 
131
173
  #### Parameters
132
174
 
133
- **conditions?**: `EntityCondition`\<`T`\>
175
+ ##### conditions?
176
+
177
+ `EntityCondition`\<`T`\>
134
178
 
135
179
  The conditions to match for the entities.
136
180
 
137
- **sortProperties?**: `object`[]
181
+ ##### sortProperties?
182
+
183
+ `object`[]
138
184
 
139
185
  The optional sort order.
140
186
 
141
- **properties?**: keyof `T`[]
187
+ ##### properties?
188
+
189
+ keyof `T`[]
142
190
 
143
191
  The optional properties to return, defaults to all.
144
192
 
145
- **cursor?**: `string`
193
+ ##### cursor?
194
+
195
+ `string`
146
196
 
147
197
  The cursor to request the next page of entities.
148
198
 
149
- **pageSize?**: `number`
199
+ ##### pageSize?
200
+
201
+ `number`
150
202
 
151
203
  The suggested number of entities to return in each chunk, in some scenarios can return a different amount.
152
204
 
153
205
  #### Returns
154
206
 
155
- `Promise`\<`object`\>
207
+ `Promise`\<\{ `entities`: `Partial`\<`T`\>[]; `cursor`: `string`; \}\>
156
208
 
157
209
  All the entities for the storage matching the conditions,
158
210
  and a cursor which can be used to request more entities.
159
211
 
160
- ##### entities
161
-
162
- > **entities**: `Partial`\<`T`\>[]
163
-
164
- The entities, which can be partial if a limited keys list was provided.
165
-
166
- ##### cursor?
167
-
168
- > `optional` **cursor**: `string`
169
-
170
- An optional cursor, when defined can be used to call find to get more entities.
171
-
172
212
  #### Implementation of
173
213
 
174
214
  `IEntityStorageConnector.query`
@@ -3,3 +3,7 @@
3
3
  ## Classes
4
4
 
5
5
  - [MemoryEntityStorageConnector](classes/MemoryEntityStorageConnector.md)
6
+
7
+ ## Interfaces
8
+
9
+ - [IMemoryEntityStorageConnectorConstructorOptions](interfaces/IMemoryEntityStorageConnectorConstructorOptions.md)
@@ -0,0 +1,11 @@
1
+ # Interface: IMemoryEntityStorageConnectorConstructorOptions
2
+
3
+ Options for the Memory Entity Storage Connector constructor.
4
+
5
+ ## Properties
6
+
7
+ ### entitySchema
8
+
9
+ > **entitySchema**: `string`
10
+
11
+ The schema for the entity.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@twin.org/entity-storage-connector-memory",
3
- "version": "0.0.1-next.2",
3
+ "version": "0.0.1-next.21",
4
4
  "description": "Entity Storage connector implementation using in-memory storage",
5
5
  "repository": {
6
6
  "type": "git",
@@ -13,50 +13,22 @@
13
13
  "engines": {
14
14
  "node": ">=20.0.0"
15
15
  },
16
- "scripts": {
17
- "clean": "rimraf dist coverage docs/reference",
18
- "build": "tspc",
19
- "test": "vitest --run --config ./vitest.config.ts --no-cache",
20
- "coverage": "vitest --run --coverage --config ./vitest.config.ts --no-cache",
21
- "bundle:esm": "rollup --config rollup.config.mjs --environment MODULE:esm",
22
- "bundle:cjs": "rollup --config rollup.config.mjs --environment MODULE:cjs",
23
- "bundle": "npm run bundle:esm && npm run bundle:cjs",
24
- "docs:clean": "rimraf docs/reference",
25
- "docs:generate": "typedoc",
26
- "docs": "npm run docs:clean && npm run docs:generate",
27
- "dist": "npm run clean && npm run build && npm run test && npm run bundle && npm run docs"
28
- },
29
16
  "dependencies": {
30
17
  "@twin.org/core": "next",
31
18
  "@twin.org/entity": "next",
32
- "@twin.org/nameof": "next",
33
- "@twin.org/entity-storage-models": "0.0.1-next.2"
34
- },
35
- "devDependencies": {
36
- "@twin.org/nameof-transformer": "next",
37
- "@vitest/coverage-v8": "2.1.1",
38
- "copyfiles": "2.4.1",
39
- "dotenv": "16.4.5",
40
- "rimraf": "6.0.1",
41
- "rollup": "4.21.3",
42
- "rollup-plugin-copy": "3.5.0",
43
- "rollup-plugin-typescript2": "0.36.0",
44
- "ts-patch": "3.2.1",
45
- "typedoc": "0.26.7",
46
- "typedoc-plugin-markdown": "4.2.7",
47
- "typescript": "5.6.2",
48
- "vitest": "2.1.1"
19
+ "@twin.org/entity-storage-models": "0.0.1-next.21",
20
+ "@twin.org/nameof": "next"
49
21
  },
50
22
  "main": "./dist/cjs/index.cjs",
51
23
  "module": "./dist/esm/index.mjs",
52
24
  "types": "./dist/types/index.d.ts",
53
25
  "exports": {
54
26
  ".": {
27
+ "types": "./dist/types/index.d.ts",
55
28
  "require": "./dist/cjs/index.cjs",
56
- "import": "./dist/esm/index.mjs",
57
- "types": "./dist/types/index.d.ts"
29
+ "import": "./dist/esm/index.mjs"
58
30
  },
59
- "./locales": "./locales"
31
+ "./locales/*.json": "./locales/*.json"
60
32
  },
61
33
  "files": [
62
34
  "dist/cjs",