@tremho/mist-lift 2.2.8 → 2.4.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 (66) hide show
  1. package/README.md +9 -1
  2. package/build/commands/actions/updateDeployedPermissions.js +109 -0
  3. package/build/commands/actions/updateDeployedPermissions.js.map +1 -0
  4. package/build/commands/builtin/ApiDocMaker.js +18 -10
  5. package/build/commands/builtin/ApiDocMaker.js.map +1 -1
  6. package/build/commands/builtin/BuiltInHandler.js +6 -3
  7. package/build/commands/builtin/BuiltInHandler.js.map +1 -1
  8. package/build/commands/builtin/ExportWebroot.js +242 -0
  9. package/build/commands/builtin/ExportWebroot.js.map +1 -0
  10. package/build/commands/builtin/StageWebrootZip.js +10 -6
  11. package/build/commands/builtin/StageWebrootZip.js.map +1 -1
  12. package/build/commands/builtin/prebuilt-zips/API.zip +0 -0
  13. package/build/commands/builtin/prebuilt-zips/FileServe.zip +0 -0
  14. package/build/commands/builtin/prebuilt-zips/Webroot.zip +0 -0
  15. package/build/commands/builtin/webroot-export/s3webroot.js +117 -0
  16. package/build/commands/builtin/webroot-export/s3webroot.js.map +1 -0
  17. package/build/commands/deploy.js +6 -4
  18. package/build/commands/deploy.js.map +1 -1
  19. package/build/commands/package.js +31 -1
  20. package/build/commands/package.js.map +1 -1
  21. package/build/commands/publish.js +40 -13
  22. package/build/commands/publish.js.map +1 -1
  23. package/build/commands/start.js +2 -1
  24. package/build/commands/start.js.map +1 -1
  25. package/build/commands/update.js +1 -0
  26. package/build/commands/update.js.map +1 -1
  27. package/build/expressRoutes/all.js +1 -0
  28. package/build/expressRoutes/all.js.map +1 -1
  29. package/build/expressRoutes/functionBinder.js +159 -17
  30. package/build/expressRoutes/functionBinder.js.map +1 -1
  31. package/build/lib/DirectoryUtils.js +2 -1
  32. package/build/lib/DirectoryUtils.js.map +1 -1
  33. package/build/lib/IdSrc.js +29 -5
  34. package/build/lib/IdSrc.js.map +1 -1
  35. package/build/lib/TypeCheck.js +1204 -0
  36. package/build/lib/TypeCheck.js.map +1 -0
  37. package/build/lib/executeCommand.js +1 -1
  38. package/build/lib/executeCommand.js.map +1 -1
  39. package/build/lib/openAPI/openApiConstruction.js +238 -54
  40. package/build/lib/openAPI/openApiConstruction.js.map +1 -1
  41. package/build/lift.js +1 -1
  42. package/build/lift.js.map +1 -1
  43. package/package.json +5 -2
  44. package/src/commands/actions/updateDeployedPermissions.ts +80 -0
  45. package/src/commands/builtin/ApiDocMaker.ts +17 -10
  46. package/src/commands/builtin/BuiltInHandler.ts +7 -2
  47. package/src/commands/builtin/ExportWebroot.ts +195 -0
  48. package/src/commands/builtin/StageWebrootZip.ts +13 -5
  49. package/src/commands/builtin/prebuilt-zips/API.zip +0 -0
  50. package/src/commands/builtin/prebuilt-zips/FileServe.zip +0 -0
  51. package/src/commands/builtin/prebuilt-zips/Webroot.zip +0 -0
  52. package/src/commands/builtin/webroot-export/s3webroot.ts +78 -0
  53. package/src/commands/deploy.ts +6 -4
  54. package/src/commands/package.ts +33 -2
  55. package/src/commands/publish.ts +37 -12
  56. package/src/commands/start.ts +2 -1
  57. package/src/commands/update.ts +1 -0
  58. package/src/expressRoutes/all.ts +1 -0
  59. package/src/expressRoutes/functionBinder.ts +152 -16
  60. package/src/lib/DirectoryUtils.ts +2 -1
  61. package/src/lib/IdSrc.ts +17 -4
  62. package/src/lib/TypeCheck.ts +1168 -0
  63. package/src/lib/executeCommand.ts +1 -1
  64. package/src/lib/openAPI/openApiConstruction.ts +225 -41
  65. package/src/lift.ts +1 -1
  66. package/templateData/function-main-ts +8 -1
@@ -28,13 +28,17 @@ import { addBuiltInDefinitions, MakeBuiltinApiDoc } from './builtin/ApiDocMaker'
28
28
  import { DeployApiBuiltin, DeployRootFileserves, DeployWebrootBuiltIn } from './builtin/BuiltInHandler'
29
29
  import { esbuilder } from '../lib/ESBuild'
30
30
  import { getIdSrc, getIdDelimiter } from '../lib/IdSrc'
31
+ import { ExportWebroot, getWebrootSettings } from './builtin/ExportWebroot'
32
+ import { doDeployAsync } from './deploy'
33
+ import updateDeployedPermissions from './actions/updateDeployedPermissions'
31
34
 
32
35
  let projectPaths: any
33
36
 
34
- export async function doPublishAsync (stageName?: string): Promise<number> {
35
- // let retCode = await doDeployAsync([])
36
- // if(retCode) return retCode
37
- const retCode = 0
37
+ export async function doPublishAsync (args: string[] = []): Promise<number> {
38
+ const stageName = 'Dev'
39
+ const retCode = await doDeployAsync(args)
40
+ if (retCode) return retCode
41
+ // const retCode = 0
38
42
 
39
43
  projectPaths = resolvePaths()
40
44
  if (projectPaths.verified !== true) {
@@ -57,9 +61,10 @@ async function publishApi (
57
61
  await esbuilder(null, true)
58
62
  // do the built-in deploys
59
63
  // console.log(ac.gray.dim('>> webroot '))
60
- await DeployWebrootBuiltIn()
61
- // console.log(ac.gray.dim('>> fileserves '))
62
- await DeployRootFileserves()
64
+ // await DeployWebrootBuiltIn()
65
+ // // console.log(ac.gray.dim('>> fileserves '))
66
+ // await DeployRootFileserves()
67
+ await ExportWebroot()
63
68
  // console.log(ac.gray.dim('>> api built in '))
64
69
  await DeployApiBuiltin()
65
70
  // console.log(ac.gray.dim('>> past api built in '))
@@ -131,15 +136,20 @@ async function publishApi (
131
136
  if (apiId === '') return
132
137
 
133
138
  console.log(ac.grey('Continuing with binding...'))
139
+ // console.log("prerequisite values")
134
140
  const prereq = await PrequisiteValues(apiId ?? '')
135
- // console.log(ac.gray.dim('>> making intRequests'))
141
+ // console.log('>> making intRequests')
136
142
  const intRequests = prereq.MakeRequests()
137
- // console.log(ac.magenta.dim('>> putting integration'), intRequests)
143
+ // console.log('>> putting integration')
144
+ // console.log(ac.green("finalizing deployment..."))
138
145
  await PutIntegrations(intRequests)
146
+ // console.log("deploy api")
139
147
  const success = await DeployApi(apiId ?? '', stageName)
140
148
  const region = getSettings()?.awsPreferredRegion ?? ''
141
149
  const publishUrl = `https://${apiId ?? ''}.execute-api.${region}.amazonaws.com/${stageName}`
142
150
  const characterize = success ? 'Successfully' : ''
151
+ console.log(ac.green.italic('Updating bound function permissions...'))
152
+ await updateDeployedPermissions(apiId)
143
153
  console.log(ac.green.bold(`\n ${characterize} deployed to ${publishUrl}`))
144
154
  recordLatestPublish(publishUrl)
145
155
  }
@@ -224,17 +234,19 @@ class PrereqInfo {
224
234
  }
225
235
 
226
236
  public findARN (name: string): string {
237
+ // console.log("findARN")
227
238
  let lastDelim = name.lastIndexOf(getIdDelimiter())
228
239
  if (lastDelim !== -1) name = name.substring(0, lastDelim)
229
240
  // console.log(ac.grey.dim.italic("binding "+name))
230
241
  // console.warn(`>>> finding name ${name} in ${this.functions.length} functions`)
231
242
  for (const f of this.functions ?? []) {
243
+ // console.log("inspecting function " + f.name)
232
244
  lastDelim = f.name.lastIndexOf(getIdDelimiter())
233
245
  const fname = f.name.substring(0, lastDelim)
234
246
  // console.warn('comparing name, fname, lc ', {lastus: lastDelim, fname, name})
235
247
  if (fname.toLowerCase() === name.toLowerCase()) {
236
248
  // console.warn(">>> Match! ", f)
237
- console.log(ac.grey.dim.italic('binding ' + name))
249
+ // console.log(ac.grey.dim.italic('binding ' + name + ' to arn '+ f.arn))
238
250
  return f.arn
239
251
  }
240
252
  }
@@ -247,8 +259,10 @@ class PrereqInfo {
247
259
  const region = getSettings()?.awsPreferredRegion ?? ''
248
260
  const out: PutIntegrationRequest[] = []
249
261
 
262
+ // console.log("MakeRequests ", {region, defs:this.defs})
250
263
  for (const d of this.defs) {
251
264
  const def = (d)
265
+ // if(def.name === 'Webroot' || def.name.substring(0,9) === 'fileServe') continue
252
266
  // console.log(ac.magenta.dim('>> finding api and arn for '), {pathMap:def.pathMap, name: def.name})
253
267
  const api = this.findApi(def.pathMap, def.method)
254
268
  const arn = this.findARN(def.name) ?? ''
@@ -269,17 +283,27 @@ class PrereqInfo {
269
283
  })
270
284
  }
271
285
  }
286
+ // console.log("MakeRequests return ", {out})
272
287
  return out
273
288
  }
274
289
  }
275
290
 
276
291
  async function PrequisiteValues (id: string): Promise<PrereqInfo> {
292
+ // console.log("PrerequisiteValues", {id})
277
293
  const pri = new PrereqInfo()
278
294
  const out = await GetFunctionInfo(pri)
295
+ // console.log("function info", {functionList: out.functions})
279
296
  out.defs = gatherFunctionDefinitions()
280
- addBuiltInDefinitions(out.defs)
297
+ // console.log("gatherFunctionDefinitions returned ", {defs: out.defs})
298
+ const wrs = await getWebrootSettings()
299
+ const withWebroot = (wrs.webrootMethod ?? 'SELF') === 'SELF'
300
+ // console.log("wrs.webrootMethod=",wrs.webrootMethod)
301
+ // console.log("addBuiltInDefinitions", {withWebroot})
302
+ addBuiltInDefinitions(out.defs, withWebroot)
281
303
  out.requestApiId = id
304
+ // console.log("getMethodResources")
282
305
  await GetMethodResources(id, out)
306
+ // console.log("Prerequisite Values out", JSON.stringify(out,null,2))
283
307
 
284
308
  return out
285
309
  }
@@ -324,7 +348,7 @@ async function GetMethodResources (
324
348
  restApiId: id
325
349
  })
326
350
  const response: any = await client.send(listCommand)
327
- // ClogInfo("Resources response", response)
351
+ // console.log("Resources response", response)
328
352
  if ((response?.items) != null) info.apis = response.items
329
353
 
330
354
  return info
@@ -348,6 +372,7 @@ async function PutIntegrations (integrations: PutIntegrationRequest[]): Promise<
348
372
  async function DeployApi (restApiId: string, stageName: string): Promise<boolean> {
349
373
  let success = true
350
374
  try {
375
+ // console.log("Creating deployment for "+restApiId+", stage "+stageName)
351
376
  const client = new APIGatewayClient(getAWSCredentials())
352
377
  const command: any = new CreateDeploymentCommand({
353
378
  restApiId,
@@ -39,8 +39,9 @@ export async function startLocalServer (): Promise<void> {
39
39
  await functionBinder()
40
40
  // Log.Trace('done calling functionBinder')
41
41
  // for JSON posts
42
+ // app.use(express.raw({limit: '6mb'}))
42
43
  app.use(bodyParser.json({ limit: '50mb' }))
43
- app.use(express.json())
44
+ app.use(express.json({ limit: '6mb' }))
44
45
  // for form posts
45
46
  app.use(express.urlencoded({ extended: true }))
46
47
 
@@ -22,6 +22,7 @@ export async function doUpdateAsync (
22
22
  try {
23
23
  // console.warn(">>> esbuilder")
24
24
  await esbuilder(null, true)
25
+ console.log('>>>> TODO: Call ExportWebroot on update instead of these next two functions')
25
26
  // console.warn(">>> DeployRootFileserves")
26
27
  await DeployRootFileserves()
27
28
  // console.warn(">>> DeployWebrootBuiltIn")
@@ -7,6 +7,7 @@ import { gatherFunctionDefinitions } from '../lib/openAPI/ApiBuildCollector'
7
7
 
8
8
  import express from 'express'
9
9
  const router = express.Router()
10
+ // router.use( express.raw({type: 'application/octet-stream'}))
10
11
 
11
12
  export function allBinder (): void {
12
13
  const projectPaths = resolvePaths()
@@ -7,10 +7,12 @@ import { resolvePaths } from '../lib/pathResolve'
7
7
  import express from 'express'
8
8
  import { gatherFunctionDefinitions } from '../lib/openAPI/ApiBuildCollector'
9
9
  import { buildOpenApi } from '../lib/openAPI/openApiConstruction'
10
- import { Log } from '@tremho/inverse-y'
10
+ import { BadRequest, Log } from '@tremho/inverse-y'
11
+ import { parseConstraints } from '../lib/TypeCheck'
11
12
 
12
13
  const clearModule = require('clear-module')
13
14
  const router = express.Router()
15
+ router.use(express.raw({ type: '*/*', limit: '6mb' }))
14
16
 
15
17
  export function functionBinder (): void {
16
18
  const defs = gatherFunctionDefinitions()
@@ -43,23 +45,38 @@ export function functionBinder (): void {
43
45
  const n = entryRoot.indexOf('/{')
44
46
  if (n !== -1) entryRoot = entryRoot.substring(0, n) + '/*'
45
47
 
46
- const callHandler = (pathMap: string, req: any, res: any): void => {
47
- const event = requestToEvent(pathMap, req)
48
+ const callHandler = (def: any, req: any, res: any): void => {
49
+ console.log('>>>>>>> YES WE ARE HERE<<<<<<<<<')
50
+ if (Buffer.isBuffer(req.body)) {
51
+ const buffer: Buffer = req.body
52
+ console.log('body is a buffer at callHandler. Length is ' + buffer.byteLength)
53
+ console.log('First 16 bytes:', buffer.subarray(0, 16).toString('hex'))
54
+ }
55
+ const message = testPathRoute(def, req)
56
+ if (message) {
57
+ return handleResponse(res, { statusCode: 403, body: { error: message } })
58
+ }
59
+ const event = requestToEvent(def, req)
60
+ try {
61
+ performParameterTesting(def, event)
62
+ } catch (e: any) {
63
+ return handleResponse(res, { statusCode: 400, body: { error: e.message } })
64
+ }
48
65
  Promise.resolve(start(event, null, null)).then(respOut => {
49
66
  handleResponse(res, respOut)
50
67
  }).catch<any>((reason: any) => undefined)
51
68
  }
52
69
 
53
70
  if (method === 'get') {
54
- router.get(entryRoot, (req, res) => callHandler(pathMap, req, res))
71
+ router.get(entryRoot, (req, res) => callHandler(def, req, res))
55
72
  } else if (method === 'post') {
56
- router.post(entryRoot, (req, res) => callHandler(pathMap, req, res))
73
+ router.post(entryRoot, (req, res) => callHandler(def, req, res))
57
74
  } else if (method === 'put') {
58
- router.put(entryRoot, (req, res) => callHandler(pathMap, req, res))
75
+ router.put(entryRoot, (req, res) => callHandler(def, req, res))
59
76
  } else if (method === 'patch') {
60
- router.patch(entryRoot, (req, res) => callHandler(pathMap, req, res))
77
+ router.patch(entryRoot, (req, res) => callHandler(def, req, res))
61
78
  } else if (method === 'delete') {
62
- router.delete(entryRoot, (req, res) => callHandler(pathMap, req, res))
79
+ router.delete(entryRoot, (req, res) => callHandler(def, req, res))
63
80
  } else {
64
81
  console.log(ac.red.bold('Cannot map method ') + ac.blue.bold(method))
65
82
  }
@@ -73,19 +90,136 @@ export function functionBinder (): void {
73
90
  }).catch<any>((reason: any) => undefined)
74
91
  }
75
92
 
76
- function requestToEvent (template: string, req: any): any {
77
- console.log('requestToEvent (express)...', req.body, typeof (req.body))
93
+ // compare request route to the definition of this function to see if it matches
94
+ function testPathRoute (def: any, req: any) {
95
+ let path = req.path
96
+ let pathMap = def.pathMap
97
+ if (path.endsWith('/')) path = path.substring(0, path.length - 1)
98
+ if (pathMap.endsWith('/')) pathMap = pathMap.substring(0, path.length - 1)
99
+ const defParts = pathMap.split('/')
100
+ const pathParts = path.split('/')
101
+
102
+ let message = ''
103
+ if (pathParts.length > defParts.length) {
104
+ message = 'Too many parameters passed on path'
105
+ }
106
+ if (pathParts.length < defParts.length) {
107
+ message = 'Too few parameters passed on path'
108
+ }
109
+ return message
110
+ }
111
+
112
+ function performParameterTesting (def: any, event: any) {
113
+ // for every parameter defined in def
114
+ // find the corresponding value in event.parameters (by name)
115
+ // find the constraints for that parameter in def
116
+ // test the value against the constraints
117
+ for (const pdef of (def.parameters ?? [])) {
118
+ const constraints = Array.isArray(pdef.constraints) ? parseConstraints(pdef.type, pdef.constraints.join('\n'), '\n') : undefined
119
+ let value: any = event.parameters[pdef.name]
120
+ if (value === undefined) {
121
+ if (!pdef.required) return // okay to be undefined
122
+ }
123
+ if (pdef.type === 'number') value = Number(value) // TODO: Type coercion for all types
124
+ constraints?.test(value)
125
+ }
126
+ }
127
+
128
+ // returns 'text', 'json', or undefined
129
+ function bodyTypeCollapse (type: string) {
130
+ const options: any = {
131
+ text: 'text',
132
+ json: 'json',
133
+ 'application/json': 'json'
134
+ }
135
+ if (type) {
136
+ type = type.toLowerCase().trim()
137
+ if (type.substring(0, 5) === 'text/') return 'text'
138
+ return options[type]
139
+ }
140
+ }
141
+
142
+ function requestToEvent (def: any, req: any): any {
143
+ console.warn('requestToEvent (express)... body is type ', typeof (req.body))
144
+ const isBuffer = Buffer.isBuffer(req.body)
145
+ console.log('Body is a buffer ', isBuffer)
146
+ console.log('bodyType from def is ', def.bodyType)
147
+ // lets assume template says the type
148
+ const type = bodyTypeCollapse(def.bodyType)
149
+ console.log('collapsed bodyType is ', type)
150
+ if (type === 'text') {
151
+ console.log('>> we want plain text')
152
+ if (typeof req.body === 'object') {
153
+ console.log('>> requestToEvent modifying body (text)')
154
+ if (Buffer.isBuffer(req.body)) {
155
+ req.body = req.body.toString()
156
+ console.log('>> just turned it to a string ', req.body)
157
+ } else {
158
+ req.body = JSON.stringify(req.body)
159
+ console.log('>> is is an object, make it a json string ', req.body)
160
+ }
161
+ }
162
+ } else if (type === 'json') {
163
+ console.log('>> we want json')
164
+ if (typeof req.body === 'object') {
165
+ if (Buffer.isBuffer(req.body)) {
166
+ console.log('>> converting first from buffer to string')
167
+ req.body = req.body.toString()
168
+ }
169
+ }
170
+ if (typeof req.body === 'string') {
171
+ console.log('>> body is a string', req.body)
172
+ try {
173
+ console.log('>> requestToEvent modifying body (json2)')
174
+ req.body = JSON.parse(req.body)
175
+ console.log(">> it's now an object ", req.body)
176
+ } catch (e: any) {
177
+ console.error(ac.bold.red('Failed request body JSON parse '), req.body)
178
+ }
179
+ } else {
180
+ console.log('We already have an object here as ', req.body)
181
+ }
182
+ } else {
183
+ console.log('>> binary type path')
184
+ // binary expects a buffer
185
+ if (!Buffer.isBuffer(req.body)) { // if already a buffer, leave as is
186
+ if (typeof req.body === 'object') {
187
+ req.body = JSON.stringify(req.body) // make a string first before we bufferize the json
188
+ }
189
+ req.body = Buffer.from(req.body)
190
+ }
191
+ }
192
+ if (Buffer.isBuffer(req.body)) {
193
+ const buffer: Buffer = req.body
194
+ console.log('body is buffer eventToRequest, Length = ' + buffer.byteLength)
195
+ console.log('First 16 bytes:', buffer.subarray(0, 16).toString('hex'))
196
+ }
197
+ const template = def.pathMap
198
+
78
199
  // unpack weird choice of express when passed from curl.
79
- if (typeof (req.body) === 'object') {
80
- const bprops = Object.getOwnPropertyNames(req.body)
200
+ /*
201
+ if (typeof (req.body) === 'object' && !Buffer.isBuffer(req.body)) {
202
+ console.log(">> in curl case", req.body)
203
+ let bprops:string[] = []
204
+ try {
205
+ bprops = Object.getOwnPropertyNames(req.body)
206
+ console.log(">> bprops ", bprops)
207
+ } catch(e:any) {}
81
208
  if (bprops.length === 1) {
209
+ const bText = req.body[bprops[0]]
210
+ console.log(">> bText ",bText)
82
211
  try {
83
- req.body = JSON.parse(bprops[0])
212
+ req.body = JSON.parse(bText)
84
213
  } catch (e: any) {
85
- console.error('failed request body parse', bprops[0])
214
+ console.warn(ac.bold.yellow.italic('Failed request body JSON parse Yellow'), '(curl)')
215
+ req.body = bText
216
+ return requestToEvent(def, req)
86
217
  }
87
218
  }
88
219
  }
220
+ */
221
+
222
+ console.log('last look at body', req.body)
89
223
 
90
224
  let path: string = req.originalUrl ?? ''
91
225
  const qi = path.indexOf('?')
@@ -115,7 +249,9 @@ function requestToEvent (template: string, req: any): any {
115
249
  const brknm = (tslots[i] ?? '').trim()
116
250
  if (brknm.charAt(0) === '{') {
117
251
  const pn = brknm.substring(1, brknm.length - 1)
118
- parameters[pn] = (pslots[i] ?? '').trim()
252
+ let pv: string | undefined = (pslots[i] ?? '').trim()
253
+ if (pv === 'undefined' || pv === '~') pv = undefined
254
+ parameters[pn] = pv
119
255
  }
120
256
  }
121
257
  for (const p of Object.getOwnPropertyNames(req.query)) {
@@ -125,7 +261,7 @@ function requestToEvent (template: string, req: any): any {
125
261
  // console.warn(">>> functionBinder geting headers", {req, headers})
126
262
  // const apiKey = req.header('x-api-key')
127
263
  // console.warn(">>> apiKey returned using header function", {apiKey})
128
- console.log('making eventOut with req.body=', req.body)
264
+ // console.log('making eventOut with req.body=', req.body)
129
265
  const eventOut: any = {
130
266
  requestContext: req,
131
267
  request: {
@@ -7,7 +7,8 @@ export type RecurseCB = (filepath: string, stats: Stats) => boolean
7
7
 
8
8
  // Recurse a directory, calling back to a 'for-each' callback for all files in tree
9
9
  export function recurseDirectory (dirpath: string, callback?: RecurseCB): void {
10
- fs.readdirSync(dirpath).forEach((file: string) => {
10
+ const fl = fs.readdirSync(dirpath)
11
+ fl.forEach((file: string) => {
11
12
  const fpath = path.join(dirpath, file)
12
13
  // if(fpath.indexOf('node_modules') === -1) {
13
14
  const stat = fs.statSync(fpath)
package/src/lib/IdSrc.ts CHANGED
@@ -1,6 +1,7 @@
1
1
 
2
2
  import { getProjectName, getProjectVersion } from '../lib/LiftVersion'
3
3
  import sha1 from 'sha1'
4
+ import { STSClient, GetCallerIdentityCommand } from '@aws-sdk/client-sts'
4
5
 
5
6
  export function getIdDelimiter (): string {
6
7
  return '_-_'
@@ -10,10 +11,14 @@ export function getIdSrc (): string {
10
11
  while (idsrc.includes(' ')) idsrc = idsrc.replace(' ', '_')
11
12
  while (idsrc.includes('.')) idsrc = idsrc.replace('.', '-')
12
13
 
14
+ const projectHash = sha1(idsrc).toString().substring(0, 8)
15
+ // console.log("project hash", {idsrc, projectHash})
16
+ idsrc = getProjectName() + '_' + projectHash
17
+ // console.log("idsrc is "+idsrc)
13
18
  return idsrc
14
19
  }
15
20
  export function decoratedName (name: string): string {
16
- if (name.includes(getIdDelimiter())) {
21
+ if (name.includes(getIdDelimiter()) && name.includes(getIdSrc())) {
17
22
  // console.warn('name '+name+' appears to be decorated already')
18
23
  return name
19
24
  }
@@ -22,13 +27,21 @@ export function decoratedName (name: string): string {
22
27
 
23
28
  const hash8 = sha1(name.toLowerCase()).toString().substring(0, 8)
24
29
 
25
- const fullName = name + getIdDelimiter() + getIdSrc()
30
+ const fullName = name + getIdDelimiter() + '_' + getIdSrc()
31
+ // console.log("fullname is "+fullName)
26
32
  let dname
27
33
  if (name.startsWith('fileserve_')) {
28
- dname = ('fileServe_' + hash8 + getIdDelimiter() + getIdSrc()).substring(0, 64)
34
+ dname = ('fileServe_' + hash8 + getIdDelimiter() + '_' + getIdSrc()).substring(0, 64)
29
35
  } else {
30
- dname = fullName.substring(0, 50) + '_' + hash8
36
+ dname = fullName // .substring(0, 50) + '_' + hash8
31
37
  }
32
38
  // console.warn('decorated to '+dname+' from '+name)
33
39
  return dname
34
40
  }
41
+
42
+ export async function getAccountId () {
43
+ const client = new STSClient({} as any)
44
+ const command: any = new GetCallerIdentityCommand({})
45
+ const response: any = await client.send(command)
46
+ return response.Account // This is your AWS account ID
47
+ }