diff --git a/packages/dynamoose/lib/utils/dynamoose/index_changes.ts b/packages/dynamoose/lib/utils/dynamoose/index_changes.ts index 419492d70..b9ce4a3be 100644 --- a/packages/dynamoose/lib/utils/dynamoose/index_changes.ts +++ b/packages/dynamoose/lib/utils/dynamoose/index_changes.ts @@ -34,6 +34,13 @@ const index_changes = async (table: Table, existingIndexes = []): Promise<(Model identicalProperties.pop(); } + const sanitizeIndex = (index: IndexItem) => { + if (Array.isArray(index.Projection.NonKeyAttributes)) { + index.Projection.NonKeyAttributes.sort(); + } + return index; + }; + const deleteIndexes: ModelIndexDeleteChange[] = existingIndexes.filter((index) => { const cleanedIndex = deep_copy(index); obj.entries(cleanedIndex).forEach(([key, value]) => { @@ -42,7 +49,10 @@ const index_changes = async (table: Table, existingIndexes = []): Promise<(Model } }); - return !(expectedIndexes.GlobalSecondaryIndexes || []).find((searchIndex) => obj.equals(obj.pick(cleanedIndex, identicalProperties), obj.pick(searchIndex as any, identicalProperties))); + return !(expectedIndexes.GlobalSecondaryIndexes || []).find((searchIndex) => obj.equals( + sanitizeIndex(obj.pick(cleanedIndex, identicalProperties) as any), + sanitizeIndex(obj.pick(searchIndex as any, identicalProperties) as any) + )); }).map((index) => ({"name": index.IndexName as string, "type": TableIndexChangeType.delete})); output.push(...deleteIndexes); diff --git a/packages/dynamoose/test/utils/dynamoose/index_changes.js b/packages/dynamoose/test/utils/dynamoose/index_changes.js index b23004b7c..03ec24642 100644 --- a/packages/dynamoose/test/utils/dynamoose/index_changes.js +++ b/packages/dynamoose/test/utils/dynamoose/index_changes.js @@ -215,6 +215,87 @@ describe("utils.dynamoose.index_changes", () => { ], "schema": {"id": String, "data": {"type": String, "index": {"name": "data-index-1", "type": "global", "project": true}}}, "output": [] + }, + { + "input": [], + "schema": {"id": String, "data1": {"type": String, "index": {"type": "global", "project": ["data2"]}}, "data2": String, "data3": String}, + "output": [{ + "spec": { + "IndexName": "data1GlobalIndex", + "KeySchema": [ + { + "AttributeName": "data1", + "KeyType": "HASH" + } + ], + "Projection": { + "NonKeyAttributes": ["data2"], + "ProjectionType": "INCLUDE" + }, + "ProvisionedThroughput": { + "ReadCapacityUnits": 1, + "WriteCapacityUnits": 1 + } + }, + "type": "add" + }] + }, + { + "input": [ + { + "IndexName": "data-index-1", + "KeySchema": [ + { + "AttributeName": "data1", + "KeyType": "HASH" + } + ], + "Projection": { + "NonKeyAttributes": ["data2", "data3"], // order not same as schema definition + "ProjectionType": "INCLUDE" + }, + "IndexStatus": "ACTIVE", + "ProvisionedThroughput": { + "ReadCapacityUnits": 1, + "WriteCapacityUnits": 1 + }, + "IndexSizeBytes": 0, + "ItemCount": 0, + "IndexArn": "arn:aws:dynamodb:ddblocal:000000000000:table/User/index/data-index-1" + } + ], + "schema": {"id": String, "data1": {"type": String, "index": {"name": "data-index-1", "type": "global", "project": ["data3", "data2"]}}, "data2": String, "data3": String}, + "output": [] + }, + { + "input": [ + { + "IndexName": "data-index-1", + "KeySchema": [ + { + "AttributeName": "data1", + "KeyType": "HASH" + } + ], + "Projection": { + "NonKeyAttributes": ["data2"], + "ProjectionType": "INCLUDE" + }, + "IndexStatus": "ACTIVE", + "ProvisionedThroughput": { + "ReadCapacityUnits": 1, + "WriteCapacityUnits": 1 + }, + "IndexSizeBytes": 0, + "ItemCount": 0, + "IndexArn": "arn:aws:dynamodb:ddblocal:000000000000:table/User/index/data-index-1" + } + ], + "schema": {"id": String, "data1": {"type": String, "index": {"name": "data-index-1", "type": "global", "project": ["data3", "data2"]}}, "data2": String, "data3": String}, + "output": [{ + "name": "data-index-1", + "type": "delete" + }] } ];