@livequery/client 2.0.31 → 2.0.105

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.
Files changed (51) hide show
  1. package/README.md +477 -0
  2. package/dist/LivequeryClient.d.ts +67 -0
  3. package/dist/LivequeryClient.d.ts.map +1 -0
  4. package/dist/LivequeryClient.js +343 -0
  5. package/dist/LivequeryClient.js.map +1 -0
  6. package/dist/LivequeryCollection.d.ts +92 -0
  7. package/dist/LivequeryCollection.d.ts.map +1 -0
  8. package/dist/LivequeryCollection.js +231 -0
  9. package/dist/LivequeryCollection.js.map +1 -0
  10. package/dist/LivequeryDocument.d.ts +23 -0
  11. package/dist/LivequeryDocument.d.ts.map +1 -0
  12. package/dist/LivequeryDocument.js +22 -0
  13. package/dist/LivequeryDocument.js.map +1 -0
  14. package/dist/LivequeryMemoryStorage.d.ts +14 -0
  15. package/dist/LivequeryMemoryStorage.d.ts.map +1 -0
  16. package/dist/LivequeryMemoryStorage.js +89 -0
  17. package/dist/LivequeryMemoryStorage.js.map +1 -0
  18. package/dist/LivequeryStorge.d.ts +12 -0
  19. package/dist/LivequeryStorge.d.ts.map +1 -0
  20. package/dist/LivequeryStorge.js +2 -0
  21. package/dist/LivequeryStorge.js.map +1 -0
  22. package/dist/LivequeryTransporter.d.ts +22 -0
  23. package/dist/LivequeryTransporter.d.ts.map +1 -0
  24. package/dist/LivequeryTransporter.js +2 -0
  25. package/dist/LivequeryTransporter.js.map +1 -0
  26. package/dist/helpers/filterDocs.d.ts +5 -0
  27. package/dist/helpers/filterDocs.d.ts.map +1 -0
  28. package/dist/helpers/filterDocs.js +80 -0
  29. package/dist/helpers/filterDocs.js.map +1 -0
  30. package/dist/helpers/tryCatch.d.ts +2 -0
  31. package/dist/helpers/tryCatch.d.ts.map +1 -0
  32. package/dist/helpers/tryCatch.js +10 -0
  33. package/dist/helpers/tryCatch.js.map +1 -0
  34. package/dist/helpers/whenCompleted.d.ts +3 -0
  35. package/dist/helpers/whenCompleted.d.ts.map +1 -0
  36. package/dist/helpers/whenCompleted.js +5 -0
  37. package/dist/helpers/whenCompleted.js.map +1 -0
  38. package/dist/index.d.ts +9 -0
  39. package/dist/index.d.ts.map +1 -0
  40. package/dist/index.js +9 -0
  41. package/dist/index.js.map +1 -0
  42. package/dist/types.d.ts +70 -0
  43. package/dist/types.d.ts.map +1 -0
  44. package/dist/types.js +2 -0
  45. package/dist/types.js.map +1 -0
  46. package/package.json +95 -18
  47. package/build/Collection.d.ts +0 -52
  48. package/build/Collection.js +0 -366
  49. package/build/index.d.ts +0 -1
  50. package/build/index.js +0 -1
  51. package/build/tsconfig.tsbuildinfo +0 -1
package/dist/index.js ADDED
@@ -0,0 +1,9 @@
1
+ export * from "./LivequeryCollection.js";
2
+ export * from "./LivequeryClient.js";
3
+ export * from "./LivequeryMemoryStorage.js";
4
+ export * from "./LivequeryStorge.js";
5
+ export * from "./LivequeryTransporter.js";
6
+ export * from "./types.js";
7
+ export * from "./helpers/filterDocs.js";
8
+ export * from "./LivequeryDocument.js";
9
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,0BAA0B,CAAA;AACxC,cAAc,sBAAsB,CAAA;AACpC,cAAc,6BAA6B,CAAA;AAC3C,cAAc,sBAAsB,CAAA;AACpC,cAAc,2BAA2B,CAAA;AACzC,cAAc,YAAY,CAAA;AAC1B,cAAc,yBAAyB,CAAA;AACvC,cAAc,wBAAwB,CAAA"}
@@ -0,0 +1,70 @@
1
+ export type Doc<T = {}> = T & {
2
+ id: string;
3
+ };
4
+ export type DocError = {
5
+ code: string;
6
+ message: string;
7
+ transporter_id: string;
8
+ };
9
+ export type DocState<T extends Doc> = T & {
10
+ _deleting?: boolean;
11
+ _deleting_error?: DocError;
12
+ _updating?: boolean;
13
+ _updating_error?: DocError;
14
+ _adding?: boolean;
15
+ _adding_error?: DocError;
16
+ _remotes?: Record<string, string | number>;
17
+ _prev?: Partial<T>;
18
+ };
19
+ export type RealtimeChangeSource = 'realtime' | 'action' | 'query';
20
+ type FlatObjectKeys<T, MatchType, K extends keyof T = keyof T> = (K extends string ? (0 extends (1 & T[K]) ? never : (T[K] extends MatchType ? K : (T[K] extends {
21
+ [key: string]: any;
22
+ } ? (`${K}.${FlatObjectKeys<T[K], MatchType>}`) : never))) : never);
23
+ type QueryBuilder<T extends Doc, FieldType, PostFix extends string | number, Value> = {
24
+ [K in keyof T as `${FlatObjectKeys<T, FieldType>}${PostFix extends string ? `:${PostFix}` : ''}`]?: Value;
25
+ };
26
+ export type LivequeryPagingFilters = {
27
+ ':limit': number;
28
+ ':before': string;
29
+ ':after': string;
30
+ ':around': string;
31
+ ':page': number;
32
+ };
33
+ export type LivequeryInlineFilters<T extends Doc> = (QueryBuilder<T, number, 'sort', 'asc' | 'desc'> & QueryBuilder<T, string, 'sort', 'asc' | 'desc'> & QueryBuilder<T, number, 'gt', number> & QueryBuilder<T, number, 'gte', number> & QueryBuilder<T, number, 'lt', number> & QueryBuilder<T, number, 'lte', number> & QueryBuilder<T, number, 'eq-number', number> & QueryBuilder<T, number, 'in', number[]> & QueryBuilder<T, number, 'nin', number[]> & QueryBuilder<T, number[], 'include', number> & QueryBuilder<T, boolean, 'boolean', 'true' | 'false' | 'not-true' | 'not-false'> & QueryBuilder<T, string, 'like', string> & QueryBuilder<T, string, 1, string> & QueryBuilder<T, string, 'in', string[]> & QueryBuilder<T, string, 'nin', string[]> & QueryBuilder<T, string[], 'include', string> & QueryBuilder<T, any, 'null', 'null-only' | 'not-null'>);
34
+ export type LivequeryFilters<T extends Doc> = LivequeryPagingFilters & LivequeryInlineFilters<T>;
35
+ export type DataChangeEvent = {
36
+ collection_ref: string;
37
+ id: string;
38
+ type: 'added' | 'removed' | 'modified';
39
+ data?: Record<string, any>;
40
+ };
41
+ export type LivequeryPaging = {
42
+ next?: {
43
+ count: number;
44
+ cursor: string;
45
+ };
46
+ prev?: {
47
+ count: number;
48
+ cursor: string;
49
+ };
50
+ total: number;
51
+ current: number;
52
+ };
53
+ export type LivequeryQueryParams<T extends Doc> = {
54
+ ref: string;
55
+ filters?: Partial<LivequeryFilters<T>>;
56
+ headers?: Record<string, string>;
57
+ };
58
+ export type LivequeryAction = Omit<LivequeryQueryParams<Doc>, 'query_id' | 'filters'> & {
59
+ action: string;
60
+ payload?: Record<string, any>;
61
+ };
62
+ export type LivequeryResult<T> = {
63
+ data: T;
64
+ error?: {
65
+ code: string;
66
+ message: string;
67
+ };
68
+ };
69
+ export {};
70
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/dist/types.js ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
package/package.json CHANGED
@@ -1,29 +1,106 @@
1
1
  {
2
2
  "name": "@livequery/client",
3
+ "version": "2.0.105",
3
4
  "type": "module",
4
- "repository": {
5
- "url": "https://github.com/livequery/client"
5
+ "main": "./dist/index.js",
6
+ "module": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.js",
12
+ "default": "./dist/index.js"
13
+ },
14
+ "./LivequeryCollection": {
15
+ "types": "./dist/LivequeryCollection.d.ts",
16
+ "import": "./dist/LivequeryCollection.js",
17
+ "default": "./dist/LivequeryCollection.js"
18
+ },
19
+ "./LivequeryClient": {
20
+ "types": "./dist/LivequeryClient.d.ts",
21
+ "import": "./dist/LivequeryClient.js",
22
+ "default": "./dist/LivequeryClient.js"
23
+ },
24
+ "./LivequeryDocument": {
25
+ "types": "./dist/LivequeryDocument.d.ts",
26
+ "import": "./dist/LivequeryDocument.js",
27
+ "default": "./dist/LivequeryDocument.js"
28
+ },
29
+ "./LivequeryMemoryStorage": {
30
+ "types": "./dist/LivequeryMemoryStorage.d.ts",
31
+ "import": "./dist/LivequeryMemoryStorage.js",
32
+ "default": "./dist/LivequeryMemoryStorage.js"
33
+ },
34
+ "./LivequeryStorge": {
35
+ "types": "./dist/LivequeryStorge.d.ts",
36
+ "import": "./dist/LivequeryStorge.js",
37
+ "default": "./dist/LivequeryStorge.js"
38
+ },
39
+ "./LivequeryTransporter": {
40
+ "types": "./dist/LivequeryTransporter.d.ts",
41
+ "import": "./dist/LivequeryTransporter.js",
42
+ "default": "./dist/LivequeryTransporter.js"
43
+ },
44
+ "./types": {
45
+ "types": "./dist/types.d.ts",
46
+ "import": "./dist/types.js",
47
+ "default": "./dist/types.js"
48
+ },
49
+ "./helpers/filterDocs": {
50
+ "types": "./dist/helpers/filterDocs.d.ts",
51
+ "import": "./dist/helpers/filterDocs.js",
52
+ "default": "./dist/helpers/filterDocs.js"
53
+ },
54
+ "./package.json": "./package.json"
55
+ },
56
+ "typesVersions": {
57
+ "*": {
58
+ "LivequeryCollection": [
59
+ "./dist/LivequeryCollection.d.ts"
60
+ ],
61
+ "LivequeryClient": [
62
+ "./dist/LivequeryClient.d.ts"
63
+ ],
64
+ "LivequeryDocument": [
65
+ "./dist/LivequeryDocument.d.ts"
66
+ ],
67
+ "LivequeryMemoryStorage": [
68
+ "./dist/LivequeryMemoryStorage.d.ts"
69
+ ],
70
+ "LivequeryStorge": [
71
+ "./dist/LivequeryStorge.d.ts"
72
+ ],
73
+ "LivequeryTransporter": [
74
+ "./dist/LivequeryTransporter.d.ts"
75
+ ],
76
+ "types": [
77
+ "./dist/types.d.ts"
78
+ ],
79
+ "helpers/filterDocs": [
80
+ "./dist/helpers/filterDocs.d.ts"
81
+ ]
82
+ }
6
83
  },
7
- "version": "2.0.31",
8
- "description": "",
9
- "main": "build/index.js",
10
- "types": "build/index.d.ts",
11
84
  "files": [
12
- "build/**/*"
85
+ "dist"
13
86
  ],
14
- "dependencies": {
15
- "uuid": "^8.3.2"
87
+ "sideEffects": false,
88
+ "scripts": {
89
+ "clean": "rm -rf dist",
90
+ "build:js": "bunx tsc -p tsconfig.build.json --emitDeclarationOnly false --declaration false --declarationMap false",
91
+ "build:types": "bunx tsc -p tsconfig.build.json --emitDeclarationOnly",
92
+ "build": "bun run clean && bun run build:js && bun run build:types",
93
+ "build:watch": "bunx tsc -p tsconfig.build.json --watch --preserveWatchOutput",
94
+ "prepublishOnly": "bun run build"
16
95
  },
17
96
  "devDependencies": {
18
- "typescript": "^5.6.3",
19
- "rxjs": "^7.8.1",
20
- "@livequery/types": "^2.0.22"
97
+ "@types/bun": "latest",
98
+ "@types/chrome": "^0.1.38",
99
+ "typescript": "^5"
21
100
  },
22
- "scripts": {
23
- "test": "echo \"Error: no test specified\" && exit 1",
24
- "build": "rm -rf build; tsc -b .",
25
- "deploy": "yarn build; git add .; git commit -m \"Update\"; git push origin master; npm publish --access public"
101
+ "dependencies": {
102
+ "rxjs": "^7.8.2",
103
+ "uuidv7": "^1.2.1"
26
104
  },
27
- "author": "",
28
- "license": "ISC"
105
+ "private": false
29
106
  }
@@ -1,52 +0,0 @@
1
- import { Subject, BehaviorSubject } from 'rxjs';
2
- import { LivequeryBaseEntity, QueryOption, Transporter, UpdatedData, Paging, Response } from '@livequery/types';
3
- export type LoadingIndicator = false | 'backward' | 'forward' | 'both';
4
- export type CollectionOption<T extends LivequeryBaseEntity = LivequeryBaseEntity> = {
5
- transporter: Transporter;
6
- sync_delay?: number;
7
- options?: Partial<QueryOption<T>>;
8
- realtime?: boolean;
9
- };
10
- export type SmartQueryItem<T> = T & {
11
- __remove: Function;
12
- __removing: boolean;
13
- __update: (data: Partial<T>) => any;
14
- __updating: boolean;
15
- __adding: boolean;
16
- __trigger: <R extends {}>(name: string, payload?: any, query?: any) => Promise<Response<R>>;
17
- __ref: string;
18
- toJson: () => T;
19
- };
20
- export type CollectionStream<T extends LivequeryBaseEntity = LivequeryBaseEntity> = {
21
- n: number;
22
- items: SmartQueryItem<T>[];
23
- paging: Partial<Paging>;
24
- loading?: LoadingIndicator;
25
- options: Partial<QueryOption<T>>;
26
- error?: boolean;
27
- code?: string;
28
- message?: string;
29
- summary?: {
30
- [key: string]: any;
31
- };
32
- };
33
- export declare class CollectionObservable<T extends LivequeryBaseEntity = LivequeryBaseEntity> extends BehaviorSubject<CollectionStream<T>> {
34
- #private;
35
- private ref;
36
- private collection_options;
37
- readonly $changes: Subject<UpdatedData<T>>;
38
- unsubscribe(): void;
39
- constructor(ref: string | false | null | '' | undefined, collection_options: CollectionOption<T>);
40
- set_realtime(realtime: boolean): void;
41
- private fetch_data;
42
- reset(): void;
43
- fetch_more(): void;
44
- fetch_prev(): void;
45
- filter(filters: Partial<QueryOption<T>>): void;
46
- add(payload: Partial<T>): Promise<import("@livequery/types").DocumentResponse<T & LivequeryBaseEntity>>;
47
- update({ id: update_payload_id, ...payload }: Partial<T>): Promise<import("@livequery/types").DocumentResponse<T & LivequeryBaseEntity> | undefined>;
48
- remove(remove_document_id?: string): Promise<import("@livequery/types").DocumentResponse<LivequeryBaseEntity> | undefined>;
49
- trigger<R extends {}>(name: string, payload?: object, trigger_document_id?: string, query?: {
50
- [key: string]: string | number | boolean;
51
- }): Promise<Response<R>>;
52
- }
@@ -1,366 +0,0 @@
1
- import { Subject, merge, BehaviorSubject } from 'rxjs';
2
- import { bufferTime, filter, finalize, first, map, share, skip, tap, toArray } from 'rxjs/operators';
3
- export class CollectionObservable extends BehaviorSubject {
4
- ref;
5
- collection_options;
6
- $changes = new Subject();
7
- #pages = new Map();
8
- #queries = new Set();
9
- #sorters = new Array;
10
- #IdMap = new Map();
11
- #refs = [];
12
- unsubscribe() {
13
- super.unsubscribe();
14
- this.#queries.forEach(s => s.unsubscribe());
15
- }
16
- constructor(ref, collection_options) {
17
- super({
18
- n: 0,
19
- items: [],
20
- loading: false,
21
- paging: {},
22
- options: collection_options.options || {}
23
- });
24
- this.ref = ref;
25
- this.collection_options = collection_options;
26
- if (ref && (ref.startsWith('/') || ref.endsWith('/')))
27
- throw 'INVAILD_REF_FORMAT';
28
- this.#refs = this.#ref_parser(ref);
29
- }
30
- #ref_parser(path) {
31
- if (!path)
32
- return [];
33
- const refs_builder = (paths) => {
34
- const [a, b, ...c] = paths;
35
- if (!b)
36
- return paths;
37
- const r = a.map(aa => b.map(bb => `${aa}/${bb}`)).flat(2);
38
- const d = [r, ...c];
39
- return refs_builder(d);
40
- };
41
- return path.split(',').map(f => refs_builder(f.trim().split('/').map(l => l.split('|')))).flat(2);
42
- }
43
- set_realtime(realtime) {
44
- this.collection_options.realtime = realtime;
45
- }
46
- #sync(stream, from, direction) {
47
- if (from == 'realtime' && this.collection_options.realtime == false)
48
- return;
49
- const state = this.getValue();
50
- const actions = { reindex: false };
51
- for (const { data, error, code, message, } of stream) {
52
- if (from == 'request') {
53
- state.loading = false;
54
- state.n = state.n + 1;
55
- }
56
- // Error & paging
57
- if (error) {
58
- state.error = true;
59
- state.code = code;
60
- state.message = message;
61
- }
62
- if (data?.summary) {
63
- state.summary = data.summary;
64
- }
65
- // Sync
66
- for (const change of data?.changes || []) {
67
- if (!change?.data?.id)
68
- continue;
69
- const { data: payload, type } = change;
70
- this.$changes.next(change);
71
- const index = this.#IdMap.get(payload.id) ?? -1;
72
- if (index == -1 && type == 'added') {
73
- if (
74
- // Is first value from HTTP query
75
- from == 'request'
76
- || (
77
- // Is realtime update that match filters
78
- from == 'realtime' && Object
79
- .keys(state.options || {})
80
- .filter(key => !key.startsWith(':'))
81
- .every(key => {
82
- const [field, expression] = key.split(':');
83
- const a = payload[field];
84
- const b = state.options?.[field];
85
- const map = {
86
- eq: () => a == b,
87
- ne: () => a != b,
88
- lt: () => typeof a == 'number' && typeof b == 'number' && a < b,
89
- lte: () => typeof a == 'number' && typeof b == 'number' && a <= b,
90
- gt: () => typeof a == 'number' && typeof b == 'number' && a > b,
91
- gte: () => typeof a == 'number' && typeof b == 'number' && a >= b,
92
- in: () => Array.isArray(a) && a?.includes(b),
93
- like: () => typeof a == 'string' && a.includes(`${b}`),
94
- between: () => typeof a == 'number' && Array.isArray(b) && typeof b[0] == 'number' && b[0] <= a && typeof b[1] == 'number' && a <= b[1]
95
- };
96
- try {
97
- const expr = expression == '' ? 'eq' : expression;
98
- if (map[expr])
99
- return map[expr]();
100
- }
101
- catch (e) { }
102
- return true;
103
- }))) {
104
- const item = {
105
- ...payload,
106
- id: payload.id || payload._id,
107
- __adding: false,
108
- __updating: false,
109
- __removing: false,
110
- __remove: () => this.remove(payload?.id),
111
- __trigger: (name, input = undefined, query) => this.trigger(name, input, payload?.id, query),
112
- __update: (input) => this.update({ ...input, id: payload?.id }),
113
- __ref: change.ref,
114
- toJson: () => payload
115
- };
116
- direction == 'forward' ? state.items.push(item) : state.items.unshift(item);
117
- actions.reindex = true;
118
- }
119
- }
120
- if (index >= 0) {
121
- if (type == 'added' || type == 'modified') {
122
- const sort_key_value_updated = this.#sorters.some(({ key }) => {
123
- const value = payload[key];
124
- if (typeof value == 'string' || typeof value == 'number')
125
- return true;
126
- });
127
- if (sort_key_value_updated) {
128
- actions.reindex = true;
129
- }
130
- state.items[index] = {
131
- ...state.items[index],
132
- __adding: false,
133
- __updating: false,
134
- __removing: false,
135
- ...payload
136
- };
137
- }
138
- if (type == 'removed') {
139
- state.items.splice(index, 1);
140
- for (const [document_id, i] of this.#IdMap) {
141
- i == index && this.#IdMap.delete(document_id);
142
- i > index && this.#IdMap.set(document_id, i - 1);
143
- }
144
- }
145
- }
146
- }
147
- }
148
- if (actions.reindex) {
149
- state.items = state.items.sort((a, b) => {
150
- for (const { key, order } of this.#sorters) {
151
- const aa = a[key];
152
- const bb = b[key];
153
- if (typeof aa == 'number' && typeof bb == 'number') {
154
- const rs = aa - bb;
155
- if (rs == 0)
156
- continue;
157
- return rs * order;
158
- }
159
- if (typeof aa == 'string' && typeof bb == 'string') {
160
- const rs = aa.localeCompare(bb);
161
- if (rs == 0)
162
- continue;
163
- return rs * order;
164
- }
165
- }
166
- return -1;
167
- });
168
- this.#IdMap.clear();
169
- state.items.map((item, index) => this.#IdMap.set(item.id, index));
170
- }
171
- if (state.paging?.count) {
172
- const d = state.items.length - state.paging.count.current;
173
- state.paging.count.current = state.items.length;
174
- state.paging.count.total += d;
175
- }
176
- if (direction && stream.some(d => d.data?.paging)) {
177
- // Cache paging
178
- this.#pages.clear();
179
- stream.forEach(s => s.data?.paging && this.#pages.set(s.ref, s.data?.paging));
180
- // Caculate paging here
181
- const last_page_total = state.items.length;
182
- const total = stream.reduce((p, c) => p + (c.data?.paging?.count?.total || 0), 0);
183
- const prev = stream.reduce((p, c) => p + (c.data?.paging?.count?.prev || 0), 0);
184
- const next = stream.reduce((p, c) => p + (c.data?.paging?.count?.next || 0), 0);
185
- state.paging = {
186
- count: {
187
- current: state.items.length,
188
- next: next - (direction == 'backward' ? last_page_total : 0),
189
- prev: prev - (direction == 'forward' ? last_page_total : 0),
190
- total
191
- },
192
- has: {
193
- next: stream.some(s => s.data?.paging?.has?.next),
194
- prev: stream.some(s => s.data?.paging?.has?.prev)
195
- },
196
- page: {
197
- current: Math.min(...stream.map(s => s.data?.paging?.page?.current || 0)),
198
- total: Math.max(...stream.map(s => s.data?.paging?.page?.total || 0))
199
- }
200
- };
201
- }
202
- this.next(state);
203
- }
204
- fetch_data(options = {}, loading, flush = false) {
205
- if (flush) {
206
- this.#pages.clear();
207
- this.#queries.forEach(s => s.unsubscribe());
208
- this.#queries.clear();
209
- this.#IdMap.clear();
210
- }
211
- if (!this.ref)
212
- return;
213
- if (this.#refs.length == 0)
214
- return;
215
- if (this.getValue().loading && !flush)
216
- return;
217
- const remain_data_refs = this.#refs.filter(ref => {
218
- const paging = this.#pages.get(ref);
219
- if (!paging)
220
- return true;
221
- return loading == 'forward' ? paging.has?.next : paging.has?.prev;
222
- });
223
- if (remain_data_refs.length == 0)
224
- return;
225
- this.next({
226
- ...this.getValue(),
227
- items: flush ? [] : this.getValue().items,
228
- loading,
229
- options: {
230
- ...this.getValue().options || {},
231
- ...options
232
- }
233
- });
234
- this.collection_options.options = options;
235
- this.#sorters = Object.keys(options).filter(k => k.endsWith(':sort')).map(k => {
236
- const key = k.split(':sort')[0];
237
- const order = options[k] == 1 ? 1 : -1;
238
- return { key, order };
239
- });
240
- this.#sorters.every(a => a.key != 'id') && this.#sorters.push({ key: 'id', order: -1 });
241
- const queries = remain_data_refs.map((ref, index) => {
242
- const cursor = this.#pages.get(ref)?.cursor;
243
- const opts = {
244
- ...options,
245
- ...loading == 'backward' && cursor?.first ? { ':before': cursor?.first } : {},
246
- ...loading == 'forward' && cursor?.last ? { ':after': cursor?.last } : {},
247
- };
248
- return this
249
- .collection_options
250
- .transporter
251
- .query(ref, opts).pipe(map(data => ({
252
- ...data,
253
- ref
254
- })), share());
255
- });
256
- const first_values = merge(...queries.map(q => q.pipe(filter(r => !!r.data?.paging || !!r.error), first()))).pipe(toArray(), tap(list => this.#sync(list, 'request', loading))).subscribe();
257
- const subscription = merge(...queries.map(q => q.pipe(skip(1)))).pipe(bufferTime(this.collection_options?.sync_delay || 500), filter(list => list.length > 0), map(data => this.#sync(data, 'realtime', loading)), finalize(() => first_values.unsubscribe())).subscribe();
258
- this.#queries.add(subscription);
259
- }
260
- reset() {
261
- this.fetch_data({}, 'both', true);
262
- }
263
- fetch_more() {
264
- const { options } = this.getValue();
265
- this.fetch_data(options, 'forward');
266
- }
267
- fetch_prev() {
268
- const { options } = this.getValue();
269
- this.fetch_data(options, 'backward');
270
- }
271
- filter(filters) {
272
- this.fetch_data(filters, 'forward', true);
273
- }
274
- #find_ref_by_id(id) {
275
- if (!id || !this.ref)
276
- return { ref: this.ref, collection_ref: this.ref, doc: null };
277
- const index = this.#IdMap.get(id);
278
- if (index == undefined)
279
- return {};
280
- const doc = this.getValue().items[index];
281
- const origin_ref = doc.__ref;
282
- if (!origin_ref)
283
- throw 'COLLECTION_REF_NOT_FOUND';
284
- const refs = origin_ref.split('/');
285
- const collection_ref = refs.slice(0, refs.length - (refs.length % 2 == 1 ? 0 : 1)).join('/');
286
- const ref = `${collection_ref}/${id}`;
287
- return { ref, id, collection_ref, index, doc };
288
- }
289
- async add(payload) {
290
- const r = await this.collection_options.transporter.add(`${this.ref}`, payload);
291
- if (r.data && r.data.item && !r.data.item.id) {
292
- r.data.item.id = r.data.item._id;
293
- }
294
- return r;
295
- }
296
- async update({ id: update_payload_id, ...payload }) {
297
- const { id, ref, doc } = this.#find_ref_by_id(update_payload_id);
298
- if (!ref)
299
- return;
300
- // Trigger local update
301
- this.#sync([{
302
- ref,
303
- data: {
304
- changes: [{
305
- data: { ...payload, id, __updating: true },
306
- ref,
307
- type: 'modified'
308
- }]
309
- }
310
- }], 'local');
311
- try {
312
- return await this.collection_options.transporter.update(ref, payload);
313
- }
314
- catch (e) {
315
- this.#sync([{
316
- ref,
317
- data: {
318
- changes: [{
319
- data: { ...doc || {}, id, __updating: false },
320
- ref,
321
- type: 'modified'
322
- }]
323
- }
324
- }], 'local');
325
- throw e;
326
- }
327
- }
328
- async remove(remove_document_id) {
329
- const { id, ref } = this.#find_ref_by_id(remove_document_id);
330
- if (!ref)
331
- return;
332
- this.#sync([{
333
- ref,
334
- data: {
335
- changes: [{
336
- data: { id, __removing: true },
337
- ref,
338
- type: 'modified'
339
- }]
340
- }
341
- }], 'local');
342
- // Trigger
343
- try {
344
- return await this.collection_options.transporter.remove(ref);
345
- }
346
- catch (e) {
347
- this.#sync([{
348
- ref,
349
- data: {
350
- changes: [{
351
- data: { id, __removing: false },
352
- ref,
353
- type: 'modified'
354
- }]
355
- }
356
- }], 'local');
357
- throw e;
358
- }
359
- }
360
- async trigger(name, payload, trigger_document_id, query = {}) {
361
- const { ref } = this.#find_ref_by_id(trigger_document_id);
362
- if (!ref)
363
- throw new Error('INVAILD_REF');
364
- return await this.collection_options.transporter.trigger(ref, name, payload, query);
365
- }
366
- }
package/build/index.d.ts DELETED
@@ -1 +0,0 @@
1
- export * from './Collection.js';
package/build/index.js DELETED
@@ -1 +0,0 @@
1
- export * from './Collection.js';
@@ -1 +0,0 @@
1
- {"root":["../src/index.ts","../src/collection.ts"],"version":"5.6.3"}