@aws-amplify/datastore 3.7.3 → 3.7.4-custom-pk.86

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 (137) hide show
  1. package/CHANGELOG.md +144 -17
  2. package/README.md +154 -0
  3. package/dist/aws-amplify-datastore.js +3740 -1599
  4. package/dist/aws-amplify-datastore.js.map +1 -1
  5. package/dist/aws-amplify-datastore.min.js +25 -95
  6. package/dist/aws-amplify-datastore.min.js.map +1 -1
  7. package/lib/authModeStrategies/multiAuthStrategy.d.ts +2 -2
  8. package/lib/authModeStrategies/multiAuthStrategy.js +32 -26
  9. package/lib/authModeStrategies/multiAuthStrategy.js.map +1 -1
  10. package/lib/datastore/datastore.d.ts +17 -16
  11. package/lib/datastore/datastore.js +291 -83
  12. package/lib/datastore/datastore.js.map +1 -1
  13. package/lib/index.d.ts +3 -19
  14. package/lib/predicates/index.d.ts +3 -2
  15. package/lib/predicates/index.js +12 -2
  16. package/lib/predicates/index.js.map +1 -1
  17. package/lib/storage/adapter/AsyncStorageAdapter.d.ts +6 -2
  18. package/lib/storage/adapter/AsyncStorageAdapter.js +361 -193
  19. package/lib/storage/adapter/AsyncStorageAdapter.js.map +1 -1
  20. package/lib/storage/adapter/AsyncStorageDatabase.d.ts +4 -4
  21. package/lib/storage/adapter/AsyncStorageDatabase.js +59 -28
  22. package/lib/storage/adapter/AsyncStorageDatabase.js.map +1 -1
  23. package/lib/storage/adapter/InMemoryStore.js +2 -2
  24. package/lib/storage/adapter/InMemoryStore.js.map +1 -1
  25. package/lib/storage/adapter/IndexedDBAdapter.d.ts +7 -2
  26. package/lib/storage/adapter/IndexedDBAdapter.js +454 -252
  27. package/lib/storage/adapter/IndexedDBAdapter.js.map +1 -1
  28. package/lib/storage/adapter/index.d.ts +1 -1
  29. package/lib/storage/storage.d.ts +3 -3
  30. package/lib/storage/storage.js +106 -28
  31. package/lib/storage/storage.js.map +1 -1
  32. package/lib/sync/index.d.ts +23 -7
  33. package/lib/sync/index.js +18 -17
  34. package/lib/sync/index.js.map +1 -1
  35. package/lib/sync/merger.d.ts +3 -3
  36. package/lib/sync/merger.js +8 -6
  37. package/lib/sync/merger.js.map +1 -1
  38. package/lib/sync/outbox.d.ts +2 -2
  39. package/lib/sync/outbox.js +12 -9
  40. package/lib/sync/outbox.js.map +1 -1
  41. package/lib/sync/processors/errorMaps.d.ts +17 -0
  42. package/lib/sync/processors/errorMaps.js +125 -0
  43. package/lib/sync/processors/errorMaps.js.map +1 -0
  44. package/lib/sync/processors/mutation.d.ts +22 -4
  45. package/lib/sync/processors/mutation.js +119 -51
  46. package/lib/sync/processors/mutation.js.map +1 -1
  47. package/lib/sync/processors/subscription.d.ts +4 -2
  48. package/lib/sync/processors/subscription.js +76 -41
  49. package/lib/sync/processors/subscription.js.map +1 -1
  50. package/lib/sync/processors/sync.d.ts +4 -2
  51. package/lib/sync/processors/sync.js +62 -27
  52. package/lib/sync/processors/sync.js.map +1 -1
  53. package/lib/sync/utils.d.ts +3 -2
  54. package/lib/sync/utils.js +58 -7
  55. package/lib/sync/utils.js.map +1 -1
  56. package/lib/types.d.ts +90 -34
  57. package/lib/types.js +31 -2
  58. package/lib/types.js.map +1 -1
  59. package/lib/util.d.ts +48 -33
  60. package/lib/util.js +219 -57
  61. package/lib/util.js.map +1 -1
  62. package/lib-esm/authModeStrategies/multiAuthStrategy.d.ts +2 -2
  63. package/lib-esm/authModeStrategies/multiAuthStrategy.js +32 -26
  64. package/lib-esm/authModeStrategies/multiAuthStrategy.js.map +1 -1
  65. package/lib-esm/datastore/datastore.d.ts +17 -16
  66. package/lib-esm/datastore/datastore.js +293 -85
  67. package/lib-esm/datastore/datastore.js.map +1 -1
  68. package/lib-esm/index.d.ts +3 -19
  69. package/lib-esm/predicates/index.d.ts +3 -2
  70. package/lib-esm/predicates/index.js +13 -3
  71. package/lib-esm/predicates/index.js.map +1 -1
  72. package/lib-esm/storage/adapter/AsyncStorageAdapter.d.ts +6 -2
  73. package/lib-esm/storage/adapter/AsyncStorageAdapter.js +361 -193
  74. package/lib-esm/storage/adapter/AsyncStorageAdapter.js.map +1 -1
  75. package/lib-esm/storage/adapter/AsyncStorageDatabase.d.ts +4 -4
  76. package/lib-esm/storage/adapter/AsyncStorageDatabase.js +60 -29
  77. package/lib-esm/storage/adapter/AsyncStorageDatabase.js.map +1 -1
  78. package/lib-esm/storage/adapter/InMemoryStore.js +2 -2
  79. package/lib-esm/storage/adapter/InMemoryStore.js.map +1 -1
  80. package/lib-esm/storage/adapter/IndexedDBAdapter.d.ts +7 -2
  81. package/lib-esm/storage/adapter/IndexedDBAdapter.js +454 -252
  82. package/lib-esm/storage/adapter/IndexedDBAdapter.js.map +1 -1
  83. package/lib-esm/storage/adapter/index.d.ts +1 -1
  84. package/lib-esm/storage/storage.d.ts +3 -3
  85. package/lib-esm/storage/storage.js +106 -28
  86. package/lib-esm/storage/storage.js.map +1 -1
  87. package/lib-esm/sync/index.d.ts +23 -7
  88. package/lib-esm/sync/index.js +20 -19
  89. package/lib-esm/sync/index.js.map +1 -1
  90. package/lib-esm/sync/merger.d.ts +3 -3
  91. package/lib-esm/sync/merger.js +8 -6
  92. package/lib-esm/sync/merger.js.map +1 -1
  93. package/lib-esm/sync/outbox.d.ts +2 -2
  94. package/lib-esm/sync/outbox.js +13 -10
  95. package/lib-esm/sync/outbox.js.map +1 -1
  96. package/lib-esm/sync/processors/errorMaps.d.ts +17 -0
  97. package/lib-esm/sync/processors/errorMaps.js +119 -0
  98. package/lib-esm/sync/processors/errorMaps.js.map +1 -0
  99. package/lib-esm/sync/processors/mutation.d.ts +22 -4
  100. package/lib-esm/sync/processors/mutation.js +122 -54
  101. package/lib-esm/sync/processors/mutation.js.map +1 -1
  102. package/lib-esm/sync/processors/subscription.d.ts +4 -2
  103. package/lib-esm/sync/processors/subscription.js +77 -42
  104. package/lib-esm/sync/processors/subscription.js.map +1 -1
  105. package/lib-esm/sync/processors/sync.d.ts +4 -2
  106. package/lib-esm/sync/processors/sync.js +62 -27
  107. package/lib-esm/sync/processors/sync.js.map +1 -1
  108. package/lib-esm/sync/utils.d.ts +3 -2
  109. package/lib-esm/sync/utils.js +58 -8
  110. package/lib-esm/sync/utils.js.map +1 -1
  111. package/lib-esm/types.d.ts +90 -34
  112. package/lib-esm/types.js +29 -3
  113. package/lib-esm/types.js.map +1 -1
  114. package/lib-esm/util.d.ts +48 -33
  115. package/lib-esm/util.js +207 -54
  116. package/lib-esm/util.js.map +1 -1
  117. package/package.json +10 -9
  118. package/src/authModeStrategies/multiAuthStrategy.ts +24 -21
  119. package/src/datastore/datastore.ts +448 -148
  120. package/src/predicates/index.ts +32 -10
  121. package/src/storage/adapter/AsyncStorageAdapter.ts +305 -78
  122. package/src/storage/adapter/AsyncStorageDatabase.ts +65 -26
  123. package/src/storage/adapter/InMemoryStore.ts +2 -2
  124. package/src/storage/adapter/IndexedDBAdapter.ts +344 -101
  125. package/src/storage/adapter/index.ts +1 -1
  126. package/src/storage/storage.ts +85 -24
  127. package/src/sync/index.ts +74 -58
  128. package/src/sync/merger.ts +16 -4
  129. package/src/sync/outbox.ts +22 -8
  130. package/src/sync/processors/errorMaps.ts +93 -0
  131. package/src/sync/processors/mutation.ts +143 -84
  132. package/src/sync/processors/subscription.ts +67 -36
  133. package/src/sync/processors/sync.ts +37 -12
  134. package/src/sync/utils.ts +67 -16
  135. package/src/types.ts +252 -50
  136. package/src/util.ts +256 -42
  137. package/ssr/package.json +1 -1
package/src/util.ts CHANGED
@@ -1,9 +1,11 @@
1
1
  import { Buffer } from 'buffer';
2
2
  import { monotonicFactory, ULID } from 'ulid';
3
3
  import { v4 as uuid } from 'uuid';
4
+ import { produce, applyPatches, Patch } from 'immer';
4
5
  import { ModelInstanceCreator } from './datastore/datastore';
5
6
  import {
6
7
  AllOperators,
8
+ ProducerModelPredicate,
7
9
  isPredicateGroup,
8
10
  isPredicateObj,
9
11
  ModelInstanceMetadata,
@@ -25,9 +27,96 @@ import {
25
27
  NonModelTypeConstructor,
26
28
  DeferredCallbackResolverOptions,
27
29
  LimitTimerRaceResolvedValues,
30
+ SchemaModel,
31
+ ModelAttribute,
32
+ IndexesType,
28
33
  } from './types';
29
34
  import { WordArray } from 'amazon-cognito-identity-js';
30
35
 
36
+ const ID = 'id';
37
+
38
+ export const errorMessages = {
39
+ idEmptyString: 'An index field cannot contain an empty string value',
40
+ };
41
+
42
+ export function extractKeyIfExists(
43
+ modelDefinition: SchemaModel
44
+ ): ModelAttribute | undefined {
45
+ const keyAttribute = modelDefinition?.attributes?.find(isModelAttributeKey);
46
+
47
+ return keyAttribute;
48
+ }
49
+
50
+ export function extractPrimaryKeyFieldNames(
51
+ modelDefinition: SchemaModel
52
+ ): string[] {
53
+ const keyAttribute = extractKeyIfExists(modelDefinition);
54
+ if (keyAttribute && isModelAttributePrimaryKey(keyAttribute)) {
55
+ return keyAttribute.properties.fields;
56
+ }
57
+
58
+ return [ID];
59
+ }
60
+
61
+ export function extractPrimaryKeyValues<T extends PersistentModel>(
62
+ model: T,
63
+ keyFields: string[]
64
+ ): string[] {
65
+ return keyFields.map(key => model[key]);
66
+ }
67
+
68
+ export function extractPrimaryKeysAndValues<T extends PersistentModel>(
69
+ model: T,
70
+ keyFields: string[]
71
+ ): any {
72
+ const primaryKeysAndValues = {};
73
+ keyFields.forEach(key => (primaryKeysAndValues[key] = model[key]));
74
+ return primaryKeysAndValues;
75
+ }
76
+
77
+ // IdentifierFields<ManagedIdentifier>
78
+ // Default behavior without explicit @primaryKey defined
79
+ export function isIdManaged(modelDefinition: SchemaModel): boolean {
80
+ const keyAttribute = extractKeyIfExists(modelDefinition);
81
+
82
+ if (keyAttribute && isModelAttributePrimaryKey(keyAttribute)) {
83
+ return false;
84
+ }
85
+
86
+ return true;
87
+ }
88
+
89
+ // IdentifierFields<OptionallyManagedIdentifier>
90
+ // @primaryKey with explicit `id` in the PK. Single key or composite
91
+ export function isIdOptionallyManaged(modelDefinition: SchemaModel): boolean {
92
+ const keyAttribute = extractKeyIfExists(modelDefinition);
93
+
94
+ if (keyAttribute && isModelAttributePrimaryKey(keyAttribute)) {
95
+ // const idInKey = !!keyAttribute.properties.fields.find(
96
+ // field => field === ID
97
+ // );
98
+ // return idInKey && keyAttribute.properties.fields.length === 1;
99
+ return keyAttribute.properties.fields[0] === ID;
100
+ }
101
+
102
+ return false;
103
+ }
104
+
105
+ export enum NAMESPACES {
106
+ DATASTORE = 'datastore',
107
+ USER = 'user',
108
+ SYNC = 'sync',
109
+ STORAGE = 'storage',
110
+ }
111
+
112
+ const DATASTORE = NAMESPACES.DATASTORE;
113
+ const USER = NAMESPACES.USER;
114
+ const SYNC = NAMESPACES.SYNC;
115
+ const STORAGE = NAMESPACES.STORAGE;
116
+
117
+ export { USER, SYNC, STORAGE, DATASTORE };
118
+ export const USER_AGENT_SUFFIX_DATASTORE = '/DataStore';
119
+
31
120
  export const exhaustiveCheck = (obj: never, throwOnError: boolean = true) => {
32
121
  if (throwOnError) {
33
122
  throw new Error(`Invalid ${obj}`);
@@ -146,7 +235,7 @@ export const isNonModelConstructor = (
146
235
  return nonModelClasses.has(obj);
147
236
  };
148
237
 
149
- /*
238
+ /*
150
239
  When we have GSI(s) with composite sort keys defined on a model
151
240
  There are some very particular rules regarding which fields must be included in the update mutation input
152
241
  The field selection becomes more complex as the number of GSIs with composite sort keys grows
@@ -156,7 +245,7 @@ export const isNonModelConstructor = (
156
245
  2. all of the fields from any other composite sort key that intersect with the fields from 1.
157
246
 
158
247
  E.g.,
159
- Model @model
248
+ Model @model
160
249
  @key(name: 'key1' fields: ['hk', 'a', 'b', 'c'])
161
250
  @key(name: 'key2' fields: ['hk', 'a', 'b', 'd'])
162
251
  @key(name: 'key3' fields: ['hk', 'x', 'y', 'z'])
@@ -192,7 +281,7 @@ export const processCompositeKeys = (
192
281
  .filter(isModelAttributeCompositeKey)
193
282
  .map(extractCompositeSortKey);
194
283
 
195
- /*
284
+ /*
196
285
  if 2 sets of fields have any intersecting fields => combine them into 1 union set
197
286
  e.g., ['a', 'b', 'c'] and ['a', 'b', 'd'] => ['a', 'b', 'c', 'd']
198
287
  */
@@ -256,13 +345,19 @@ export const establishRelationAndKeys = (
256
345
  modelName: fieldAttribute.type.model,
257
346
  relationType: connectionType,
258
347
  targetName: fieldAttribute.association['targetName'],
348
+ targetNames: fieldAttribute.association['targetNames'],
259
349
  associatedWith: fieldAttribute.association['associatedWith'],
260
350
  });
261
351
 
262
352
  if (connectionType === 'BELONGS_TO') {
263
- relationship[mKey].indexes.push(
264
- fieldAttribute.association['targetName']
353
+ const targetNames = extractTargetNamesFromSrc(
354
+ fieldAttribute.association
265
355
  );
356
+
357
+ if (targetNames) {
358
+ const idxName = indexNameFromKeys(targetNames);
359
+ relationship[mKey].indexes.push([idxName, targetNames]);
360
+ }
266
361
  }
267
362
  }
268
363
  });
@@ -275,20 +370,36 @@ export const establishRelationAndKeys = (
275
370
  continue;
276
371
  }
277
372
 
373
+ const { fields } = attribute.properties;
374
+
278
375
  if (isModelAttributePrimaryKey(attribute)) {
279
- keys[mKey].primaryKey = attribute.properties.fields;
376
+ keys[mKey].primaryKey = fields;
377
+ continue;
280
378
  }
281
379
 
282
- const { fields } = attribute.properties;
283
- for (const field of fields) {
284
- // only add index if it hasn't already been added
285
- const exists = relationship[mKey].indexes.includes(field);
286
- if (!exists) {
287
- relationship[mKey].indexes.push(field);
288
- }
380
+ // create indexes for all other keys
381
+ const idxName = indexNameFromKeys(fields);
382
+ const idxExists = relationship[mKey].indexes.find(
383
+ ([index]) => index === idxName
384
+ );
385
+
386
+ if (!idxExists) {
387
+ relationship[mKey].indexes.push([idxName, fields]);
289
388
  }
290
389
  }
291
390
  }
391
+
392
+ // set 'id' as the PK for models without a custom PK explicitly defined
393
+ if (!keys[mKey].primaryKey) {
394
+ keys[mKey].primaryKey = [ID];
395
+ }
396
+
397
+ // create primary index
398
+ relationship[mKey].indexes.push([
399
+ 'byPk',
400
+ keys[mKey].primaryKey as string[],
401
+ { unique: true },
402
+ ]);
292
403
  });
293
404
 
294
405
  return [relationship, keys];
@@ -307,12 +418,14 @@ export const traverseModel = <T extends PersistentModel>(
307
418
  ) => PersistentModelConstructor<any>
308
419
  ) => {
309
420
  const relationships = namespace.relationships;
421
+
310
422
  const modelConstructor = getModelConstructorByModelName(
311
423
  namespace.name,
312
424
  srcModelName
313
425
  );
314
426
 
315
427
  const relation = relationships[srcModelName];
428
+
316
429
  const result: {
317
430
  modelName: string;
318
431
  item: T;
@@ -346,15 +459,36 @@ export const traverseModel = <T extends PersistentModel>(
346
459
  instance: modelInstance,
347
460
  });
348
461
 
349
- // targetName will be defined for Has One if feature flag
462
+ const targetNames: string[] | undefined =
463
+ extractTargetNamesFromSrc(rItem);
464
+
465
+ // `targetName` will be defined for Has One if feature flag
350
466
  // https://docs.amplify.aws/cli/reference/feature-flags/#useAppsyncModelgenPlugin
351
467
  // is true (default as of 5/7/21)
352
468
  // Making this conditional for backward-compatibility
353
- if (rItem.targetName) {
354
- (<any>draftInstance)[rItem.targetName] = (<PersistentModel>(
355
- draftInstance[rItem.fieldName]
356
- )).id;
357
- delete draftInstance[rItem.fieldName];
469
+ if (targetNames) {
470
+ targetNames.forEach((targetName, idx) => {
471
+ // Get the connected record
472
+ const relatedRecordInProxy = <PersistentModel>(
473
+ draftInstance[rItem.fieldName]
474
+ );
475
+
476
+ // Previously, we used the hardcoded 'id' as they key,
477
+ // now we need the value of the key to get the PK (and SK)
478
+ // values from the related record
479
+
480
+ const { primaryKey } = namespace.keys[modelConstructor.name];
481
+ const keyField = primaryKey && primaryKey[idx];
482
+
483
+ // Get the value
484
+ const relatedRecordInProxyPkValue =
485
+ relatedRecordInProxy[keyField];
486
+
487
+ // Set the targetName value
488
+ (<any>draftInstance)[targetName] = relatedRecordInProxyPkValue;
489
+ });
490
+ // Delete the instance from the proxy
491
+ delete (<any>draftInstance)[rItem.fieldName];
358
492
  } else {
359
493
  (<any>draftInstance)[rItem.fieldName] = (<PersistentModel>(
360
494
  draftInstance[rItem.fieldName]
@@ -389,10 +523,33 @@ export const traverseModel = <T extends PersistentModel>(
389
523
  }
390
524
 
391
525
  if (draftInstance[rItem.fieldName]) {
392
- (<any>draftInstance)[rItem.targetName] = (<PersistentModel>(
393
- draftInstance[rItem.fieldName]
394
- )).id;
395
- delete draftInstance[rItem.fieldName];
526
+ const targetNames: string[] | undefined =
527
+ extractTargetNamesFromSrc(rItem);
528
+
529
+ if (targetNames) {
530
+ targetNames.forEach((targetName, idx) => {
531
+ // Get the connected record
532
+ const relatedRecordInProxy = <PersistentModel>(
533
+ draftInstance[rItem.fieldName]
534
+ );
535
+ // Previously, we used the hardcoded `id` for the key.
536
+ // Now, we need the value of the key to get the PK (and SK)
537
+ // values from the related record
538
+ const { primaryKey } = namespace.keys[modelConstructor.name];
539
+
540
+ // fall back to ID if
541
+ const keyField = primaryKey && primaryKey[idx];
542
+
543
+ // Get the value
544
+ const relatedRecordInProxyPkValue =
545
+ relatedRecordInProxy[keyField];
546
+
547
+ // Set the targetName value
548
+ (<any>draftInstance)[targetName] = relatedRecordInProxyPkValue;
549
+ });
550
+ // Delete the instance from the proxy
551
+ delete (<any>draftInstance)[rItem.fieldName];
552
+ }
396
553
  }
397
554
 
398
555
  break;
@@ -430,7 +587,7 @@ export const traverseModel = <T extends PersistentModel>(
430
587
  return result;
431
588
  };
432
589
 
433
- export const getIndex = (rel: RelationType[], src: string): string => {
590
+ export const getIndex = (rel: RelationType[], src: any): string | undefined => {
434
591
  let index = '';
435
592
  rel.some((relItem: RelationType) => {
436
593
  if (relItem.modelName === src) {
@@ -441,26 +598,20 @@ export const getIndex = (rel: RelationType[], src: string): string => {
441
598
  };
442
599
 
443
600
  export const getIndexFromAssociation = (
444
- indexes: string[],
445
- src: string
446
- ): string => {
447
- const index = indexes.find(idx => idx === src);
448
- return index;
449
- };
450
-
451
- export enum NAMESPACES {
452
- DATASTORE = 'datastore',
453
- USER = 'user',
454
- SYNC = 'sync',
455
- STORAGE = 'storage',
456
- }
601
+ indexes: IndexesType,
602
+ src: string | string[]
603
+ ): string | undefined => {
604
+ let indexName: string;
457
605
 
458
- const DATASTORE = NAMESPACES.DATASTORE;
459
- const USER = NAMESPACES.USER;
460
- const SYNC = NAMESPACES.SYNC;
461
- const STORAGE = NAMESPACES.STORAGE;
606
+ if (Array.isArray(src)) {
607
+ indexName = indexNameFromKeys(src);
608
+ } else {
609
+ indexName = src;
610
+ }
462
611
 
463
- export { USER, SYNC, STORAGE, DATASTORE };
612
+ const associationIndex = indexes.find(([idxName]) => idxName === indexName);
613
+ return associationIndex && associationIndex[0];
614
+ };
464
615
 
465
616
  let privateModeCheckResult;
466
617
 
@@ -773,3 +924,66 @@ export class DeferredCallbackResolver {
773
924
  this.limitPromise.resolve(LimitTimerRaceResolvedValues.LIMIT);
774
925
  }
775
926
  }
927
+
928
+ /**
929
+ * merge two sets of patches created by immer produce.
930
+ * newPatches take precedent over oldPatches for patches modifying the same path.
931
+ * In the case many consecutive pathces are merged the original model should
932
+ * always be the root model.
933
+ *
934
+ * Example:
935
+ * A -> B, patches1
936
+ * B -> C, patches2
937
+ *
938
+ * mergePatches(A, patches1, patches2) to get patches for A -> C
939
+ *
940
+ * @param originalSource the original Model the patches should be applied to
941
+ * @param oldPatches immer produce patch list
942
+ * @param newPatches immer produce patch list (will take precedence)
943
+ * @return merged patches
944
+ */
945
+ export function mergePatches<T>(
946
+ originalSource: T,
947
+ oldPatches: Patch[],
948
+ newPatches: Patch[]
949
+ ): Patch[] {
950
+ const patchesToMerge = oldPatches.concat(newPatches);
951
+ let patches: Patch[];
952
+ produce(
953
+ originalSource,
954
+ draft => {
955
+ applyPatches(draft, patchesToMerge);
956
+ },
957
+ p => {
958
+ patches = p;
959
+ }
960
+ );
961
+ return patches;
962
+ }
963
+
964
+ /* Backwards-compatability for schema generated prior to custom primary key support:
965
+ the single field `targetName` has been replaced with an array of `targetNames`
966
+ */
967
+ export function extractTargetNamesFromSrc(src: any): string[] | undefined {
968
+ const targetName = src?.targetName;
969
+ const targetNames = src?.targetNames;
970
+
971
+ if (Array.isArray(targetNames) && targetNames?.length) {
972
+ return targetNames;
973
+ } else if (typeof targetName === 'string') {
974
+ return [targetName];
975
+ } else {
976
+ return undefined;
977
+ }
978
+ }
979
+
980
+ // Generates snake-cased index name from an aray of key field names
981
+ // E.g. for keys `[id, title]` => 'id-title'
982
+ export function indexNameFromKeys(keys: string[]): string {
983
+ return keys.reduce((prev: string, cur: string, idx: number) => {
984
+ if (idx === 0) {
985
+ return cur;
986
+ }
987
+ return `${prev}-${cur}`;
988
+ }, '');
989
+ }
package/ssr/package.json CHANGED
@@ -5,4 +5,4 @@
5
5
  "react-native": {
6
6
  "../lib/ssr/index": "../lib-esm/ssr/index.js"
7
7
  }
8
- }
8
+ }