@tremho/mist-lift 1.0.0

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.
Files changed (121) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +37 -0
  3. package/build/commands/actions/initQuestions.js +136 -0
  4. package/build/commands/actions/initQuestions.js.map +1 -0
  5. package/build/commands/actions/makePackageJson.js +2 -0
  6. package/build/commands/actions/makePackageJson.js.map +1 -0
  7. package/build/commands/actions/setupPackageJson.js +68 -0
  8. package/build/commands/actions/setupPackageJson.js.map +1 -0
  9. package/build/commands/build.js +191 -0
  10. package/build/commands/build.js.map +1 -0
  11. package/build/commands/builtin/ApiDocMaker.js +72 -0
  12. package/build/commands/builtin/ApiDocMaker.js.map +1 -0
  13. package/build/commands/builtin/BuiltInHandler.js +62 -0
  14. package/build/commands/builtin/BuiltInHandler.js.map +1 -0
  15. package/build/commands/builtin/DeployBuiltInZip.js +57 -0
  16. package/build/commands/builtin/DeployBuiltInZip.js.map +1 -0
  17. package/build/commands/builtin/StageWebrootZip.js +70 -0
  18. package/build/commands/builtin/StageWebrootZip.js.map +1 -0
  19. package/build/commands/builtin/prebuilt-zips/API.zip +0 -0
  20. package/build/commands/builtin/prebuilt-zips/FileServe.zip +0 -0
  21. package/build/commands/builtin/prebuilt-zips/Webroot.zip +0 -0
  22. package/build/commands/create.js +75 -0
  23. package/build/commands/create.js.map +1 -0
  24. package/build/commands/deploy.js +187 -0
  25. package/build/commands/deploy.js.map +1 -0
  26. package/build/commands/doctor.js +137 -0
  27. package/build/commands/doctor.js.map +1 -0
  28. package/build/commands/help.js +205 -0
  29. package/build/commands/help.js.map +1 -0
  30. package/build/commands/init.js +92 -0
  31. package/build/commands/init.js.map +1 -0
  32. package/build/commands/package.js +249 -0
  33. package/build/commands/package.js.map +1 -0
  34. package/build/commands/publish.js +344 -0
  35. package/build/commands/publish.js.map +1 -0
  36. package/build/commands/settings.js +95 -0
  37. package/build/commands/settings.js.map +1 -0
  38. package/build/commands/start.js +66 -0
  39. package/build/commands/start.js.map +1 -0
  40. package/build/commands/test.js +52 -0
  41. package/build/commands/test.js.map +1 -0
  42. package/build/commands/user.js +20 -0
  43. package/build/commands/user.js.map +1 -0
  44. package/build/expressRoutes/all.js +129 -0
  45. package/build/expressRoutes/all.js.map +1 -0
  46. package/build/expressRoutes/api.js +22 -0
  47. package/build/expressRoutes/api.js.map +1 -0
  48. package/build/expressRoutes/functionBinder.js +191 -0
  49. package/build/expressRoutes/functionBinder.js.map +1 -0
  50. package/build/lib/CaseUtils.js +57 -0
  51. package/build/lib/CaseUtils.js.map +1 -0
  52. package/build/lib/DirectoryUtils.js +37 -0
  53. package/build/lib/DirectoryUtils.js.map +1 -0
  54. package/build/lib/LiftConfig.js +83 -0
  55. package/build/lib/LiftConfig.js.map +1 -0
  56. package/build/lib/LiftVersion.js +117 -0
  57. package/build/lib/LiftVersion.js.map +1 -0
  58. package/build/lib/Tests/fileCompare.test.js +55 -0
  59. package/build/lib/Tests/fileCompare.test.js.map +1 -0
  60. package/build/lib/askQuestion.js +41 -0
  61. package/build/lib/askQuestion.js.map +1 -0
  62. package/build/lib/executeCommand.js +45 -0
  63. package/build/lib/executeCommand.js.map +1 -0
  64. package/build/lib/fileCompare.js +48 -0
  65. package/build/lib/fileCompare.js.map +1 -0
  66. package/build/lib/openAPI/ApiBuildCollector.js +58 -0
  67. package/build/lib/openAPI/ApiBuildCollector.js.map +1 -0
  68. package/build/lib/openAPI/WebrootFileSupport.js +44 -0
  69. package/build/lib/openAPI/WebrootFileSupport.js.map +1 -0
  70. package/build/lib/openAPI/openApiConstruction.js +203 -0
  71. package/build/lib/openAPI/openApiConstruction.js.map +1 -0
  72. package/build/lib/pathResolve.js +27 -0
  73. package/build/lib/pathResolve.js.map +1 -0
  74. package/build/lib/utils.js +76 -0
  75. package/build/lib/utils.js.map +1 -0
  76. package/build/lift.js +124 -0
  77. package/build/lift.js.map +1 -0
  78. package/package.json +69 -0
  79. package/src/commands/actions/initQuestions.ts +131 -0
  80. package/src/commands/actions/makePackageJson.ts +0 -0
  81. package/src/commands/actions/setupPackageJson.ts +36 -0
  82. package/src/commands/build.ts +165 -0
  83. package/src/commands/builtin/ApiDocMaker.ts +70 -0
  84. package/src/commands/builtin/BuiltInHandler.ts +51 -0
  85. package/src/commands/builtin/DeployBuiltInZip.ts +27 -0
  86. package/src/commands/builtin/StageWebrootZip.ts +39 -0
  87. package/src/commands/builtin/prebuilt-zips/API.zip +0 -0
  88. package/src/commands/builtin/prebuilt-zips/FileServe.zip +0 -0
  89. package/src/commands/builtin/prebuilt-zips/Webroot.zip +0 -0
  90. package/src/commands/create.ts +55 -0
  91. package/src/commands/deploy.ts +171 -0
  92. package/src/commands/doctor.ts +102 -0
  93. package/src/commands/help.ts +171 -0
  94. package/src/commands/init.ts +62 -0
  95. package/src/commands/package.ts +228 -0
  96. package/src/commands/publish.ts +350 -0
  97. package/src/commands/settings.ts +76 -0
  98. package/src/commands/start.ts +46 -0
  99. package/src/commands/test.ts +38 -0
  100. package/src/commands/user.ts +20 -0
  101. package/src/expressRoutes/all.ts +104 -0
  102. package/src/expressRoutes/api.ts +24 -0
  103. package/src/expressRoutes/functionBinder.ts +169 -0
  104. package/src/lib/CaseUtils.ts +68 -0
  105. package/src/lib/DirectoryUtils.ts +36 -0
  106. package/src/lib/LiftConfig.ts +83 -0
  107. package/src/lib/LiftVersion.ts +95 -0
  108. package/src/lib/Tests/dir1/file.1 +0 -0
  109. package/src/lib/Tests/dir1/file.2 +0 -0
  110. package/src/lib/Tests/dir2/file.1 +0 -0
  111. package/src/lib/Tests/fileCompare.test.ts +34 -0
  112. package/src/lib/askQuestion.ts +18 -0
  113. package/src/lib/executeCommand.ts +38 -0
  114. package/src/lib/fileCompare.ts +46 -0
  115. package/src/lib/openAPI/ApiBuildCollector.ts +47 -0
  116. package/src/lib/openAPI/WebrootFileSupport.ts +21 -0
  117. package/src/lib/openAPI/openApiConstruction.ts +202 -0
  118. package/src/lib/pathResolve.ts +32 -0
  119. package/src/lib/utils.ts +45 -0
  120. package/src/lift.ts +82 -0
  121. package/tsconfig.json +28 -0
@@ -0,0 +1,202 @@
1
+ /**
2
+ * This is part 2 of 2 -- we take our pre-built json array of definitions and apply them to openApi in this phase.
3
+ */
4
+ import { OpenApiBuilder } from 'openapi3-ts/oas30';
5
+ import fs, {mkdirSync} from 'fs'
6
+ import path from 'path'
7
+ import {resolvePaths} from "../pathResolve";
8
+ import {recurseDirectory} from "../DirectoryUtils";
9
+ import {getSettings} from "../LiftConfig";
10
+
11
+ export async function buildOpenApi(
12
+ defs:any[],
13
+ includePrivate:boolean = false,
14
+ yamlFile?:string
15
+ ):Promise<Uint8Array>
16
+ {
17
+ const builder = new OpenApiBuilder();
18
+
19
+ const projectPaths = await resolvePaths();
20
+ if(!projectPaths.verified) return new Uint8Array(0); // don't continue if not valid
21
+
22
+ // Read our package.json and construct info from that
23
+ const pkgFile = projectPaths.packagePath;
24
+ let pkg:any = {}
25
+ try { pkg = JSON.parse(fs.readFileSync(pkgFile).toString()); } catch {}
26
+ let title = pkg.name;
27
+ // let summary = pkg.description;
28
+ let spdx = pkg.license;
29
+ let contactName = pkg.author;
30
+ let version = pkg.version;
31
+
32
+ // license and version definitely come from package.json
33
+ // description and title might get overridden by service.info file
34
+ const infoFile = path.join(projectPaths.functionPath, "apiService.info.json")
35
+ var svcInfo:any = {};
36
+ if(fs.existsSync(infoFile)) {
37
+ svcInfo = JSON.parse(fs.readFileSync(infoFile).toString())
38
+ }
39
+ spdx = svcInfo.contact?.spdx ?? spdx;
40
+
41
+ const info = {
42
+ title: svcInfo.name ?? title,
43
+ // summary: summary,
44
+ description: svcInfo.description,
45
+ version: svcInfo.version ?? version ?? new Date().toUTCString()
46
+ }
47
+ builder.addInfo(info)
48
+
49
+ // map our defs into openApi values
50
+ for (let def of defs) {
51
+ let pathDef = {}
52
+ if(def.private && !includePrivate) continue; // skip private
53
+
54
+ const parameters = def.parameters ?? []
55
+ const methods = def.allowedMethods.split(',')
56
+ const schemas = def.schemas ?? {}
57
+ for(let schemaName of Object.getOwnPropertyNames(schemas)) {
58
+ const schema = schemas[schemaName];
59
+ addTypeSchema(builder, schemaName, schema)
60
+ }
61
+ for (let method of methods) {
62
+ method = method.trim().toLowerCase()
63
+ addFunctionMethod(pathDef, method, def)
64
+ for (let param of parameters) {
65
+ addParameter(pathDef, param)
66
+ }
67
+ }
68
+ addCORSOptionMethod(pathDef)
69
+ builder.addPath((def.pathMap ?? "/"+def.name), pathDef)
70
+
71
+ builder.addSchema("Empty",{
72
+ title : "Empty Schema",
73
+ type:"object"
74
+ })
75
+ }
76
+
77
+ const outFile = yamlFile ?? path.join(projectPaths.basePath, 'webroot', 'docs','apidoc.yaml')
78
+
79
+ const str2ab = (str:string):Uint8Array => {
80
+ var buf = new ArrayBuffer(str.length * 2); // 2 bytes for each char
81
+ var bufView = new Uint8Array(buf);
82
+ for (var i = 0, strLen = str.length; i < strLen; i++) {
83
+ bufView[i] = str.charCodeAt(i);
84
+ }
85
+ return bufView;
86
+ }
87
+
88
+ const yaml = builder.getSpecAsYaml();
89
+ const bytes = str2ab(yaml);
90
+ if(!includePrivate) {
91
+ fs.writeFileSync(outFile, yaml)
92
+ }
93
+ return bytes
94
+ }
95
+
96
+ function addTypeSchema(builder:any, schemaName:string, schema:any)
97
+ {
98
+ const ref:any = {title: schemaName, type:"object", properties:{}}
99
+ for(let prop of Object.getOwnPropertyNames(schema))
100
+ {
101
+ const scType:any = schemaType("", schema[prop],false)
102
+
103
+ ref.properties[prop] = scType
104
+ }
105
+
106
+ builder.addSchema(schemaName, ref)
107
+ }
108
+
109
+ function addFunctionMethod(pathDef:any, method:string, def:any) {
110
+
111
+ // TODO: Define a return schema and put that here
112
+ const retDef:any = (def.returns as any)["200"];
113
+ const content:any = {}
114
+ const mime = retDef?.content ?? retDef?.mime ?? "text/plain"
115
+ content[mime] = {}
116
+
117
+ const region = getSettings().awsPreferredRegion;
118
+ const accountId = "545650260286";
119
+ const methData = {
120
+ summary: def.name,
121
+ description: def.description,
122
+ responses: {
123
+ "200": {
124
+ description: retDef?.description ?? "Success Response",
125
+ content
126
+ }
127
+ }
128
+ }
129
+ pathDef[method] = methData;
130
+ }
131
+ function addCORSOptionMethod(pathDef:any) {
132
+ if (pathDef["options"]) return; // already assinged by definition
133
+ // add options for CORS
134
+ pathDef["options"] = {
135
+ "responses" : {
136
+ "200" : {
137
+ "description" : "200 response",
138
+ "content" : {
139
+ "application/json" : {
140
+ "schema" : {
141
+ "$ref" : "#/components/schemas/Empty"
142
+ }
143
+ }
144
+ }
145
+ }
146
+ },
147
+ "x-amazon-apigateway-integration" : {
148
+ "responses" : {
149
+ "default" : {
150
+ "statusCode" : "200"
151
+ }
152
+ },
153
+ "requestTemplates" : {
154
+ "application/json" : "{\"statusCode\": 200}"
155
+ },
156
+ "passthroughBehavior" : "when_no_match",
157
+ "type" : "mock"
158
+ }
159
+ }
160
+ }
161
+
162
+ function addParameter(pathDef:any, param:any) {
163
+ if(!pathDef.parameters) pathDef.parameters = [];
164
+ const parameters = pathDef.parameters
165
+ const example = param.example ?? param.default ?? "";
166
+ const type = param.type ?? typeof example
167
+ let deflt = param.default ?? example
168
+
169
+ parameters.push({
170
+ in: param.in,
171
+ name: param.name,
172
+ description: param.description,
173
+ example: example,
174
+ required: param.required,
175
+ schema: schemaType(deflt, type, true)
176
+ })
177
+
178
+ }
179
+
180
+ function schemaType(deflt:string, namedType:string, innerOnly:boolean) {
181
+ if(typeof namedType == "object") return namedType;
182
+ const typeFormat = namedType.split(':')
183
+ let type = typeFormat[0]
184
+ const format = typeFormat.length > 1 ? typeFormat[1] : undefined
185
+ if(!( type === "string"
186
+ || type === "number"
187
+ || type === "integer"
188
+ || type === "boolean"
189
+ || type === "int"
190
+ || type === "bool"
191
+ )) {
192
+ return innerOnly ? {
193
+ $ref: `#/components/schemas/${type}`
194
+ } : { schema: {
195
+ $ref: `#/components/schemas/${type}`
196
+ } }
197
+ }
198
+ if( type === 'int') type = 'integer';
199
+ if( type === 'bool') type = 'boolean';
200
+ return innerOnly ? { type, format, example:deflt } : { schema: { type, format, example:deflt } }
201
+
202
+ }
@@ -0,0 +1,32 @@
1
+ import path from "path";
2
+ import fs from "fs";
3
+
4
+
5
+ // Find the path roots in the project directory
6
+ export function resolvePaths(
7
+ ) : {
8
+ basePath:string, // project base
9
+ buildPath:string, // build folder
10
+ functionPath:string, // functions folder
11
+ packagePath:string, // package.json
12
+ verified:boolean // all of these exist if true, else, may be incomplete project
13
+ }
14
+ {
15
+ const cwd = process.cwd()
16
+ let funcPath = path.join(cwd, 'functions')
17
+ while(true)
18
+ {
19
+ if(!fs.existsSync(funcPath))
20
+ {
21
+ funcPath = path.normalize(path.join(funcPath, ".."))
22
+ }
23
+ else
24
+ {
25
+ const basePath = path.normalize(path.join(funcPath, ".."))
26
+ const buildPath = path.join(basePath, "build");
27
+ const packagePath = path.join(basePath,"package.json");
28
+ const verified = fs.existsSync(basePath) && fs.existsSync(funcPath) && fs.existsSync(packagePath);
29
+ return {basePath, buildPath, functionPath:funcPath, packagePath, verified}
30
+ }
31
+ }
32
+ }
@@ -0,0 +1,45 @@
1
+ import {executeCommand} from "./executeCommand";
2
+ import * as ac from "ansi-colors";
3
+ import * as fs from 'fs'
4
+
5
+ /** General utilities */
6
+
7
+ const zipDir = require('zip-dir')
8
+
9
+ // pause the given number of milliseconds
10
+ export async function delay(
11
+ ms:number // milliseconds to delay
12
+ )
13
+ {
14
+ return new Promise(resolve => {setTimeout(resolve, ms)})
15
+ }
16
+
17
+ export async function FolderToZip(
18
+ folderPath:string,
19
+ zipPath: string
20
+ ):Promise<Uint8Array>
21
+ {
22
+ return new Promise(resolve => {
23
+ zipDir(folderPath, { saveTo: zipPath }, function (err:any, buffer:Uint8Array) {
24
+ if(err) throw err
25
+ // `buffer` is the buffer of the zipped file
26
+ // And the buffer was saved to `~/myzip.zip`
27
+ resolve(buffer);
28
+ })
29
+ })
30
+ }
31
+ export async function UnzipToFolder(
32
+ zipPath:string,
33
+ folderPath:string,
34
+ replace:boolean = true
35
+ )
36
+ {
37
+ // TODO: using CLI -- find a good package. "unzip" has vulnerabilities. Try others.
38
+
39
+ if(replace) fs.rmSync(folderPath, {recursive: true, force: true})
40
+ let result = await executeCommand('unzip', [zipPath,'-d', folderPath])
41
+ if (result.retcode) {
42
+ console.error(ac.red.bold(`failed to stage webroot (${result.retcode}): ${result.errStr}`));
43
+ throw Error();
44
+ }
45
+ }
package/src/lift.ts ADDED
@@ -0,0 +1,82 @@
1
+ #!/usr/bin/env node
2
+
3
+ import * as ac from 'ansi-colors'
4
+ import * as process from 'process'
5
+
6
+ import {getLiftVersion} from "./lib/LiftVersion";
7
+
8
+ import {doHelp} from "./commands/help"
9
+ import {doInit} from "./commands/init"
10
+ import {doCreate} from "./commands/create"
11
+ import {doBuildAsync} from "./commands/build"
12
+ import {doTestAsync} from "./commands/test"
13
+ import {doPackageAsync} from "./commands/package"
14
+ import {doDeployAsync} from "./commands/deploy";
15
+ import {doPublishAsync} from "./commands/publish";
16
+ import {doDoctor} from "./commands/doctor";
17
+ import {startLocalServer} from "./commands/start";
18
+ import {doSettings} from "./commands/settings";
19
+
20
+ const command = process.argv[2] || 'help'
21
+ const args = process.argv.slice(3)
22
+
23
+ async function processCommand() {
24
+ switch (command) {
25
+ case 'version':
26
+ case '--version':
27
+ case '-v':
28
+ console.log(`Lift v${getLiftVersion()}`);
29
+ return;
30
+ case 'help':
31
+ return doHelp(args[0] ?? '')
32
+ case 'doctor':
33
+ return doDoctor();
34
+ case 'init':
35
+ return doInit(args[0] ?? '')
36
+ case 'create':
37
+ return doCreate(args[0] ?? '')
38
+ case 'build': {
39
+ const ret = await doBuildAsync ( args )
40
+ if (ret) process.exit( -1 )
41
+ }
42
+ return;
43
+ case 'test': {
44
+ const ret = await doTestAsync(args);
45
+ if (ret) process.exit(ret);
46
+ }
47
+ return;
48
+ case 'start':
49
+ return startLocalServer();
50
+
51
+ case 'package': {
52
+ const ret = await doPackageAsync(args);
53
+ if (ret) process.exit(ret);
54
+ }
55
+ return;
56
+ case 'deploy': {
57
+ const ret = await doDeployAsync(args);
58
+ if (ret) process.exit(ret);
59
+ }
60
+ return;
61
+ case 'publish': {
62
+ const ret = await doPublishAsync();
63
+ if (ret) process.exit(ret);
64
+ }
65
+ return;
66
+ case 'settings': {
67
+ const ret = await doSettings();
68
+ if (ret) process.exit(ret);
69
+ }
70
+ return;
71
+ }
72
+ return doUnknown(command)
73
+ }
74
+
75
+ function doUnknown(command:string) {
76
+ console.log(ac.red.bold(`Unrecognized command ${command || ''}`))
77
+ console.log(ac.grey.dim('try'))
78
+ console.log(ac.blue.dim('help, init, create, build, test, start, package, deploy, publish, settings'))
79
+ console.log('')
80
+ }
81
+
82
+ processCommand()
package/tsconfig.json ADDED
@@ -0,0 +1,28 @@
1
+ {
2
+ "compilerOptions": {
3
+ "sourceMap": true,
4
+ "outDir": "./build",
5
+ "allowJs": true,
6
+ "target": "ES2015", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */
7
+ "module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */
8
+ "lib": [
9
+ "dom",
10
+ "es2015",
11
+ "scripthost",
12
+ "es2015.proxy"
13
+ ],
14
+ /* Advanced Options */
15
+ "strict": true, /* Enable all strict type-checking options. */
16
+ "esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
17
+ "skipLibCheck": true, /* Skip type checking of declaration files. */
18
+ "forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */
19
+ },
20
+ "exclude": [
21
+ "./node_modules/"
22
+ ],
23
+ "include": [
24
+ "**/*.ts",
25
+ "src/preload.js"
26
+ ]
27
+ }
28
+