@tremho/mist-lift 1.0.2-pre-release.4 → 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +12 -0
- package/build/commands/actions/initQuestions.js +24 -22
- package/build/commands/actions/initQuestions.js.map +1 -1
- package/build/commands/actions/setupPackageJson.js +4 -4
- package/build/commands/actions/setupPackageJson.js.map +1 -1
- package/build/commands/build.js +31 -25
- package/build/commands/build.js.map +1 -1
- package/build/commands/builtin/ApiDocMaker.js +60 -23
- package/build/commands/builtin/ApiDocMaker.js.map +1 -1
- package/build/commands/builtin/BuiltInHandler.js +6 -6
- package/build/commands/builtin/BuiltInHandler.js.map +1 -1
- package/build/commands/builtin/DeployBuiltInZip.js +4 -4
- package/build/commands/builtin/DeployBuiltInZip.js.map +1 -1
- package/build/commands/builtin/StageWebrootZip.js +1 -0
- package/build/commands/builtin/StageWebrootZip.js.map +1 -1
- package/build/commands/create.js +10 -11
- package/build/commands/create.js.map +1 -1
- package/build/commands/deploy.js +38 -42
- package/build/commands/deploy.js.map +1 -1
- package/build/commands/doctor.js +38 -37
- package/build/commands/doctor.js.map +1 -1
- package/build/commands/help.js +93 -93
- package/build/commands/help.js.map +1 -1
- package/build/commands/init.js +7 -7
- package/build/commands/init.js.map +1 -1
- package/build/commands/package.js +50 -51
- package/build/commands/package.js.map +1 -1
- package/build/commands/publish.js +98 -102
- package/build/commands/publish.js.map +1 -1
- package/build/commands/settings.js +19 -18
- package/build/commands/settings.js.map +1 -1
- package/build/commands/start.js +4 -4
- package/build/commands/start.js.map +1 -1
- package/build/commands/test.js +3 -3
- package/build/commands/test.js.map +1 -1
- package/build/commands/user.js +1 -1
- package/build/commands/user.js.map +1 -1
- package/build/expressRoutes/all.js +27 -26
- package/build/expressRoutes/all.js.map +1 -1
- package/build/expressRoutes/api.js +9 -7
- package/build/expressRoutes/api.js.map +1 -1
- package/build/expressRoutes/functionBinder.js +38 -36
- package/build/expressRoutes/functionBinder.js.map +1 -1
- package/build/lib/CaseUtils.js +2 -2
- package/build/lib/CaseUtils.js.map +1 -1
- package/build/lib/DirectoryUtils.js +4 -3
- package/build/lib/DirectoryUtils.js.map +1 -1
- package/build/lib/LiftConfig.js +18 -20
- package/build/lib/LiftConfig.js.map +1 -1
- package/build/lib/LiftVersion.js +17 -12
- package/build/lib/LiftVersion.js.map +1 -1
- package/build/lib/Tests/fileCompare.test.js +11 -10
- package/build/lib/Tests/fileCompare.test.js.map +1 -1
- package/build/lib/askQuestion.js +3 -2
- package/build/lib/askQuestion.js.map +1 -1
- package/build/lib/executeCommand.js +46 -33
- package/build/lib/executeCommand.js.map +1 -1
- package/build/lib/fileCompare.js +9 -8
- package/build/lib/fileCompare.js.map +1 -1
- package/build/lib/openAPI/ApiBuildCollector.js +9 -8
- package/build/lib/openAPI/ApiBuildCollector.js.map +1 -1
- package/build/lib/openAPI/WebrootFileSupport.js +4 -3
- package/build/lib/openAPI/WebrootFileSupport.js.map +1 -1
- package/build/lib/openAPI/openApiConstruction.js +62 -61
- package/build/lib/openAPI/openApiConstruction.js.map +1 -1
- package/build/lib/pathResolve.js +4 -4
- package/build/lib/pathResolve.js.map +1 -1
- package/build/lib/utils.js +5 -4
- package/build/lib/utils.js.map +1 -1
- package/build/lift.js +14 -15
- package/build/lift.js.map +1 -1
- package/package.json +2 -1
- package/src/commands/actions/initQuestions.ts +112 -112
- package/src/commands/actions/setupPackageJson.ts +21 -25
- package/src/commands/build.ts +143 -146
- package/src/commands/builtin/ApiDocMaker.ts +86 -54
- package/src/commands/builtin/BuiltInHandler.ts +31 -35
- package/src/commands/builtin/DeployBuiltInZip.ts +15 -17
- package/src/commands/builtin/StageWebrootZip.ts +29 -32
- package/src/commands/create.ts +40 -47
- package/src/commands/deploy.ts +139 -152
- package/src/commands/doctor.ts +86 -82
- package/src/commands/help.ts +152 -153
- package/src/commands/init.ts +37 -39
- package/src/commands/package.ts +201 -204
- package/src/commands/publish.ts +277 -312
- package/src/commands/settings.ts +67 -70
- package/src/commands/start.ts +32 -37
- package/src/commands/test.ts +15 -16
- package/src/commands/user.ts +1 -1
- package/src/expressRoutes/all.ts +73 -78
- package/src/expressRoutes/api.ts +14 -16
- package/src/expressRoutes/functionBinder.ts +144 -151
- package/src/lib/CaseUtils.ts +49 -54
- package/src/lib/DirectoryUtils.ts +25 -27
- package/src/lib/LiftConfig.ts +46 -54
- package/src/lib/LiftVersion.ts +69 -77
- package/src/lib/Tests/fileCompare.test.ts +27 -26
- package/src/lib/askQuestion.ts +12 -13
- package/src/lib/executeCommand.ts +40 -33
- package/src/lib/fileCompare.ts +46 -37
- package/src/lib/openAPI/ApiBuildCollector.ts +36 -36
- package/src/lib/openAPI/WebrootFileSupport.ts +15 -17
- package/src/lib/openAPI/openApiConstruction.ts +169 -175
- package/src/lib/pathResolve.ts +22 -28
- package/src/lib/utils.ts +31 -33
- package/src/lift.ts +68 -67
|
@@ -1,169 +1,162 @@
|
|
|
1
|
-
|
|
2
|
-
import
|
|
3
|
-
|
|
4
|
-
const clearModule = require('clear-module')
|
|
5
|
-
|
|
6
|
-
import * as ac from "ansi-colors"
|
|
7
|
-
import {resolvePaths} from "../lib/pathResolve";
|
|
8
|
-
import {GetWebrootServePaths} from "../lib/openAPI/WebrootFileSupport"
|
|
9
|
-
import {doBuildAsync} from "../commands/build"
|
|
1
|
+
/* eslint @typescript-eslint/no-var-requires: "off" */
|
|
2
|
+
import path from 'path'
|
|
10
3
|
|
|
4
|
+
import * as ac from 'ansi-colors'
|
|
5
|
+
import { resolvePaths } from '../lib/pathResolve'
|
|
11
6
|
|
|
12
7
|
import express from 'express'
|
|
13
|
-
import {gatherFunctionDefinitions} from
|
|
14
|
-
import {buildOpenApi} from
|
|
15
|
-
const router = express.Router();
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
export function functionBinder() {
|
|
19
|
-
const defs = gatherFunctionDefinitions();
|
|
20
|
-
buildOpenApi(defs).then(() => { // creates apidoc.yaml for when /api is run
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
const projectPaths = resolvePaths();
|
|
8
|
+
import { gatherFunctionDefinitions } from '../lib/openAPI/ApiBuildCollector'
|
|
9
|
+
import { buildOpenApi } from '../lib/openAPI/openApiConstruction'
|
|
24
10
|
|
|
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
|
-
} else if (method === 'delete') {
|
|
61
|
-
router.delete(entryRoot, (req, res) => callNoBody(pathMap, req, res))
|
|
62
|
-
} else {
|
|
63
|
-
console.log(ac.red.bold("Cannot map method ") + ac.blue.bold(method))
|
|
64
|
-
}
|
|
11
|
+
// import * as clearModule from 'clear-module'
|
|
12
|
+
const clearModule = require('clear-module')
|
|
13
|
+
const router = express.Router()
|
|
14
|
+
|
|
15
|
+
export function functionBinder (): void {
|
|
16
|
+
const defs = gatherFunctionDefinitions()
|
|
17
|
+
buildOpenApi(defs).then(() => { // creates apidoc.yaml for when /api is run
|
|
18
|
+
const projectPaths = resolvePaths()
|
|
19
|
+
|
|
20
|
+
for (const def of defs) {
|
|
21
|
+
const { name, pathMap, allowedMethods } = def
|
|
22
|
+
const methods = allowedMethods.split(',')
|
|
23
|
+
for (let method of methods) {
|
|
24
|
+
method = method.trim().toLowerCase()
|
|
25
|
+
const rpath = path.join(projectPaths.buildPath, 'functions', name, 'src', 'main.js')
|
|
26
|
+
clearModule(rpath)
|
|
27
|
+
const { start } = require(rpath)
|
|
28
|
+
|
|
29
|
+
let entryRoot: string = pathMap
|
|
30
|
+
const n = entryRoot.indexOf('/{')
|
|
31
|
+
if (n !== -1) entryRoot = entryRoot.substring(0, n) + '/*'
|
|
32
|
+
|
|
33
|
+
const callNoBody = (pathMap: string, req: any, res: any): void => {
|
|
34
|
+
const event = requestToEvent(pathMap, req)
|
|
35
|
+
Promise.resolve(start(event, null, null)).then(respOut => {
|
|
36
|
+
handleResponse(res, respOut)
|
|
37
|
+
}).catch<any>((reason: any) => undefined)
|
|
38
|
+
}
|
|
39
|
+
const callWithBody = (pathMap: string, req: any, res: any): void => {
|
|
40
|
+
const event = requestToEvent(pathMap, req)
|
|
41
|
+
event.body = req.body
|
|
42
|
+
Promise.resolve(start(event, null, null)).then(respOut => {
|
|
43
|
+
handleResponse(res, respOut)
|
|
44
|
+
}).catch<any>((reason: any) => undefined)
|
|
45
|
+
}
|
|
65
46
|
|
|
66
|
-
|
|
47
|
+
if (method === 'get') {
|
|
48
|
+
router.get(entryRoot, (req, res) => callNoBody(pathMap, req, res))
|
|
49
|
+
} else if (method === 'post') {
|
|
50
|
+
router.get(entryRoot, (req, res) => callWithBody(pathMap, req, res))
|
|
51
|
+
} else if (method === 'put') {
|
|
52
|
+
router.put(entryRoot, (req, res) => callWithBody(pathMap, req, res))
|
|
53
|
+
} else if (method === 'patch') {
|
|
54
|
+
router.patch(entryRoot, (req, res) => callWithBody(pathMap, req, res))
|
|
55
|
+
} else if (method === 'delete') {
|
|
56
|
+
router.delete(entryRoot, (req, res) => callNoBody(pathMap, req, res))
|
|
57
|
+
} else {
|
|
58
|
+
console.log(ac.red.bold('Cannot map method ') + ac.blue.bold(method))
|
|
67
59
|
}
|
|
68
|
-
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}).catch<any>((reason: any) => undefined)
|
|
69
63
|
}
|
|
70
64
|
|
|
71
|
-
function requestToEvent(template:string, req:any) {
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
}
|
|
86
|
-
if(!host) {
|
|
87
|
-
// todo: http or https?
|
|
88
|
-
host = "http://"+req.headers?.host ?? "";
|
|
89
|
-
}
|
|
65
|
+
function requestToEvent (template: string, req: any): any {
|
|
66
|
+
let path: string = req.originalUrl ?? ''
|
|
67
|
+
const qi = path.indexOf('?')
|
|
68
|
+
if (qi !== -1) path = path.substring(0, qi)
|
|
69
|
+
const ptci: number = path.indexOf('://') + 3
|
|
70
|
+
const ei: number = path.indexOf('/', ptci)
|
|
71
|
+
let host: string = path.substring(0, ei)
|
|
72
|
+
if (ptci < 3) {
|
|
73
|
+
host = req.headers?.origin ?? ''
|
|
74
|
+
if (host !== '') {
|
|
75
|
+
host = req.headers?.referer ?? ''
|
|
76
|
+
const ptci: number = path.indexOf('://') + 3
|
|
77
|
+
const ei: number = path.indexOf('/', ptci)
|
|
78
|
+
host = ptci > 3 ? path.substring(0, ei) : ''
|
|
90
79
|
}
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
for(let c of crumbs) {
|
|
95
|
-
const pair:string[] = c.split('=');
|
|
96
|
-
if(pair.length === 2) cookies[pair[0]] = pair[1]
|
|
80
|
+
if (host !== '') {
|
|
81
|
+
// todo: http or https?
|
|
82
|
+
host = `http://${(req.headers?.host as string | undefined) ?? ''}`
|
|
97
83
|
}
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
84
|
+
}
|
|
85
|
+
const cookies: any = {}
|
|
86
|
+
const cookieString = req.headers?.cookie ?? ''
|
|
87
|
+
const crumbs = cookieString.split(';')
|
|
88
|
+
for (const c of crumbs) {
|
|
89
|
+
const pair: string[] = c.split('=')
|
|
90
|
+
if (pair.length === 2) cookies[pair[0]] = pair[1]
|
|
91
|
+
}
|
|
92
|
+
const parameters: any = {}
|
|
93
|
+
const tslots = template.split('/')
|
|
94
|
+
const pslots = path.split('/')
|
|
95
|
+
for (let i = 0; i < tslots.length; i++) {
|
|
96
|
+
const brknm = (tslots[i] ?? '').trim()
|
|
97
|
+
if (brknm.charAt(0) === '{') {
|
|
98
|
+
const pn = brknm.substring(1, brknm.length - 1)
|
|
99
|
+
parameters[pn] = (pslots[i] ?? '').trim()
|
|
107
100
|
}
|
|
108
|
-
|
|
109
|
-
|
|
101
|
+
}
|
|
102
|
+
for (const p of Object.getOwnPropertyNames(req.query)) {
|
|
103
|
+
parameters[p] = req.query[p]
|
|
104
|
+
}
|
|
105
|
+
const eventOut: any = {
|
|
106
|
+
requestContext: req,
|
|
107
|
+
request: {
|
|
108
|
+
originalUrl: host + (req.originalUrl as string),
|
|
109
|
+
headers: req.headers
|
|
110
|
+
},
|
|
111
|
+
cookies,
|
|
112
|
+
parameters
|
|
113
|
+
}
|
|
114
|
+
return eventOut
|
|
115
|
+
}
|
|
116
|
+
function handleResponse (res: any, resp: any): void {
|
|
117
|
+
// console.log(">>>>>>>> Handling response >>>>>>>>>")
|
|
118
|
+
|
|
119
|
+
if (resp !== undefined) {
|
|
120
|
+
if (resp.cookies !== undefined) {
|
|
121
|
+
// console.log("--- see cookies", resp.cookies)
|
|
122
|
+
let cookies: any = []
|
|
123
|
+
if (Array.isArray(resp.cookies)) {
|
|
124
|
+
cookies = resp.cookies
|
|
125
|
+
} else {
|
|
126
|
+
const age: number = resp.cookies.expireSeconds ?? 60 // 1 minute
|
|
127
|
+
delete resp.expireSeconds
|
|
128
|
+
Object.getOwnPropertyNames(resp.cookies).forEach(name => {
|
|
129
|
+
const value: string = resp.cookies[name]
|
|
130
|
+
cookies.push(`${name}=${value}; Max-Age=${age}; `)
|
|
131
|
+
})
|
|
132
|
+
}
|
|
133
|
+
// console.log("cookies being set", cookies)
|
|
134
|
+
res.setHeader('set-cookie', cookies)
|
|
135
|
+
delete resp.cookies
|
|
110
136
|
}
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
137
|
+
if (resp.headers !== undefined) {
|
|
138
|
+
// if (resp.statusCode === 301) ClogTrace("Redirecting...");
|
|
139
|
+
for (const hdr of Object.getOwnPropertyNames(resp.headers)) {
|
|
140
|
+
// ClogTrace("Setting header ", hdr, resp.headers[hdr]);
|
|
141
|
+
res.setHeader(hdr, resp.headers[hdr])
|
|
142
|
+
}
|
|
143
|
+
delete resp.headers
|
|
144
|
+
// console.log("past setting headers");
|
|
145
|
+
}
|
|
146
|
+
if (resp.statusCode !== undefined) {
|
|
147
|
+
res.statusCode = resp.statusCode
|
|
148
|
+
delete resp.statusCode
|
|
119
149
|
}
|
|
120
|
-
return eventOut;
|
|
121
|
-
}
|
|
122
|
-
function handleResponse(res:any, resp:any)
|
|
123
|
-
{
|
|
124
|
-
// console.log(">>>>>>>> Handling response >>>>>>>>>")
|
|
125
|
-
|
|
126
|
-
if(resp) {
|
|
127
|
-
if (resp.cookies !== undefined) {
|
|
128
|
-
// console.log("--- see cookies", resp.cookies)
|
|
129
|
-
var cookies:any = []
|
|
130
|
-
if(Array.isArray(resp.cookies)) {
|
|
131
|
-
cookies = resp.cookies
|
|
132
|
-
} else {
|
|
133
|
-
var age = resp.cookies.expireSeconds ?? 60; // 1 minute
|
|
134
|
-
delete resp.expireSeconds;
|
|
135
|
-
Object.getOwnPropertyNames(resp.cookies).forEach(name => {
|
|
136
|
-
var value = resp.cookies[name];
|
|
137
|
-
cookies.push(`${name}=${value}; Max-Age=${age}; `);
|
|
138
|
-
})
|
|
139
|
-
}
|
|
140
|
-
// console.log("cookies being set", cookies)
|
|
141
|
-
res.setHeader("set-cookie", cookies);
|
|
142
|
-
delete resp.cookies;
|
|
143
|
-
}
|
|
144
|
-
if (resp.headers !== undefined) {
|
|
145
|
-
// if (resp.statusCode === 301) ClogTrace("Redirecting...");
|
|
146
|
-
for (var hdr of Object.getOwnPropertyNames(resp.headers)) {
|
|
147
|
-
// ClogTrace("Setting header ", hdr, resp.headers[hdr]);
|
|
148
|
-
res.setHeader(hdr, resp.headers[hdr])
|
|
149
|
-
}
|
|
150
|
-
delete resp.headers;
|
|
151
|
-
// console.log("past setting headers");
|
|
152
|
-
}
|
|
153
|
-
if (resp.statusCode !== undefined) {
|
|
154
|
-
res.statusCode = resp.statusCode;
|
|
155
|
-
delete resp.statusCode
|
|
156
|
-
}
|
|
157
150
|
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
}
|
|
162
|
-
if(resp.body) resp = resp.body;
|
|
151
|
+
if (resp.contentType !== undefined) {
|
|
152
|
+
res.setHeader('Content-Type', resp.contentType)
|
|
153
|
+
delete resp.contentType
|
|
163
154
|
}
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
155
|
+
if (resp.body !== undefined) resp = resp.body
|
|
156
|
+
}
|
|
157
|
+
// console.log("headers to be sent", res.getHeaders())
|
|
158
|
+
// console.log("-- Sending response", resp)
|
|
159
|
+
res.send(resp)
|
|
167
160
|
}
|
|
168
161
|
|
|
169
162
|
export default router
|
package/src/lib/CaseUtils.ts
CHANGED
|
@@ -1,68 +1,63 @@
|
|
|
1
1
|
|
|
2
2
|
// separate a case-joined string into a string of space-separated words
|
|
3
|
-
export function separated(
|
|
4
|
-
|
|
5
|
-
):string
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
outstr += ' ';
|
|
12
|
-
}
|
|
13
|
-
outstr += c.toLowerCase();
|
|
3
|
+
export function separated (
|
|
4
|
+
instr: string
|
|
5
|
+
): string {
|
|
6
|
+
let outstr = ''
|
|
7
|
+
for (let i = 0; i < instr.length; i++) {
|
|
8
|
+
const c = instr.charAt(i)
|
|
9
|
+
if (!isAlphaNum(c) || isUpperCase(c)) {
|
|
10
|
+
outstr += ' '
|
|
14
11
|
}
|
|
12
|
+
outstr += c.toLowerCase()
|
|
13
|
+
}
|
|
15
14
|
|
|
16
|
-
|
|
15
|
+
return outstr.trim()
|
|
17
16
|
}
|
|
18
17
|
|
|
19
|
-
function isUpperCase(instr:string) {
|
|
20
|
-
|
|
18
|
+
function isUpperCase (instr: string): boolean {
|
|
19
|
+
return instr?.toUpperCase() === instr
|
|
21
20
|
}
|
|
22
|
-
function isAlphaNum(char:string) {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
21
|
+
function isAlphaNum (char: string): boolean {
|
|
22
|
+
let alnum = false
|
|
23
|
+
const cc = char.toUpperCase().charCodeAt(0)
|
|
24
|
+
if (cc >= 'A'.charCodeAt(0) && cc <= 'Z'.charCodeAt(0)) alnum = true
|
|
25
|
+
if (cc >= '0'.charCodeAt(0) && cc <= '9'.charCodeAt(0)) alnum = true
|
|
26
|
+
return alnum
|
|
28
27
|
}
|
|
29
28
|
|
|
30
|
-
export function camelCase(
|
|
31
|
-
|
|
32
|
-
):string
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
return seps.join('')
|
|
29
|
+
export function camelCase (
|
|
30
|
+
instr: string
|
|
31
|
+
): string {
|
|
32
|
+
const seps = separated(instr).split(' ')
|
|
33
|
+
for (let i = 1; i < seps.length; i++) {
|
|
34
|
+
seps[i] = seps[i].charAt(0).toUpperCase() + seps[i].substring(1)
|
|
35
|
+
}
|
|
36
|
+
return seps.join('')
|
|
39
37
|
}
|
|
40
38
|
|
|
41
|
-
export function pascalCase(
|
|
42
|
-
|
|
43
|
-
):string
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
return seps.join('')
|
|
39
|
+
export function pascalCase (
|
|
40
|
+
instr: string
|
|
41
|
+
): string {
|
|
42
|
+
const seps = separated(instr).split(' ')
|
|
43
|
+
for (let i = 0; i < seps.length; i++) {
|
|
44
|
+
seps[i] = seps[i].charAt(0).toUpperCase() + seps[i].substring(1)
|
|
45
|
+
}
|
|
46
|
+
return seps.join('')
|
|
50
47
|
}
|
|
51
48
|
|
|
52
|
-
export function snakeCase(
|
|
53
|
-
|
|
54
|
-
):string
|
|
55
|
-
|
|
56
|
-
|
|
49
|
+
export function snakeCase (
|
|
50
|
+
instr: string
|
|
51
|
+
): string {
|
|
52
|
+
return dashCase(instr, '_')
|
|
53
|
+
}
|
|
54
|
+
export function dashCase (
|
|
55
|
+
instr: string,
|
|
56
|
+
dashChar: string = '-',
|
|
57
|
+
allCaps: boolean = false
|
|
58
|
+
): string {
|
|
59
|
+
const seps = separated(instr).split(' ')
|
|
60
|
+
let out = seps.join(dashChar)
|
|
61
|
+
if (allCaps) out = out.toUpperCase()
|
|
62
|
+
return out
|
|
57
63
|
}
|
|
58
|
-
export function dashCase(
|
|
59
|
-
instr:string,
|
|
60
|
-
dashChar: string = '-',
|
|
61
|
-
allCaps: boolean = false
|
|
62
|
-
):string
|
|
63
|
-
{
|
|
64
|
-
const seps = separated(instr).split(' ')
|
|
65
|
-
let out = seps.join(dashChar)
|
|
66
|
-
if(allCaps) out = out.toUpperCase();
|
|
67
|
-
return out;
|
|
68
|
-
}
|
|
@@ -1,36 +1,34 @@
|
|
|
1
1
|
|
|
2
|
-
import fs from 'fs'
|
|
3
|
-
import {Stats} from 'fs'
|
|
2
|
+
import fs, { Stats } from 'fs'
|
|
4
3
|
import path from 'path'
|
|
5
4
|
|
|
6
5
|
// Callback definition for recurseDirectory
|
|
7
|
-
export
|
|
8
|
-
(filepath: string, stats: Stats): boolean|void;
|
|
9
|
-
}
|
|
6
|
+
export type RecurseCB = (filepath: string, stats: Stats) => boolean
|
|
10
7
|
|
|
11
8
|
// Recurse a directory, calling back to a 'for-each' callback for all files in tree
|
|
12
|
-
export function recurseDirectory(dirpath:string, callback
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
9
|
+
export function recurseDirectory (dirpath: string, callback?: RecurseCB): void {
|
|
10
|
+
fs.readdirSync(dirpath).forEach((file: string) => {
|
|
11
|
+
const fpath = path.join(dirpath, file)
|
|
12
|
+
const stat = fs.lstatSync(fpath)
|
|
13
|
+
if ((callback != null) && !callback(fpath, stat)) {
|
|
14
|
+
if (stat.isDirectory()) {
|
|
15
|
+
recurseDirectory(fpath, callback)
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
})
|
|
22
19
|
}
|
|
23
20
|
|
|
24
21
|
// find the latest mod time for matching files in this folder tree
|
|
25
|
-
export function latestModification(dirpath:string, match:string) {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
|
|
22
|
+
export function latestModification (dirpath: string, match: string): Date {
|
|
23
|
+
let latestTime = new Date(0)
|
|
24
|
+
if (fs.existsSync(dirpath)) {
|
|
25
|
+
recurseDirectory(dirpath, (filepath: string, stats: Stats) => {
|
|
26
|
+
const basefile = filepath.substring(filepath.lastIndexOf('/') + 1)
|
|
27
|
+
if (basefile.match(match) != null) {
|
|
28
|
+
if (stats.mtime > latestTime) latestTime = stats.mtime
|
|
29
|
+
}
|
|
30
|
+
return false
|
|
31
|
+
})
|
|
32
|
+
}
|
|
33
|
+
return latestTime
|
|
34
|
+
}
|
package/src/lib/LiftConfig.ts
CHANGED
|
@@ -1,58 +1,55 @@
|
|
|
1
1
|
// configuration for setting cloud provider credentials
|
|
2
2
|
// may expand later for other MistLift settings/preferences
|
|
3
3
|
|
|
4
|
-
import path from
|
|
5
|
-
import fs from
|
|
6
|
-
import
|
|
4
|
+
import path from 'path'
|
|
5
|
+
import fs from 'fs'
|
|
6
|
+
import { fromIni } from '@aws-sdk/credential-providers'
|
|
7
7
|
|
|
8
|
-
let
|
|
8
|
+
let sLiftConfigLoaded: LiftConfig | null = null
|
|
9
9
|
|
|
10
10
|
// Defines the structure of the .mistlft json file
|
|
11
11
|
// All relevant configuration for the cloud host goes here
|
|
12
12
|
export class LiftConfig {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
13
|
+
public cloudHost: string = 'AWS' // all we support now
|
|
14
|
+
public awsIniProfile?: string
|
|
15
|
+
public awsPreferredRegion?: string
|
|
16
|
+
public awsNodeRuntime?: RuntimeType
|
|
17
|
+
public awsServiceRoleARN?: string
|
|
18
18
|
}
|
|
19
|
-
export type RuntimeType =
|
|
19
|
+
export type RuntimeType = 'nodejs' | 'nodejs4.3' | 'nodejs6.10' | 'nodejs8.10' | 'nodejs10.x' | 'nodejs12.x' | 'nodejs14.x' | 'nodejs16.x' | 'java8' | 'java8.al2' | 'java11' | 'python2.7' | 'python3.6' | 'python3.7' | 'python3.8' | 'python3.9' | 'dotnetcore1.0' | 'dotnetcore2.0' | 'dotnetcore2.1' | 'dotnetcore3.1' | 'dotnet6' | 'dotnet8' | 'nodejs4.3-edge' | 'go1.x' | 'ruby2.5' | 'ruby2.7' | 'provided' | 'provided.al2' | 'nodejs18.x' | 'python3.10' | 'java17' | 'ruby3.2' | 'ruby3.3' | 'python3.11' | 'nodejs20.x' | 'provided.al2023' | 'python3.12' | 'java21'
|
|
20
20
|
|
|
21
21
|
// Available for general use because, why not?
|
|
22
|
-
export function getUserHome() {
|
|
23
|
-
|
|
22
|
+
export function getUserHome (): string {
|
|
23
|
+
return process.env.HOME ?? process.env.HOMEPATH ?? process.env.USERPROFILE ?? '~'
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
-
export function LoadLiftConfig()
|
|
27
|
-
{
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
//
|
|
38
|
-
}
|
|
39
|
-
}
|
|
26
|
+
export function LoadLiftConfig (): LiftConfig | null {
|
|
27
|
+
if (sLiftConfigLoaded == null) {
|
|
28
|
+
const mistlift = path.join(getUserHome(), '.mistlift')
|
|
29
|
+
let configJson = '{}'
|
|
30
|
+
if (fs.existsSync(mistlift)) {
|
|
31
|
+
try {
|
|
32
|
+
configJson = fs.readFileSync(mistlift).toString()
|
|
33
|
+
sLiftConfigLoaded = JSON.parse(configJson)
|
|
34
|
+
} catch (e: any) {
|
|
35
|
+
//
|
|
36
|
+
}
|
|
40
37
|
}
|
|
41
|
-
|
|
38
|
+
}
|
|
39
|
+
return sLiftConfigLoaded
|
|
42
40
|
}
|
|
43
|
-
export function resetLiftConfig()
|
|
44
|
-
|
|
45
|
-
s_liftConfigLoaded = null;
|
|
41
|
+
export function resetLiftConfig (): void {
|
|
42
|
+
sLiftConfigLoaded = null
|
|
46
43
|
}
|
|
47
44
|
|
|
48
|
-
export function areSettingsAvailable():boolean {
|
|
49
|
-
|
|
50
|
-
|
|
45
|
+
export function areSettingsAvailable (): boolean {
|
|
46
|
+
const mistlift = path.join(getUserHome(), '.mistlift')
|
|
47
|
+
return fs.existsSync(mistlift)
|
|
51
48
|
}
|
|
52
49
|
|
|
53
|
-
export function getSettings()
|
|
54
|
-
|
|
55
|
-
|
|
50
|
+
export function getSettings (): LiftConfig {
|
|
51
|
+
if (sLiftConfigLoaded == null) LoadLiftConfig()
|
|
52
|
+
return sLiftConfigLoaded as LiftConfig
|
|
56
53
|
}
|
|
57
54
|
|
|
58
55
|
/**
|
|
@@ -61,22 +58,17 @@ export function getSettings() : LiftConfig {
|
|
|
61
58
|
* We will use the standard .aws config ini file, looked up by profile or default
|
|
62
59
|
* Prior attempts to have it do more than this failed, and resulted in a default profile choice anyway.
|
|
63
60
|
*/
|
|
64
|
-
export function getAWSCredentials()
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
if(profile) {
|
|
78
|
-
credentials = fromIni({profile})
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
return credentials;
|
|
61
|
+
export function getAWSCredentials (): any {
|
|
62
|
+
let config = LoadLiftConfig()
|
|
63
|
+
if (config == null) {
|
|
64
|
+
// console.error("No .mistlift configuration found - using AWS default profile");
|
|
65
|
+
config = { cloudHost: 'AWS', awsIniProfile: 'default' }
|
|
66
|
+
}
|
|
67
|
+
if (config.cloudHost?.toUpperCase() !== 'AWS') {
|
|
68
|
+
throw Error('HostType Not Supported')
|
|
69
|
+
}
|
|
70
|
+
let credentials = {}
|
|
71
|
+
const profile = config.awsIniProfile ?? 'default'
|
|
72
|
+
credentials = fromIni({ profile })
|
|
73
|
+
return credentials
|
|
82
74
|
}
|