@tremho/mist-lift 1.1.1 → 1.1.3-pre-release.1

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 (75) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +65 -65
  3. package/build/commands/actions/initQuestions.js +35 -33
  4. package/build/commands/actions/initQuestions.js.map +1 -1
  5. package/build/commands/build.js +1 -1
  6. package/build/commands/build.js.map +1 -1
  7. package/build/commands/create.js +1 -1
  8. package/build/commands/create.js.map +1 -1
  9. package/build/commands/deploy.js +1 -1
  10. package/build/commands/deploy.js.map +1 -1
  11. package/build/commands/info.js +1 -1
  12. package/build/commands/info.js.map +1 -1
  13. package/build/commands/init.js +2 -2
  14. package/build/commands/init.js.map +1 -1
  15. package/build/commands/package.js +2 -2
  16. package/build/commands/package.js.map +1 -1
  17. package/build/commands/publish.js +2 -2
  18. package/build/commands/publish.js.map +1 -1
  19. package/build/expressRoutes/functionBinder.js.map +1 -1
  20. package/build/integration-tests/quickstart-scenario.test.js +76 -0
  21. package/build/integration-tests/quickstart-scenario.test.js.map +1 -0
  22. package/build/lib/utils.js +1 -1
  23. package/build/lib/utils.js.map +1 -1
  24. package/build/lift.js +1 -1
  25. package/build/lift.js.map +1 -1
  26. package/package.json +79 -72
  27. package/src/commands/actions/initQuestions.ts +133 -131
  28. package/src/commands/actions/setupPackageJson.ts +32 -32
  29. package/src/commands/build.ts +170 -170
  30. package/src/commands/builtin/ApiDocMaker.ts +102 -102
  31. package/src/commands/builtin/BuiltInHandler.ts +47 -47
  32. package/src/commands/builtin/DeployBuiltInZip.ts +25 -25
  33. package/src/commands/builtin/StageWebrootZip.ts +36 -36
  34. package/src/commands/create.ts +52 -52
  35. package/src/commands/deploy.ts +161 -161
  36. package/src/commands/doctor.ts +106 -106
  37. package/src/commands/help.ts +178 -178
  38. package/src/commands/info.ts +42 -43
  39. package/src/commands/init.ts +61 -60
  40. package/src/commands/package.ts +234 -234
  41. package/src/commands/publish.ts +330 -330
  42. package/src/commands/settings.ts +73 -73
  43. package/src/commands/start.ts +43 -43
  44. package/src/commands/test.ts +37 -37
  45. package/src/commands/user.ts +20 -20
  46. package/src/expressRoutes/all.ts +99 -99
  47. package/src/expressRoutes/api.ts +22 -22
  48. package/src/expressRoutes/functionBinder.ts +155 -156
  49. package/src/integration-tests/quickstart-scenario.test.ts +74 -0
  50. package/src/lib/CaseUtils.ts +63 -63
  51. package/src/lib/DirectoryUtils.ts +34 -34
  52. package/src/lib/LiftConfig.ts +74 -74
  53. package/src/lib/LiftVersion.ts +87 -87
  54. package/src/lib/Tests/fileCompare.test.ts +35 -35
  55. package/src/lib/askQuestion.ts +17 -17
  56. package/src/lib/executeCommand.ts +45 -45
  57. package/src/lib/fileCompare.ts +55 -55
  58. package/src/lib/openAPI/ApiBuildCollector.ts +47 -47
  59. package/src/lib/openAPI/WebrootFileSupport.ts +19 -19
  60. package/src/lib/openAPI/openApiConstruction.ts +196 -196
  61. package/src/lib/pathResolve.ts +26 -26
  62. package/src/lib/utils.ts +43 -43
  63. package/src/lift.ts +87 -87
  64. package/templateData/function-definition-template +20 -20
  65. package/templateData/function-local-ts +16 -16
  66. package/templateData/function-main-ts +16 -16
  67. package/templateData/function-runmain-mjs +6 -6
  68. package/templateData/function-test-template +11 -11
  69. package/templateData/swagger-ui-bundle.js +2 -2
  70. package/templateData/swagger-ui-standalone-preset.js +2 -2
  71. package/templateData/swagger-ui.css +2 -2
  72. package/tsconfig.json +28 -28
  73. /package/build/commands/builtin/{prebuilt-zips → prebult-zips}/API.zip +0 -0
  74. /package/build/commands/builtin/{prebuilt-zips → prebult-zips}/FileServe.zip +0 -0
  75. /package/build/commands/builtin/{prebuilt-zips → prebult-zips}/Webroot.zip +0 -0
@@ -1,330 +1,330 @@
1
-
2
- import {
3
- LambdaClient,
4
- ListFunctionsCommand
5
- } from '@aws-sdk/client-lambda'
6
- import {
7
- APIGatewayClient,
8
- ImportRestApiCommand,
9
- GetRestApisCommand,
10
- GetResourcesCommand, GetResourcesCommandOutput,
11
- DeleteRestApiCommand,
12
- PutIntegrationRequest,
13
- PutIntegrationCommand,
14
- CreateDeploymentCommand
15
- } from '@aws-sdk/client-api-gateway'
16
-
17
- import { getAWSCredentials, getSettings } from '../lib/LiftConfig'
18
-
19
- import * as ac from 'ansi-colors'
20
-
21
- import path from 'path'
22
- import fs, { mkdirSync } from 'fs'
23
- import os from 'os'
24
- import { resolvePaths } from '../lib/pathResolve'
25
- import { gatherFunctionDefinitions } from '../lib/openAPI/ApiBuildCollector'
26
- import { delay } from '../lib/utils'
27
- import { addBuiltInDefinitions, MakeBuiltinApiDoc } from './builtin/ApiDocMaker'
28
- import { DeployApiBuiltin, DeployRootFileserves, DeployWebrootBuiltIn } from './builtin/BuiltInHandler'
29
- import { getProjectName, getProjectVersion } from '../lib/LiftVersion'
30
- import md5 from 'md5'
31
-
32
- let projectPaths: any
33
-
34
- export async function doPublishAsync (stageName?: string): Promise<number> {
35
- // let retCode = await doDeployAsync([])
36
- // if(retCode) return retCode
37
- const retCode = 0
38
-
39
- projectPaths = resolvePaths()
40
- if(!projectPaths.verified) {
41
- console.log(ac.bold.magenta("current directory is not at project root"))
42
- return -1;
43
- }
44
-
45
- await publishApi(stageName ?? 'Dev')
46
-
47
- return retCode
48
- }
49
-
50
- async function publishApi (
51
- stageName?: string
52
- ): Promise<void> {
53
- if (stageName === undefined) stageName = 'Dev'
54
- console.log(ac.green.bold(`Publishing Api to ${stageName}`))
55
-
56
- // do the built-in deploys
57
- await DeployWebrootBuiltIn()
58
- await DeployRootFileserves()
59
- await DeployApiBuiltin()
60
-
61
- // make a private api
62
- // const fs = require('fs')
63
- // const os = require('os')
64
- // const path = require('path')
65
-
66
- let tmpDir
67
- let apiBytes
68
- const appPrefix = 'MistLift'
69
- try {
70
- tmpDir = path.join(os.tmpdir(), appPrefix)
71
- // console.log("making "+tmpDir)
72
- mkdirSync(tmpDir, { recursive: true })
73
-
74
- const yamlFile = path.join(tmpDir, 'papi.yaml')
75
- await MakeBuiltinApiDoc(yamlFile)
76
- // console.log("reading "+yamlFile)
77
- apiBytes = fs.readFileSync(yamlFile)
78
- } catch (e: any) {
79
- console.error(ac.red.bold('Error creating temp staging folder ') + (e.message as string))
80
- throw Error()
81
- } finally {
82
- try {
83
- if (tmpDir !== undefined) {
84
- fs.rmSync(tmpDir, { recursive: true })
85
- }
86
- } catch (e: any) {
87
- console.error(`An error has occurred while removing the temp folder at ${tmpDir ?? ''}. Please remove it manually. Error: ${(e.message as string)}`)
88
- }
89
- }
90
-
91
- const client = new APIGatewayClient(getAWSCredentials())
92
-
93
- await RemoveExistingVersions(client)
94
-
95
- const command = new ImportRestApiCommand({
96
- failOnWarnings: false,
97
- body: apiBytes
98
- })
99
- let apiId
100
- try {
101
- const response = await client.send(command)
102
- const { name, id, version, warnings } = response
103
- console.log(ac.grey(`\n\nAPI ${name ?? ''} version ${version ?? ''} [${id ?? ''}] schema created`))
104
- apiId = id ?? ''
105
- if (warnings?.length !== 0) {
106
- console.log(ac.magenta(` with ${warnings?.length ?? 0} warnings`))
107
- if (warnings !== undefined) {
108
- for (const warning of warnings) {
109
- console.log(ac.grey.italic(` ${warning}`))
110
- }
111
- }
112
- }
113
- } catch (e: any) {
114
- console.error(ac.bold.red(e.message))
115
- }
116
- // const apidoc = new TextDecoder().decode(apiBytes)
117
- // console.log(apidoc)
118
- if (apiId === '') return
119
-
120
- console.log(ac.grey('Continuing with binding...'))
121
- const prereq = await PrequisiteValues(apiId ?? '')
122
- const intRequests = prereq.MakeRequests()
123
- await PutIntegrations(intRequests)
124
- await DeployApi(apiId ?? '', stageName)
125
- const region = getSettings()?.awsPreferredRegion ?? ''
126
- const publishUrl = `https://${apiId ?? ''}.execute-api.${region}.amazonaws.com/${stageName}`
127
- console.log(ac.green.bold(`\n Successfully deployed to ${publishUrl}`))
128
- recordLatestPublish(publishUrl)
129
- }
130
- function findApiName (): string {
131
- const infoFile = path.join(projectPaths.functionPath, 'apiService.info.json')
132
- const pkgFile = projectPaths.packagePath
133
- let pkg: any = {}
134
- if (fs.existsSync(pkgFile)) { pkg = JSON.parse(fs.readFileSync(pkgFile).toString()) }
135
- let info: any = {}
136
- if (fs.existsSync(infoFile)) { info = JSON.parse(fs.readFileSync(infoFile).toString()) }
137
-
138
- return info.title ?? pkg.name ?? 'API'
139
- }
140
-
141
- async function RemoveExistingVersions (client: APIGatewayClient): Promise<void> {
142
- await new Promise(resolve => {
143
- const ourName = findApiName()
144
- // ClogDebug("looking for name "+ ourName)
145
- const listCommand = new GetRestApisCommand({})
146
- client.send(listCommand).then((response: any) => {
147
- // ClogInfo(`There are ${response.items.length} other APIs`)
148
-
149
- const DeleteMatchingApis = async (i: number = 0): Promise<any> => {
150
- if (i >= response.items.length) {
151
- resolve(undefined)
152
- return await Promise.resolve(undefined)
153
- }
154
- const item: { name: string, id: string } = response.items[i]
155
- if (item.name === ourName) {
156
- // ClogInfo(`Found previous ${ourName}, [${item.id}] -- deleting...`)
157
- const deleteCommand = new DeleteRestApiCommand({
158
- restApiId: item.id
159
- })
160
- return await client.send(deleteCommand).then(() => {
161
- delay(5000).then(async () => {
162
- console.log(ac.magenta.bold(`Removed previous id ${item.id}`))
163
- return await DeleteMatchingApis(++i)
164
- }).catch<any>((reason: any) => undefined)
165
- }).catch<any>((reason: any) => undefined)
166
- } else {
167
- return await DeleteMatchingApis(++i)
168
- }
169
- }
170
- DeleteMatchingApis().catch<any>((reason: any) => undefined)
171
- }).catch<any>((reason: any) => undefined)
172
- }).catch<any>((reason: any) => undefined)
173
- }
174
-
175
- class FunctionInfo {
176
- name: string = ''
177
- arn: string = ''
178
- }
179
-
180
- class PrereqInfo {
181
- requestApiId: string = ''
182
- functions: FunctionInfo[] = []
183
- apis: any[] = [] // Resource + method
184
- defs: any[] = []
185
-
186
- public constructor () {
187
- this.functions = []
188
- this.apis = []
189
- this.defs = []
190
- }
191
-
192
- public findApi (pathMap: string, allowedMethods: string): any {
193
- // find the pathmap in the apis list
194
- // console.log("findApi "+pathMap, allowedMethods)
195
- // see that this method exists in method map
196
- for (const api of this.apis) {
197
- if (api?.path === pathMap) {
198
- // console.log("resourceMethods", api.resourceMethods)
199
- const methodList = Object.getOwnPropertyNames(api.resourceMethods)
200
- // ClogTrace("methodList", methodList)
201
- for (const meth of allowedMethods.toUpperCase().split(',')) {
202
- // console.log("meth", meth)
203
- if (methodList.includes(meth)) {
204
- (api).method = meth
205
- return api
206
- }
207
- }
208
- }
209
- }
210
- return null
211
- }
212
-
213
- public findARN (name: string): string {
214
- for (const f of this.functions ?? []) {
215
- const lastus = f.name.lastIndexOf('_')
216
- const fname = f.name.substring(0, lastus)
217
- if (fname.toLowerCase() === name.toLowerCase()) return f.arn
218
- }
219
- console.log("$$$ Couldn't find " + name + ' in ', this.functions)
220
- return ''
221
- }
222
-
223
- public MakeRequests (): PutIntegrationRequest[] {
224
- const region = getSettings()?.awsPreferredRegion ?? ''
225
- const out: PutIntegrationRequest[] = []
226
- for (const d of this.defs) {
227
- const def = (d)
228
- const api = this.findApi(def.pathMap, def.allowedMethods)
229
- const arn = this.findARN(def.name) ?? ''
230
- if (arn === '') {
231
- console.log(`>>> No ARN for ${(def.name as string)} ${(def.pathMap as string)}, ${(api.id as string)}`)
232
- }
233
- if (api !== undefined) {
234
- out.push({
235
- restApiId: this.requestApiId,
236
- resourceId: api.id, // api.parentId
237
- httpMethod: api.method,
238
- integrationHttpMethod: 'POST', // api.method,
239
- type: 'AWS_PROXY',
240
- uri: `arn:aws:apigateway:${region}:lambda:path/2015-03-31/functions/${arn}/invocations`,
241
- credentials: 'arn:aws:iam::545650260286:role/TBDLambdaExecution2'
242
- })
243
- }
244
- }
245
- return out
246
- }
247
- }
248
-
249
- async function PrequisiteValues (id: string): Promise<PrereqInfo> {
250
- const pri = new PrereqInfo()
251
- const out = await GetFunctionInfo(pri)
252
- out.defs = gatherFunctionDefinitions()
253
- addBuiltInDefinitions(out.defs)
254
- out.requestApiId = id
255
- await GetMethodResources(id, out)
256
-
257
- return out
258
- }
259
-
260
- async function GetFunctionInfo (info: PrereqInfo): Promise<PrereqInfo> {
261
- const client = new LambdaClient(getAWSCredentials())
262
- const listCommand: any = new ListFunctionsCommand({})
263
- const response: any = await client.send(listCommand)
264
-
265
- const sfx = '_' + md5((getProjectName() ?? '') + (getProjectVersion()?.toString() ?? ''))
266
-
267
- for (const func of response.Functions ?? []) {
268
- const fName: string = func?.FunctionName ?? ''
269
- if (fName.endsWith(sfx)) {
270
- info.functions.push({
271
- name: func.FunctionName ?? '',
272
- arn: func.FunctionArn ?? ''
273
- })
274
- }
275
- }
276
- return info
277
- }
278
-
279
- async function GetMethodResources (
280
- id: string,
281
- info: PrereqInfo
282
- ): Promise<PrereqInfo> {
283
- const client = new APIGatewayClient(getAWSCredentials())
284
- const listCommand = new GetResourcesCommand({
285
- restApiId: id
286
- })
287
- const response: GetResourcesCommandOutput = await client.send(listCommand)
288
- // ClogInfo("Resources response", response)
289
- if ((response?.items) != null) info.apis = response.items
290
-
291
- return info
292
- }
293
-
294
- async function PutIntegrations (integrations: PutIntegrationRequest[]): Promise<void> {
295
- const client = new APIGatewayClient(getAWSCredentials())
296
- for (const input of integrations) {
297
- try {
298
- const command = new PutIntegrationCommand(input)
299
- /* const intResp = */ await client.send(command)
300
- // ClogDebug("integration response", intResp);
301
- await delay(5000)
302
- } catch (e: any) {
303
- console.error('Problem with integration for ' + (input.uri as string), { input })
304
- throw e
305
- }
306
- }
307
- }
308
-
309
- async function DeployApi (restApiId: string, stageName: string): Promise<void> {
310
- try {
311
- const client = new APIGatewayClient(getAWSCredentials())
312
- const command = new CreateDeploymentCommand({
313
- restApiId,
314
- stageName
315
- })
316
- await client.send(command)
317
- } catch (e: any) {
318
- console.error(ac.red.bold(`Error with deployApi: ${e.message as string}`))
319
- throw e
320
- }
321
- }
322
-
323
- function recordLatestPublish(publishUrl:string): void {
324
- const publishRecord = {
325
- url: publishUrl,
326
- time: Date.now()
327
- }
328
- const publishedFile = path.join(projectPaths.basePath, '.published')
329
- fs.writeFileSync(publishedFile, JSON.stringify(publishRecord))
330
- }
1
+
2
+ import {
3
+ LambdaClient,
4
+ ListFunctionsCommand
5
+ } from '@aws-sdk/client-lambda'
6
+ import {
7
+ APIGatewayClient,
8
+ ImportRestApiCommand,
9
+ GetRestApisCommand,
10
+ GetResourcesCommand, GetResourcesCommandOutput,
11
+ DeleteRestApiCommand,
12
+ PutIntegrationRequest,
13
+ PutIntegrationCommand,
14
+ CreateDeploymentCommand
15
+ } from '@aws-sdk/client-api-gateway'
16
+
17
+ import { getAWSCredentials, getSettings } from '../lib/LiftConfig'
18
+
19
+ import * as ac from 'ansi-colors'
20
+
21
+ import path from 'path'
22
+ import fs, { mkdirSync } from 'fs'
23
+ import os from 'os'
24
+ import { resolvePaths } from '../lib/pathResolve'
25
+ import { gatherFunctionDefinitions } from '../lib/openAPI/ApiBuildCollector'
26
+ import { delay } from '../lib/utils'
27
+ import { addBuiltInDefinitions, MakeBuiltinApiDoc } from './builtin/ApiDocMaker'
28
+ import { DeployApiBuiltin, DeployRootFileserves, DeployWebrootBuiltIn } from './builtin/BuiltInHandler'
29
+ import { getProjectName, getProjectVersion } from '../lib/LiftVersion'
30
+ import md5 from 'md5'
31
+
32
+ let projectPaths: any
33
+
34
+ export async function doPublishAsync (stageName?: string): Promise<number> {
35
+ // let retCode = await doDeployAsync([])
36
+ // if(retCode) return retCode
37
+ const retCode = 0
38
+
39
+ projectPaths = resolvePaths()
40
+ if (projectPaths.verified !== true) {
41
+ console.log(ac.bold.magenta('current directory is not at project root'))
42
+ return -1
43
+ }
44
+
45
+ await publishApi(stageName ?? 'Dev')
46
+
47
+ return retCode
48
+ }
49
+
50
+ async function publishApi (
51
+ stageName?: string
52
+ ): Promise<void> {
53
+ if (stageName === undefined) stageName = 'Dev'
54
+ console.log(ac.green.bold(`Publishing Api to ${stageName}`))
55
+
56
+ // do the built-in deploys
57
+ await DeployWebrootBuiltIn()
58
+ await DeployRootFileserves()
59
+ await DeployApiBuiltin()
60
+
61
+ // make a private api
62
+ // const fs = require('fs')
63
+ // const os = require('os')
64
+ // const path = require('path')
65
+
66
+ let tmpDir
67
+ let apiBytes
68
+ const appPrefix = 'MistLift'
69
+ try {
70
+ tmpDir = path.join(os.tmpdir(), appPrefix)
71
+ // console.log("making "+tmpDir)
72
+ mkdirSync(tmpDir, { recursive: true })
73
+
74
+ const yamlFile = path.join(tmpDir, 'papi.yaml')
75
+ await MakeBuiltinApiDoc(yamlFile)
76
+ // console.log("reading "+yamlFile)
77
+ apiBytes = fs.readFileSync(yamlFile)
78
+ } catch (e: any) {
79
+ console.error(ac.red.bold('Error creating temp staging folder ') + (e.message as string))
80
+ throw Error()
81
+ } finally {
82
+ try {
83
+ if (tmpDir !== undefined) {
84
+ fs.rmSync(tmpDir, { recursive: true })
85
+ }
86
+ } catch (e: any) {
87
+ console.error(`An error has occurred while removing the temp folder at ${tmpDir ?? ''}. Please remove it manually. Error: ${(e.message as string)}`)
88
+ }
89
+ }
90
+
91
+ const client = new APIGatewayClient(getAWSCredentials())
92
+
93
+ await RemoveExistingVersions(client)
94
+
95
+ const command = new ImportRestApiCommand({
96
+ failOnWarnings: false,
97
+ body: apiBytes
98
+ })
99
+ let apiId
100
+ try {
101
+ const response = await client.send(command)
102
+ const { name, id, version, warnings } = response
103
+ console.log(ac.grey(`\n\nAPI ${name ?? ''} version ${version ?? ''} [${id ?? ''}] schema created`))
104
+ apiId = id ?? ''
105
+ if (warnings?.length !== 0) {
106
+ console.log(ac.magenta(` with ${warnings?.length ?? 0} warnings`))
107
+ if (warnings !== undefined) {
108
+ for (const warning of warnings) {
109
+ console.log(ac.grey.italic(` ${warning}`))
110
+ }
111
+ }
112
+ }
113
+ } catch (e: any) {
114
+ console.error(ac.bold.red(e.message))
115
+ }
116
+ // const apidoc = new TextDecoder().decode(apiBytes)
117
+ // console.log(apidoc)
118
+ if (apiId === '') return
119
+
120
+ console.log(ac.grey('Continuing with binding...'))
121
+ const prereq = await PrequisiteValues(apiId ?? '')
122
+ const intRequests = prereq.MakeRequests()
123
+ await PutIntegrations(intRequests)
124
+ await DeployApi(apiId ?? '', stageName)
125
+ const region = getSettings()?.awsPreferredRegion ?? ''
126
+ const publishUrl = `https://${apiId ?? ''}.execute-api.${region}.amazonaws.com/${stageName}`
127
+ console.log(ac.green.bold(`\n Successfully deployed to ${publishUrl}`))
128
+ recordLatestPublish(publishUrl)
129
+ }
130
+ function findApiName (): string {
131
+ const infoFile = path.join(projectPaths.functionPath, 'apiService.info.json')
132
+ const pkgFile = projectPaths.packagePath
133
+ let pkg: any = {}
134
+ if (fs.existsSync(pkgFile)) { pkg = JSON.parse(fs.readFileSync(pkgFile).toString()) }
135
+ let info: any = {}
136
+ if (fs.existsSync(infoFile)) { info = JSON.parse(fs.readFileSync(infoFile).toString()) }
137
+
138
+ return info.title ?? pkg.name ?? 'API'
139
+ }
140
+
141
+ async function RemoveExistingVersions (client: APIGatewayClient): Promise<void> {
142
+ await new Promise(resolve => {
143
+ const ourName = findApiName()
144
+ // ClogDebug("looking for name "+ ourName)
145
+ const listCommand = new GetRestApisCommand({})
146
+ client.send(listCommand).then((response: any) => {
147
+ // ClogInfo(`There are ${response.items.length} other APIs`)
148
+
149
+ const DeleteMatchingApis = async (i: number = 0): Promise<any> => {
150
+ if (i >= response.items.length) {
151
+ resolve(undefined)
152
+ return await Promise.resolve(undefined)
153
+ }
154
+ const item: { name: string, id: string } = response.items[i]
155
+ if (item.name === ourName) {
156
+ // ClogInfo(`Found previous ${ourName}, [${item.id}] -- deleting...`)
157
+ const deleteCommand = new DeleteRestApiCommand({
158
+ restApiId: item.id
159
+ })
160
+ return await client.send(deleteCommand).then(() => {
161
+ delay(5000).then(async () => {
162
+ console.log(ac.magenta.bold(`Removed previous id ${item.id}`))
163
+ return await DeleteMatchingApis(++i)
164
+ }).catch<any>((reason: any) => undefined)
165
+ }).catch<any>((reason: any) => undefined)
166
+ } else {
167
+ return await DeleteMatchingApis(++i)
168
+ }
169
+ }
170
+ DeleteMatchingApis().catch<any>((reason: any) => undefined)
171
+ }).catch<any>((reason: any) => undefined)
172
+ }).catch<any>((reason: any) => undefined)
173
+ }
174
+
175
+ class FunctionInfo {
176
+ name: string = ''
177
+ arn: string = ''
178
+ }
179
+
180
+ class PrereqInfo {
181
+ requestApiId: string = ''
182
+ functions: FunctionInfo[] = []
183
+ apis: any[] = [] // Resource + method
184
+ defs: any[] = []
185
+
186
+ public constructor () {
187
+ this.functions = []
188
+ this.apis = []
189
+ this.defs = []
190
+ }
191
+
192
+ public findApi (pathMap: string, allowedMethods: string): any {
193
+ // find the pathmap in the apis list
194
+ // console.log("findApi "+pathMap, allowedMethods)
195
+ // see that this method exists in method map
196
+ for (const api of this.apis) {
197
+ if (api?.path === pathMap) {
198
+ // console.log("resourceMethods", api.resourceMethods)
199
+ const methodList = Object.getOwnPropertyNames(api.resourceMethods)
200
+ // ClogTrace("methodList", methodList)
201
+ for (const meth of allowedMethods.toUpperCase().split(',')) {
202
+ // console.log("meth", meth)
203
+ if (methodList.includes(meth)) {
204
+ (api).method = meth
205
+ return api
206
+ }
207
+ }
208
+ }
209
+ }
210
+ return null
211
+ }
212
+
213
+ public findARN (name: string): string {
214
+ for (const f of this.functions ?? []) {
215
+ const lastus = f.name.lastIndexOf('_')
216
+ const fname = f.name.substring(0, lastus)
217
+ if (fname.toLowerCase() === name.toLowerCase()) return f.arn
218
+ }
219
+ console.log("$$$ Couldn't find " + name + ' in ', this.functions)
220
+ return ''
221
+ }
222
+
223
+ public MakeRequests (): PutIntegrationRequest[] {
224
+ const region = getSettings()?.awsPreferredRegion ?? ''
225
+ const out: PutIntegrationRequest[] = []
226
+ for (const d of this.defs) {
227
+ const def = (d)
228
+ const api = this.findApi(def.pathMap, def.allowedMethods)
229
+ const arn = this.findARN(def.name) ?? ''
230
+ if (arn === '') {
231
+ console.log(`>>> No ARN for ${(def.name as string)} ${(def.pathMap as string)}, ${(api.id as string)}`)
232
+ }
233
+ if (api !== undefined) {
234
+ out.push({
235
+ restApiId: this.requestApiId,
236
+ resourceId: api.id, // api.parentId
237
+ httpMethod: api.method,
238
+ integrationHttpMethod: 'POST', // api.method,
239
+ type: 'AWS_PROXY',
240
+ uri: `arn:aws:apigateway:${region}:lambda:path/2015-03-31/functions/${arn}/invocations`,
241
+ credentials: 'arn:aws:iam::545650260286:role/TBDLambdaExecution2'
242
+ })
243
+ }
244
+ }
245
+ return out
246
+ }
247
+ }
248
+
249
+ async function PrequisiteValues (id: string): Promise<PrereqInfo> {
250
+ const pri = new PrereqInfo()
251
+ const out = await GetFunctionInfo(pri)
252
+ out.defs = gatherFunctionDefinitions()
253
+ addBuiltInDefinitions(out.defs)
254
+ out.requestApiId = id
255
+ await GetMethodResources(id, out)
256
+
257
+ return out
258
+ }
259
+
260
+ async function GetFunctionInfo (info: PrereqInfo): Promise<PrereqInfo> {
261
+ const client = new LambdaClient(getAWSCredentials())
262
+ const listCommand: any = new ListFunctionsCommand({})
263
+ const response: any = await client.send(listCommand)
264
+
265
+ const sfx = '_' + md5((getProjectName() ?? '') + (getProjectVersion()?.toString() ?? ''))
266
+
267
+ for (const func of response.Functions ?? []) {
268
+ const fName: string = func?.FunctionName ?? ''
269
+ if (fName.endsWith(sfx)) {
270
+ info.functions.push({
271
+ name: func.FunctionName ?? '',
272
+ arn: func.FunctionArn ?? ''
273
+ })
274
+ }
275
+ }
276
+ return info
277
+ }
278
+
279
+ async function GetMethodResources (
280
+ id: string,
281
+ info: PrereqInfo
282
+ ): Promise<PrereqInfo> {
283
+ const client = new APIGatewayClient(getAWSCredentials())
284
+ const listCommand = new GetResourcesCommand({
285
+ restApiId: id
286
+ })
287
+ const response: GetResourcesCommandOutput = await client.send(listCommand)
288
+ // ClogInfo("Resources response", response)
289
+ if ((response?.items) != null) info.apis = response.items
290
+
291
+ return info
292
+ }
293
+
294
+ async function PutIntegrations (integrations: PutIntegrationRequest[]): Promise<void> {
295
+ const client = new APIGatewayClient(getAWSCredentials())
296
+ for (const input of integrations) {
297
+ try {
298
+ const command = new PutIntegrationCommand(input)
299
+ /* const intResp = */ await client.send(command)
300
+ // ClogDebug("integration response", intResp);
301
+ await delay(5000)
302
+ } catch (e: any) {
303
+ console.error('Problem with integration for ' + (input.uri as string), { input })
304
+ throw e
305
+ }
306
+ }
307
+ }
308
+
309
+ async function DeployApi (restApiId: string, stageName: string): Promise<void> {
310
+ try {
311
+ const client = new APIGatewayClient(getAWSCredentials())
312
+ const command = new CreateDeploymentCommand({
313
+ restApiId,
314
+ stageName
315
+ })
316
+ await client.send(command)
317
+ } catch (e: any) {
318
+ console.error(ac.red.bold(`Error with deployApi: ${e.message as string}`))
319
+ throw e
320
+ }
321
+ }
322
+
323
+ function recordLatestPublish (publishUrl: string): void {
324
+ const publishRecord = {
325
+ url: publishUrl,
326
+ time: Date.now()
327
+ }
328
+ const publishedFile = path.join(projectPaths.basePath, '.published')
329
+ fs.writeFileSync(publishedFile, JSON.stringify(publishRecord))
330
+ }