Skip to content

Commit

Permalink
initial
Browse files Browse the repository at this point in the history
  • Loading branch information
nulldef committed Aug 18, 2020
0 parents commit 5797ed5
Show file tree
Hide file tree
Showing 10 changed files with 1,334 additions and 0 deletions.
1 change: 1 addition & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
node_modules/
10 changes: 10 additions & 0 deletions .eslintrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"parser": "babel-eslint",
"env": {
"node": true,
"es6": true
},
"rules": {
"quotes": ["error", "double"]
}
}
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
node_modules/
53 changes: 53 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# ucdn

Tool for uploading assets to AWS S3.

## Installation

```sh
$ yarn global add @umbrellio/ucdn
```

or

```sh
$ npm i -g @umbrellio/ucdn
```

## Usage

### Upload

```sh
$ ucdn upload -c /path/to/config/file.yaml -C production
```

## Options

All following options except `config` and `config-key` can be configured using the config file.

```
--config, -c path to config file
--config-key, -C root config key
--dir, -d assets directory
--bucket, -b AWS bucket for upload
--exclude, -e excluded extenstions
--accessKeyId, --access-key-id AWS access key ID
--secretAccessKey, --secret-access-key AWS secret access key
```

## Contributing

Bug reports and pull requests are welcome on GitHub at https://github.com/umbrellio/ucdn.

## License

Released under MIT License.

## Authors

Created by [Aleksei Bespalov](https://github.com/nulldef).

<a href="https://github.com/umbrellio/">
<img style="float: left;" src="https://umbrellio.github.io/Umbrellio/supported_by_umbrellio.svg" alt="Supported by Umbrellio" width="439" height="72">
</a>
5 changes: 5 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
const upload = require("./upload")

module.exports = {
upload,
}
23 changes: 23 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"name": "@umbrellio/ucdn",
"version": "0.1.0",
"bin": "ucdn",
"main": "index.js",
"repository": "git@github.com:umbrellio/ucdn.git",
"license": "MIT",
"author": "Aleksei Bespalov <nulldefiner@gmail.com>",
"homepage": "https://github.com/umbrellio/ucdn",
"scripts": {
"lint": "eslint ."
},
"dependencies": {
"aws-sdk": "^2.701.0",
"js-yaml": "^3.14.0",
"mime-types": "^2.1.27",
"yargs": "^15.3.1"
},
"devDependencies": {
"babel-eslint": "^10.1.0",
"eslint": "^7.3.0"
}
}
70 changes: 70 additions & 0 deletions ucdn
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
#!/usr/bin/env node

const yargs = require("yargs")

const pkg = require("./package")
const utils = require("./utils")
const upload = require("./upload")

const toDashCase = str => str.replace(/([A-Z])/g, (g) => `-${g[0].toLowerCase()}`);

yargs
.env("UCDN")
.command("upload", "upload assets to AWS S3", {}, upload)
.options({
config: {
alias: "c",
describe: "path to config file",
default: "./ucdn.yml",
type: "string",
},
dir: {
alias: "d",
describe: "assets directory",
default: "dist/",
type: "string",
},
bucket: {
alias: "b",
describe: "AWS bucket for upload",
type: "string",
default: null,
},
exclude: {
alias: "e",
describe: "excluded extenstions",
default: ["html", "gz"],
type: "array",
},
accessKeyId: {
alias: "access-key-id",
describe: "AWS access key ID",
type: "string",
demand: true,
},
secretAccessKey: {
alias: "secret-access-key",
describe: "AWS secret access key",
type: "string",
demand: true,
},
"config-key": {
alias: "C",
describe: "root config key",
}
})
.demandCommand(1)
.help()
.version(pkg.version)
.strict()
.middleware(argv => {
const config = utils.loadYamlFile(argv.config)
const configObject = argv.C ? (config[argv.C] || {}) : config

Object
.entries(configObject)
.filter(([_, value]) => value != null)
.forEach(([key, value]) => (argv[key] = argv[key] || value))

}, true)
.parse()
83 changes: 83 additions & 0 deletions upload.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
const fs = require("fs")
const path = require("path")
const mime = require("mime-types")
const AWS = require("aws-sdk")

const s3 = new AWS.S3()
const configDefaults = {
dir: null,
bucket: null,
exclude: [],
accessKeyId: null,
secretAccessKey: null,
}

const getConfig = passedConfig => {
const receivedConfig = passedConfig || {}
return { ...configDefaults, ...receivedConfig }
}

const findFiles = directory => {
const files = fs.readdirSync(directory, { withFileTypes: true })
return files.reduce((mem, file) => {
const filepath = path.join(directory, file.name)
return file.isDirectory()
? [...mem, ...findFiles(filepath) ]
: [...mem, filepath]
}, [])
}

const getKey = (file, root) => path.relative(root, file)

const uploadFile = (config, file, key) => new Promise((resolve, reject) => {
const { bucket } = config
const stream = fs.createReadStream(file)
const basename = path.basename(file)
const params = {
Bucket: bucket,
Body: stream,
Key: key,
ContentType: mime.contentType(basename),
}

stream.on("error", reject)
s3.upload(params, (err, data) => {
stream.close()
if (err) reject(err)
else resolve(data)
})
})

const upload = argv => {
const config = getConfig(argv)
const { accessKeyId, secretAccessKey, dir, exclude } = config

AWS.config.update({
accessKeyId: accessKeyId || "unknown",
secretAccessKey: secretAccessKey || "unknown",
})

const directory = path.resolve(dir)
const files = findFiles(directory).filter(x => {
const ext = path.extname(x).slice(1)
return !exclude.includes(ext)
})

const promises = files.map(file => {
const key = getKey(file, directory)
return uploadFile(config, file, key)
.then(data => console.log("Uploaded", data.Location))
})

return Promise.all(promises)
.then(() => {
console.log("Completed")
process.exit(0)
})
.catch(error => {
console.error(error)
process.exit(1)
})
}

module.exports = upload
16 changes: 16 additions & 0 deletions utils.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
const path = require("path")
const fs = require("fs")
const yaml = require("js-yaml")

const toDashCase = str => str.replace(/([A-Z])/g, (g) => `-${g[0].toLowerCase()}`);

const loadYamlFile = filePath => {
const configPath = path.resolve(filePath)
const content = fs.readFileSync(configPath)
return yaml.safeLoad(content)
}

module.exports = {
toDashCase,
loadYamlFile,
}
Loading

0 comments on commit 5797ed5

Please sign in to comment.