@converse/skeletor 3.0.0 → 3.1.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 +330 -38
- package/dist/skeletor.d.ts +193 -56
- package/dist/skeletor.esm.js +12328 -0
- package/dist/skeletor.esm.js.map +1 -0
- package/dist/skeletor.js +740 -456
- package/dist/skeletor.js.map +1 -0
- package/dist/skeletor.min.js +6 -19
- package/dist/skeletor.node.js +12494 -0
- package/dist/skeletor.node.mjs +12481 -0
- package/package.json +32 -5
- package/src/autosync.ts +156 -0
- package/src/collection.ts +140 -35
- package/src/drivers/helpers.ts +61 -0
- package/src/drivers/nodeSQLiteStorage.ts +162 -0
- package/src/drivers/sessionStorage.ts +16 -22
- package/src/drivers/types.ts +25 -0
- package/src/eventemitter.ts +9 -0
- package/src/helpers.ts +57 -10
- package/src/index.node.ts +8 -0
- package/src/index.ts +11 -3
- package/src/model.ts +254 -13
- package/src/storage.ts +78 -38
- package/src/types.ts +34 -9
- package/src/utils/events.ts +6 -6
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
import { DatabaseSync, type StatementSync } from 'node:sqlite';
|
|
2
|
+
import fsMod from 'node:fs';
|
|
3
|
+
import pathMod from 'node:path';
|
|
4
|
+
import { normalizeKey, serializeSync, deserialize, sanitizePathSegment } from './helpers';
|
|
5
|
+
import { StorageDriver } from './types';
|
|
6
|
+
|
|
7
|
+
const DEFAULT_BASE_DIR = '.skeletor-storage';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* SQLite-backed implementation of StorageDriver.
|
|
11
|
+
* Uses a single table with key/value columns, storing values as JSON strings.
|
|
12
|
+
*/
|
|
13
|
+
export class NodeSQLiteStorage implements StorageDriver {
|
|
14
|
+
private db: DatabaseSync;
|
|
15
|
+
private stmt: {
|
|
16
|
+
insert: StatementSync;
|
|
17
|
+
select: StatementSync;
|
|
18
|
+
delete: StatementSync;
|
|
19
|
+
clear: StatementSync;
|
|
20
|
+
count: StatementSync;
|
|
21
|
+
keyByIndex: StatementSync;
|
|
22
|
+
keys: StatementSync;
|
|
23
|
+
getItems: StatementSync;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
ready(): Promise<void> {
|
|
27
|
+
return Promise.resolve();
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
debouncedSetItems?: {
|
|
31
|
+
(items: Record<string, any>): Promise<void>;
|
|
32
|
+
flush?: () => void;
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
constructor(name: string, storageDir?: string, inMemory?: boolean) {
|
|
36
|
+
if (inMemory) {
|
|
37
|
+
this.db = new DatabaseSync(':memory:');
|
|
38
|
+
} else {
|
|
39
|
+
const safeName = sanitizePathSegment(name);
|
|
40
|
+
const baseDir = storageDir || DEFAULT_BASE_DIR;
|
|
41
|
+
const dbFilePath = pathMod.join(baseDir, `${safeName}.db`);
|
|
42
|
+
|
|
43
|
+
// Ensure parent directory exists
|
|
44
|
+
const dir = pathMod.dirname(dbFilePath);
|
|
45
|
+
if (!fsMod.existsSync(dir)) {
|
|
46
|
+
fsMod.mkdirSync(dir, { recursive: true });
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
this.db = new DatabaseSync(dbFilePath);
|
|
50
|
+
}
|
|
51
|
+
// Use DELETE journal mode (default, no separate WAL files)
|
|
52
|
+
this.db.exec('PRAGMA journal_mode=DELETE');
|
|
53
|
+
// Enable busy timeout
|
|
54
|
+
this.db.exec('PRAGMA busy_timeout=5000');
|
|
55
|
+
|
|
56
|
+
// Create the kv table if it doesn't exist
|
|
57
|
+
this.db.exec(`
|
|
58
|
+
CREATE TABLE IF NOT EXISTS kv (
|
|
59
|
+
key TEXT PRIMARY KEY,
|
|
60
|
+
value TEXT NOT NULL
|
|
61
|
+
) STRICT
|
|
62
|
+
`);
|
|
63
|
+
|
|
64
|
+
// Prepare all statements once
|
|
65
|
+
this.stmt = {
|
|
66
|
+
insert: this.db.prepare('INSERT OR REPLACE INTO kv (key, value) VALUES (?, ?)'),
|
|
67
|
+
select: this.db.prepare('SELECT value FROM kv WHERE key = ?'),
|
|
68
|
+
delete: this.db.prepare('DELETE FROM kv WHERE key = ?'),
|
|
69
|
+
clear: this.db.prepare('DELETE FROM kv'),
|
|
70
|
+
count: this.db.prepare('SELECT COUNT(*) as count FROM kv'),
|
|
71
|
+
keyByIndex: this.db.prepare('SELECT key FROM kv ORDER BY key LIMIT 1 OFFSET ?'),
|
|
72
|
+
keys: this.db.prepare('SELECT key FROM kv ORDER BY key'),
|
|
73
|
+
getItems: this.db.prepare('SELECT key, value FROM kv WHERE key IN (SELECT value FROM json_each(?))'),
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
setItem(key: string, value: any): Promise<any> {
|
|
78
|
+
key = normalizeKey(key);
|
|
79
|
+
const coerced = value ?? null;
|
|
80
|
+
this.stmt.insert.run(key, serializeSync(coerced));
|
|
81
|
+
return Promise.resolve(value);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
getItem<T>(key: string): Promise<T | null> {
|
|
85
|
+
key = normalizeKey(key);
|
|
86
|
+
const row = this.stmt.select.get(key) as { value: string } | undefined;
|
|
87
|
+
if (!row) {
|
|
88
|
+
return Promise.resolve(null);
|
|
89
|
+
}
|
|
90
|
+
return Promise.resolve(deserialize<T>(row.value));
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
removeItem(key: string): Promise<void> {
|
|
94
|
+
key = normalizeKey(key);
|
|
95
|
+
this.stmt.delete.run(key);
|
|
96
|
+
return Promise.resolve();
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
clear(): Promise<void> {
|
|
100
|
+
this.stmt.clear.run();
|
|
101
|
+
return Promise.resolve();
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
length(): Promise<number> {
|
|
105
|
+
const row = this.stmt.count.get() as { count: number };
|
|
106
|
+
return Promise.resolve(row.count);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
key(n: number): Promise<string | null> {
|
|
110
|
+
const row = this.stmt.keyByIndex.get(n) as { key: string } | undefined;
|
|
111
|
+
return Promise.resolve(row ? row.key : null);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
keys(): Promise<string[]> {
|
|
115
|
+
const rows = this.stmt.keys.all() as Array<{ key: string }>;
|
|
116
|
+
return Promise.resolve(rows.map((r) => r.key));
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
setItems(items: Record<string, any>): Promise<void> {
|
|
120
|
+
this.db.exec('BEGIN IMMEDIATE');
|
|
121
|
+
try {
|
|
122
|
+
for (const [key, value] of Object.entries(items)) {
|
|
123
|
+
const normalizedKey = normalizeKey(key);
|
|
124
|
+
const coerced = value ?? null;
|
|
125
|
+
this.stmt.insert.run(normalizedKey, serializeSync(coerced));
|
|
126
|
+
}
|
|
127
|
+
this.db.exec('COMMIT');
|
|
128
|
+
} catch (e) {
|
|
129
|
+
try {
|
|
130
|
+
this.db.exec('ROLLBACK');
|
|
131
|
+
} catch (rollbackError) {
|
|
132
|
+
// If ROLLBACK fails, attach it as cause to the original error
|
|
133
|
+
// This preserves the root cause while providing full context
|
|
134
|
+
if (e instanceof Error && rollbackError instanceof Error) {
|
|
135
|
+
(e as Error & { cause?: Error }).cause = rollbackError;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
throw e;
|
|
139
|
+
}
|
|
140
|
+
return Promise.resolve();
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
getItems(keys: string[]): Promise<Record<string, any>> {
|
|
144
|
+
if (keys.length === 0) {
|
|
145
|
+
return Promise.resolve({});
|
|
146
|
+
}
|
|
147
|
+
const keysJson = JSON.stringify(keys);
|
|
148
|
+
const rows = this.stmt.getItems.all(keysJson) as Array<{ key: string; value: string }>;
|
|
149
|
+
const result: Record<string, any> = {};
|
|
150
|
+
for (const row of rows) {
|
|
151
|
+
result[row.key] = deserialize(row.value);
|
|
152
|
+
}
|
|
153
|
+
return Promise.resolve(result);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Close the database connection. Useful for cleanup in tests.
|
|
158
|
+
*/
|
|
159
|
+
close(): void {
|
|
160
|
+
this.db.close();
|
|
161
|
+
}
|
|
162
|
+
}
|
|
@@ -14,13 +14,7 @@
|
|
|
14
14
|
// See the License for the specific language governing permissions and
|
|
15
15
|
// limitations under the License.
|
|
16
16
|
|
|
17
|
-
import
|
|
18
|
-
import getCallback from 'localforage/src/utils/getCallback';
|
|
19
|
-
import normalizeKey from 'localforage/src/utils/normalizeKey';
|
|
20
|
-
import serializer from 'localforage/src/utils/serializer';
|
|
21
|
-
|
|
22
|
-
const serialize = serializer['serialize'];
|
|
23
|
-
const deserialize = serializer['deserialize'];
|
|
17
|
+
import { chainCallback, getCallback, normalizeKey, serialize, deserialize } from './helpers';
|
|
24
18
|
|
|
25
19
|
interface DbInfo {
|
|
26
20
|
keyPrefix: string;
|
|
@@ -92,7 +86,7 @@ function clear(callback?: (err: any) => void): Promise<void> {
|
|
|
92
86
|
}
|
|
93
87
|
});
|
|
94
88
|
|
|
95
|
-
|
|
89
|
+
chainCallback(promise, callback);
|
|
96
90
|
return promise;
|
|
97
91
|
}
|
|
98
92
|
|
|
@@ -111,13 +105,13 @@ function getItem<T>(key: string, callback?: (err: any, value: T | null) => void)
|
|
|
111
105
|
return null;
|
|
112
106
|
});
|
|
113
107
|
|
|
114
|
-
|
|
108
|
+
chainCallback(promise, callback);
|
|
115
109
|
return promise;
|
|
116
110
|
}
|
|
117
111
|
|
|
118
112
|
function iterate<T, U>(
|
|
119
113
|
iterator: IteratorCallback<T, U>,
|
|
120
|
-
callback?: (err: any, result: U | undefined) => void
|
|
114
|
+
callback?: (err: any, result: U | undefined) => void,
|
|
121
115
|
): Promise<U | undefined> {
|
|
122
116
|
const self = this;
|
|
123
117
|
|
|
@@ -148,7 +142,7 @@ function iterate<T, U>(
|
|
|
148
142
|
return;
|
|
149
143
|
});
|
|
150
144
|
|
|
151
|
-
|
|
145
|
+
chainCallback(promise, callback);
|
|
152
146
|
return promise;
|
|
153
147
|
}
|
|
154
148
|
|
|
@@ -171,7 +165,7 @@ function key(n: number, callback?: (err: any, key: string | null) => void): Prom
|
|
|
171
165
|
return result;
|
|
172
166
|
});
|
|
173
167
|
|
|
174
|
-
|
|
168
|
+
chainCallback(promise, callback);
|
|
175
169
|
return promise;
|
|
176
170
|
}
|
|
177
171
|
|
|
@@ -190,7 +184,7 @@ function keys(callback?: (err: any, keys: string[]) => void): Promise<string[]>
|
|
|
190
184
|
return keys;
|
|
191
185
|
});
|
|
192
186
|
|
|
193
|
-
|
|
187
|
+
chainCallback(promise, callback);
|
|
194
188
|
return promise;
|
|
195
189
|
}
|
|
196
190
|
|
|
@@ -201,7 +195,7 @@ function length(callback?: (err: any, numberOfKeys: number) => void): Promise<nu
|
|
|
201
195
|
return keys.length;
|
|
202
196
|
});
|
|
203
197
|
|
|
204
|
-
|
|
198
|
+
chainCallback(promise, callback);
|
|
205
199
|
return promise;
|
|
206
200
|
}
|
|
207
201
|
|
|
@@ -210,7 +204,7 @@ function removeItem(key: string, callback?: (err: any) => void): Promise<void> {
|
|
|
210
204
|
const promise = this.ready().then(function () {
|
|
211
205
|
sessionStorage.removeItem(dbInfo.keyPrefix + key);
|
|
212
206
|
});
|
|
213
|
-
|
|
207
|
+
chainCallback(promise, callback);
|
|
214
208
|
return promise;
|
|
215
209
|
}
|
|
216
210
|
|
|
@@ -225,29 +219,29 @@ async function setItem<T>(key: string, value: T, callback?: (err: any, value: T)
|
|
|
225
219
|
dbInfo.serializer.serialize(value, (serializedValue: string, error: any) => {
|
|
226
220
|
if (error) {
|
|
227
221
|
reject(error);
|
|
228
|
-
|
|
222
|
+
chainCallback(Promise.reject(error), callback);
|
|
229
223
|
return;
|
|
230
224
|
}
|
|
231
225
|
|
|
232
226
|
try {
|
|
233
227
|
sessionStorage.setItem(dbInfo.keyPrefix + key, serializedValue);
|
|
234
228
|
resolve(originalValue);
|
|
235
|
-
|
|
229
|
+
chainCallback(Promise.resolve(originalValue), callback);
|
|
236
230
|
} catch (e: any) {
|
|
237
231
|
if (e.name === 'QuotaExceededError' || e.name === 'NS_ERROR_DOM_QUOTA_REACHED') {
|
|
238
232
|
console.error('Your sessionStorage capacity is used up.');
|
|
239
233
|
}
|
|
240
234
|
reject(e);
|
|
241
|
-
|
|
235
|
+
chainCallback(Promise.reject(e), callback);
|
|
242
236
|
}
|
|
243
237
|
});
|
|
244
238
|
});
|
|
245
239
|
}
|
|
246
240
|
|
|
247
|
-
function dropInstance(
|
|
248
|
-
callback = getCallback
|
|
241
|
+
function dropInstance(this: any, ...args: any[]): Promise<void> {
|
|
242
|
+
const callback = getCallback(...args);
|
|
249
243
|
|
|
250
|
-
options = (typeof
|
|
244
|
+
let options = (typeof args[0] !== 'function' && args[0]) || {};
|
|
251
245
|
if (!options.name) {
|
|
252
246
|
const currentConfig = this.config();
|
|
253
247
|
options.name = options.name || currentConfig.name;
|
|
@@ -275,7 +269,7 @@ function dropInstance(options: any, callback?: (err: any) => void): Promise<void
|
|
|
275
269
|
});
|
|
276
270
|
}
|
|
277
271
|
|
|
278
|
-
|
|
272
|
+
chainCallback(promise, callback);
|
|
279
273
|
return promise;
|
|
280
274
|
}
|
|
281
275
|
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Storage driver interface for key-value persistence.
|
|
3
|
+
* @public
|
|
4
|
+
*/
|
|
5
|
+
export interface StorageDriver {
|
|
6
|
+
ready(): Promise<void>;
|
|
7
|
+
setItem(key: string, value: any): Promise<any>;
|
|
8
|
+
getItem(key: string): Promise<any>;
|
|
9
|
+
removeItem(key: string): Promise<void>;
|
|
10
|
+
clear(): Promise<void>;
|
|
11
|
+
length(): Promise<number>;
|
|
12
|
+
key(keyIndex: number): Promise<string | null>;
|
|
13
|
+
keys(): Promise<string[]>;
|
|
14
|
+
setItems?(items: Record<string, any>): Promise<void>;
|
|
15
|
+
getItems?(keys: string[]): Promise<Record<string, any>>;
|
|
16
|
+
debouncedSetItems?: {
|
|
17
|
+
(items: Record<string, any>): Promise<void>;
|
|
18
|
+
flush?: () => void;
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* @public
|
|
24
|
+
*/
|
|
25
|
+
export type StoreType = 'local' | 'session' | 'indexed' | 'in_memory' | 'node';
|
package/src/eventemitter.ts
CHANGED
|
@@ -160,6 +160,15 @@ export function EventEmitter<T extends ClassConstructor>(Base: T) {
|
|
|
160
160
|
eventsApi(triggerApi, this._events, name, undefined, args);
|
|
161
161
|
return this;
|
|
162
162
|
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Subscribe to an event. Returns an unsubscribe function.
|
|
166
|
+
* Compatible with `useSyncExternalStore` and other store-style APIs.
|
|
167
|
+
*/
|
|
168
|
+
subscribe(event: string, callback: EventCallback, context?: EventContext): () => void {
|
|
169
|
+
this.on(event, callback, context);
|
|
170
|
+
return () => this.off(event, callback, context);
|
|
171
|
+
}
|
|
163
172
|
};
|
|
164
173
|
}
|
|
165
174
|
|
package/src/helpers.ts
CHANGED
|
@@ -7,6 +7,7 @@ import result from 'lodash-es/result';
|
|
|
7
7
|
import { Model } from './model';
|
|
8
8
|
import { Collection } from './collection';
|
|
9
9
|
import { type SyncOptions, SyncOperation } from './types';
|
|
10
|
+
import type PersistentStorage from './storage';
|
|
10
11
|
|
|
11
12
|
/**
|
|
12
13
|
* Custom error for indicating timeouts
|
|
@@ -33,7 +34,7 @@ export function guid(): string {
|
|
|
33
34
|
//
|
|
34
35
|
export function inherits<T extends new (...args: any[]) => any>(
|
|
35
36
|
protoProps: Record<string, any> | null,
|
|
36
|
-
staticProps?: Record<string, any
|
|
37
|
+
staticProps?: Record<string, any>,
|
|
37
38
|
): T {
|
|
38
39
|
// eslint-disable-next-line @typescript-eslint/no-this-alias
|
|
39
40
|
const parent = this;
|
|
@@ -90,19 +91,21 @@ export function getResolveablePromise(): ResolveablePromise {
|
|
|
90
91
|
}) as ResolveablePromise;
|
|
91
92
|
|
|
92
93
|
Object.assign(promise, wrapper);
|
|
94
|
+
// This `then` only mirrors settlement into the state flags. It must NOT
|
|
95
|
+
// rethrow on rejection: the derived promise is discarded, so rethrowing would
|
|
96
|
+
// surface as an unhandled rejection whenever the promise is rejected. The real
|
|
97
|
+
// consumer still awaits `promise` itself, which rejects normally.
|
|
93
98
|
promise.then(
|
|
94
|
-
function (
|
|
99
|
+
function () {
|
|
95
100
|
promise.isResolved = true;
|
|
96
101
|
promise.isPending = false;
|
|
97
102
|
promise.isRejected = false;
|
|
98
|
-
return v;
|
|
99
103
|
},
|
|
100
|
-
function (
|
|
104
|
+
function () {
|
|
101
105
|
promise.isResolved = false;
|
|
102
106
|
promise.isPending = false;
|
|
103
107
|
promise.isRejected = true;
|
|
104
|
-
|
|
105
|
-
}
|
|
108
|
+
},
|
|
106
109
|
);
|
|
107
110
|
return promise;
|
|
108
111
|
}
|
|
@@ -112,12 +115,19 @@ export function urlError(): never {
|
|
|
112
115
|
throw new Error('A "url" property or function must be specified');
|
|
113
116
|
}
|
|
114
117
|
|
|
115
|
-
// Wrap an optional error callback with a fallback error event.
|
|
116
|
-
|
|
118
|
+
// Wrap an optional error callback with a fallback error event. When a
|
|
119
|
+
// `promise` is supplied (the `{ promise: true }` fetch/save path), the error is
|
|
120
|
+
// also forwarded to `promise.reject` so the returned promise settles on failure.
|
|
121
|
+
export function wrapError(
|
|
122
|
+
model: Model<any> | Collection<any>,
|
|
123
|
+
options: any,
|
|
124
|
+
promise?: ResolveablePromise,
|
|
125
|
+
): void {
|
|
117
126
|
const error = options.error;
|
|
118
127
|
options.error = function (resp: any) {
|
|
119
128
|
if (error) error.call(options.context, model, resp, options);
|
|
120
129
|
model.trigger('error', model, resp, options);
|
|
130
|
+
promise && promise.reject && promise.reject(resp);
|
|
121
131
|
};
|
|
122
132
|
}
|
|
123
133
|
|
|
@@ -130,9 +140,46 @@ const methodMap: Record<string, string> = {
|
|
|
130
140
|
read: 'GET',
|
|
131
141
|
};
|
|
132
142
|
|
|
143
|
+
// Tracks the classes we've already warned about, so the `browserStorage`
|
|
144
|
+
// deprecation notice is logged at most once per class rather than once per
|
|
145
|
+
// instance (a collection can resolve storage once per contained model).
|
|
146
|
+
const warnedBrowserStorage = new WeakSet<object>();
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Emit a one-time-per-class deprecation warning nudging downstream code from
|
|
150
|
+
* the `browserStorage` alias to the canonical `storage` accessor.
|
|
151
|
+
*/
|
|
152
|
+
export function warnBrowserStorageDeprecation(obj: Model<any> | Collection<any>): void {
|
|
153
|
+
const ctor = obj?.constructor;
|
|
154
|
+
if (!ctor || warnedBrowserStorage.has(ctor)) return;
|
|
155
|
+
warnedBrowserStorage.add(ctor);
|
|
156
|
+
const name = (ctor as { name?: string }).name;
|
|
157
|
+
console.warn(
|
|
158
|
+
`Skeletor: \`browserStorage\` is deprecated and will be removed in a future major version; ` +
|
|
159
|
+
`use \`storage\` instead${name ? ` (on \`${name}\`)` : ''}.`,
|
|
160
|
+
);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* Return the PersistentStorage instance configured on `obj`, checking both
|
|
165
|
+
* the canonical `storage` accessor and the deprecated `browserStorage` alias
|
|
166
|
+
* so that subclasses that still override `get browserStorage()` continue to work.
|
|
167
|
+
* @public
|
|
168
|
+
*/
|
|
169
|
+
export function getStorage(obj: Model<any> | Collection<any> | null | undefined): PersistentStorage | undefined {
|
|
170
|
+
if (!obj) return undefined;
|
|
171
|
+
const storage = result(obj, 'storage') as PersistentStorage | undefined;
|
|
172
|
+
if (storage != null) return storage;
|
|
173
|
+
// Fall back to the deprecated alias; warn only when it actually supplies the
|
|
174
|
+
// store, so storage-less models/collections don't trip the notice.
|
|
175
|
+
const legacy = result(obj, 'browserStorage') as PersistentStorage | undefined;
|
|
176
|
+
if (legacy != null) warnBrowserStorageDeprecation(obj);
|
|
177
|
+
return legacy;
|
|
178
|
+
}
|
|
179
|
+
|
|
133
180
|
export function getSyncMethod(model: Model | Collection<any>): typeof sync & { __name__?: string } {
|
|
134
|
-
const store =
|
|
135
|
-
return store ?
|
|
181
|
+
const store = getStorage(model) || getStorage((model as Model).collection);
|
|
182
|
+
return store ? store.sync() : sync;
|
|
136
183
|
}
|
|
137
184
|
|
|
138
185
|
/**
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Node.js entry point for @converse/skeletor.
|
|
3
|
+
* Re-exports everything from the browser entry and additionally
|
|
4
|
+
* exports the NodeSQLiteStorage LocalForage implementation.
|
|
5
|
+
*/
|
|
6
|
+
export * from './index';
|
|
7
|
+
export { default } from './index';
|
|
8
|
+
export { NodeSQLiteStorage } from './drivers/nodeSQLiteStorage';
|
package/src/index.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/* global global */
|
|
2
2
|
import { EventEmitter } from './eventemitter';
|
|
3
|
-
import
|
|
3
|
+
import PersistentStorage from './storage';
|
|
4
4
|
import { Collection } from './collection';
|
|
5
5
|
import { Model } from './model';
|
|
6
6
|
import { sync } from './helpers';
|
|
@@ -54,12 +54,20 @@ skeletor.noConflict = noConflict;
|
|
|
54
54
|
root.Skeletor = skeletor;
|
|
55
55
|
export default skeletor;
|
|
56
56
|
|
|
57
|
-
|
|
57
|
+
/**
|
|
58
|
+
* @deprecated Use `PersistentStorage` instead.
|
|
59
|
+
* @public
|
|
60
|
+
*/
|
|
61
|
+
const BrowserStorage = PersistentStorage;
|
|
62
|
+
export { noConflict, Collection, EventEmitter, Model, PersistentStorage, BrowserStorage, sync };
|
|
63
|
+
export { getStorage } from './helpers';
|
|
58
64
|
|
|
59
|
-
export type {
|
|
65
|
+
export type { StorageDriver, StoreType } from './drivers/types';
|
|
60
66
|
export type {
|
|
61
67
|
ClassConstructor,
|
|
62
68
|
CollectionOptions,
|
|
69
|
+
ComputedProperties,
|
|
70
|
+
ComputedProperty,
|
|
63
71
|
Comparator,
|
|
64
72
|
EventCallback,
|
|
65
73
|
EventCallbackMap,
|