@tremho/mist-lift 2.2.1 → 2.2.3

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 (38) hide show
  1. package/README.md +8 -0
  2. package/build/commands/build.js +39 -27
  3. package/build/commands/build.js.map +1 -1
  4. package/build/commands/builtin/ApiDocMaker.js +23 -6
  5. package/build/commands/builtin/ApiDocMaker.js.map +1 -1
  6. package/build/commands/builtin/BuiltInHandler.js +3 -1
  7. package/build/commands/builtin/BuiltInHandler.js.map +1 -1
  8. package/build/commands/builtin/DeployBuiltInZip.js +6 -38
  9. package/build/commands/builtin/DeployBuiltInZip.js.map +1 -1
  10. package/build/commands/builtin/StageWebrootZip.js +16 -2
  11. package/build/commands/builtin/StageWebrootZip.js.map +1 -1
  12. package/build/commands/deploy.js +9 -0
  13. package/build/commands/deploy.js.map +1 -1
  14. package/build/commands/doctor.js +21 -1
  15. package/build/commands/doctor.js.map +1 -1
  16. package/build/commands/publish.js +32 -14
  17. package/build/commands/publish.js.map +1 -1
  18. package/build/commands/test.js +42 -12
  19. package/build/commands/test.js.map +1 -1
  20. package/build/commands/update.js +1 -1
  21. package/build/commands/update.js.map +1 -1
  22. package/build/lib/IdSrc.js +21 -1
  23. package/build/lib/IdSrc.js.map +1 -1
  24. package/build/lift.js +1 -2
  25. package/build/lift.js.map +1 -1
  26. package/package.json +1 -1
  27. package/src/commands/build.ts +36 -29
  28. package/src/commands/builtin/ApiDocMaker.ts +20 -3
  29. package/src/commands/builtin/BuiltInHandler.ts +3 -1
  30. package/src/commands/builtin/DeployBuiltInZip.ts +5 -15
  31. package/src/commands/builtin/StageWebrootZip.ts +16 -2
  32. package/src/commands/deploy.ts +10 -0
  33. package/src/commands/doctor.ts +19 -0
  34. package/src/commands/publish.ts +35 -15
  35. package/src/commands/test.ts +16 -7
  36. package/src/commands/update.ts +1 -1
  37. package/src/lib/IdSrc.ts +19 -1
  38. package/src/lift.ts +1 -1
@@ -68,12 +68,16 @@ export async function doDeployAsync (
68
68
  })
69
69
  }
70
70
 
71
+ // console.log(ac.gray.dim('>> beginning loop in doDeployAsync '))
72
+
71
73
  for (const funcName of funcsToDeploy) {
72
74
  const zipFile = path.join(projectPaths.basePath, 'MistLift_Zips', funcName + '.zip')
73
75
  if (fs.existsSync(zipFile)) {
74
76
  const zipTime = fs.statSync(zipFile).mtime
75
77
  if (zipTime.getTime() > (deploymentRecord[funcName] ?? 0)) {
78
+ // console.log(ac.gray.dim('>> calling deployPackage '))
76
79
  await deployPackage(funcName)
80
+ // console.log(ac.gray.dim('>> recording result '))
77
81
  deploymentRecord[funcName] = Date.now()
78
82
  }
79
83
  } else {
@@ -84,6 +88,7 @@ export async function doDeployAsync (
84
88
 
85
89
  try { fs.writeFileSync(deploymentRecordPath, JSON.stringify(deploymentRecord)) } catch {}
86
90
 
91
+ // console.log(ac.gray.dim('>> returning from doDeployAsync '))
87
92
  return 0
88
93
  }
89
94
 
@@ -132,10 +137,13 @@ export async function deployPackage (
132
137
  const principal = parts[4]
133
138
  await AddPermissions(client, dFuncName, principal)
134
139
  let deployMsg: string = `Successfully deployed ${funcName}`
140
+ // console.log(ac.gray.dim('>> deploy trace 1'))
135
141
  if (memorySize > 0 || timeout > 0) {
142
+ // console.log(ac.gray.dim('>> deploy trace 1a'))
136
143
  deployMsg += ac.grey.italic(' with ')
137
144
  const useAnd = memorySize > 9 && timeout > 0
138
145
  if (memorySize > 0) {
146
+ // console.log(ac.gray.dim('>> deploy trace 1b'))
139
147
  deployMsg += ac.grey(`memorySize ${memorySize}mb`)
140
148
  if (useAnd) deployMsg += ac.grey.italic(' and ')
141
149
  }
@@ -143,11 +151,13 @@ export async function deployPackage (
143
151
  deployMsg += ac.grey(`timeout ${timeout} seconds`)
144
152
  }
145
153
  }
154
+ // console.log(ac.gray.dim('>> deploy trace 2'))
146
155
 
147
156
  console.log(ac.green.bold(deployMsg))
148
157
  } catch (e: any) {
149
158
  console.error(ac.red.bold.italic('Error deploying ' + funcName), e)
150
159
  }
160
+ // console.log(ac.gray.dim('>> deploy trace 3'))
151
161
  }
152
162
  async function CreateCloudFunction (
153
163
  funcName: string,
@@ -5,6 +5,8 @@ import { executeCommand } from '../lib/executeCommand'
5
5
  import { resolvePaths } from '../lib/pathResolve'
6
6
  import { areSettingsAvailable } from '../lib/LiftConfig'
7
7
 
8
+ const minTapVersion = '19.2.5'
9
+
8
10
  export async function doDoctor (): Promise<boolean> {
9
11
  console.log(ac.blue.bold('Lift doctor'))
10
12
 
@@ -26,6 +28,11 @@ export async function doDoctor (): Promise<boolean> {
26
28
  ok = ok && report('Npm', npmVersion, isWin ? '9.6.4' : '10.3.0')
27
29
  report('Git', gitVersion, '2.0.0')
28
30
  report('unzip', unzipVersion, '1.0.0')
31
+
32
+ if (!await isTapInstalled()) {
33
+ console.log(ac.yellow.dim.bold.italic('\nTap is necessary for the lift test command.\nInstall with ') + ac.black.bold('npm i -g tap\n'))
34
+ }
35
+
29
36
  if (!settingsAvail) {
30
37
  console.log('')
31
38
  console.log(ac.yellow.dim.bold('Cloud Settings are not set. ') + ac.blue('run ' + ac.bold('lift settings')))
@@ -81,6 +88,13 @@ async function fetchNpmVersion (
81
88
  return vstr
82
89
  }
83
90
 
91
+ async function fetchTapVersion (): Promise<string> {
92
+ const result = await executeCommand('tap', ['-v'])
93
+ if (result.retcode !== 0) return 'Tap not found'
94
+ const vstr = versionTrim(result.stdStr)
95
+ return vstr
96
+ }
97
+
84
98
  async function fetchGitVersion (
85
99
 
86
100
  ): Promise<string> {
@@ -116,3 +130,8 @@ function report (
116
130
  }
117
131
  return ok
118
132
  }
133
+
134
+ export async function isTapInstalled (): Promise<boolean> {
135
+ const v = await fetchTapVersion()
136
+ return report('tap', v, minTapVersion)
137
+ }
@@ -27,7 +27,7 @@ import { delay } from '../lib/utils'
27
27
  import { addBuiltInDefinitions, MakeBuiltinApiDoc } from './builtin/ApiDocMaker'
28
28
  import { DeployApiBuiltin, DeployRootFileserves, DeployWebrootBuiltIn } from './builtin/BuiltInHandler'
29
29
  import { esbuilder } from '../lib/ESBuild'
30
- import { decoratedName, getIdDelimiter } from '../lib/IdSrc'
30
+ import { getIdSrc, getIdDelimiter } from '../lib/IdSrc'
31
31
 
32
32
  let projectPaths: any
33
33
 
@@ -53,19 +53,24 @@ async function publishApi (
53
53
  if (stageName === undefined) stageName = 'Dev'
54
54
  console.log(ac.green.bold(`Publishing Api to ${stageName}`))
55
55
 
56
- // console.log('esbuild...')
57
- await esbuilder()
58
- // console.log('done')
56
+ // console.log(ac.gray.dim('>> esbuilder '))
57
+ await esbuilder(null, true)
59
58
  // do the built-in deploys
59
+ // console.log(ac.gray.dim('>> webroot '))
60
60
  await DeployWebrootBuiltIn()
61
+ // console.log(ac.gray.dim('>> fileserves '))
61
62
  await DeployRootFileserves()
63
+ // console.log(ac.gray.dim('>> api built in '))
62
64
  await DeployApiBuiltin()
65
+ // console.log(ac.gray.dim('>> past api built in '))
63
66
 
64
67
  // make a private api
65
68
  // const fs = require('fs')
66
69
  // const os = require('os')
67
70
  // const path = require('path')
68
71
 
72
+ // console.log(ac.gray.dim('>> create staging folder '))
73
+
69
74
  let tmpDir
70
75
  let apiBytes
71
76
  const appPrefix = 'MistLift'
@@ -75,7 +80,9 @@ async function publishApi (
75
80
  mkdirSync(tmpDir, { recursive: true })
76
81
 
77
82
  const yamlFile = path.join(tmpDir, 'papi.yaml')
83
+ // console.log(ac.gray.dim('>> Make builtin ApiDoc '))
78
84
  await MakeBuiltinApiDoc(yamlFile)
85
+ // console.log(ac.gray.dim('>> Past making builtin ApiDoc '))
79
86
  // console.log("reading "+yamlFile)
80
87
  apiBytes = fs.readFileSync(yamlFile)
81
88
  } catch (e: any) {
@@ -90,9 +97,11 @@ async function publishApi (
90
97
  console.error(`An error has occurred while removing the temp folder at ${tmpDir ?? ''}. Please remove it manually. Error: ${(e.message as string)}`)
91
98
  }
92
99
  }
100
+ // console.log(ac.gray.dim('>> past that part, onto API Gateway '))
93
101
 
94
102
  const client = new APIGatewayClient(getAWSCredentials())
95
103
 
104
+ // console.log(ac.gray.dim('>> remove Existing versions '))
96
105
  await RemoveExistingVersions(client)
97
106
 
98
107
  const command: any = new ImportRestApiCommand({
@@ -123,15 +132,17 @@ async function publishApi (
123
132
 
124
133
  console.log(ac.grey('Continuing with binding...'))
125
134
  const prereq = await PrequisiteValues(apiId ?? '')
135
+ // console.log(ac.gray.dim('>> making intRequests'))
126
136
  const intRequests = prereq.MakeRequests()
137
+ // console.log(ac.magenta.dim('>> putting integration'), intRequests)
127
138
  await PutIntegrations(intRequests)
128
139
  await DeployApi(apiId ?? '', stageName)
129
140
  const region = getSettings()?.awsPreferredRegion ?? ''
130
141
  const publishUrl = `https://${apiId ?? ''}.execute-api.${region}.amazonaws.com/${stageName}`
131
142
  console.log(ac.green.bold(`\n Successfully deployed to ${publishUrl}`))
132
143
  recordLatestPublish(publishUrl)
133
- // process.exit(0) // this was a dumb idea
134
144
  }
145
+
135
146
  function findApiName (): string {
136
147
  const infoFile = path.join(projectPaths.functionPath, 'apiService.info.json')
137
148
  const pkgFile = projectPaths.packagePath
@@ -198,7 +209,7 @@ class PrereqInfo {
198
209
  if (api?.path === pathMap) {
199
210
  // console.log("resourceMethods", api.resourceMethods)
200
211
  const methodList: string[] = Object.getOwnPropertyNames(api.resourceMethods)
201
- // ClogTrace("methodList", methodList)
212
+ // console.log("methodList", methodList)
202
213
  for (const meth of allowedMethods.toUpperCase().split(',')) { // NOTE: we no longer try to support multiples, but this still works as is.
203
214
  // console.log("meth", meth)
204
215
  if (methodList.includes(meth)) {
@@ -212,9 +223,11 @@ class PrereqInfo {
212
223
  }
213
224
 
214
225
  public findARN (name: string): string {
215
- // console.warn(`>>> finding name ${name} in functions ${JSON.stringify(this.functions)}`)
226
+ let lastus = name.lastIndexOf(getIdDelimiter())
227
+ if (lastus !== -1) name = name.substring(0, lastus)
228
+ // console.warn(`>>> finding name ${name} in ${this.functions.length} functions`)
216
229
  for (const f of this.functions ?? []) {
217
- const lastus = f.name.lastIndexOf(getIdDelimiter())
230
+ lastus = f.name.lastIndexOf(getIdDelimiter())
218
231
  const fname = f.name.substring(0, lastus)
219
232
  // console.warn('comparing name, fname, lc ', {lastus, fname, name})
220
233
  if (fname.toLowerCase() === name.toLowerCase()) {
@@ -222,21 +235,26 @@ class PrereqInfo {
222
235
  return f.arn
223
236
  }
224
237
  }
225
- console.log("$$$ Couldn't find " + name + ' in ', this.functions)
238
+ console.error(ac.red.bold("$$ Couldn't find " + name + ' in integration list'))
239
+ process.exit(1)
226
240
  return ''
227
241
  }
228
242
 
229
243
  public MakeRequests (): PutIntegrationRequest[] {
230
244
  const region = getSettings()?.awsPreferredRegion ?? ''
231
245
  const out: PutIntegrationRequest[] = []
246
+
232
247
  for (const d of this.defs) {
233
248
  const def = (d)
249
+ // console.log(ac.magenta.dim('>> finding api and arn for '), {pathMap:def.pathMap, name: def.name})
234
250
  const api = this.findApi(def.pathMap, def.method)
235
251
  const arn = this.findARN(def.name) ?? ''
236
252
  if (arn === '') {
237
- console.log(`>>> No ARN for ${(def.name as string)} ${(def.pathMap as string)}, ${(api.id as string)}`)
253
+ console.log(ac.red.dim(`>>> No ARN for ${(def.name as string)} ${(def.pathMap as string)}, ${(api.id as string)}`))
254
+ process.exit(1)
238
255
  }
239
- if (api !== undefined) {
256
+ // console.log(ac.magenta.dim.italic('>> api for '+arn), api)
257
+ if (api !== null && api !== undefined && arn !== '') {
240
258
  out.push({
241
259
  restApiId: this.requestApiId,
242
260
  resourceId: api.id, // api.parentId
@@ -268,11 +286,13 @@ async function GetFunctionInfo (info: PrereqInfo): Promise<PrereqInfo> {
268
286
  const listCommand: any = new ListFunctionsCommand({})
269
287
  const response: any = await client.send(listCommand)
270
288
 
271
- const sfx = decoratedName('')
289
+ const sfx = getIdSrc()
272
290
 
273
291
  for (const func of response.Functions ?? []) {
274
292
  const fName: string = func?.FunctionName ?? ''
275
- if (fName.endsWith(sfx)) {
293
+ // console.log(ac.gray.dim('>> checking if '+fName+' has our suffix '+sfx))
294
+ if (fName.includes(sfx)) {
295
+ // console.log(ac.gray.dim('>>> Yes'))
276
296
  info.functions.push({
277
297
  name: func.FunctionName ?? '',
278
298
  arn: func.FunctionArn ?? ''
@@ -321,8 +341,8 @@ async function DeployApi (restApiId: string, stageName: string): Promise<void> {
321
341
  })
322
342
  await client.send(command)
323
343
  } catch (e: any) {
324
- console.error(ac.red.bold(`Error with deployApi: ${e.message as string}`))
325
- throw e
344
+ console.error(ac.red.bold(`Fatal Error with deployApi: ${e.message as string}`))
345
+ process.exit(-1)
326
346
  }
327
347
  }
328
348
 
@@ -1,14 +1,23 @@
1
1
  import { executeCommand } from '../lib/executeCommand'
2
2
  import { doBuildAsync } from './build'
3
+ import { isTapInstalled } from './doctor'
4
+ import * as ac from 'ansi-colors'
3
5
 
4
6
  export async function doTestAsync (args: string[]): Promise<number> {
5
7
  if (await doBuildAsync(args) !== 0) return 1 // don't test if build fails
8
+
9
+ if (!await isTapInstalled()) {
10
+ // don't continue if tap unavaiable
11
+ console.log(ac.yellow.dim.bold.italic('\nTap is necessary for the lift test command.\nInstall with ') + ac.black.bold('npm i -g tap\n'))
12
+ return 1
13
+ }
14
+
6
15
  if (args.length === 0) args = ['*']
7
16
  let ret = 0
8
17
  for (const funcName of args) {
9
18
  const result = await executeCommand('tap', [
10
- `build/functions/${funcName}/*.test.js`,
11
- /*
19
+ `functions/${funcName}/*.test.ts`,
20
+ /*
12
21
  - base -- looks a lot like terse
13
22
  - terse -- pass/fail counts
14
23
  - min -- errors only
@@ -20,11 +29,11 @@ export async function doTestAsync (args: string[]): Promise<number> {
20
29
  - junit
21
30
  - tap
22
31
  */
23
- '--reporter=base',
24
- '--color',
25
- '--passes',
26
- '--allow-empty-coverage',
27
- '--allow-incomplete-coverage'
32
+ '--reporter=base',
33
+ '--color',
34
+ '--passes',
35
+ '--allow-empty-coverage',
36
+ '--allow-incomplete-coverage'
28
37
 
29
38
  ], '', true)
30
39
 
@@ -21,7 +21,7 @@ export async function doUpdateAsync (
21
21
 
22
22
  try {
23
23
  // console.warn(">>> esbuilder")
24
- await esbuilder()
24
+ await esbuilder(null, true)
25
25
  // console.warn(">>> DeployRootFileserves")
26
26
  await DeployRootFileserves()
27
27
  // console.warn(">>> DeployWebrootBuiltIn")
package/src/lib/IdSrc.ts CHANGED
@@ -1,5 +1,6 @@
1
1
 
2
2
  import { getProjectName, getProjectVersion } from '../lib/LiftVersion'
3
+ import sha1 from 'sha1'
3
4
 
4
5
  export function getIdDelimiter (): string {
5
6
  return '_-_'
@@ -12,5 +13,22 @@ export function getIdSrc (): string {
12
13
  return idsrc
13
14
  }
14
15
  export function decoratedName (name: string): string {
15
- return name + getIdDelimiter() + getIdSrc()
16
+ if (name.includes(getIdDelimiter())) {
17
+ // console.warn('name '+name+' appears to be decorated already')
18
+ return name
19
+ }
20
+
21
+ while (name.includes('/')) name = name.replace('/', '')
22
+
23
+ const hash8 = sha1(name.toLowerCase()).toString().substring(0, 8)
24
+
25
+ const fullName = name + getIdDelimiter() + getIdSrc()
26
+ let dname
27
+ if (name.startsWith('fileserve_')) {
28
+ dname = ('fileServe_' + hash8 + getIdDelimiter() + getIdSrc()).substring(0, 64)
29
+ } else {
30
+ dname = fullName.substring(0, 50) + '_' + hash8
31
+ }
32
+ // console.warn('decorated to '+dname+' from '+name)
33
+ return dname
16
34
  }
package/src/lift.ts CHANGED
@@ -65,7 +65,7 @@ async function processCommand (): Promise<void> {
65
65
  return
66
66
  case 'publish': {
67
67
  const ret = await doPublishAsync()
68
- if (ret !== 0) process.exit(ret)
68
+ process.exit(ret)
69
69
  }
70
70
  return
71
71
  case 'update': {