@aws-amplify/graphql-model-transformer 2.2.2 → 2.3.0-amplify-table-preview.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.
Files changed (24) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/lib/graphql-model-transformer.d.ts.map +1 -1
  3. package/lib/graphql-model-transformer.js +4 -0
  4. package/lib/graphql-model-transformer.js.map +1 -1
  5. package/lib/rds-lambda.zip +0 -0
  6. package/lib/rds-notification-lambda.zip +0 -0
  7. package/lib/rds-patching-lambda.zip +0 -0
  8. package/lib/resources/amplify-dynamodb-table/amplify-dynamo-model-resource-generator.d.ts +13 -0
  9. package/lib/resources/amplify-dynamodb-table/amplify-dynamo-model-resource-generator.d.ts.map +1 -0
  10. package/lib/resources/amplify-dynamodb-table/amplify-dynamo-model-resource-generator.js +167 -0
  11. package/lib/resources/amplify-dynamodb-table/amplify-dynamo-model-resource-generator.js.map +1 -0
  12. package/lib/resources/amplify-dynamodb-table/amplify-dynamodb-table-construct/index.d.ts +40 -0
  13. package/lib/resources/amplify-dynamodb-table/amplify-dynamodb-table-construct/index.d.ts.map +1 -0
  14. package/lib/resources/amplify-dynamodb-table/amplify-dynamodb-table-construct/index.js +242 -0
  15. package/lib/resources/amplify-dynamodb-table/amplify-dynamodb-table-construct/index.js.map +1 -0
  16. package/lib/resources/amplify-dynamodb-table/amplify-table-manager-lambda/amplify-table-manager-handler.d.ts +13 -0
  17. package/lib/resources/amplify-dynamodb-table/amplify-table-manager-lambda/amplify-table-manager-handler.d.ts.map +1 -0
  18. package/lib/resources/amplify-dynamodb-table/amplify-table-manager-lambda/amplify-table-manager-handler.js +665 -0
  19. package/lib/resources/amplify-dynamodb-table/amplify-table-manager-lambda/amplify-table-manager-handler.js.map +1 -0
  20. package/lib/resources/dynamo-model-resource-generator.d.ts +5 -2
  21. package/lib/resources/dynamo-model-resource-generator.d.ts.map +1 -1
  22. package/lib/resources/dynamo-model-resource-generator.js +46 -60
  23. package/lib/resources/dynamo-model-resource-generator.js.map +1 -1
  24. package/package.json +7 -6
@@ -0,0 +1,665 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.toCreateTableInput = exports.extractTableInputFromEvent = exports.getPointInTimeRecoveryUpdate = exports.getTtlUpdate = exports.getDeletionProtectionUpdate = exports.getSseUpdate = exports.getStreamUpdate = exports.getNextGSIUpdate = exports.isComplete = exports.onEvent = void 0;
4
+ const aws_sdk_1 = require("aws-sdk");
5
+ const ddbClient = new aws_sdk_1.DynamoDB();
6
+ const finished = {
7
+ IsComplete: true,
8
+ };
9
+ const notFinished = {
10
+ IsComplete: false,
11
+ };
12
+ const log = (msg, ...other) => {
13
+ console.log(msg, other.map((o) => (typeof o === 'object' ? JSON.stringify(o, undefined, 2) : o)));
14
+ };
15
+ const onEvent = async (event) => {
16
+ var _a;
17
+ console.log(event);
18
+ const tableDef = (0, exports.extractTableInputFromEvent)(event);
19
+ console.log('Input table state: ', tableDef);
20
+ let result;
21
+ switch (event.RequestType) {
22
+ case 'Create':
23
+ console.log('Initiating CREATE event');
24
+ const createTableInput = (0, exports.toCreateTableInput)(tableDef);
25
+ console.log('Create Table Params: ', createTableInput);
26
+ const response = await createNewTable(createTableInput);
27
+ result = {
28
+ PhysicalResourceId: response.tableName,
29
+ Data: {
30
+ TableArn: response.tableArn,
31
+ TableStreamArn: response.streamArn,
32
+ TableName: response.tableName,
33
+ },
34
+ };
35
+ console.log('Returning result: ', result);
36
+ return result;
37
+ case 'Update':
38
+ if (!event.PhysicalResourceId) {
39
+ throw new Error(`Could not find the physical ID for the updated resource`);
40
+ }
41
+ console.log('Fetching current table state');
42
+ const describeTableResult = await ddbClient.describeTable({ TableName: event.PhysicalResourceId }).promise();
43
+ if (!describeTableResult.Table) {
44
+ throw new Error(`Could not find ${event.PhysicalResourceId} to update`);
45
+ }
46
+ log('Current table state: ', describeTableResult);
47
+ if (isKeySchemaModified(describeTableResult.Table.KeySchema, tableDef.keySchema)) {
48
+ console.log('Update requires replacement');
49
+ console.log('Deleting the old table');
50
+ await ddbClient.deleteTable({ TableName: event.PhysicalResourceId }).promise();
51
+ await retry(async () => await doesTableExist(event.PhysicalResourceId), (res) => res === false);
52
+ console.log(`Table '${event.PhysicalResourceId}' does not exist. Deletion is finished.`);
53
+ const createTableInput = (0, exports.toCreateTableInput)(tableDef);
54
+ const response = await createNewTable(createTableInput);
55
+ result = {
56
+ PhysicalResourceId: response.tableName,
57
+ Data: {
58
+ TableArn: response.tableArn,
59
+ TableStreamArn: response.streamArn,
60
+ TableName: response.tableName,
61
+ IsTableReplaced: true,
62
+ },
63
+ };
64
+ log('Returning result', result);
65
+ return result;
66
+ }
67
+ const describePointInTimeRecoveryResult = await ddbClient
68
+ .describeContinuousBackups({ TableName: event.PhysicalResourceId })
69
+ .promise();
70
+ console.log('Current point in time recovery: ', describePointInTimeRecoveryResult);
71
+ const pointInTimeUpdate = (0, exports.getPointInTimeRecoveryUpdate)(describePointInTimeRecoveryResult.ContinuousBackupsDescription, tableDef);
72
+ if (pointInTimeUpdate) {
73
+ log('Computed point in time recovery update', pointInTimeUpdate);
74
+ await ddbClient.updateContinuousBackups(pointInTimeUpdate).promise();
75
+ await retry(async () => await isTableReady(event.PhysicalResourceId), (res) => res === true);
76
+ console.log(`Table '${event.PhysicalResourceId}' is ready after the update of PointInTimeRecovery.`);
77
+ }
78
+ const deletionProtectionUpdate = (0, exports.getDeletionProtectionUpdate)(describeTableResult.Table, tableDef);
79
+ if (deletionProtectionUpdate) {
80
+ log('Computed deletion protection update', deletionProtectionUpdate);
81
+ await ddbClient.updateTable(deletionProtectionUpdate).promise();
82
+ await retry(async () => await isTableReady(event.PhysicalResourceId), (res) => res === true);
83
+ console.log(`Table '${event.PhysicalResourceId}' is ready after the update of deletion protection.`);
84
+ }
85
+ const sseUpdate = (0, exports.getSseUpdate)(describeTableResult.Table, tableDef);
86
+ if (sseUpdate) {
87
+ log('Computed server side encryption update', sseUpdate);
88
+ await ddbClient.updateTable(sseUpdate).promise();
89
+ await retry(async () => await isTableReady(event.PhysicalResourceId), (res) => res === true);
90
+ console.log(`Table '${event.PhysicalResourceId}' is ready after the update of sever side encryption.`);
91
+ }
92
+ const streamUpdate = await (0, exports.getStreamUpdate)(describeTableResult.Table, tableDef);
93
+ if (streamUpdate) {
94
+ log('Computed stream specification update', streamUpdate);
95
+ await ddbClient.updateTable(streamUpdate).promise();
96
+ await retry(async () => await isTableReady(event.PhysicalResourceId), (res) => res === true);
97
+ console.log(`Table '${event.PhysicalResourceId}' is ready after the update of stream specificaion.`);
98
+ }
99
+ const describeTimeToLiveResult = await ddbClient.describeTimeToLive({ TableName: event.PhysicalResourceId }).promise();
100
+ console.log('Current TTL: ', describeTimeToLiveResult);
101
+ const ttlUpdate = (0, exports.getTtlUpdate)(describeTimeToLiveResult.TimeToLiveDescription, tableDef);
102
+ if (ttlUpdate) {
103
+ log('Computed time to live update', ttlUpdate);
104
+ console.log('Initiating TTL update');
105
+ await ddbClient.updateTimeToLive(ttlUpdate).promise();
106
+ result = {
107
+ PhysicalResourceId: event.PhysicalResourceId,
108
+ Data: {
109
+ TableArn: describeTableResult.Table.TableArn,
110
+ TableStreamArn: describeTableResult.Table.LatestStreamArn,
111
+ TableName: describeTableResult.Table.TableName,
112
+ },
113
+ };
114
+ return result;
115
+ }
116
+ const nextGsiUpdate = (0, exports.getNextGSIUpdate)(describeTableResult.Table, tableDef);
117
+ if (nextGsiUpdate) {
118
+ log('Computed next update', nextGsiUpdate);
119
+ console.log('Initiating table GSI update');
120
+ await ddbClient.updateTable(nextGsiUpdate).promise();
121
+ }
122
+ result = {
123
+ PhysicalResourceId: event.PhysicalResourceId,
124
+ Data: {
125
+ TableArn: describeTableResult.Table.TableArn,
126
+ TableStreamArn: describeTableResult.Table.LatestStreamArn,
127
+ TableName: describeTableResult.Table.TableName,
128
+ },
129
+ };
130
+ return result;
131
+ case 'Delete':
132
+ if (!event.PhysicalResourceId) {
133
+ throw new Error(`Could not find the physical ID for the resource`);
134
+ }
135
+ result = {
136
+ PhysicalResourceId: event.PhysicalResourceId,
137
+ };
138
+ console.log('Fetching current table state');
139
+ const describeTableResultBeforeDeletion = await ddbClient.describeTable({ TableName: event.PhysicalResourceId }).promise();
140
+ if ((_a = describeTableResultBeforeDeletion.Table) === null || _a === void 0 ? void 0 : _a.DeletionProtectionEnabled) {
141
+ return result;
142
+ }
143
+ try {
144
+ console.log('Initiating table deletion');
145
+ await ddbClient.deleteTable({ TableName: event.PhysicalResourceId }).promise();
146
+ return result;
147
+ }
148
+ catch (err) {
149
+ if (err.code === 'ResourceNotFoundException') {
150
+ return result;
151
+ }
152
+ throw err;
153
+ }
154
+ default:
155
+ throw new Error(`Event type ${event.RequestType} is not supported`);
156
+ }
157
+ };
158
+ exports.onEvent = onEvent;
159
+ const isComplete = async (event) => {
160
+ var _a, _b, _c;
161
+ log('got event', event);
162
+ if (event.RequestType === 'Delete') {
163
+ console.log('Delete is finished');
164
+ return finished;
165
+ }
166
+ if (!event.PhysicalResourceId) {
167
+ throw new Error('PhysicalResourceId not set in call to isComplete');
168
+ }
169
+ console.log('Fetching current table state');
170
+ const describeTableResult = await retry(async () => await ddbClient.describeTable({ TableName: event.PhysicalResourceId }).promise(), (result) => !!(result === null || result === void 0 ? void 0 : result.Table));
171
+ if (((_a = describeTableResult.Table) === null || _a === void 0 ? void 0 : _a.TableStatus) !== 'ACTIVE') {
172
+ console.log('Table not active yet');
173
+ return notFinished;
174
+ }
175
+ if ((_b = describeTableResult.Table.GlobalSecondaryIndexes) === null || _b === void 0 ? void 0 : _b.some((gsi) => gsi.IndexStatus !== 'ACTIVE' || gsi.Backfilling)) {
176
+ console.log('Some GSI is not active yet');
177
+ return notFinished;
178
+ }
179
+ const endState = (0, exports.extractTableInputFromEvent)(event);
180
+ if (event.RequestType === 'Create' || ((_c = event.Data) === null || _c === void 0 ? void 0 : _c.IsTableReplaced) === true) {
181
+ const describePointInTimeRecoveryResult = await ddbClient.describeContinuousBackups({ TableName: event.PhysicalResourceId }).promise();
182
+ const pointInTimeUpdate = (0, exports.getPointInTimeRecoveryUpdate)(describePointInTimeRecoveryResult.ContinuousBackupsDescription, endState);
183
+ if (pointInTimeUpdate) {
184
+ console.log('Updating table with point in time recovery enabled');
185
+ await ddbClient.updateContinuousBackups(pointInTimeUpdate).promise();
186
+ return notFinished;
187
+ }
188
+ const describeTimeToLiveResult = await ddbClient.describeTimeToLive({ TableName: event.PhysicalResourceId }).promise();
189
+ const ttlUpdate = (0, exports.getTtlUpdate)(describeTimeToLiveResult.TimeToLiveDescription, endState);
190
+ if (ttlUpdate) {
191
+ console.log('Updating table with TTL enabled');
192
+ await ddbClient.updateTimeToLive(ttlUpdate).promise();
193
+ return notFinished;
194
+ }
195
+ console.log('Create is finished');
196
+ return finished;
197
+ }
198
+ const nextUpdate = (0, exports.getNextGSIUpdate)(describeTableResult.Table, endState);
199
+ log('Computed next update', nextUpdate);
200
+ if (!nextUpdate) {
201
+ console.log('No additional updates needed. Update finished');
202
+ return finished;
203
+ }
204
+ console.log('Initiating table update');
205
+ await ddbClient.updateTable(nextUpdate).promise();
206
+ return notFinished;
207
+ };
208
+ exports.isComplete = isComplete;
209
+ const getNextGSIUpdate = (currentState, endState) => {
210
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p;
211
+ const endStateGSIs = endState.globalSecondaryIndexes || [];
212
+ const endStateGSINames = endStateGSIs.map((gsi) => gsi.indexName);
213
+ const currentStateGSIs = currentState.GlobalSecondaryIndexes || [];
214
+ const currentStateGSINames = currentStateGSIs.map((gsi) => gsi.IndexName);
215
+ const isTableBillingModeModified = (((_a = currentState.BillingModeSummary) === null || _a === void 0 ? void 0 : _a.BillingMode) !== undefined && ((_b = currentState.BillingModeSummary) === null || _b === void 0 ? void 0 : _b.BillingMode) !== endState.billingMode) ||
216
+ (((_c = currentState.BillingModeSummary) === null || _c === void 0 ? void 0 : _c.BillingMode) == undefined && endState.billingMode === 'PAY_PER_REQUEST');
217
+ const isTableProvisionThroughputModified = (((_d = endState.provisionedThroughput) === null || _d === void 0 ? void 0 : _d.readCapacityUnits) !== undefined &&
218
+ ((_e = currentState.ProvisionedThroughput) === null || _e === void 0 ? void 0 : _e.ReadCapacityUnits) !== ((_f = endState.provisionedThroughput) === null || _f === void 0 ? void 0 : _f.readCapacityUnits)) ||
219
+ (((_g = endState.provisionedThroughput) === null || _g === void 0 ? void 0 : _g.writeCapacityUnits) !== undefined &&
220
+ ((_h = currentState.ProvisionedThroughput) === null || _h === void 0 ? void 0 : _h.WriteCapacityUnits) !== ((_j = endState.provisionedThroughput) === null || _j === void 0 ? void 0 : _j.writeCapacityUnits));
221
+ if (isTableBillingModeModified || isTableProvisionThroughputModified) {
222
+ let updateInput = {
223
+ TableName: currentState.TableName,
224
+ BillingMode: isTableBillingModeModified ? endState.billingMode : undefined,
225
+ ProvisionedThroughput: isTableProvisionThroughputModified && endState.billingMode === 'PROVISIONED'
226
+ ? {
227
+ ReadCapacityUnits: (_k = endState.provisionedThroughput) === null || _k === void 0 ? void 0 : _k.readCapacityUnits,
228
+ WriteCapacityUnits: (_l = endState.provisionedThroughput) === null || _l === void 0 ? void 0 : _l.writeCapacityUnits,
229
+ }
230
+ : undefined,
231
+ };
232
+ if (isTableBillingModeModified && endState.billingMode === 'PROVISIONED') {
233
+ const indexToBeUpdated = currentStateGSIs.map((gsiToUpdate) => {
234
+ var _a, _b;
235
+ return {
236
+ Update: {
237
+ IndexName: gsiToUpdate.IndexName,
238
+ ProvisionedThroughput: {
239
+ ReadCapacityUnits: (_a = endState.provisionedThroughput) === null || _a === void 0 ? void 0 : _a.readCapacityUnits,
240
+ WriteCapacityUnits: (_b = endState.provisionedThroughput) === null || _b === void 0 ? void 0 : _b.writeCapacityUnits,
241
+ },
242
+ },
243
+ };
244
+ });
245
+ updateInput = {
246
+ ...updateInput,
247
+ GlobalSecondaryIndexUpdates: indexToBeUpdated.length > 0 ? indexToBeUpdated : undefined,
248
+ };
249
+ }
250
+ return parsePropertiesToDynamoDBInput(updateInput);
251
+ }
252
+ const gsiRequiresReplacementPredicate = (currentGSI) => {
253
+ if (!endStateGSINames.includes(currentGSI.IndexName))
254
+ return true;
255
+ const respectiveEndStateGSI = endStateGSIs.find((endStateGSI) => endStateGSI.indexName === currentGSI.IndexName);
256
+ if (isProjectionModified(currentGSI.Projection, respectiveEndStateGSI.projection))
257
+ return true;
258
+ if (isKeySchemaModified(currentGSI.KeySchema, respectiveEndStateGSI.keySchema))
259
+ return true;
260
+ return false;
261
+ };
262
+ const gsiToRemove = currentStateGSIs.find(gsiRequiresReplacementPredicate);
263
+ if (gsiToRemove) {
264
+ return {
265
+ TableName: currentState.TableName,
266
+ GlobalSecondaryIndexUpdates: [
267
+ {
268
+ Delete: {
269
+ IndexName: gsiToRemove.IndexName,
270
+ },
271
+ },
272
+ ],
273
+ };
274
+ }
275
+ const gsiRequiresCreationPredicate = (endStateGSI) => !currentStateGSINames.includes(endStateGSI.indexName);
276
+ const gsiToAdd = endStateGSIs.find(gsiRequiresCreationPredicate);
277
+ if (gsiToAdd) {
278
+ const attributeNamesToInclude = gsiToAdd.keySchema.map((schema) => schema.attributeName);
279
+ const gsiToAddAction = {
280
+ IndexName: gsiToAdd.indexName,
281
+ KeySchema: gsiToAdd.keySchema,
282
+ Projection: gsiToAdd.projection,
283
+ ProvisionedThroughput: gsiToAdd.provisionedThroughput,
284
+ };
285
+ return {
286
+ TableName: currentState.TableName,
287
+ AttributeDefinitions: (_m = endState.attributeDefinitions) === null || _m === void 0 ? void 0 : _m.filter((def) => attributeNamesToInclude.includes(def.attributeName)).map((def) => usePascalCaseForObjectKeys(def)),
288
+ GlobalSecondaryIndexUpdates: [
289
+ {
290
+ Create: parsePropertiesToDynamoDBInput(gsiToAddAction),
291
+ },
292
+ ],
293
+ };
294
+ }
295
+ const gsiRequiresUpdatePredicate = (endStateGSI) => {
296
+ var _a, _b, _c, _d;
297
+ if (endState.provisionedThroughput &&
298
+ endState.provisionedThroughput.readCapacityUnits &&
299
+ endState.provisionedThroughput.writeCapacityUnits &&
300
+ currentStateGSINames.includes(endStateGSI.indexName)) {
301
+ const currentStateGSI = currentStateGSIs.find((gsi) => gsi.IndexName === endStateGSI.indexName);
302
+ if (currentStateGSI) {
303
+ if (((_a = currentStateGSI.ProvisionedThroughput) === null || _a === void 0 ? void 0 : _a.ReadCapacityUnits) !== ((_b = endStateGSI.provisionedThroughput) === null || _b === void 0 ? void 0 : _b.readCapacityUnits) ||
304
+ ((_c = currentStateGSI.ProvisionedThroughput) === null || _c === void 0 ? void 0 : _c.WriteCapacityUnits) !== ((_d = endStateGSI.provisionedThroughput) === null || _d === void 0 ? void 0 : _d.writeCapacityUnits)) {
305
+ return true;
306
+ }
307
+ }
308
+ }
309
+ return false;
310
+ };
311
+ const gsiToUpdate = endStateGSIs.find(gsiRequiresUpdatePredicate);
312
+ if (gsiToUpdate) {
313
+ return {
314
+ TableName: currentState.TableName,
315
+ GlobalSecondaryIndexUpdates: [
316
+ {
317
+ Update: {
318
+ IndexName: gsiToUpdate.indexName,
319
+ ProvisionedThroughput: {
320
+ ReadCapacityUnits: (_o = gsiToUpdate.provisionedThroughput) === null || _o === void 0 ? void 0 : _o.readCapacityUnits,
321
+ WriteCapacityUnits: (_p = gsiToUpdate.provisionedThroughput) === null || _p === void 0 ? void 0 : _p.writeCapacityUnits,
322
+ },
323
+ },
324
+ },
325
+ ],
326
+ };
327
+ }
328
+ return undefined;
329
+ };
330
+ exports.getNextGSIUpdate = getNextGSIUpdate;
331
+ const getStreamUpdate = async (currentState, endState) => {
332
+ var _a, _b, _c, _d, _e, _f;
333
+ let streamUpdate;
334
+ if (((_a = endState.streamSpecification) === null || _a === void 0 ? void 0 : _a.streamViewType) !== undefined &&
335
+ (currentState.StreamSpecification === undefined || currentState.StreamSpecification.StreamEnabled === false)) {
336
+ streamUpdate = { StreamEnabled: true, StreamViewType: endState.streamSpecification.streamViewType };
337
+ }
338
+ else if (((_b = endState.streamSpecification) === null || _b === void 0 ? void 0 : _b.streamViewType) === undefined && ((_c = currentState.StreamSpecification) === null || _c === void 0 ? void 0 : _c.StreamEnabled) === true) {
339
+ streamUpdate = { StreamEnabled: false };
340
+ }
341
+ else if (((_d = currentState.StreamSpecification) === null || _d === void 0 ? void 0 : _d.StreamEnabled) === true &&
342
+ ((_e = endState.streamSpecification) === null || _e === void 0 ? void 0 : _e.streamViewType) !== undefined &&
343
+ currentState.StreamSpecification.StreamViewType !== ((_f = endState.streamSpecification) === null || _f === void 0 ? void 0 : _f.streamViewType)) {
344
+ console.log('Detect stream view type is changed. Disabling stream before the type change.');
345
+ await ddbClient
346
+ .updateTable({
347
+ TableName: currentState.TableName,
348
+ StreamSpecification: { StreamEnabled: false },
349
+ })
350
+ .promise();
351
+ await retry(async () => await isTableReady(currentState.TableName), (res) => res === true);
352
+ streamUpdate = { StreamEnabled: true, StreamViewType: endState.streamSpecification.streamViewType };
353
+ }
354
+ if (streamUpdate) {
355
+ return {
356
+ TableName: currentState.TableName,
357
+ StreamSpecification: streamUpdate,
358
+ };
359
+ }
360
+ return undefined;
361
+ };
362
+ exports.getStreamUpdate = getStreamUpdate;
363
+ const getSseUpdate = (currentState, endState) => {
364
+ var _a, _b, _c;
365
+ let sseUpdate;
366
+ if (currentState.SSEDescription) {
367
+ if (!((_a = endState.sseSpecification) === null || _a === void 0 ? void 0 : _a.sseEnabled)) {
368
+ sseUpdate = {
369
+ Enabled: false,
370
+ };
371
+ }
372
+ else if (((_b = endState.sseSpecification) === null || _b === void 0 ? void 0 : _b.sseEnabled) === true &&
373
+ endState.sseSpecification.sseType !== undefined &&
374
+ endState.sseSpecification.sseType !== currentState.SSEDescription.SSEType) {
375
+ sseUpdate = {
376
+ Enabled: true,
377
+ SSEType: endState.sseSpecification.sseType,
378
+ KMSMasterKeyId: endState.sseSpecification.kmsMasterKeyId,
379
+ };
380
+ }
381
+ }
382
+ else {
383
+ if ((_c = endState.sseSpecification) === null || _c === void 0 ? void 0 : _c.sseEnabled) {
384
+ sseUpdate = {
385
+ Enabled: true,
386
+ SSEType: endState.sseSpecification.sseType,
387
+ KMSMasterKeyId: endState.sseSpecification.kmsMasterKeyId,
388
+ };
389
+ }
390
+ }
391
+ if (sseUpdate) {
392
+ return parsePropertiesToDynamoDBInput({
393
+ TableName: currentState.TableName,
394
+ SSESpecification: sseUpdate,
395
+ });
396
+ }
397
+ return undefined;
398
+ };
399
+ exports.getSseUpdate = getSseUpdate;
400
+ const getDeletionProtectionUpdate = (currentState, endState) => {
401
+ if (endState.deletionProtectionEnabled !== undefined && currentState.DeletionProtectionEnabled !== endState.deletionProtectionEnabled) {
402
+ return {
403
+ TableName: currentState.TableName,
404
+ DeletionProtectionEnabled: endState.deletionProtectionEnabled,
405
+ };
406
+ }
407
+ else if (endState.deletionProtectionEnabled === undefined && currentState.DeletionProtectionEnabled === true) {
408
+ return {
409
+ TableName: currentState.TableName,
410
+ DeletionProtectionEnabled: false,
411
+ };
412
+ }
413
+ return undefined;
414
+ };
415
+ exports.getDeletionProtectionUpdate = getDeletionProtectionUpdate;
416
+ const getTtlUpdate = (currentTTL, endState) => {
417
+ const endTTL = endState.timeToLiveSpecification;
418
+ if (currentTTL && currentTTL.TimeToLiveStatus) {
419
+ if (currentTTL.TimeToLiveStatus === 'ENABLED' && currentTTL.AttributeName) {
420
+ if (!endTTL || !endTTL.enabled) {
421
+ return {
422
+ TableName: endState.tableName,
423
+ TimeToLiveSpecification: {
424
+ Enabled: false,
425
+ AttributeName: currentTTL.AttributeName,
426
+ },
427
+ };
428
+ }
429
+ else if (currentTTL.AttributeName !== endTTL.attributeName) {
430
+ return {
431
+ TableName: endState.tableName,
432
+ TimeToLiveSpecification: {
433
+ Enabled: true,
434
+ AttributeName: endTTL.attributeName,
435
+ },
436
+ };
437
+ }
438
+ }
439
+ else if (currentTTL.TimeToLiveStatus === 'DISABLED' && endTTL && endTTL.enabled) {
440
+ return {
441
+ TableName: endState.tableName,
442
+ TimeToLiveSpecification: {
443
+ Enabled: true,
444
+ AttributeName: endTTL.attributeName,
445
+ },
446
+ };
447
+ }
448
+ }
449
+ return undefined;
450
+ };
451
+ exports.getTtlUpdate = getTtlUpdate;
452
+ const getPointInTimeRecoveryUpdate = (currentPointInTime, endState) => {
453
+ var _a, _b;
454
+ if (!currentPointInTime) {
455
+ return undefined;
456
+ }
457
+ const currentStatus = (_a = currentPointInTime.PointInTimeRecoveryDescription) === null || _a === void 0 ? void 0 : _a.PointInTimeRecoveryStatus;
458
+ const endStatus = (_b = endState.pointInTimeRecoverySpecification) === null || _b === void 0 ? void 0 : _b.pointInTimeRecoveryEnabled;
459
+ if (endStatus === undefined || endStatus === false) {
460
+ if (currentStatus === 'ENABLED') {
461
+ return {
462
+ TableName: endState.tableName,
463
+ PointInTimeRecoverySpecification: {
464
+ PointInTimeRecoveryEnabled: false,
465
+ },
466
+ };
467
+ }
468
+ }
469
+ else {
470
+ if (currentStatus === 'DISABLED') {
471
+ return {
472
+ TableName: endState.tableName,
473
+ PointInTimeRecoverySpecification: {
474
+ PointInTimeRecoveryEnabled: true,
475
+ },
476
+ };
477
+ }
478
+ }
479
+ return undefined;
480
+ };
481
+ exports.getPointInTimeRecoveryUpdate = getPointInTimeRecoveryUpdate;
482
+ const extractTableInputFromEvent = (event) => {
483
+ const resourceProperties = { ...event.ResourceProperties };
484
+ delete resourceProperties.ServiceToken;
485
+ const tableDef = convertStringToBooleanOrNumber(resourceProperties);
486
+ return tableDef;
487
+ };
488
+ exports.extractTableInputFromEvent = extractTableInputFromEvent;
489
+ const parsePropertiesToDynamoDBInput = (obj) => {
490
+ return usePascalCaseForObjectKeys(removeUndefinedAttributes(obj));
491
+ };
492
+ const usePascalCaseForObjectKeys = (obj) => {
493
+ const result = {};
494
+ for (const key in obj) {
495
+ if (obj.hasOwnProperty(key) && key !== '') {
496
+ const capitalizedKey = key.charAt(0).toUpperCase() + key.slice(1);
497
+ const value = obj[key];
498
+ if (Array.isArray(value)) {
499
+ result[capitalizedKey] = value.map((v) => usePascalCaseForObjectKeys(v));
500
+ }
501
+ else if (typeof value === 'object' && value !== null) {
502
+ result[capitalizedKey] = usePascalCaseForObjectKeys(value);
503
+ }
504
+ else {
505
+ result[capitalizedKey] = value;
506
+ }
507
+ }
508
+ }
509
+ return result;
510
+ };
511
+ const convertStringToBooleanOrNumber = (obj) => {
512
+ for (const key in obj) {
513
+ if (Array.isArray(obj[key])) {
514
+ obj[key] = obj[key].map((o) => convertStringToBooleanOrNumber(o));
515
+ }
516
+ else if (typeof obj[key] === 'object') {
517
+ obj[key] = convertStringToBooleanOrNumber(obj[key]);
518
+ }
519
+ else if (typeof obj[key] === 'string') {
520
+ if (obj[key] === 'true' || obj[key] === 'false') {
521
+ obj[key] = obj[key] === 'true';
522
+ }
523
+ else if (!isNaN(Number(obj[key]))) {
524
+ obj[key] = Number(obj[key]);
525
+ }
526
+ }
527
+ }
528
+ return obj;
529
+ };
530
+ const removeUndefinedAttributes = (obj) => {
531
+ for (const key in obj) {
532
+ if (Array.isArray(obj[key])) {
533
+ obj[key].map((o) => removeUndefinedAttributes(o));
534
+ }
535
+ else if (typeof obj[key] === 'object') {
536
+ removeUndefinedAttributes(obj[key]);
537
+ }
538
+ else if (obj[key] === undefined) {
539
+ delete obj[key];
540
+ }
541
+ }
542
+ return obj;
543
+ };
544
+ const toCreateTableInput = (props) => {
545
+ const createTableInput = {
546
+ TableName: props.tableName,
547
+ AttributeDefinitions: props.attributeDefinitions,
548
+ KeySchema: props.keySchema,
549
+ GlobalSecondaryIndexes: props.globalSecondaryIndexes,
550
+ BillingMode: props.billingMode,
551
+ StreamSpecification: props.streamSpecification
552
+ ? {
553
+ StreamEnabled: true,
554
+ StreamViewType: props.streamSpecification.streamViewType,
555
+ }
556
+ : undefined,
557
+ ProvisionedThroughput: props.provisionedThroughput,
558
+ SSESpecification: props.sseSpecification ? { Enabled: props.sseSpecification.sseEnabled } : undefined,
559
+ };
560
+ return parsePropertiesToDynamoDBInput(createTableInput);
561
+ };
562
+ exports.toCreateTableInput = toCreateTableInput;
563
+ const createNewTable = async (input) => {
564
+ var _a, _b;
565
+ const tableName = input.TableName;
566
+ const createTableInput = input;
567
+ const result = await ddbClient.createTable(createTableInput).promise();
568
+ return { tableName, tableArn: (_a = result.TableDescription) === null || _a === void 0 ? void 0 : _a.TableArn, streamArn: (_b = result.TableDescription) === null || _b === void 0 ? void 0 : _b.LatestStreamArn };
569
+ };
570
+ const doesTableExist = async (tableName) => {
571
+ try {
572
+ await ddbClient.describeTable({ TableName: tableName }).promise();
573
+ return true;
574
+ }
575
+ catch (error) {
576
+ if (error.code === 'ResourceNotFoundException') {
577
+ return false;
578
+ }
579
+ throw error;
580
+ }
581
+ };
582
+ const isTableReady = async (tableName) => {
583
+ var _a, _b;
584
+ const result = await ddbClient.describeTable({ TableName: tableName }).promise();
585
+ if (((_a = result.Table) === null || _a === void 0 ? void 0 : _a.TableStatus) !== 'ACTIVE') {
586
+ console.log('Table not active yet');
587
+ return false;
588
+ }
589
+ if ((_b = result.Table.GlobalSecondaryIndexes) === null || _b === void 0 ? void 0 : _b.some((gsi) => gsi.IndexStatus !== 'ACTIVE' || gsi.Backfilling)) {
590
+ console.log('Some GSI is not active yet');
591
+ return false;
592
+ }
593
+ return true;
594
+ };
595
+ const isProjectionModified = (currentProjection, endProjection) => {
596
+ if (currentProjection.ProjectionType !== endProjection.projectionType)
597
+ return true;
598
+ if (currentProjection.ProjectionType === 'ALL')
599
+ return false;
600
+ const currentNonKeyAttributes = currentProjection.NonKeyAttributes || [];
601
+ const endNonKeyAttributes = endProjection.nonKeyAttributes || [];
602
+ if (currentNonKeyAttributes.length !== endNonKeyAttributes.length)
603
+ return true;
604
+ if (currentNonKeyAttributes.some((currentNonKeyAttribute) => !endNonKeyAttributes.includes(currentNonKeyAttribute)))
605
+ return true;
606
+ return false;
607
+ };
608
+ const isKeySchemaModified = (currentSchema, endSchema) => {
609
+ const currentHashKey = currentSchema.find((schema) => schema.KeyType === 'HASH');
610
+ const endHashKey = endSchema.find((schema) => schema.keyType === 'HASH');
611
+ if ((currentHashKey === null || currentHashKey === void 0 ? void 0 : currentHashKey.AttributeName) !== (endHashKey === null || endHashKey === void 0 ? void 0 : endHashKey.attributeName))
612
+ return true;
613
+ const currentSortKey = currentSchema.find((schema) => schema.KeyType === 'RANGE');
614
+ const endSortKey = endSchema.find((schema) => schema.keyType === 'RANGE');
615
+ if (currentSortKey === undefined && endSortKey === undefined)
616
+ return false;
617
+ if ((currentSortKey === undefined && endSortKey !== undefined) || (currentSortKey !== undefined && endSortKey === undefined))
618
+ return true;
619
+ if ((currentSortKey === null || currentSortKey === void 0 ? void 0 : currentSortKey.AttributeName) !== (endSortKey === null || endSortKey === void 0 ? void 0 : endSortKey.attributeName))
620
+ return true;
621
+ return false;
622
+ };
623
+ const defaultSettings = {
624
+ times: Infinity,
625
+ delayMS: 1000 * 15,
626
+ timeoutMS: 1000 * 60 * 14,
627
+ stopOnError: false,
628
+ };
629
+ const retry = async (func, successPredicate, settings, failurePredicate) => {
630
+ const { times, delayMS, timeoutMS, stopOnError } = {
631
+ ...defaultSettings,
632
+ ...settings,
633
+ };
634
+ let count = 0;
635
+ let result;
636
+ let terminate = false;
637
+ const startTime = Date.now();
638
+ do {
639
+ try {
640
+ result = await func();
641
+ if (successPredicate(result)) {
642
+ return result;
643
+ }
644
+ if (typeof failurePredicate === 'function' && failurePredicate(result)) {
645
+ throw new Error('Retry-able function execution result matched failure predicate. Stopping retries.');
646
+ }
647
+ console.warn(`Retry-able function execution did not match success predicate. Result was [${JSON.stringify(result)}]. Retrying...`);
648
+ }
649
+ catch (err) {
650
+ console.warn(`Retry-able function execution failed with [${err.message || err}]`);
651
+ if (stopOnError) {
652
+ console.log('Stopping retries on error.');
653
+ }
654
+ else {
655
+ console.log('Retrying...');
656
+ }
657
+ terminate = stopOnError;
658
+ }
659
+ count++;
660
+ await sleep(delayMS);
661
+ } while (!terminate && count <= times && Date.now() - startTime < timeoutMS);
662
+ throw new Error('Retry-able function did not match predicate within the given retry constraints');
663
+ };
664
+ const sleep = async (milliseconds) => new Promise((resolve) => setTimeout(resolve, milliseconds));
665
+ //# sourceMappingURL=amplify-table-manager-handler.js.map