Skip to content

Commit

Permalink
Remove bluebird and lodash (#21)
Browse files Browse the repository at this point in the history
  • Loading branch information
domdomegg authored Oct 15, 2023
1 parent 95d57d9 commit 2e5fae4
Show file tree
Hide file tree
Showing 4 changed files with 44 additions and 88 deletions.
41 changes: 18 additions & 23 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
"use strict";
const _ = require("lodash");
const AWS = require("aws-sdk");
const dynamodbLocal = require("aws-dynamodb-local");
const seeder = require("./src/seeder");
Expand All @@ -11,11 +10,10 @@ class ServerlessDynamodbLocal {
this.service = serverless.service;
this.serverlessLog = serverless.cli.log.bind(serverless.cli);
this.config = this.service.custom && this.service.custom['serverless-dynamodb'] || this.service.custom.dynamodb || {};
this.options = _.merge({
localPath: serverless.config && path.join(serverless.config.servicePath, '.dynamodb')
},
options
);
this.options = {
localPath: serverless.config && path.join(serverless.config.servicePath, '.dynamodb'),
...options,
};
this.provider = "aws";
this.commands = {
dynamodb: {
Expand Down Expand Up @@ -156,13 +154,11 @@ class ServerlessDynamodbLocal {
}

get port() {
const port = _.get(this.config, "start.port", 8000);
return port;
return this.config?.start?.port ?? 8000;
}

get host() {
const host = _.get(this.config, "start.host", "localhost");
return host;
return this.config?.start?.host ?? "localhost";
}

/**
Expand Down Expand Up @@ -254,13 +250,12 @@ class ServerlessDynamodbLocal {

startHandler() {
if (this.shouldExecute()) {
const options = _.merge({
sharedDb: this.options.sharedDb || true,
installPath: this.options.localPath
},
this.config.start,
this.options
);
const options = {
sharedDb: this.options.sharedDb ?? true,
installPath: this.options.localPath,
...this.config.start,
...this.options
}

// otherwise endHandler will be mis-informed
this.options = options;
Expand Down Expand Up @@ -288,19 +283,19 @@ class ServerlessDynamodbLocal {
}

getDefaultStack() {
return _.get(this.service, "resources");
return this.service.resources;
}

getAdditionalStacks() {
return _.values(_.get(this.service, "custom.additionalStacks", {}));
return Object.values(this.service.custom?.additionalStacks ?? {});
}

hasAdditionalStacksPlugin() {
return _.get(this.service, "plugins", []).includes("serverless-plugin-additional-stacks");
return (this.service.plugins ?? []).includes("serverless-plugin-additional-stacks");
}

getTableDefinitionsFromStack(stack) {
const resources = _.get(stack, "Resources", []);
const resources = stack.Resources ?? [];
return Object.keys(resources).map((key) => {
if (resources[key].Type === "AWS::DynamoDB::Table") {
return resources[key].Properties;
Expand All @@ -320,7 +315,7 @@ class ServerlessDynamodbLocal {
}

if (this.hasAdditionalStacksPlugin()) {
stacks = stacks.concat(this.getAdditionalStacks());
stacks.push(...this.getAdditionalStacks());
}

return stacks.map((stack) => this.getTableDefinitionsFromStack(stack)).reduce((tables, tablesInStack) => tables.concat(tablesInStack), []);
Expand All @@ -330,7 +325,7 @@ class ServerlessDynamodbLocal {
* Gets the seeding sources
*/
get seedSources() {
const seedConfig = _.get(this.config, "seed", {});
const seedConfig = this.config.seed ?? {};
const seed = this.options.seed || this.config.start.seed || seedConfig;
let categories;
if (typeof seed === "string") {
Expand Down
12 changes: 3 additions & 9 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 1 addition & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,7 @@
},
"dependencies": {
"aws-dynamodb-local": "^0.0.11",
"aws-sdk": "^2.7.0",
"bluebird": "^3.4.6",
"lodash": "^4.17.0"
"aws-sdk": "^2.7.0"
},
"devDependencies": {
"chai": "^4.1.1",
Expand Down
75 changes: 22 additions & 53 deletions src/seeder.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,11 @@
"use strict";
const BbPromise = require("bluebird");
const _ = require("lodash");
const path = require("path");
const fs = require("fs");
const path = require("node:path");
const fs = require("node:fs");

// DynamoDB has a 25 item limit in batch requests
// https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_BatchWriteItem.html
const MAX_MIGRATION_CHUNK = 25;

// TODO: let this be configurable
const MIGRATION_SEED_CONCURRENCY = 5;

/**
* Writes a batch chunk of migration seeds to DynamoDB. DynamoDB has a limit on the number of
* items that may be written in a batch operation.
Expand Down Expand Up @@ -67,59 +62,36 @@ function writeSeeds(dynamodbWriteFunction, tableName, seeds) {
}

if (seeds.length > 0) {
const seedChunks = _.chunk(seeds, MAX_MIGRATION_CHUNK);
return BbPromise.map(
seedChunks,
(chunk) => writeSeedBatch(dynamodbWriteFunction, tableName, chunk),
{ concurrency: MIGRATION_SEED_CONCURRENCY }
)
const seedChunks = chunk(seeds, MAX_MIGRATION_CHUNK);
return Promise.all(seedChunks.map((chunk) => writeSeedBatch(dynamodbWriteFunction, tableName, chunk)))
.then(() => console.log("Seed running complete for table: " + tableName));
}
}

/**
* A promise-based function that determines if a file exists
* @param {string} fileName The path to the file
*/
function fileExists(fileName) {
return new Promise((resolve) => {
fs.exists(fileName, (exists) => resolve(exists));
});
}

/**
* Transform all selerialized Buffer value in a Buffer value inside a json object
*
* @param {json} json with serialized Buffer value.
* @return {json} json with Buffer object.
*/
function unmarshalBuffer(json) {
_.forEach(json, function(value, key) {
// Null check to prevent creation of Buffer when value is null
if (value !== null && value.type==="Buffer") {
json[key]= new Buffer(value.data);
}
});
return json;
}
const chunk = (input, size) => {
return input.reduce((arr, item, idx) => {
return idx % size === 0
? [...arr, [item]]
: [...arr.slice(0, -1), [...arr.slice(-1)[0], item]];
}, []);
};

/**
* Scrapes seed files out of a given location. This file may contain
* either a simple json object, or an array of simple json objects. An array
* of json objects is returned.
*
* @param {any} location the filename to read seeds from.
* @param {string} location the filename to read seeds from.
* @returns {object[]} json
*/
function getSeedsAtLocation(location) {
// load the file as JSON
const result = require(location);

// Ensure the output is an array
if (Array.isArray(result)) {
return _.forEach(result, unmarshalBuffer);
} else {
return [ unmarshalBuffer(result) ];
}
const array = Array.isArray(result) ? result : [result];

return array;
}

/**
Expand All @@ -131,15 +103,12 @@ function locateSeeds(sources, cwd) {
cwd = cwd || process.cwd();

const locations = sources.map((source) => path.join(cwd, source));
return BbPromise.map(locations, (location) => {
return fileExists(location).then((exists) => {
if(!exists) {
throw new Error("source file " + location + " does not exist");
}
return getSeedsAtLocation(location);
});
// Smash the arrays together
}).then((seedArrays) => [].concat.apply([], seedArrays));
return locations.map((location) => {
if(!fs.existsSync(location)) {
throw new Error("source file " + location + " does not exist");
}
return getSeedsAtLocation(location);
}).flat(1);
}

module.exports = { writeSeeds, locateSeeds };

0 comments on commit 2e5fae4

Please sign in to comment.