@microphi/list 2.4.0

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/README.md ADDED
@@ -0,0 +1,51 @@
1
+ # @microphi/list [![npm version](https://badge.fury.io/js/%40microphi%2Flist.svg)](https://badge.fury.io/js/%40microphi%2Flist)
2
+
3
+ > Simple and fast list-like class
4
+
5
+ It combines internally a map and an array of ids. The combination give this class the flexibility of an array and the ability to access directly to an element from its id.
6
+
7
+ ## Install
8
+ With your preferred package manager install
9
+ ```
10
+ @microphi/list
11
+ ```
12
+
13
+ ## How to use
14
+ ```typescript
15
+
16
+ interface Entity {
17
+ id: string;
18
+ user: {
19
+ email: string;
20
+ name: string;
21
+ };
22
+ anotherField?: any;
23
+ }
24
+
25
+ const users: Entity[] = [
26
+ { id: 'abc', user: {email: 'email1', name: 'name1'}},
27
+ { id: 'bcd', user: {email: 'email2', name: 'name2'}},
28
+ { id: 'cdf', user: {email: 'email3', name: 'name3'}},
29
+ ];
30
+
31
+ // Create a list of users, specifying the `id` field and optionally an array of initial values.
32
+ const list = new List<Entity>('id', users);
33
+
34
+ // upsert items. I.e.: append if new, update otherwise
35
+ list.upsert({
36
+ id: 'trs',
37
+ user: {email: 'emailtrs', name: 'nametrs'},
38
+ });
39
+
40
+ const user1 = {
41
+ id: 'lmn',
42
+ user: {email: 'emaillmn', name: 'namelmn'}
43
+ };
44
+
45
+ // prepend items. I.e.: add at the beginning if new, update otherwise
46
+ list.prepend(user1);
47
+
48
+ // remove items.
49
+ list.delete(user1);
50
+
51
+ ```
package/lib/index.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ export * from './lib/list/list';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAC"}
package/lib/index.js ADDED
@@ -0,0 +1,2 @@
1
+ export * from './lib/list/list';
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAC","sourcesContent":["export * from './lib/list/list';\n"]}
@@ -0,0 +1,31 @@
1
+ import { Subject } from 'rxjs';
2
+ import { $Keys, FunctionKeys } from 'utility-types';
3
+ export interface Operation {
4
+ op: FunctionKeys<List<any>>;
5
+ payload?: unknown;
6
+ timestamp: Date;
7
+ }
8
+ export declare class List<EntityType extends object> implements Iterable<EntityType> {
9
+ private IDField;
10
+ operations$: Subject<Operation>;
11
+ readonly entities: Map<string, EntityType>;
12
+ /**
13
+ * maps entities position from the original array to their ids
14
+ */
15
+ private readonly ids;
16
+ get size(): number;
17
+ has(id: string): boolean;
18
+ get(id: string): EntityType | undefined;
19
+ private getId;
20
+ constructor(IDField: $Keys<EntityType>, entities?: EntityType[]);
21
+ [Symbol.iterator](): IterableIterator<EntityType>;
22
+ /**
23
+ * Upsert one or more items. I.e.: append if new update otherwise
24
+ * */
25
+ upsert(...entities: EntityType[]): void;
26
+ prepend(...entities: EntityType[]): void;
27
+ clear(): void;
28
+ delete(...entities: EntityType[]): void;
29
+ append(...entities: EntityType[]): void;
30
+ }
31
+ //# sourceMappingURL=list.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list.d.ts","sourceRoot":"","sources":["../../../src/lib/list/list.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAC/B,OAAO,EAAE,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAGpD,MAAM,WAAW,SAAS;IAExB,EAAE,EAAE,YAAY,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;IAC5B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,SAAS,EAAE,IAAI,CAAC;CACjB;AAED,qBAAa,IAAI,CAAC,UAAU,SAAS,MAAM,CAAE,YAAW,QAAQ,CAAC,UAAU,CAAC;IAgC9D,OAAO,CAAC,OAAO;IA9BpB,WAAW,qBAA4B;IAE9C,SAAgB,QAAQ,0BAAiC;IAEzD;;OAEG;IACH,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAgB;IAEpC,IAAW,IAAI,WAOd;IAEM,GAAG,CAAC,EAAE,EAAE,MAAM;IAId,GAAG,CAAC,EAAE,EAAE,MAAM;IAIrB,OAAO,CAAC,KAAK;gBAIO,OAAO,EAAE,KAAK,CAAC,UAAU,CAAC,EAAE,QAAQ,GAAE,UAAU,EAAO;IAW1E,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,gBAAgB,CAAC,UAAU,CAAC;IAalD;;QAEI;IACG,MAAM,CAAC,GAAG,QAAQ,EAAE,UAAU,EAAE;IAehC,OAAO,CAAC,GAAG,QAAQ,EAAE,UAAU,EAAE;IAgBjC,KAAK;IAQL,MAAM,CAAC,GAAG,QAAQ,EAAE,UAAU,EAAE;IAehC,MAAM,CAAC,GAAG,QAAQ,EAAE,UAAU,EAAE;CAgBxC"}
@@ -0,0 +1,97 @@
1
+ import { Subject } from 'rxjs';
2
+ export class List {
3
+ get size() {
4
+ if (this.ids.length !== this.entities.size) {
5
+ throw new Error(`Size Mismatch ${this.ids.length} !== ${this.entities.size}`);
6
+ }
7
+ return this.entities.size;
8
+ }
9
+ has(id) {
10
+ return this.entities.has(id);
11
+ }
12
+ get(id) {
13
+ return this.entities.get(id);
14
+ }
15
+ getId(entity) {
16
+ return entity[this.IDField];
17
+ }
18
+ constructor(IDField, entities = []) {
19
+ this.IDField = IDField;
20
+ this.operations$ = new Subject();
21
+ this.entities = new Map();
22
+ /**
23
+ * maps entities position from the original array to their ids
24
+ */
25
+ this.ids = [];
26
+ this.ids = entities.map((e) => this.getId(e));
27
+ entities
28
+ .forEach((item) => {
29
+ const id = this.getId(item);
30
+ this.entities.set(id, item);
31
+ });
32
+ }
33
+ *[Symbol.iterator]() {
34
+ for (const idx in this.ids) {
35
+ const id = this.ids[idx];
36
+ const entity = this.entities.get(id);
37
+ if (entity) {
38
+ yield entity;
39
+ }
40
+ else {
41
+ throw new Error(`Cannot get entity with id ${id}`);
42
+ }
43
+ }
44
+ }
45
+ /**
46
+ * Upsert one or more items. I.e.: append if new update otherwise
47
+ * */
48
+ upsert(...entities) {
49
+ entities.forEach((e) => {
50
+ const id = this.getId(e);
51
+ if (!this.entities.has(id)) {
52
+ this.ids.push(id);
53
+ }
54
+ this.entities.set(id, e);
55
+ });
56
+ this.operations$.next({ op: 'upsert', payload: entities, timestamp: new Date() });
57
+ }
58
+ prepend(...entities) {
59
+ entities.reverse().forEach((e) => {
60
+ const id = this.getId(e);
61
+ if (this.entities.has(id)) {
62
+ this.delete(e);
63
+ }
64
+ this.ids.unshift(id);
65
+ this.entities.set(id, e);
66
+ });
67
+ this.operations$.next({ op: 'prepend', payload: entities, timestamp: new Date() });
68
+ }
69
+ clear() {
70
+ this.ids.length = 0;
71
+ this.entities.clear();
72
+ this.operations$.next({ op: 'clear', timestamp: new Date() });
73
+ }
74
+ delete(...entities) {
75
+ entities.forEach((e) => {
76
+ const id = this.getId(e);
77
+ const indexOfId = this.ids.findIndex((_id) => _id === id);
78
+ if (indexOfId >= 0) {
79
+ this.ids.splice(indexOfId, 1);
80
+ this.entities.delete(id);
81
+ }
82
+ });
83
+ this.operations$.next({ op: 'delete', payload: entities, timestamp: new Date() });
84
+ }
85
+ append(...entities) {
86
+ entities.forEach((e) => {
87
+ const id = this.getId(e);
88
+ if (this.entities.has(id)) {
89
+ this.delete(e);
90
+ }
91
+ this.ids.push(id);
92
+ this.entities.set(id, e);
93
+ });
94
+ this.operations$.next({ op: 'append', payload: entities, timestamp: new Date() });
95
+ }
96
+ }
97
+ //# sourceMappingURL=list.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list.js","sourceRoot":"","sources":["../../../src/lib/list/list.ts"],"names":[],"mappings":"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","sourcesContent":["import { Subject } from 'rxjs';\nimport { $Keys, FunctionKeys } from 'utility-types';\n\n\nexport interface Operation {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n op: FunctionKeys<List<any>>;\n payload?: unknown;\n timestamp: Date;\n}\n\nexport class List<EntityType extends object> implements Iterable<EntityType> {\n\n public operations$ = new Subject<Operation>();\n\n public readonly entities = new Map<string, EntityType>();\n\n /**\n * maps entities position from the original array to their ids\n */\n private readonly ids: string[] = [];\n\n public get size() {\n if (this.ids.length !== this.entities.size) {\n\n throw new Error(`Size Mismatch ${this.ids.length} !== ${this.entities.size}`);\n }\n\n return this.entities.size;\n }\n\n public has(id: string) {\n return this.entities.has(id);\n }\n\n public get(id: string) {\n return this.entities.get(id);\n }\n\n private getId(entity: EntityType): string {\n return entity[this.IDField] as string;\n }\n\n constructor(private IDField: $Keys<EntityType>, entities: EntityType[] = []) {\n\n this.ids = entities.map((e) => this.getId(e));\n\n entities\n .forEach((item) => {\n const id = this.getId(item);\n this.entities.set(id, item);\n });\n }\n\n *[Symbol.iterator](): IterableIterator<EntityType> {\n for (const idx in this.ids) {\n const id = this.ids[idx];\n\n const entity = this.entities.get(id);\n if (entity) {\n yield entity;\n } else {\n throw new Error(`Cannot get entity with id ${id}`);\n }\n }\n }\n\n /**\n * Upsert one or more items. I.e.: append if new update otherwise\n * */\n public upsert(...entities: EntityType[]) {\n entities.forEach((e) => {\n const id = this.getId(e);\n\n if (!this.entities.has(id)) {\n this.ids.push(id);\n }\n\n this.entities.set(id, e);\n\n });\n\n this.operations$.next({ op: 'upsert', payload: entities, timestamp: new Date() });\n }\n\n public prepend(...entities: EntityType[]) {\n entities.reverse().forEach((e) => {\n const id = this.getId(e);\n\n if (this.entities.has(id)) {\n this.delete(e);\n }\n\n this.ids.unshift(id);\n\n this.entities.set(id, e);\n\n });\n this.operations$.next({ op: 'prepend', payload: entities, timestamp: new Date() });\n }\n\n public clear() {\n\n this.ids.length = 0;\n this.entities.clear();\n this.operations$.next({ op: 'clear', timestamp: new Date() });\n\n }\n\n public delete(...entities: EntityType[]) {\n\n entities.forEach((e) => {\n const id = this.getId(e);\n const indexOfId = this.ids.findIndex((_id) => _id === id);\n\n if (indexOfId >= 0) {\n this.ids.splice(indexOfId, 1);\n this.entities.delete(id);\n }\n });\n\n this.operations$.next({ op: 'delete', payload: entities, timestamp: new Date() });\n }\n\n public append(...entities: EntityType[]) {\n entities.forEach((e) => {\n const id = this.getId(e);\n\n if (this.entities.has(id)) {\n this.delete(e);\n }\n\n this.ids.push(id);\n this.entities.set(id, e);\n });\n\n this.operations$.next({ op: 'append', payload: entities, timestamp: new Date() });\n }\n\n\n}\n"]}
package/package.json ADDED
@@ -0,0 +1,42 @@
1
+ {
2
+ "name": "@microphi/list",
3
+ "version": "2.4.0",
4
+ "description": "Simple and fast list-like class",
5
+ "main": "lib/index.js",
6
+ "typings": "lib/index.d.ts",
7
+ "module": "lib/index.js",
8
+ "directories": {
9
+ "lib": "lib"
10
+ },
11
+ "files": [
12
+ "lib"
13
+ ],
14
+ "license": "MIT",
15
+ "keywords": [
16
+ "list"
17
+ ],
18
+ "author": {
19
+ "email": "cavaliere.davide@gmail.com",
20
+ "name": "Davide Cavaliere",
21
+ "url": "www.dcsoftware.io"
22
+ },
23
+ "homepage": "https://github.com/microph1/microphi",
24
+ "scripts": {
25
+ "build": "tsc -b tsconfig.build.json",
26
+ "build:ci": "yarn build",
27
+ "test:ci": "jest --coverage --ci",
28
+ "prepack": "yarn build",
29
+ "lint": "eslint ./src"
30
+ },
31
+ "dependencies": {
32
+ "@microphi/debug": "^2.3.0"
33
+ },
34
+ "devDependencies": {
35
+ "@babel/plugin-transform-modules-commonjs": "^7.23.3",
36
+ "@types/node": "^20.11.30",
37
+ "utility-types": "^3.10.0"
38
+ },
39
+ "peerDependencies": {
40
+ "rxjs": "~7.8.0"
41
+ }
42
+ }