This repository has been archived by the owner on Oct 8, 2020. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdeploy
executable file
·125 lines (108 loc) · 2.8 KB
/
deploy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
#!/usr/bin/env node
'use strict'
const {
pipe, fork, assign, tap,
switchCase,
map,
and, not, gte,
get,
} = require('rubico')
const fs = require('fs').promises
const nodePath = require('path')
const execa = require('execa')
const identity = x => x
const trace = tap(console.log)
const slice = (...args) => x => x.slice(...args)
// process.argv => { bucketname, entrypoint }
const parseArgs = pipe([
slice(2),
switchCase([
gte(get('length'), 2), identity,
() => {
throw new Error('at least two arguments required')
},
]),
fork({
bucketname: get(0),
entrypoint: get(1),
}),
])
const ignoredExpressions = new Set([/.git/, /deploy/])
// dirent => boolean
const isIgnored = dirent => {
for (const re of ignoredExpressions) {
if (re.test(dirent.name)) return true
}
return false
}
// dirent => boolean
const isDirectory = dirent => dirent.isDirectory()
// entrypoint => filepaths
const walk = entrypoint => pipe([
entrypoint => fs.readdir(entrypoint, { withFileTypes: true }),
map(switchCase([
isIgnored, () => [],
isDirectory, pipe([
get('name'),
filename => nodePath.resolve(entrypoint, filename),
walk,
]),
pipe([
get('name'),
filename => nodePath.resolve(entrypoint, filename),
]),
])),
])(entrypoint)
const flattenAll = arr => arr.flat(Infinity)
const extensionContentTypeMap = new Map([
['.webmanifest', 'application/manifest+json'],
['.json', 'application/json'],
['.js', 'text/javascript'],
['.html', 'text/html'],
['.css', 'text/css'],
['.gif', 'image/gif'],
['.png', 'image/png'],
['.ico', 'image/x-icon'],
])
// filepath => contentType
const getContentType = pipe([
nodePath.parse,
get('ext'),
ext => extensionContentTypeMap.get(ext) || 'text/plain',
])
// (entrypoint, filepath) => bucket_key
const toS3Key = (entrypoint, filepath) => (
filepath.replace(`${nodePath.resolve(entrypoint)}/`, '')
)
// https://stackoverflow.com/questions/29643455/how-do-i-set-content-type-when-uploading-to-s3-with-aws-cli
const main = pipe([
parseArgs,
assign({
filepaths: pipe([
get('entrypoint'),
walk,
flattenAll,
]),
}),
({ entrypoint, bucketname, filepaths }) => map(pipe([
tap(filepath => console.log(
'uploading', filepath, '->',
`${bucketname}/${toS3Key(entrypoint, filepath)}`,
)),
filepath => [
's3api', 'put-object',
'--bucket', bucketname,
'--key', toS3Key(entrypoint, filepath),
'--body', filepath,
'--content-type', getContentType(filepath),
'--acl', 'public-read',
],
args => execa('aws', args),
]))(filepaths),
tap(() => console.log('done')),
])
if (process.argv.includes('-h') || process.argv.includes('--help')) {
console.log('usage: ./deploy <bucket> <entrypoint>')
process.exit(0)
}
main(process.argv)