diff --git a/action.yml b/action.yml index 83c0e249..b4562c8c 100644 --- a/action.yml +++ b/action.yml @@ -36,6 +36,17 @@ inputs: description: 'Item Value, Only required for batch-put operation' required: false + #Update Operation + updateExpression: + description: 'Attribute variables, Only required for update operation' + required: false + expressionAttributeValues: + description: 'Attribute values to be updated, Only required for update operation' + required: false + expressionAttributeFiles: + description: 'Attribute files to be updated, Only required for update operation' + required: false + outputs: item: description: 'JSON-serialized Item' diff --git a/dist/index.js b/dist/index.js index 98fdc4fe..be688768 100644 --- a/dist/index.js +++ b/dist/index.js @@ -11,7 +11,7 @@ const processor = new processor_1.Processor(); operation: (_a = core.getInput("operation")) === null || _a === void 0 ? void 0 : _a.toLowerCase(), region: core.getInput("region"), table: core.getInput("table"), - // Get / Delete Operation + // Get / Delete / Update Operation key: helpers_1.forgivingJSONParse(core.getInput("key")), consistent: helpers_1.forgivingJSONParse(core.getInput("consistent")), // Put Operation @@ -20,6 +20,10 @@ const processor = new processor_1.Processor(); // BatchPut Operation items: helpers_1.forgivingJSONParse(core.getInput("items")), files: core.getInput("files"), + // Update Operation + updateExpression: core.getInput("updateExpression"), + expressionAttributeValues: core.getInput("expressionAttributeValues"), + expressionAttributeFiles: core.getInput("expressionAttributeFiles") }; const output = await processor.process(input); if (output) { diff --git a/dist/operations/batch-put.js b/dist/operations/batch-put.js index 088c4318..c9c9f993 100644 --- a/dist/operations/batch-put.js +++ b/dist/operations/batch-put.js @@ -2,7 +2,7 @@ Object.defineProperty(exports, "__esModule", { value: true }); exports.BatchPutOperation = void 0; const glob = require("@actions/glob"); -const Joi = require("@hapi/joi"); +const Joi = require("joi"); const fs_1 = require("fs"); const helpers_1 = require("../helpers"); const BaseInputSchema = Joi.object({ diff --git a/dist/operations/delete.js b/dist/operations/delete.js index de9ad447..09d3b9ae 100644 --- a/dist/operations/delete.js +++ b/dist/operations/delete.js @@ -1,7 +1,7 @@ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.DeleteOperation = void 0; -const Joi = require("@hapi/joi"); +const Joi = require("joi"); const helpers_1 = require("../helpers"); const InputSchema = Joi.object({ operation: Joi.string().lowercase().valid("delete").required(), diff --git a/dist/operations/get.js b/dist/operations/get.js index e176d07d..c544cd55 100644 --- a/dist/operations/get.js +++ b/dist/operations/get.js @@ -1,7 +1,7 @@ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.GetOperation = void 0; -const Joi = require("@hapi/joi"); +const Joi = require("joi"); const helpers_1 = require("../helpers"); const InputSchema = Joi.object({ operation: Joi.string().lowercase().valid("get").required(), diff --git a/dist/operations/index.js b/dist/operations/index.js index 2810ef89..af282a0a 100644 --- a/dist/operations/index.js +++ b/dist/operations/index.js @@ -7,7 +7,7 @@ var __createBinding = (this && this.__createBinding) || (Object.create ? (functi o[k2] = m[k]; })); var __exportStar = (this && this.__exportStar) || function(m, exports) { - for (var p in m) if (p !== "default" && !exports.hasOwnProperty(p)) __createBinding(exports, m, p); + for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); }; Object.defineProperty(exports, "__esModule", { value: true }); __exportStar(require("./base"), exports); @@ -15,3 +15,4 @@ __exportStar(require("./batch-put"), exports); __exportStar(require("./delete"), exports); __exportStar(require("./get"), exports); __exportStar(require("./put"), exports); +__exportStar(require("./update"), exports); diff --git a/dist/operations/put.js b/dist/operations/put.js index 6c7cabd2..15f2fa92 100644 --- a/dist/operations/put.js +++ b/dist/operations/put.js @@ -1,7 +1,7 @@ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.PutOperation = void 0; -const Joi = require("@hapi/joi"); +const Joi = require("joi"); const fs_1 = require("fs"); const helpers_1 = require("../helpers"); const BaseInputSchema = Joi.object({ diff --git a/dist/operations/update.js b/dist/operations/update.js new file mode 100644 index 00000000..ddc86cfe --- /dev/null +++ b/dist/operations/update.js @@ -0,0 +1,96 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.UpdateOperation = void 0; +const Joi = require("joi"); +const fs_1 = require("fs"); +const helpers_1 = require("../helpers"); +const BaseInputSchema = Joi.object({ + operation: Joi.string().lowercase().valid("update").required(), + region: Joi.string().lowercase().required(), + table: Joi.string().required(), + updateExpression: Joi.string().required() +}); +const InputSchema = Joi.alternatives([ + BaseInputSchema.append({ + expressionAttributeValues: Joi.string().required(), + key: Joi.object().required(), + }), + BaseInputSchema.append({ + expressionAttributeFiles: Joi.string().required(), + key: Joi.object().required(), + }), +]).required(); +class UpdateOperation { + constructor() { + this.name = "update"; + } + async validate(input) { + const validationResult = InputSchema.validate(input, { + stripUnknown: true, + }); + if (validationResult.error) { + throw validationResult.error; + } + return validationResult.value; + } + async execute(input) { + const ddb = helpers_1.createClient(input.region); + let updateExp = ``; + let attValues = {}; + const expressions = await this.buildExpression(updateExp, input); + const attributes = await this.buildAttributes(expressions, attValues, input); + console.log(expressions); + console.log(attributes); + await ddb.update({ + TableName: input.table, + Key: input.key, + UpdateExpression: expressions, + ExpressionAttributeValues: attributes + }).promise(); + } + async read(path) { + const content = await fs_1.promises.readFile(path, { encoding: "utf8" }); + return JSON.parse(content); + } + async buildExpression(updateExp, input) { + const updateExpressions = input.updateExpression.split(','); + for (let i = 0; i < updateExpressions.length; i++) { + if (i === 0 && updateExpressions.length > 1) { + updateExp = `set ${updateExpressions[i]} = :${updateExpressions[i]},`; + } + else if (i === 0 && updateExpressions.length === 1) { + updateExp = `set ${updateExpressions[i]} = :${updateExpressions[i]}`; + } + else if (i === updateExpressions.length - 1) { + updateExp += ` ${updateExpressions[i]} = :${updateExpressions[i]}`; + } + else { + updateExp += ` ${updateExpressions[i]} = :${updateExpressions[i]},`; + } + } + return updateExp; + } + async buildAttributes(updateExp, attValues, input) { + const updateExpressions = updateExp.split(','); + if (input.expressionAttributeValues) { + const expAttValues = input.expressionAttributeValues.split(', '); + const keyValues = []; + for (let i = 0; i < updateExpressions.length; i++) { + updateExpressions[i] = updateExpressions[i].substring(updateExpressions[i].indexOf(":")); + keyValues[i] = [updateExpressions[i], expAttValues[i]]; + } + attValues = Object.fromEntries(keyValues); + } + else if (input.expressionAttributeFiles) { + const expAttValues = input.expressionAttributeFiles.split(','); + const keyValues = []; + for (let i = 0; i < updateExpressions.length; i++) { + updateExpressions[i] = updateExpressions[i].substring(updateExpressions[i].indexOf(":")); + keyValues[i] = [updateExpressions[i], await this.read(expAttValues[i])]; + } + attValues = Object.fromEntries(keyValues); + } + return attValues; + } +} +exports.UpdateOperation = UpdateOperation; diff --git a/dist/processor.js b/dist/processor.js index f8ec2a32..61f950fd 100644 --- a/dist/processor.js +++ b/dist/processor.js @@ -9,6 +9,7 @@ class Processor { new operations_1.DeleteOperation(), new operations_1.GetOperation(), new operations_1.PutOperation(), + new operations_1.UpdateOperation() ]; } async process(input) { diff --git a/package-lock.json b/package-lock.json index 0d88e5b0..f7c2c076 100644 --- a/package-lock.json +++ b/package-lock.json @@ -222,6 +222,20 @@ "@commitlint/top-level": "^11.0.0", "fs-extra": "^9.0.0", "git-raw-commits": "^2.0.0" + }, + "dependencies": { + "fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dev": true, + "requires": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + } } }, "@commitlint/resolve-extends": { @@ -308,40 +322,10 @@ "integrity": "sha512-VoNqai1vR5anRF5Tuh/+SWDFk7xi7oMwHrHrbm1BprYXjB2RJsWLhUrStMssDxEl5lW/z3EUdg8RvH/IUBccSQ==", "dev": true }, - "@hapi/address": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/@hapi/address/-/address-4.1.0.tgz", - "integrity": "sha512-SkszZf13HVgGmChdHo/PxchnSaCJ6cetVqLzyciudzZRT0jcOouIF/Q93mgjw8cce+D+4F4C1Z/WrfFN+O3VHQ==", - "requires": { - "@hapi/hoek": "^9.0.0" - } - }, - "@hapi/formula": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@hapi/formula/-/formula-2.0.0.tgz", - "integrity": "sha512-V87P8fv7PI0LH7LiVi8Lkf3x+KCO7pQozXRssAHNXXL9L1K+uyu4XypLXwxqVDKgyQai6qj3/KteNlrqDx4W5A==" - }, "@hapi/hoek": { - "version": "9.1.1", - "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.1.1.tgz", - "integrity": "sha512-CAEbWH7OIur6jEOzaai83jq3FmKmv4PmX1JYfs9IrYcGEVI/lyL1EXJGCj7eFVJ0bg5QR8LMxBlEtA+xKiLpFw==" - }, - "@hapi/joi": { - "version": "17.1.1", - "resolved": "https://registry.npmjs.org/@hapi/joi/-/joi-17.1.1.tgz", - "integrity": "sha512-p4DKeZAoeZW4g3u7ZeRo+vCDuSDgSvtsB/NpfjXEHTUjSeINAi/RrVOWiVQ1isaoLzMvFEhe8n5065mQq1AdQg==", - "requires": { - "@hapi/address": "^4.0.1", - "@hapi/formula": "^2.0.0", - "@hapi/hoek": "^9.0.0", - "@hapi/pinpoint": "^2.0.0", - "@hapi/topo": "^5.0.0" - } - }, - "@hapi/pinpoint": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@hapi/pinpoint/-/pinpoint-2.0.0.tgz", - "integrity": "sha512-vzXR5MY7n4XeIvLpfl3HtE3coZYO4raKXW766R6DZw/6aLqR26iuZ109K7a0NtF2Db0jxqh7xz2AxkUwpUFybw==" + "version": "9.2.0", + "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.2.0.tgz", + "integrity": "sha512-sqKVVVOe5ivCaXDWivIJYVSaEgdQK9ul7a4Kity5Iw7u9+wBAPbX1RMSnLLmp7O4Vzj0WOWwMAJsTL00xwaNug==" }, "@hapi/topo": { "version": "5.0.0", @@ -527,6 +511,20 @@ "aggregate-error": "^3.0.0", "fs-extra": "^9.0.0", "lodash": "^4.17.4" + }, + "dependencies": { + "fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dev": true, + "requires": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + } } }, "@semantic-release/commit-analyzer": { @@ -858,6 +856,24 @@ } } }, + "@sideway/address": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.2.tgz", + "integrity": "sha512-idTz8ibqWFrPU8kMirL0CoPH/A29XOzzAzpyN3zQ4kAWnzmNfFmRaoMNN6VI8ske5M73HZyhIaW4OuSFIdM4oA==", + "requires": { + "@hapi/hoek": "^9.0.0" + } + }, + "@sideway/formula": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@sideway/formula/-/formula-3.0.0.tgz", + "integrity": "sha512-vHe7wZ4NOXVfkoRb8T5otiENVlT7a3IAiw7H5M2+GO+9CDgcVUUsX1zalAztCmwyOr2RUTGJdgB+ZvSVqmdHmg==" + }, + "@sideway/pinpoint": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@sideway/pinpoint/-/pinpoint-2.0.0.tgz", + "integrity": "sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==" + }, "@tootallnate/once": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", @@ -870,6 +886,15 @@ "integrity": "sha512-rS27+EkB/RE1Iz3u0XtVL5q36MGDWbgYe7zWiodyKNUnthxY0rukK5V36eiUCtCisB7NN8zKYH6DO2M37qxFEQ==", "dev": true }, + "@types/fs-extra": { + "version": "9.0.11", + "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-9.0.11.tgz", + "integrity": "sha512-mZsifGG4QeQ7hlkhO56u7zt/ycBgGxSVsFI/6lGTU34VtwkiqrrSDgw0+ygs8kFGWcXnFQWMrzF2h7TtDFNixA==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, "@types/hapi__joi": { "version": "17.1.6", "resolved": "https://registry.npmjs.org/@types/hapi__joi/-/hapi__joi-17.1.6.tgz", @@ -2135,12 +2160,10 @@ } }, "fs-extra": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", - "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", - "dev": true, + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.0.0.tgz", + "integrity": "sha512-C5owb14u9eJwizKGdchcDUQeFtlSHHthBk8pbX9Vc1PFZrLombudjDnNns88aYslCyF6IY5SUw3Roz6xShcEIQ==", "requires": { - "at-least-node": "^1.0.0", "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", "universalify": "^2.0.0" @@ -2343,8 +2366,7 @@ "graceful-fs": { "version": "4.2.6", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.6.tgz", - "integrity": "sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ==", - "dev": true + "integrity": "sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ==" }, "growl": { "version": "1.10.5", @@ -2812,6 +2834,18 @@ "resolved": "https://registry.npmjs.org/jmespath/-/jmespath-0.15.0.tgz", "integrity": "sha1-o/Iiqarp+Wb10nx5ZRDigJF2Qhc=" }, + "joi": { + "version": "17.4.0", + "resolved": "https://registry.npmjs.org/joi/-/joi-17.4.0.tgz", + "integrity": "sha512-F4WiW2xaV6wc1jxete70Rw4V/VuMd6IN+a5ilZsxG4uYtUXWu2kq9W5P2dz30e7Gmw8RCbY/u/uk+dMPma9tAg==", + "requires": { + "@hapi/hoek": "^9.0.0", + "@hapi/topo": "^5.0.0", + "@sideway/address": "^4.1.0", + "@sideway/formula": "^3.0.0", + "@sideway/pinpoint": "^2.0.0" + } + }, "js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -2849,7 +2883,6 @@ "version": "6.1.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dev": true, "requires": { "graceful-fs": "^4.1.6", "universalify": "^2.0.0" @@ -6808,8 +6841,7 @@ "universalify": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", - "dev": true + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==" }, "url": { "version": "0.10.3", diff --git a/package.json b/package.json index fa95b3d4..a41cd444 100644 --- a/package.json +++ b/package.json @@ -33,6 +33,7 @@ "@semantic-release/git": "9.0.0", "@semantic-release/release-notes-generator": "9.0.3", "@types/chai": "4.2.18", + "@types/fs-extra": "^9.0.11", "@types/hapi__joi": "17.1.6", "@types/joi": "14.3.4", "@types/mocha": "8.2.2", @@ -49,8 +50,9 @@ "dependencies": { "@actions/core": "^1.2.6", "@actions/glob": "^0.2.0", - "@hapi/joi": "^17.1.1", - "aws-sdk": "^2.703.0" + "aws-sdk": "^2.703.0", + "fs-extra": "^10.0.0", + "joi": "^17.4.0" }, "config": { "commitizen": { diff --git a/src/index.ts b/src/index.ts index 4478b85c..c5688405 100644 --- a/src/index.ts +++ b/src/index.ts @@ -12,7 +12,7 @@ const processor = new Processor(); region: core.getInput("region"), table: core.getInput("table"), - // Get / Delete Operation + // Get / Delete / Update Operation key: forgivingJSONParse(core.getInput("key")), consistent: forgivingJSONParse(core.getInput("consistent")), @@ -23,6 +23,11 @@ const processor = new Processor(); // BatchPut Operation items: forgivingJSONParse(core.getInput("items")), files: core.getInput("files"), + + // Update Operation + updateExpression: core.getInput("updateExpression"), + expressionAttributeValues: core.getInput("expressionAttributeValues"), + expressionAttributeFiles: core.getInput("expressionAttributeFiles") }; const output = await processor.process(input); diff --git a/src/operations/batch-put.ts b/src/operations/batch-put.ts index 217bac4d..557e086b 100644 --- a/src/operations/batch-put.ts +++ b/src/operations/batch-put.ts @@ -1,5 +1,5 @@ import * as glob from "@actions/glob"; -import * as Joi from "@hapi/joi"; +import * as Joi from "joi"; import { promises as fs } from "fs"; import { createClient } from "../helpers"; import { Operation } from "./base"; diff --git a/src/operations/delete.ts b/src/operations/delete.ts index fb162f6c..7258a2bd 100644 --- a/src/operations/delete.ts +++ b/src/operations/delete.ts @@ -1,4 +1,4 @@ -import * as Joi from "@hapi/joi"; +import * as Joi from "joi"; import { createClient } from "../helpers"; import { Operation } from "./base"; diff --git a/src/operations/get.ts b/src/operations/get.ts index eec96bf0..ede7185d 100644 --- a/src/operations/get.ts +++ b/src/operations/get.ts @@ -1,4 +1,4 @@ -import * as Joi from "@hapi/joi"; +import * as Joi from "joi"; import { createClient } from "../helpers"; import { Operation } from "./base"; diff --git a/src/operations/index.ts b/src/operations/index.ts index 7e9d7930..fb92659d 100644 --- a/src/operations/index.ts +++ b/src/operations/index.ts @@ -4,3 +4,4 @@ export * from "./batch-put"; export * from "./delete"; export * from "./get"; export * from "./put"; +export * from "./update"; diff --git a/src/operations/put.ts b/src/operations/put.ts index d044ebc3..3dbd2bbc 100644 --- a/src/operations/put.ts +++ b/src/operations/put.ts @@ -1,4 +1,4 @@ -import * as Joi from "@hapi/joi"; +import * as Joi from "joi"; import { promises as fs } from "fs"; import { createClient } from "../helpers"; import { Operation } from "./base"; diff --git a/src/operations/update.ts b/src/operations/update.ts new file mode 100644 index 00000000..56aefe91 --- /dev/null +++ b/src/operations/update.ts @@ -0,0 +1,127 @@ +import * as Joi from "joi"; +import { promises as fs } from "fs"; +import { createClient } from "../helpers"; +import { Operation } from "./base"; + +const BaseInputSchema = Joi.object({ + operation: Joi.string().lowercase().valid("update").required(), + region: Joi.string().lowercase().required(), + table: Joi.string().required(), + updateExpression: Joi.string().required() +}); + +const InputSchema = Joi.alternatives([ + BaseInputSchema.append({ + expressionAttributeValues: Joi.string().required(), + key: Joi.object().required(), + }), + BaseInputSchema.append({ + expressionAttributeFiles: Joi.string().required(), + key: Joi.object().required(), + }), +]).required(); + +export type UpdateOperationInput = { + operation: "update"; + region: string; + table: string; + updateExpression: string; +} & ({ + expressionAttributeValues: string; + expressionAttributeFiles?: never; + key: { [key: string]: any }; +} | { + expressionAttributeValues?: never; + expressionAttributeFiles: string; + key: { [key: string]: any }; +}); + +export class UpdateOperation implements Operation { + public readonly name = "update"; + + public async validate(input: unknown): Promise { + const validationResult = InputSchema.validate(input, { + stripUnknown: true, + }); + if (validationResult.error) { + throw validationResult.error; + } + + return validationResult.value as UpdateOperationInput; + } + + public async execute(input: UpdateOperationInput) { + const ddb = createClient(input.region); + let updateExp = ``; + let attValues = {}; + + const expressions = await this.buildExpression(updateExp, input); + const attributes = await this.buildAttributes(expressions, attValues, input); + + console.log(expressions); + console.log(attributes); + + await ddb.update({ + TableName: input.table, + Key: input.key, + UpdateExpression: expressions, + ExpressionAttributeValues: attributes + }).promise(); + } + + private async read(path: string) { + const content = await fs.readFile(path, { encoding: "utf8" }); + + return JSON.parse(content); + } + + private async buildExpression(updateExp: string, input: UpdateOperationInput) { + const updateExpressions = input.updateExpression.split(','); + + for(let i=0; i 1) { + updateExp = `set ${updateExpressions[i]} = :${updateExpressions[i]},`; + } + else if(i===0 && updateExpressions.length === 1) { + updateExp = `set ${updateExpressions[i]} = :${updateExpressions[i]}`; + } + else if(i===updateExpressions.length-1) { + updateExp += ` ${updateExpressions[i]} = :${updateExpressions[i]}`; + } + else { + updateExp += ` ${updateExpressions[i]} = :${updateExpressions[i]},`; + } + } + + return updateExp; + } + + private async buildAttributes(updateExp: string, attValues: {}, input: UpdateOperationInput) { + const updateExpressions = updateExp.split(','); + + if(input.expressionAttributeValues) { + const expAttValues = input.expressionAttributeValues.split(', '); + const keyValues = []; + + for(let i=0; i[] = [ @@ -8,6 +8,7 @@ export class Processor { new DeleteOperation(), new GetOperation(), new PutOperation(), + new UpdateOperation() ]; public async process(input: {