gs-idb-pro 0.1.2 → 0.1.3

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/lib/index.cjs CHANGED
@@ -12,7 +12,7 @@ function parseDbNoneKeyPathRecord(record) {
12
12
  const { key, value } = record;
13
13
  return { key, value };
14
14
  }
15
- throw new Error(`not include value in invalid DBRecord\uFF1A${JSON.stringify(record)}`);
15
+ throw new Error(`not include value in invalid DBRecord:${JSON.stringify(record)}`);
16
16
  }
17
17
  const Break = Symbol("break"), Finished = Symbol("finished"), Continue = Symbol("continue"), ContinueKey = Symbol("continue key"), NextKey = Symbol("next key"), ContinuePrimaryKey = Symbol("continue primary key"), NextPrimaryKey = Symbol("next primary key");
18
18
  function isNativeTarget(target) {
@@ -30,7 +30,7 @@ const defaultStoreSchemaTemplate = Object.freeze({
30
30
  updatedTimeField: "updated_at"
31
31
  }), toNum = (v) => v instanceof Date ? v.getTime() : v;
32
32
  function parseIDbQuery(query) {
33
- if (gsIdbBasic.isDbQueryOrNull(query))
33
+ if (gsIdbBasic.isDbQueryOrNull(query) || !gsBase.isObject(query))
34
34
  return query;
35
35
  const range = query;
36
36
  if ("lt" in range && "gt" in range) {
@@ -53,14 +53,10 @@ function parseIDbQuery(query) {
53
53
  throw new Error(`Invalid IDBRange: gte (${range.gte}) cannot be greater than lte (${range.lte})`);
54
54
  return IDBKeyRange.bound(range.gte, range.lte, !1, !1);
55
55
  }
56
- if ("lt" in range)
57
- return IDBKeyRange.upperBound(range.lt, !0);
58
- if ("lte" in range)
59
- return IDBKeyRange.upperBound(range.lte, !1);
60
- if ("gt" in range)
61
- return IDBKeyRange.lowerBound(range.gt, !0);
62
- if ("gte" in range)
63
- return IDBKeyRange.lowerBound(range.gte, !1);
56
+ if ("lt" in range) return IDBKeyRange.upperBound(range.lt, !0);
57
+ if ("lte" in range) return IDBKeyRange.upperBound(range.lte, !1);
58
+ if ("gt" in range) return IDBKeyRange.lowerBound(range.gt, !0);
59
+ if ("gte" in range) return IDBKeyRange.lowerBound(range.gte, !1);
64
60
  }
65
61
  function isIDbQuery(query) {
66
62
  return parseIDbQuery(query) != null;
@@ -83,8 +79,7 @@ class DataOperationBase {
83
79
  return this.nativeStore?.name || this.target.store;
84
80
  }
85
81
  get storeSchema() {
86
- if (this.#storeSchema)
87
- return this.#storeSchema;
82
+ if (this.#storeSchema) return this.#storeSchema;
88
83
  const storeSchema = this.idbPro.getStoreSchema(this.storeName);
89
84
  return Object.isFrozen(storeSchema) && (this.#storeSchema = storeSchema), storeSchema;
90
85
  }
@@ -93,10 +88,8 @@ class DataOperationBase {
93
88
  }
94
89
  get nativeStore() {
95
90
  const { target } = this;
96
- if (target instanceof IDBObjectStore)
97
- return target;
98
- if (target instanceof IDBIndex)
99
- return target.objectStore;
91
+ if (target instanceof IDBObjectStore) return target;
92
+ if (target instanceof IDBIndex) return target.objectStore;
100
93
  }
101
94
  get keyPath() {
102
95
  const { target } = this;
@@ -148,7 +141,13 @@ class DataOperationBase {
148
141
  startKey,
149
142
  startPrimaryKey,
150
143
  fn: async (cursor) => {
151
- const { value: ov, primaryKey: op } = cursor, result = await fn(ov, op, i++), { control, key, primaryKey, modify, value } = gsBase.isObject(result) ? result : { control: result };
144
+ const { value: ov, primaryKey: op } = cursor, result = await fn(ov, op, i++), {
145
+ control,
146
+ key,
147
+ primaryKey,
148
+ modify,
149
+ value
150
+ } = gsBase.isObject(result) ? result : { control: result };
152
151
  switch (writable && (modify === Save ? cursor.update(value || ov) : modify === Delete && cursor.delete()), control) {
153
152
  case Break:
154
153
  return !1;
@@ -164,7 +163,15 @@ class DataOperationBase {
164
163
  }
165
164
  }, !0);
166
165
  }
167
- async cursorResult({ query, direction, preSkip, startKey, startPrimaryKey, fn, mapper: mpr }, writable) {
166
+ async cursorResult({
167
+ query,
168
+ direction,
169
+ preSkip,
170
+ startKey,
171
+ startPrimaryKey,
172
+ fn,
173
+ mapper: mpr
174
+ }, writable) {
168
175
  const { keyPath, defaultGetMapper } = this.storeSchema, mapper = getMapperFn(mpr || defaultGetMapper, keyPath), results = [];
169
176
  let i = 0;
170
177
  return await this.openCursor({
@@ -174,7 +181,13 @@ class DataOperationBase {
174
181
  startKey,
175
182
  startPrimaryKey,
176
183
  fn: async (cursor) => {
177
- const { value: ov, primaryKey: op } = cursor, { control, value, key, primaryKey, modify } = await fn?.(ov, op, i, results) || {};
184
+ const { value: ov, primaryKey: op } = cursor, {
185
+ control,
186
+ value,
187
+ key,
188
+ primaryKey,
189
+ modify
190
+ } = await fn?.(ov, op, i, results) || {};
178
191
  switch (writable && (modify === Save ? cursor.update(value || ov) : modify === Delete && cursor.delete()), (!control || control === Finished || control === NextKey || control === NextPrimaryKey) && results.push(mapper(value || ov, primaryKey || op, i)), control) {
179
192
  case Break:
180
193
  case Finished:
@@ -232,8 +245,7 @@ class DataOperators {
232
245
  const { storeName } = store, rows = data[storeName];
233
246
  rows && (result[storeName] = await store[use](rows, returns));
234
247
  }
235
- if (returns)
236
- return result;
248
+ if (returns) return result;
237
249
  }, !0);
238
250
  }
239
251
  async tx(method, fn, writable, rollbackOnError) {
@@ -264,8 +276,7 @@ class DbIterator extends DataOperationBase {
264
276
  startKey;
265
277
  startPrimaryKey;
266
278
  constructor(schema, db, option) {
267
- if (super(schema, db), !option)
268
- return;
279
+ if (super(schema, db), !option) return;
269
280
  const { parser } = option;
270
281
  this.direction = option.direction, this.query = option.query, this.writable = !!option.writable, this.endsWithNull = !!option.endsWithNull, this.preSkip = option.preSkip, this.startKey = option.startKey, this.startPrimaryKey = option.startPrimaryKey, parser && (this.parser = gsBase.isFunction(parser) ? parser : DbIteratorParsers[parser]);
271
282
  }
@@ -277,8 +288,7 @@ class DbIterator extends DataOperationBase {
277
288
  if (parser)
278
289
  for (; cursor = await gsIdbBasic.requestDbResult(request); ) {
279
290
  const { control, value } = await parser(cursor);
280
- if (control || (yield value), control === Break)
281
- break;
291
+ if (control || (yield value), control === Break) break;
282
292
  cursor.continue();
283
293
  }
284
294
  else {
@@ -328,18 +338,15 @@ async function queryFnPage(reader, info, arg) {
328
338
  }
329
339
  async function queryFnRow({ storeSchema: { defaultGetMapper } }, request, info, keyPath, hasSkip) {
330
340
  const { page, size, total, maxEmptyChecks, fn } = info, mapper = getMapperFn(info.mapper || defaultGetMapper, keyPath, !0), rows = [], preSkip = (page - 1) * info.size;
331
- if (preSkip >= total)
332
- return { info: gsBase.deepFreeze(info), rows: [] };
341
+ if (preSkip >= total) return { info: gsBase.deepFreeze(info), rows: [] };
333
342
  let i = 0;
334
343
  return await new Promise(async (resolve, reject) => {
335
344
  let ept = 0, skipped = 0;
336
345
  const rowFn = async () => {
337
346
  const { result: cursor } = request;
338
- if (!cursor)
339
- return resolve();
347
+ if (!cursor) return resolve();
340
348
  let { value, primaryKey } = cursor;
341
- if (await fn(value, primaryKey, i) ? (ept = 0, rows.push(mapper(value, primaryKey, i))) : ept++, rows.length >= size || ept >= maxEmptyChecks)
342
- return resolve();
349
+ if (await fn(value, primaryKey, i) ? (ept = 0, rows.push(mapper(value, primaryKey, i))) : ept++, rows.length >= size || ept >= maxEmptyChecks) return resolve();
343
350
  i++, cursor.continue();
344
351
  };
345
352
  request.onerror = () => reject(request.error), hasSkip ? request.onsuccess = async () => {
@@ -360,8 +367,8 @@ async function queryFnRow({ storeSchema: { defaultGetMapper } }, request, info,
360
367
  }
361
368
  class DataReader extends DataOperationBase {
362
369
  all(query, limit) {
363
- const param = {};
364
- return gsBase.isNumber(limit) && (param.limit = limit), isIDbQuery(query) ? param.query = query : gsBase.isObject(query) && Object.assign(param, query), this.tx(!1, (store) => gsIdbBasic.requestDbResult(store.getAll(parseIDbQuery(param.query), param.limit || 1e3)));
370
+ const param = isIDbQuery(query) ? { query } : query || {};
371
+ return gsBase.isNumber(limit) && (param.count = limit), gsBase.isNumber(param.count) || (param.count = 1e3), param.query = parseIDbQuery(param.query), this.tx(!1, (store) => gsIdbBasic.requestDbResult(store.getAll(param)));
365
372
  }
366
373
  async count(arg1, arg2, arg3) {
367
374
  const args = parseFilterArg(arg1, arg2, arg3), { query, direction, fn } = args;
@@ -490,22 +497,27 @@ function getValidKeyValue(keyPath, value) {
490
497
  return value[keyPath];
491
498
  const rv = [];
492
499
  for (const k of keyPath) {
493
- if (!value[k])
494
- return;
500
+ if (!value[k]) return;
495
501
  rv.push(value[k]);
496
502
  }
497
503
  return rv;
498
504
  }
499
505
  function checkAddValue(storeSchema, value) {
500
- if (!value || !(value instanceof Object) || Array.isArray(value))
501
- return value;
502
- const { addedTimeField, updatedTimeField, updatedCountField, softDeletedField } = storeSchema;
506
+ if (!value || !(value instanceof Object) || Array.isArray(value)) return value;
507
+ const {
508
+ addedTimeField,
509
+ updatedTimeField,
510
+ updatedCountField,
511
+ softDeletedField
512
+ } = storeSchema;
503
513
  return value = { ...value }, addedTimeField?.name && !gsBase.isNumber(value[addedTimeField.name]) && (value[addedTimeField.name] = Date.now()), updatedTimeField?.name && !gsBase.isNumber(value[updatedTimeField.name]) && (value[updatedTimeField.name] = Date.now()), softDeletedField?.name && !gsBase.isNumber(value[softDeletedField.name]) && (value[softDeletedField.name] = 0), updatedCountField?.name && (value[updatedCountField.name] = 0), value;
504
514
  }
505
515
  function checkUpdateValue(storeSchema, newValue, oldValue) {
506
- if (!newValue || !(newValue instanceof Object) || Array.isArray(newValue))
507
- return newValue;
508
- const { updatedTimeField, updatedCountField } = storeSchema;
516
+ if (!newValue || !(newValue instanceof Object) || Array.isArray(newValue)) return newValue;
517
+ const {
518
+ updatedTimeField,
519
+ updatedCountField
520
+ } = storeSchema;
509
521
  return newValue = { ...oldValue, ...newValue }, updatedTimeField.name && (newValue[updatedTimeField.name] = Date.now()), updatedCountField.name && (newValue[updatedCountField.name] = (newValue[updatedCountField.name] || 0) + 1), newValue;
510
522
  }
511
523
  class DataWriter extends DataReader {
@@ -534,11 +546,9 @@ class DataWriter extends DataReader {
534
546
  }
535
547
  if (w.target instanceof IDBIndex) {
536
548
  const { keyPath } = w, keyValue = getValidKeyValue(keyPath, value);
537
- if (!keyValue)
538
- return w.add(record);
549
+ if (!keyValue) return w.add(record);
539
550
  let oldValue = await w.find(keyValue);
540
- if (oldValue)
541
- return oldValue;
551
+ if (oldValue) return oldValue;
542
552
  }
543
553
  return w.add(record);
544
554
  });
@@ -577,7 +587,10 @@ class DataWriter extends DataReader {
577
587
  });
578
588
  }
579
589
  changeMany(records, option) {
580
- const { returns, throwIfMissing } = gsBase.isBoolean(option) ? { returns: option } : option || {};
590
+ const {
591
+ returns,
592
+ throwIfMissing
593
+ } = gsBase.isBoolean(option) ? { returns: option } : option || {};
581
594
  return this.batchWrite((w) => returns ? gsBase.asyncMap(records, (v) => w.change(v, throwIfMissing)) : gsBase.asyncForEach(records, (v) => w.change(v, throwIfMissing)), !0);
582
595
  }
583
596
  addOrChange(record) {
@@ -607,11 +620,15 @@ class DataWriter extends DataReader {
607
620
  return this.batchWrite((w) => returns ? gsBase.asyncMap(keys, (v) => w.delete(v, !0)) : gsBase.asyncForEach(keys, (v) => w.delete(v)), !0);
608
621
  }
609
622
  deleteRange(query, returns) {
610
- const { returns: hasRtn, physical, direction } = gsBase.isBoolean(returns) ? { returns } : returns || {}, { name } = this.storeSchema.softDeletedField || {};
623
+ const {
624
+ returns: hasRtn,
625
+ physical,
626
+ direction
627
+ } = gsBase.isBoolean(returns) ? { returns } : returns || {}, { name } = this.storeSchema.softDeletedField || {};
611
628
  return this.cursor({
612
629
  query,
613
630
  direction,
614
- fn: (value) => physical || !name ? { modify: Delete } : (value[name] = 1, { modify: Save })
631
+ fn: (value) => physical || !name ? { modify: Delete } : (value[name] = gsIdbBasic.Bool.True, { modify: Save })
615
632
  }, hasRtn);
616
633
  }
617
634
  deleteRangeMany(keys, returns) {
@@ -619,9 +636,13 @@ class DataWriter extends DataReader {
619
636
  return this.batchWrite((w) => option?.returns ? gsBase.asyncMap(keys, (v) => w.deleteRange(v, option)) : gsBase.asyncForEach(keys, (v) => w.deleteRange(v, option)), !0);
620
637
  }
621
638
  changeRange(arg, returns) {
622
- let { direction = "next", query, newValue } = "newValue" in arg ? arg : { newValue: arg };
639
+ let {
640
+ direction = "next",
641
+ query,
642
+ newValue
643
+ } = "newValue" in arg ? arg : { newValue: arg };
623
644
  if (query || (query = getValidKeyValue(this.keyPath, newValue)), !query)
624
- throw new Error(`query is required\uFF1A${JSON.stringify(arg)}`);
645
+ throw new Error(`query is required:${JSON.stringify(arg)}`);
625
646
  return this.cursor({
626
647
  query,
627
648
  direction,
@@ -725,16 +746,12 @@ class DbMap extends DataOperationBase {
725
746
  }
726
747
  }
727
748
  function equalKeyPath(p1, p2) {
728
- if (p1 == p2)
729
- return !0;
730
- if (typeof p1 != typeof p2)
731
- return !1;
749
+ if (p1 == p2) return !0;
750
+ if (typeof p1 != typeof p2) return !1;
732
751
  if (Array.isArray(p1) && Array.isArray(p2)) {
733
- if (p1.length !== p2.length)
734
- return !1;
752
+ if (p1.length !== p2.length) return !1;
735
753
  for (let i = 0; i < p1.length; i++)
736
- if (p1[i] !== p2[i])
737
- return !1;
754
+ if (p1[i] !== p2[i]) return !1;
738
755
  return !0;
739
756
  }
740
757
  return !1;
@@ -755,7 +772,7 @@ const versionDiffValidate = ({ stores, schema }) => {
755
772
  }
756
773
  }
757
774
  }
758
- return info ? `The existing database is inconsistent with the definition and cannot be corrected\uFF1A ${info}` : !0;
775
+ return info ? `The existing database is inconsistent with the definition and cannot be corrected ${info}` : !0;
759
776
  }, versionSameValidate = async (context) => {
760
777
  let result = versionDiffValidate(context);
761
778
  return gsBase.isString(result) || (result = validateStoreAndIndexes(context)), result;
@@ -765,13 +782,12 @@ const versionDiffValidate = ({ stores, schema }) => {
765
782
  const missingStoreNames = storeSchemas.map((s) => s.name).filter((s) => !dbStoreNames.includes(s));
766
783
  if (missingStoreNames.length)
767
784
  info = `store [ ${missingStoreNames.join(",")} ] not exist`;
768
- else
769
- for (const store of stores) {
770
- const ss = storeSchemas.find((s) => s.name === store.name);
771
- if (ss && (info = validateIndexes$1(store, Array.from(store.indexNames), ss.indexSchemas), info))
772
- break;
773
- }
774
- return info ? `The existing database Store index is inconsistent with the definition and requires a database version upgrade to be fixed\uFF1A ${info}` : !0;
785
+ else for (const store of stores) {
786
+ const ss = storeSchemas.find((s) => s.name === store.name);
787
+ if (ss && (info = validateIndexes$1(store, Array.from(store.indexNames), ss.indexSchemas), info))
788
+ break;
789
+ }
790
+ return info ? `The existing database Store index is inconsistent with the definition and requires a database version upgrade to be fixed: ${info}` : !0;
775
791
  };
776
792
  function validateIndexes$1(store, indexNames, schemas) {
777
793
  if (indexNames.length !== schemas.length)
@@ -874,7 +890,7 @@ function validateDefaultData(schema) {
874
890
  if (!(schema.keyPath || !schema.defaultData?.length)) {
875
891
  for (const row of schema.defaultData)
876
892
  if (!Array.isArray(row) && !("value" in row))
877
- throw new Error(`When \`defaultData\` must contain \`value\` fields or be an array\uFF1A${JSON.stringify(row)}`);
893
+ throw new Error(`When \`defaultData\` must contain \`value\` fields or be an array:${JSON.stringify(row)}`);
878
894
  }
879
895
  }
880
896
  const validateSchemaWithDefaults = (schema) => {
@@ -983,12 +999,11 @@ async function upgradeDb(dbSchema, database, e, request) {
983
999
  const { storeSchemas, beforeUpgrade, afterUpgrade, version } = dbSchema, { newVersion = version, oldVersion } = e, { transaction } = request, context = new UpgradeContext({ database, newVersion, oldVersion, dbSchema, transaction });
984
1000
  try {
985
1001
  const errors = [];
986
- if (gsBase.isFunction(beforeUpgrade))
987
- try {
988
- await beforeUpgrade(context);
989
- } catch (e2) {
990
- errors.push(e2);
991
- }
1002
+ if (gsBase.isFunction(beforeUpgrade)) try {
1003
+ await beforeUpgrade(context);
1004
+ } catch (e2) {
1005
+ errors.push(e2);
1006
+ }
992
1007
  for (const storeName of storeSchemas.map((s) => s.name))
993
1008
  try {
994
1009
  context.store(storeName);
@@ -996,34 +1011,30 @@ async function upgradeDb(dbSchema, database, e, request) {
996
1011
  errors.push(e2);
997
1012
  }
998
1013
  for (const { name, defaultData } of storeSchemas)
999
- if (defaultData)
1014
+ if (defaultData) try {
1015
+ await context.store(name).add({ oldMax: 0 }, defaultData);
1016
+ } catch (e2) {
1017
+ errors.push(e2);
1018
+ }
1019
+ for (const { name, versionData } of storeSchemas)
1020
+ if (versionData) for (const { version: version2, data, use = "addOrChange" } of versionData)
1000
1021
  try {
1001
- await context.store(name).add({ oldMax: 0 }, defaultData);
1022
+ await context.store(name)[use](version2, data);
1002
1023
  } catch (e2) {
1003
1024
  errors.push(e2);
1004
1025
  }
1005
- for (const { name, versionData } of storeSchemas)
1006
- if (versionData)
1007
- for (const { version: version2, data, use = "addOrChange" } of versionData)
1008
- try {
1009
- await context.store(name)[use](version2, data);
1010
- } catch (e2) {
1011
- errors.push(e2);
1012
- }
1013
1026
  for (const { name, storeDefined } of storeSchemas)
1014
1027
  try {
1015
1028
  await storeDefined?.(context.store(name));
1016
1029
  } catch (e2) {
1017
1030
  errors.push(e2);
1018
1031
  }
1019
- if (gsBase.isFunction(afterUpgrade))
1020
- try {
1021
- await afterUpgrade(context);
1022
- } catch (e2) {
1023
- errors.push(e2);
1024
- }
1025
- if (!errors.length)
1026
- return;
1032
+ if (gsBase.isFunction(afterUpgrade)) try {
1033
+ await afterUpgrade(context);
1034
+ } catch (e2) {
1035
+ errors.push(e2);
1036
+ }
1037
+ if (!errors.length) return;
1027
1038
  throw errors.length === 1 ? errors[0] : new AggregateError(errors, "Database upgrade error");
1028
1039
  } finally {
1029
1040
  gsBase.destroy(context);
@@ -1135,8 +1146,7 @@ class IDbPro {
1135
1146
  return this.factory.newDataOperators(results, this);
1136
1147
  }
1137
1148
  initSchema() {
1138
- if (this.initialized)
1139
- return this.#schema;
1149
+ if (this.initialized) return this.#schema;
1140
1150
  const { validateSchemaWithDefaults: validate = validateSchemaWithDefaults } = this.#schema;
1141
1151
  return this.#schema = validate(this.#schema);
1142
1152
  }
package/lib/index.d.ts CHANGED
@@ -367,10 +367,11 @@ interface IDbMap<K extends StrOrNum = StrOrNum, V = any, Tar extends OperationTa
367
367
 
368
368
  interface IGetAllArgs<T> {
369
369
  query?: IDbQuery | null;
370
+ direction?: IDBCursorDirection;
370
371
  /**
371
372
  * 最多返回条数,默认值为1000
372
373
  */
373
- limit?: number;
374
+ count?: number;
374
375
  }
375
376
  interface IDataReader<Row = any, Tar extends OperationTarget = OperationTarget> extends IValidDataOperationSchema<Tar>, ICursorReader<Row>, IForEachable<Row>, ICursorQueryable<Row>, IPageableQuery<Row> {
376
377
  readonly storeName: string;