@aws-amplify/datastore 3.12.11 → 3.12.13-unstable.1
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/CHANGELOG.md +8 -0
- package/dist/aws-amplify-datastore.js +1853 -964
- package/dist/aws-amplify-datastore.js.map +1 -1
- package/dist/aws-amplify-datastore.min.js +7 -7
- package/dist/aws-amplify-datastore.min.js.map +1 -1
- package/lib/datastore/datastore.d.ts +13 -16
- package/lib/datastore/datastore.js +130 -63
- package/lib/datastore/datastore.js.map +1 -1
- package/lib/index.d.ts +3 -19
- package/lib/predicates/index.d.ts +3 -2
- package/lib/predicates/index.js +12 -2
- package/lib/predicates/index.js.map +1 -1
- package/lib/storage/adapter/AsyncStorageAdapter.d.ts +4 -3
- package/lib/storage/adapter/AsyncStorageAdapter.js +354 -203
- package/lib/storage/adapter/AsyncStorageAdapter.js.map +1 -1
- package/lib/storage/adapter/AsyncStorageDatabase.d.ts +14 -4
- package/lib/storage/adapter/AsyncStorageDatabase.js +65 -28
- package/lib/storage/adapter/AsyncStorageDatabase.js.map +1 -1
- package/lib/storage/adapter/IndexedDBAdapter.d.ts +5 -4
- package/lib/storage/adapter/IndexedDBAdapter.js +389 -267
- package/lib/storage/adapter/IndexedDBAdapter.js.map +1 -1
- package/lib/storage/adapter/index.d.ts +1 -1
- package/lib/storage/storage.d.ts +1 -1
- package/lib/storage/storage.js +92 -27
- package/lib/storage/storage.js.map +1 -1
- package/lib/sync/index.d.ts +21 -4
- package/lib/sync/index.js +13 -11
- package/lib/sync/index.js.map +1 -1
- package/lib/sync/merger.d.ts +3 -3
- package/lib/sync/merger.js +7 -6
- package/lib/sync/merger.js.map +1 -1
- package/lib/sync/outbox.d.ts +2 -2
- package/lib/sync/outbox.js +11 -9
- package/lib/sync/outbox.js.map +1 -1
- package/lib/sync/processors/mutation.js +60 -42
- package/lib/sync/processors/mutation.js.map +1 -1
- package/lib/sync/processors/subscription.js.map +1 -1
- package/lib/sync/processors/sync.js.map +1 -1
- package/lib/sync/utils.d.ts +3 -2
- package/lib/sync/utils.js +61 -8
- package/lib/sync/utils.js.map +1 -1
- package/lib/types.d.ts +64 -25
- package/lib/types.js +10 -1
- package/lib/types.js.map +1 -1
- package/lib/util.d.ts +56 -24
- package/lib/util.js +334 -170
- package/lib/util.js.map +1 -1
- package/lib-esm/datastore/datastore.d.ts +13 -16
- package/lib-esm/datastore/datastore.js +132 -65
- package/lib-esm/datastore/datastore.js.map +1 -1
- package/lib-esm/index.d.ts +3 -19
- package/lib-esm/predicates/index.d.ts +3 -2
- package/lib-esm/predicates/index.js +13 -3
- package/lib-esm/predicates/index.js.map +1 -1
- package/lib-esm/storage/adapter/AsyncStorageAdapter.d.ts +4 -3
- package/lib-esm/storage/adapter/AsyncStorageAdapter.js +355 -204
- package/lib-esm/storage/adapter/AsyncStorageAdapter.js.map +1 -1
- package/lib-esm/storage/adapter/AsyncStorageDatabase.d.ts +14 -4
- package/lib-esm/storage/adapter/AsyncStorageDatabase.js +66 -29
- package/lib-esm/storage/adapter/AsyncStorageDatabase.js.map +1 -1
- package/lib-esm/storage/adapter/IndexedDBAdapter.d.ts +5 -4
- package/lib-esm/storage/adapter/IndexedDBAdapter.js +390 -268
- package/lib-esm/storage/adapter/IndexedDBAdapter.js.map +1 -1
- package/lib-esm/storage/adapter/index.d.ts +1 -1
- package/lib-esm/storage/storage.d.ts +1 -1
- package/lib-esm/storage/storage.js +92 -27
- package/lib-esm/storage/storage.js.map +1 -1
- package/lib-esm/sync/index.d.ts +21 -4
- package/lib-esm/sync/index.js +15 -13
- package/lib-esm/sync/index.js.map +1 -1
- package/lib-esm/sync/merger.d.ts +3 -3
- package/lib-esm/sync/merger.js +7 -6
- package/lib-esm/sync/merger.js.map +1 -1
- package/lib-esm/sync/outbox.d.ts +2 -2
- package/lib-esm/sync/outbox.js +12 -10
- package/lib-esm/sync/outbox.js.map +1 -1
- package/lib-esm/sync/processors/mutation.js +61 -43
- package/lib-esm/sync/processors/mutation.js.map +1 -1
- package/lib-esm/sync/processors/subscription.js.map +1 -1
- package/lib-esm/sync/processors/sync.js.map +1 -1
- package/lib-esm/sync/utils.d.ts +3 -2
- package/lib-esm/sync/utils.js +62 -10
- package/lib-esm/sync/utils.js.map +1 -1
- package/lib-esm/types.d.ts +64 -25
- package/lib-esm/types.js +9 -2
- package/lib-esm/types.js.map +1 -1
- package/lib-esm/util.d.ts +56 -24
- package/lib-esm/util.js +334 -170
- package/lib-esm/util.js.map +1 -1
- package/package.json +7 -7
- package/src/datastore/datastore.ts +253 -113
- package/src/predicates/index.ts +32 -10
- package/src/storage/adapter/AsyncStorageAdapter.ts +309 -93
- package/src/storage/adapter/AsyncStorageDatabase.ts +74 -26
- package/src/storage/adapter/IndexedDBAdapter.ts +319 -136
- package/src/storage/adapter/index.ts +1 -1
- package/src/storage/storage.ts +68 -21
- package/src/sync/index.ts +41 -26
- package/src/sync/merger.ts +14 -4
- package/src/sync/outbox.ts +21 -8
- package/src/sync/processors/mutation.ts +49 -45
- package/src/sync/processors/subscription.ts +0 -1
- package/src/sync/processors/sync.ts +1 -3
- package/src/sync/utils.ts +69 -12
- package/src/types.ts +181 -29
- package/src/util.ts +415 -176
package/src/sync/utils.ts
CHANGED
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
isGraphQLScalarType,
|
|
12
12
|
isPredicateObj,
|
|
13
13
|
isSchemaModel,
|
|
14
|
+
isSchemaModelWithAttributes,
|
|
14
15
|
isTargetNameAssociation,
|
|
15
16
|
isNonModelFieldType,
|
|
16
17
|
ModelFields,
|
|
@@ -27,7 +28,12 @@ import {
|
|
|
27
28
|
InternalSchema,
|
|
28
29
|
AuthModeStrategy,
|
|
29
30
|
} from '../types';
|
|
30
|
-
import {
|
|
31
|
+
import {
|
|
32
|
+
exhaustiveCheck,
|
|
33
|
+
extractPrimaryKeyFieldNames,
|
|
34
|
+
establishRelationAndKeys,
|
|
35
|
+
IDENTIFIER_KEY_SEPARATOR,
|
|
36
|
+
} from '../util';
|
|
31
37
|
import { MutationEvent } from './';
|
|
32
38
|
|
|
33
39
|
const logger = new Logger('DataStore');
|
|
@@ -47,7 +53,7 @@ export enum TransformerMutationType {
|
|
|
47
53
|
GET = 'Get',
|
|
48
54
|
}
|
|
49
55
|
|
|
50
|
-
const dummyMetadata:
|
|
56
|
+
const dummyMetadata: ModelInstanceMetadata = {
|
|
51
57
|
_version: undefined,
|
|
52
58
|
_lastChangedAt: undefined,
|
|
53
59
|
_deleted: undefined,
|
|
@@ -79,7 +85,7 @@ export function generateSelectionSet(
|
|
|
79
85
|
if (isSchemaModel(modelDefinition)) {
|
|
80
86
|
scalarAndMetadataFields = scalarAndMetadataFields
|
|
81
87
|
.concat(getMetadataFields())
|
|
82
|
-
.concat(getConnectionFields(modelDefinition));
|
|
88
|
+
.concat(getConnectionFields(modelDefinition, namespace));
|
|
83
89
|
}
|
|
84
90
|
|
|
85
91
|
const result = scalarAndMetadataFields.join('\n');
|
|
@@ -103,7 +109,7 @@ function getOwnerFields(
|
|
|
103
109
|
modelDefinition: SchemaModel | SchemaNonModel
|
|
104
110
|
): string[] {
|
|
105
111
|
const ownerFields: string[] = [];
|
|
106
|
-
if (
|
|
112
|
+
if (isSchemaModelWithAttributes(modelDefinition)) {
|
|
107
113
|
modelDefinition.attributes.forEach(attr => {
|
|
108
114
|
if (attr.properties && attr.properties.rules) {
|
|
109
115
|
const rule = attr.properties.rules.find(rule => rule.allow === 'owner');
|
|
@@ -138,8 +144,12 @@ function getScalarFields(
|
|
|
138
144
|
return result;
|
|
139
145
|
}
|
|
140
146
|
|
|
141
|
-
|
|
142
|
-
|
|
147
|
+
// Used for generating the selection set for queries and mutations
|
|
148
|
+
function getConnectionFields(
|
|
149
|
+
modelDefinition: SchemaModel,
|
|
150
|
+
namespace: SchemaNamespace
|
|
151
|
+
): string[] {
|
|
152
|
+
const result: string[] = [];
|
|
143
153
|
|
|
144
154
|
Object.values(modelDefinition.fields)
|
|
145
155
|
.filter(({ association }) => association && Object.keys(association).length)
|
|
@@ -153,7 +163,26 @@ function getConnectionFields(modelDefinition: SchemaModel): string[] {
|
|
|
153
163
|
break;
|
|
154
164
|
case 'BELONGS_TO':
|
|
155
165
|
if (isTargetNameAssociation(association)) {
|
|
156
|
-
|
|
166
|
+
// New codegen (CPK)
|
|
167
|
+
if (association.targetNames && association.targetNames.length > 0) {
|
|
168
|
+
// Need to retrieve relations in order to get connected model keys
|
|
169
|
+
const [relations] = establishRelationAndKeys(namespace);
|
|
170
|
+
|
|
171
|
+
const connectedModelName =
|
|
172
|
+
modelDefinition.fields[name].type['model'];
|
|
173
|
+
|
|
174
|
+
const byPkIndex = relations[connectedModelName].indexes.find(
|
|
175
|
+
([name]) => name === 'byPk'
|
|
176
|
+
);
|
|
177
|
+
const keyFields = byPkIndex && byPkIndex[1];
|
|
178
|
+
const keyFieldSelectionSet = keyFields?.join(' ');
|
|
179
|
+
|
|
180
|
+
// We rely on `_deleted` when we process the sync query (e.g. in batchSave in the adapters)
|
|
181
|
+
result.push(`${name} { ${keyFieldSelectionSet} _deleted }`);
|
|
182
|
+
} else {
|
|
183
|
+
// backwards-compatability for schema generated prior to custom primary key support
|
|
184
|
+
result.push(`${name} { id _deleted }`);
|
|
185
|
+
}
|
|
157
186
|
}
|
|
158
187
|
break;
|
|
159
188
|
default:
|
|
@@ -412,10 +441,13 @@ export function createMutationInstanceFromModelOperation<
|
|
|
412
441
|
return v;
|
|
413
442
|
};
|
|
414
443
|
|
|
444
|
+
const modelId = getIdentifierValue(modelDefinition, element);
|
|
445
|
+
const optionalId = OpType.INSERT && id ? { id } : {};
|
|
446
|
+
|
|
415
447
|
const mutationEvent = modelInstanceCreator(MutationEventConstructor, {
|
|
416
|
-
...
|
|
448
|
+
...optionalId,
|
|
417
449
|
data: JSON.stringify(element, replacer),
|
|
418
|
-
modelId
|
|
450
|
+
modelId,
|
|
419
451
|
model: model.name,
|
|
420
452
|
operation,
|
|
421
453
|
condition: JSON.stringify(condition),
|
|
@@ -425,7 +457,8 @@ export function createMutationInstanceFromModelOperation<
|
|
|
425
457
|
}
|
|
426
458
|
|
|
427
459
|
export function predicateToGraphQLCondition(
|
|
428
|
-
predicate: PredicatesGroup<any
|
|
460
|
+
predicate: PredicatesGroup<any>,
|
|
461
|
+
modelDefinition: SchemaModel
|
|
429
462
|
): GraphQLCondition {
|
|
430
463
|
const result = {};
|
|
431
464
|
|
|
@@ -433,17 +466,27 @@ export function predicateToGraphQLCondition(
|
|
|
433
466
|
return result;
|
|
434
467
|
}
|
|
435
468
|
|
|
469
|
+
const keyFields = extractPrimaryKeyFieldNames(modelDefinition);
|
|
470
|
+
|
|
436
471
|
predicate.predicates.forEach(p => {
|
|
437
472
|
if (isPredicateObj(p)) {
|
|
438
473
|
const { field, operator, operand } = p;
|
|
439
474
|
|
|
440
|
-
|
|
475
|
+
// This is compatible with how the GQL Transform currently generates the Condition Input,
|
|
476
|
+
// i.e. any PK and SK fields are omitted and can't be used as conditions.
|
|
477
|
+
// However, I think this limits usability.
|
|
478
|
+
// What if we want to delete all records where SK > some value
|
|
479
|
+
// Or all records where PK = some value but SKs are different values
|
|
480
|
+
|
|
481
|
+
// TODO: if the Transform gets updated ^ we'll need to modify this logic to only omit
|
|
482
|
+
// key fields from the predicate/condition when ALL of the keyFields are present and using `eq` operators
|
|
483
|
+
if (keyFields.includes(field as string)) {
|
|
441
484
|
return;
|
|
442
485
|
}
|
|
443
486
|
|
|
444
487
|
result[field] = { [operator]: operand };
|
|
445
488
|
} else {
|
|
446
|
-
result[p.type] = predicateToGraphQLCondition(p);
|
|
489
|
+
result[p.type] = predicateToGraphQLCondition(p, modelDefinition);
|
|
447
490
|
}
|
|
448
491
|
});
|
|
449
492
|
|
|
@@ -610,3 +653,17 @@ export async function getTokenForCustomAuth(
|
|
|
610
653
|
}
|
|
611
654
|
}
|
|
612
655
|
}
|
|
656
|
+
|
|
657
|
+
// Util that takes a modelDefinition and model and returns either the id value(s) or the custom primary key value(s)
|
|
658
|
+
export function getIdentifierValue(
|
|
659
|
+
modelDefinition: SchemaModel,
|
|
660
|
+
model: ModelInstanceMetadata | PersistentModel
|
|
661
|
+
): string {
|
|
662
|
+
const pkFieldNames = extractPrimaryKeyFieldNames(modelDefinition);
|
|
663
|
+
|
|
664
|
+
const idOrPk = pkFieldNames
|
|
665
|
+
.map(f => model[f])
|
|
666
|
+
.join(IDENTIFIER_KEY_SEPARATOR);
|
|
667
|
+
|
|
668
|
+
return idOrPk;
|
|
669
|
+
}
|
package/src/types.ts
CHANGED
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
isAWSURL,
|
|
11
11
|
isAWSPhone,
|
|
12
12
|
isAWSIPAddress,
|
|
13
|
+
extractPrimaryKeyFieldNames,
|
|
13
14
|
} from './util';
|
|
14
15
|
import { PredicateAll } from './predicates';
|
|
15
16
|
import { GRAPHQL_AUTH_MODE } from '@aws-amplify/api-graphql';
|
|
@@ -46,9 +47,17 @@ export type SchemaModel = {
|
|
|
46
47
|
fields: ModelFields;
|
|
47
48
|
syncable?: boolean;
|
|
48
49
|
};
|
|
50
|
+
|
|
49
51
|
export function isSchemaModel(obj: any): obj is SchemaModel {
|
|
50
52
|
return obj && (<SchemaModel>obj).pluralName !== undefined;
|
|
51
53
|
}
|
|
54
|
+
|
|
55
|
+
export function isSchemaModelWithAttributes(
|
|
56
|
+
m: SchemaModel | SchemaNonModel
|
|
57
|
+
): m is SchemaModel {
|
|
58
|
+
return isSchemaModel(m) && (m as SchemaModel).attributes !== undefined;
|
|
59
|
+
}
|
|
60
|
+
|
|
52
61
|
export type SchemaNonModels = Record<string, SchemaNonModel>;
|
|
53
62
|
export type SchemaNonModel = {
|
|
54
63
|
name: string;
|
|
@@ -63,25 +72,29 @@ type SchemaEnum = {
|
|
|
63
72
|
export type ModelAssociation = AssociatedWith | TargetNameAssociation;
|
|
64
73
|
type AssociatedWith = {
|
|
65
74
|
connectionType: 'HAS_MANY' | 'HAS_ONE';
|
|
66
|
-
associatedWith: string;
|
|
75
|
+
associatedWith: string | string[];
|
|
67
76
|
targetName?: string;
|
|
77
|
+
targetNames?: string[];
|
|
68
78
|
};
|
|
79
|
+
|
|
69
80
|
export function isAssociatedWith(obj: any): obj is AssociatedWith {
|
|
70
81
|
return obj && obj.associatedWith;
|
|
71
82
|
}
|
|
72
83
|
|
|
73
84
|
type TargetNameAssociation = {
|
|
74
85
|
connectionType: 'BELONGS_TO';
|
|
75
|
-
targetName
|
|
86
|
+
targetName?: string;
|
|
87
|
+
targetNames?: string[];
|
|
76
88
|
};
|
|
89
|
+
|
|
77
90
|
export function isTargetNameAssociation(
|
|
78
91
|
obj: any
|
|
79
92
|
): obj is TargetNameAssociation {
|
|
80
|
-
return obj
|
|
93
|
+
return obj?.targetName || obj?.targetNames;
|
|
81
94
|
}
|
|
82
95
|
|
|
83
96
|
export type ModelAttributes = ModelAttribute[];
|
|
84
|
-
type ModelAttribute = { type: string; properties?: Record<string, any> };
|
|
97
|
+
export type ModelAttribute = { type: string; properties?: Record<string, any> };
|
|
85
98
|
|
|
86
99
|
export type ModelAuthRule = {
|
|
87
100
|
allow: string;
|
|
@@ -123,6 +136,7 @@ type ModelAttributeKey = {
|
|
|
123
136
|
type ModelAttributePrimaryKey = {
|
|
124
137
|
type: 'key';
|
|
125
138
|
properties: {
|
|
139
|
+
name: never;
|
|
126
140
|
fields: string[];
|
|
127
141
|
};
|
|
128
142
|
};
|
|
@@ -336,33 +350,138 @@ export type NonModelTypeConstructor<T> = {
|
|
|
336
350
|
};
|
|
337
351
|
|
|
338
352
|
// Class for model
|
|
339
|
-
export type PersistentModelConstructor<
|
|
340
|
-
T
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
new (init: ModelInit<T, K>): T;
|
|
346
|
-
copyOf(src: T, mutator: (draft: MutableModel<T, K>) => void): T;
|
|
353
|
+
export type PersistentModelConstructor<T extends PersistentModel> = {
|
|
354
|
+
new (init: ModelInit<T, PersistentModelMetaData<T>>): T;
|
|
355
|
+
copyOf(
|
|
356
|
+
src: T,
|
|
357
|
+
mutator: (draft: MutableModel<T, PersistentModelMetaData<T>>) => void
|
|
358
|
+
): T;
|
|
347
359
|
};
|
|
348
360
|
|
|
349
361
|
export type TypeConstructorMap = Record<
|
|
350
362
|
string,
|
|
351
|
-
PersistentModelConstructor<any> | NonModelTypeConstructor<
|
|
363
|
+
PersistentModelConstructor<any> | NonModelTypeConstructor<unknown>
|
|
364
|
+
>;
|
|
365
|
+
|
|
366
|
+
/**
|
|
367
|
+
* Each identifier type is represented using nominal types, see:
|
|
368
|
+
* https://basarat.gitbook.io/typescript/main-1/nominaltyping
|
|
369
|
+
*/
|
|
370
|
+
export declare const __identifierBrand__: unique symbol;
|
|
371
|
+
export type IdentifierBrand<T, K> = T & { [__identifierBrand__]: K };
|
|
372
|
+
|
|
373
|
+
// datastore generates a uuid for you
|
|
374
|
+
export type ManagedIdentifier<T, F extends keyof T> = IdentifierBrand<
|
|
375
|
+
{ field: F extends string ? F : never; type: T },
|
|
376
|
+
'ManagedIdentifier'
|
|
377
|
+
>;
|
|
378
|
+
|
|
379
|
+
// you can provide a value, if not, datastore generates a uuid for you
|
|
380
|
+
export type OptionallyManagedIdentifier<T, F extends keyof T> = IdentifierBrand<
|
|
381
|
+
{ field: F extends string ? F : never; type: T },
|
|
382
|
+
'OptionallyManagedIdentifier'
|
|
352
383
|
>;
|
|
353
384
|
|
|
385
|
+
// You provide the values
|
|
386
|
+
export type CompositeIdentifier<T, K extends Array<keyof T>> = IdentifierBrand<
|
|
387
|
+
{ fields: K; type: T },
|
|
388
|
+
'CompositeIdentifier'
|
|
389
|
+
>;
|
|
390
|
+
|
|
391
|
+
// You provide the value
|
|
392
|
+
export type CustomIdentifier<T, K extends keyof T> = CompositeIdentifier<
|
|
393
|
+
T,
|
|
394
|
+
[K]
|
|
395
|
+
>;
|
|
396
|
+
|
|
397
|
+
export type Identifier<T> =
|
|
398
|
+
| ManagedIdentifier<T, any>
|
|
399
|
+
| OptionallyManagedIdentifier<T, any>
|
|
400
|
+
| CompositeIdentifier<T, any>
|
|
401
|
+
| CustomIdentifier<T, any>;
|
|
402
|
+
|
|
403
|
+
export type IdentifierFields<
|
|
404
|
+
T extends PersistentModel,
|
|
405
|
+
M extends PersistentModelMetaData<T> = never
|
|
406
|
+
> = (MetadataOrDefault<T, M>['identifier'] extends
|
|
407
|
+
| ManagedIdentifier<any, any>
|
|
408
|
+
| OptionallyManagedIdentifier<any, any>
|
|
409
|
+
? MetadataOrDefault<T, M>['identifier']['field']
|
|
410
|
+
: MetadataOrDefault<T, M>['identifier'] extends CompositeIdentifier<
|
|
411
|
+
T,
|
|
412
|
+
infer B
|
|
413
|
+
>
|
|
414
|
+
? B[number] // B[number]
|
|
415
|
+
: MetadataOrDefault<T, M>['identifier']['field']) &
|
|
416
|
+
string;
|
|
417
|
+
|
|
418
|
+
export type IdentifierFieldsForInit<
|
|
419
|
+
T extends PersistentModel,
|
|
420
|
+
M extends PersistentModelMetaData<T>
|
|
421
|
+
> = MetadataOrDefault<T, M>['identifier'] extends
|
|
422
|
+
| DefaultPersistentModelMetaData
|
|
423
|
+
| ManagedIdentifier<T, any>
|
|
424
|
+
? never
|
|
425
|
+
: MetadataOrDefault<T, M>['identifier'] extends OptionallyManagedIdentifier<
|
|
426
|
+
T,
|
|
427
|
+
any
|
|
428
|
+
>
|
|
429
|
+
? IdentifierFields<T, M>
|
|
430
|
+
: MetadataOrDefault<T, M>['identifier'] extends CompositeIdentifier<T, any>
|
|
431
|
+
? IdentifierFields<T, M>
|
|
432
|
+
: never;
|
|
433
|
+
|
|
354
434
|
// Instance of model
|
|
355
|
-
export
|
|
356
|
-
|
|
435
|
+
export declare const __modelMeta__: unique symbol;
|
|
436
|
+
|
|
437
|
+
export type PersistentModelMetaData<T> = {
|
|
438
|
+
identifier?: Identifier<T>;
|
|
439
|
+
readOnlyFields?: string;
|
|
357
440
|
};
|
|
358
441
|
|
|
359
|
-
export type
|
|
442
|
+
export type DefaultPersistentModelMetaData = {
|
|
443
|
+
identifier: ManagedIdentifier<{ id: string }, 'id'>;
|
|
444
|
+
readOnlyFields: never;
|
|
445
|
+
};
|
|
446
|
+
|
|
447
|
+
export type MetadataOrDefault<
|
|
448
|
+
T extends PersistentModel,
|
|
449
|
+
_ extends PersistentModelMetaData<T> = never
|
|
450
|
+
> = T extends {
|
|
451
|
+
[__modelMeta__]: PersistentModelMetaData<T>;
|
|
452
|
+
}
|
|
453
|
+
? T[typeof __modelMeta__]
|
|
454
|
+
: DefaultPersistentModelMetaData;
|
|
455
|
+
|
|
456
|
+
export type PersistentModel = Readonly<Record<string, any>>;
|
|
457
|
+
|
|
458
|
+
export type MetadataReadOnlyFields<
|
|
459
|
+
T extends PersistentModel,
|
|
460
|
+
M extends PersistentModelMetaData<T>
|
|
461
|
+
> = Extract<
|
|
462
|
+
MetadataOrDefault<T, M>['readOnlyFields'] | M['readOnlyFields'],
|
|
463
|
+
keyof T
|
|
464
|
+
>;
|
|
465
|
+
|
|
466
|
+
// This type omits the metadata field in the constructor init object
|
|
467
|
+
// This type omits identifier fields in the constructor init object
|
|
468
|
+
// This type omits readOnlyFields in the constructor init object
|
|
469
|
+
// This type requires some identifiers in the constructor init object (e.g. CustomIdentifier)
|
|
470
|
+
// This type makes optional some identifiers in the constructor init object (e.g. OptionallyManagedIdentifier)
|
|
360
471
|
export type ModelInit<
|
|
472
|
+
T extends PersistentModel,
|
|
473
|
+
M extends PersistentModelMetaData<T> = {}
|
|
474
|
+
> = Omit<
|
|
361
475
|
T,
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
476
|
+
typeof __modelMeta__ | IdentifierFields<T, M> | MetadataReadOnlyFields<T, M>
|
|
477
|
+
> &
|
|
478
|
+
(MetadataOrDefault<T, M>['identifier'] extends OptionallyManagedIdentifier<
|
|
479
|
+
T,
|
|
480
|
+
any
|
|
481
|
+
>
|
|
482
|
+
? Partial<Pick<T, IdentifierFieldsForInit<T, M>>>
|
|
483
|
+
: Required<Pick<T, IdentifierFieldsForInit<T, M>>>);
|
|
484
|
+
|
|
366
485
|
type DeepWritable<T> = {
|
|
367
486
|
-readonly [P in keyof T]: T[P] extends TypeName<T[P]>
|
|
368
487
|
? T[P]
|
|
@@ -370,22 +489,45 @@ type DeepWritable<T> = {
|
|
|
370
489
|
};
|
|
371
490
|
|
|
372
491
|
export type MutableModel<
|
|
373
|
-
T extends
|
|
374
|
-
|
|
375
|
-
readOnlyFields: 'createdAt' | 'updatedAt';
|
|
376
|
-
}
|
|
492
|
+
T extends PersistentModel,
|
|
493
|
+
M extends PersistentModelMetaData<T> = {}
|
|
377
494
|
// This provides Intellisense with ALL of the properties, regardless of read-only
|
|
378
495
|
// but will throw a linting error if trying to overwrite a read-only property
|
|
379
|
-
> = DeepWritable<
|
|
380
|
-
|
|
496
|
+
> = DeepWritable<
|
|
497
|
+
Omit<T, IdentifierFields<T, M> | MetadataReadOnlyFields<T, M>>
|
|
498
|
+
> &
|
|
499
|
+
Readonly<Pick<T, IdentifierFields<T, M> | MetadataReadOnlyFields<T, M>>>;
|
|
381
500
|
|
|
382
501
|
export type ModelInstanceMetadata = {
|
|
383
|
-
id: string;
|
|
384
502
|
_version: number;
|
|
385
503
|
_lastChangedAt: number;
|
|
386
504
|
_deleted: boolean;
|
|
387
505
|
};
|
|
388
506
|
|
|
507
|
+
export type IdentifierFieldValue<
|
|
508
|
+
T extends PersistentModel,
|
|
509
|
+
M extends PersistentModelMetaData<T>
|
|
510
|
+
> = MetadataOrDefault<T, M>['identifier'] extends CompositeIdentifier<T, any>
|
|
511
|
+
? MetadataOrDefault<T, M>['identifier']['fields'] extends [any]
|
|
512
|
+
? T[MetadataOrDefault<T, M>['identifier']['fields'][0]]
|
|
513
|
+
: never
|
|
514
|
+
: T[MetadataOrDefault<T, M>['identifier']['field']];
|
|
515
|
+
|
|
516
|
+
export type IdentifierFieldOrIdentifierObject<
|
|
517
|
+
T extends PersistentModel,
|
|
518
|
+
M extends PersistentModelMetaData<T>
|
|
519
|
+
> = Pick<T, IdentifierFields<T, M>> | IdentifierFieldValue<T, M>;
|
|
520
|
+
|
|
521
|
+
export function isIdentifierObject<T extends PersistentModel>(
|
|
522
|
+
obj: any,
|
|
523
|
+
modelDefinition: SchemaModel
|
|
524
|
+
): obj is IdentifierFields<T extends PersistentModel ? T : never, any> {
|
|
525
|
+
const keys = extractPrimaryKeyFieldNames(modelDefinition);
|
|
526
|
+
|
|
527
|
+
return (
|
|
528
|
+
typeof obj === 'object' && obj && keys.every(k => obj[k] !== undefined)
|
|
529
|
+
);
|
|
530
|
+
}
|
|
389
531
|
//#endregion
|
|
390
532
|
|
|
391
533
|
//#region Subscription messages
|
|
@@ -635,11 +777,21 @@ export type RelationType = {
|
|
|
635
777
|
modelName: string;
|
|
636
778
|
relationType: 'HAS_ONE' | 'HAS_MANY' | 'BELONGS_TO';
|
|
637
779
|
targetName?: string;
|
|
638
|
-
|
|
780
|
+
targetNames?: string[];
|
|
781
|
+
associatedWith?: string | string[];
|
|
782
|
+
};
|
|
783
|
+
|
|
784
|
+
type IndexOptions = {
|
|
785
|
+
unique?: boolean;
|
|
639
786
|
};
|
|
640
787
|
|
|
788
|
+
export type IndexesType = Array<[string, string[], IndexOptions?]>;
|
|
789
|
+
|
|
641
790
|
export type RelationshipType = {
|
|
642
|
-
[modelName: string]: {
|
|
791
|
+
[modelName: string]: {
|
|
792
|
+
indexes: IndexesType;
|
|
793
|
+
relationTypes: RelationType[];
|
|
794
|
+
};
|
|
643
795
|
};
|
|
644
796
|
|
|
645
797
|
//#endregion
|