1
- let { join } = require ( 'path' )
2
- let { existsSync, readFileSync } = require ( 'fs' )
3
1
let { updater } = require ( '@architect/utils' )
4
- let { prompt } = require ( 'enquirer' )
5
- let colors = require ( 'ansi-colors' )
6
2
let update = updater ( 'Invoker' )
7
- let mock = require ( './event-mocks ' )
8
- let { marshall } = require ( '@aws-sdk/util-dynamodb ' )
3
+ let bindInputHandler = require ( './input-handler ' )
4
+ let { start , end , defaultPragmas } = require ( './utils ' )
9
5
let deactivatedInvoke = async ( ) => console . log ( 'Sandbox not yet started!' )
10
6
11
- let lastInvoke
12
-
13
7
let sandbox = {
14
8
start : async ( { inventory : { inv } , invoke } ) => {
15
9
start ( )
10
+ let pragmas = defaultPragmas . slice ( 0 )
16
11
update . status ( `Event invoker started, select an event to invoke by pressing 'i'` )
17
12
plugin . invoke = invoke
18
- let { cwd, preferences } = inv . _project
19
- let jsonMocks = join ( cwd , 'sandbox-invoke-mocks.json' )
20
- let jsMocks = join ( cwd , 'sandbox-invoke-mocks.js' )
21
- let cjsMocks = join ( cwd , 'sandbox-invoke-mocks.cjs' )
22
- let mjsMocks = join ( cwd , 'sandbox-invoke-mocks.mjs' )
23
-
24
- let pragmas = [ 'customLambdas' , 'events' , 'queues' , 'scheduled' , 'tables-streams' ]
13
+ let { preferences } = inv . _project
25
14
let prefs = preferences ?. sandbox ?. invoker
26
15
if ( prefs ) {
27
16
if ( Array . isArray ( prefs ) ) pragmas = prefs
28
17
else if ( typeof prefs === 'string' ) pragmas = [ prefs ]
29
18
else throw Error ( 'Invalid @architect/plugin-lambda-invoker plugin preferences' )
30
19
}
31
-
32
- process . stdin . on ( 'data' , async function eventInvokeListener ( input ) {
33
- // Build out the available event list each time to prevent caching
34
- let events = { }
35
- pragmas . forEach ( pragma => {
36
- if ( inv [ pragma ] ) inv [ pragma ] . forEach ( ( { name } ) => {
37
- events [ `@${ pragma } ${ name } ` ] = { pragma, name }
38
- } )
39
- } )
40
- // Add a cancel option should one desire
41
- events . cancel = ''
42
-
43
- let lastEventName
44
- if ( lastInvoke ) {
45
- lastEventName = `Last invoke: @${ lastInvoke . pragma } ${ lastInvoke . name } (${ lastInvoke . mockName } )`
46
- events [ lastEventName ] = lastInvoke
47
- }
48
-
49
- start ( )
50
- input = String ( input )
51
- // Reset Enquirer's styles
52
- let options = {
53
- prefix : colors . white ( colors . symbols ?. question ?? '?' ) ,
54
- styles : {
55
- em : colors . cyan , // Clear underlines
56
- danger : colors . red ,
57
- strong : colors . white ,
58
- } ,
59
- }
60
- if ( input === 'i' ) {
61
- if ( Object . keys ( events ) . length === 1 ) {
62
- let none = 'No Lambdas found to invoke'
63
- if ( pragmas . length ) update . status ( none , `Using the following pragmas: @${ pragmas . join ( ', @' ) } ` )
64
- else update . status ( none )
65
- return
66
- }
67
-
68
- let userPayload = { }
69
- let mockName = 'empty'
70
- let pragma , name , mocks , skipSelection
71
-
72
- // Load invocation mocks
73
- /**/ if ( existsSync ( jsonMocks ) ) {
74
- mocks = JSON . parse ( readFileSync ( jsonMocks ) )
75
- }
76
- else if ( existsSync ( jsMocks ) ) {
77
- mocks = await getMod ( jsMocks )
78
- }
79
- else if ( existsSync ( cjsMocks ) ) {
80
- // eslint-disable-next-line
81
- mocks = require ( cjsMocks )
82
- }
83
- else if ( existsSync ( mjsMocks ) ) {
84
- mocks = await getMod ( mjsMocks )
85
- }
86
-
87
- try {
88
- let { lambda } = await prompt ( {
89
- type : 'select' ,
90
- name : 'lambda' ,
91
- numbered : true ,
92
- message : 'Which event do you want to invoke?' ,
93
- hint : '\nYou can use numbers to change your selection' ,
94
- choices : Object . keys ( events ) ,
95
- } , options )
96
- if ( lambda === 'cancel' ) return start ( )
97
- else if ( lambda === lastEventName ) {
98
- skipSelection = true
99
- var event = events [ lastEventName ]
100
- mockName = event . mockName
101
- }
102
- else {
103
- var event = events [ lambda ]
104
- }
105
- pragma = event . pragma
106
- name = event . name
107
-
108
- // Set up non-cached user payload from last event
109
- if ( lambda === lastEventName ) {
110
- userPayload = mocks [ pragma ] [ name ] [ mockName ] || { }
111
- }
112
- }
113
- catch {
114
- update . status ( 'Canceled invoke' )
115
- return start ( )
116
- }
117
-
118
- // Present options for mocks (if any)
119
- let mockable = ! [ 'scheduled' , 'tables-streams' ] . includes ( pragma )
120
- if ( mocks ?. [ pragma ] ?. [ name ] && mockable && ! skipSelection ) {
121
- let selection = await prompt ( {
122
- type : 'select' ,
123
- name : 'mock' ,
124
- numbered : true ,
125
- message : 'Which mock do you want to invoke?' ,
126
- choices : [ ...Object . keys ( mocks [ pragma ] [ name ] ) , 'empty' ] ,
127
- } , options )
128
- mockName = selection . mock
129
- userPayload = mocks [ pragma ] [ name ] [ mockName ] || { }
130
- }
131
- lastInvoke = { pragma, name, mockName, userPayload }
132
-
133
- let payload
134
- /**/ if ( pragma === 'events' ) payload = mock . events ( userPayload )
135
- else if ( pragma === 'queues' ) payload = mock . queues ( userPayload )
136
- else if ( pragma === 'scheduled' ) payload = mock . scheduled ( )
137
- else if ( pragma === 'customLambdas' ) payload = mock . customLambdas ( userPayload )
138
- else if ( pragma === 'tables-streams' ) {
139
- let { eventName } = await prompt ( {
140
- type : 'select' ,
141
- name : 'eventName' ,
142
- message : 'Which kind of Dynamo Stream event do you want to invoke?' ,
143
- choices : [ 'INSERT' , 'MODIFY' , 'REMOVE' ] ,
144
- } )
145
- payload = mock . tablesStreams ( eventName , marshallJson ( mocks ?. [ pragma ] ?. [ name ] ?. [ eventName ] ) )
146
- }
147
- else {
148
- if ( ! Object . keys ( userPayload ) . length ) {
149
- update . warning ( 'Warning: real AWS event sources generally do not emit empty payloads' )
150
- }
151
- payload = userPayload
152
- }
153
-
154
- // Wrap it up and invoke!
155
- let msg = `Invoking @${ pragma } ${ name } `
156
- msg += ` with ${ mockName === 'empty' ? 'empty' : `'${ mockName } '` } payload`
157
- update . status ( msg )
158
- await invoke ( { pragma, name, payload } )
159
- start ( )
160
- }
161
- } )
20
+ process . stdin . on ( 'data' , bindInputHandler ( update , pragmas , inv , invoke ) )
162
21
} ,
163
22
end : async ( ) => {
164
23
// Only remove our listener; removing Enquirer causes funky behavior
@@ -178,60 +37,3 @@ let plugin = {
178
37
}
179
38
module . exports = plugin
180
39
181
- // Necessary per Enquirer #326
182
- function start ( ) {
183
- if ( process . stdin . isTTY ) {
184
- process . stdin . setRawMode ( true )
185
- process . stdin . setEncoding ( 'utf8' )
186
- process . stdin . resume ( )
187
- }
188
- }
189
-
190
- // Super important to pause stdin, or Sandbox will hang forever in tests
191
- function end ( ) {
192
- if ( process . stdin . isTTY ) {
193
- process . stdin . pause ( )
194
- }
195
- }
196
-
197
-
198
- let esmErrors = [
199
- 'Cannot use import statement outside a module' ,
200
- `Unexpected token 'export'` ,
201
- 'require() of ES Module' ,
202
- 'Must use import to load ES Module' ,
203
- ]
204
- let hasEsmError = err => esmErrors . some ( msg => err . message . includes ( msg ) )
205
- async function getMod ( filepath ) {
206
- let mod
207
-
208
- // Best effort to ensure changes to mocks are always reflected
209
- delete require . cache [ require . resolve ( filepath ) ]
210
-
211
- try {
212
- mod = require ( filepath )
213
- }
214
- catch ( err ) {
215
- if ( hasEsmError ( err ) ) {
216
- let path = process . platform . startsWith ( 'win' )
217
- ? 'file://' + filepath
218
- : filepath
219
- let imported = await import ( path )
220
- mod = imported . default ? imported . default : imported
221
- }
222
- else {
223
- throw err
224
- }
225
- }
226
-
227
- return mod
228
- }
229
- // Marshalls Json from the mock into keys and newimage for tables-streams
230
- function marshallJson ( json ) {
231
- const marshalled = marshall ( json )
232
- const Keys = Object . keys ( marshalled ) . reduce ( ( keys , key ) => {
233
- keys [ key ] = { [ Object . keys ( marshalled [ key ] ) [ 0 ] ] : true }
234
- return keys
235
- } , { } )
236
- return { Keys, NewImage : marshalled }
237
- }
0 commit comments