@whook/gcp-functions 8.5.1 → 10.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 (40) hide show
  1. package/README.md +51 -40
  2. package/dist/commands/testHTTPFunction.d.ts +1 -1
  3. package/dist/commands/testHTTPFunction.js +119 -150
  4. package/dist/commands/testHTTPFunction.js.map +1 -1
  5. package/dist/index.d.ts +3 -6
  6. package/dist/index.js +182 -269
  7. package/dist/index.js.map +1 -1
  8. package/dist/libs/utils.js +16 -35
  9. package/dist/libs/utils.js.map +1 -1
  10. package/dist/services/_autoload.d.ts +14 -2
  11. package/dist/services/_autoload.js +85 -105
  12. package/dist/services/_autoload.js.map +1 -1
  13. package/dist/services/log.d.ts +4 -1
  14. package/dist/services/log.js +2 -12
  15. package/dist/services/log.js.map +1 -1
  16. package/dist/services/log.test.js +4 -9
  17. package/dist/services/log.test.js.map +1 -1
  18. package/dist/wrappers/googleHTTPFunction.js +246 -292
  19. package/dist/wrappers/googleHTTPFunction.js.map +1 -1
  20. package/package.json +55 -98
  21. package/src/commands/testHTTPFunction.ts +12 -19
  22. package/src/index.ts +48 -62
  23. package/src/libs/utils.ts +4 -5
  24. package/src/services/_autoload.ts +127 -122
  25. package/src/services/log.test.ts +2 -2
  26. package/src/wrappers/googleHTTPFunction.ts +34 -32
  27. package/dist/commands/testHTTPFunction.mjs +0 -136
  28. package/dist/commands/testHTTPFunction.mjs.map +0 -1
  29. package/dist/index.mjs +0 -265
  30. package/dist/index.mjs.map +0 -1
  31. package/dist/libs/utils.mjs +0 -27
  32. package/dist/libs/utils.mjs.map +0 -1
  33. package/dist/services/_autoload.mjs +0 -107
  34. package/dist/services/_autoload.mjs.map +0 -1
  35. package/dist/services/log.mjs +0 -4
  36. package/dist/services/log.mjs.map +0 -1
  37. package/dist/services/log.test.mjs +0 -7
  38. package/dist/services/log.test.mjs.map +0 -1
  39. package/dist/wrappers/googleHTTPFunction.mjs +0 -288
  40. package/dist/wrappers/googleHTTPFunction.mjs.map +0 -1
@@ -1,11 +1,12 @@
1
1
  import { initAutoload, noop, cleanupOpenAPI } from '@whook/whook';
2
- import Knifecycle, {
2
+ import {
3
+ Knifecycle,
3
4
  SPECIAL_PROPS,
4
5
  wrapInitializer,
5
6
  constant,
6
7
  alsoInject,
7
8
  } from 'knifecycle';
8
- import YError from 'yerror';
9
+ import { YError } from 'yerror';
9
10
  import {
10
11
  dereferenceOpenAPIOperations,
11
12
  getOpenAPIOperations,
@@ -16,12 +17,134 @@ import type {
16
17
  Initializer,
17
18
  Dependencies,
18
19
  Service,
20
+ ServiceInitializerWrapper,
19
21
  } from 'knifecycle';
20
22
  import type { WhookBuildConstantsService } from '@whook/whook';
21
23
  import type { WhookRawOperation } from '@whook/http-router';
22
24
  import type { LogService } from 'common-services';
23
25
  import type { OpenAPIV3 } from 'openapi-types';
24
- import type { WhookAPIOperationGCPFunctionConfig } from '..';
26
+ import type { WhookAPIOperationGCPFunctionConfig } from '../index.js';
27
+
28
+ const initializerWrapper: ServiceInitializerWrapper<
29
+ Autoloader<Initializer<Dependencies, Service>>,
30
+ Dependencies
31
+ > = (async (
32
+ {
33
+ BUILD_CONSTANTS = {},
34
+ $injector,
35
+ $instance,
36
+ log = noop,
37
+ }: {
38
+ BUILD_CONSTANTS?: WhookBuildConstantsService;
39
+ $injector: Injector<Service>;
40
+ $instance: Knifecycle;
41
+ log: LogService;
42
+ },
43
+ $autoload: Autoloader<Initializer<Dependencies, Service>>,
44
+ ): Promise<
45
+ (serviceName: string) => Promise<{
46
+ initializer: Initializer<Dependencies, Service>;
47
+ path: string;
48
+ }>
49
+ > => {
50
+ let API: OpenAPIV3.Document;
51
+ let OPERATION_APIS: WhookRawOperation<WhookAPIOperationGCPFunctionConfig>[];
52
+ const getAPIOperation = (() => {
53
+ return async (serviceName) => {
54
+ // eslint-disable-next-line
55
+ API = API || (await $injector(['API'])).API;
56
+ // eslint-disable-next-line
57
+ OPERATION_APIS =
58
+ OPERATION_APIS ||
59
+ getOpenAPIOperations<WhookAPIOperationGCPFunctionConfig>(API);
60
+
61
+ const OPERATION = OPERATION_APIS.find(
62
+ (operation) =>
63
+ serviceName ===
64
+ (((operation['x-whook'] || {}).sourceOperationId &&
65
+ 'OPERATION_API_' +
66
+ (operation['x-whook'] || {}).sourceOperationId) ||
67
+ 'OPERATION_API_' + operation.operationId) +
68
+ ((operation['x-whook'] || {}).suffix || ''),
69
+ );
70
+
71
+ if (!OPERATION) {
72
+ log('error', '💥 - Unable to find a lambda operation definition!');
73
+ throw new YError('E_OPERATION_NOT_FOUND', serviceName);
74
+ }
75
+
76
+ // eslint-disable-next-line
77
+ const OPERATION_API = cleanupOpenAPI({
78
+ ...API,
79
+ paths: {
80
+ [OPERATION.path]: {
81
+ [OPERATION.method]: API.paths[OPERATION.path]?.[OPERATION.method],
82
+ },
83
+ },
84
+ });
85
+
86
+ return {
87
+ ...OPERATION_API,
88
+ paths: {
89
+ [OPERATION.path]: {
90
+ [OPERATION.method]: (
91
+ await dereferenceOpenAPIOperations(OPERATION_API, [
92
+ {
93
+ path: OPERATION.path,
94
+ method: OPERATION.method,
95
+ ...OPERATION_API.paths[OPERATION.path]?.[OPERATION.method],
96
+ parameters: OPERATION.parameters,
97
+ },
98
+ ])
99
+ )[0],
100
+ },
101
+ },
102
+ };
103
+ };
104
+ })();
105
+
106
+ log('debug', '🤖 - Initializing the `$autoload` build wrapper.');
107
+
108
+ return async (serviceName) => {
109
+ try {
110
+ // TODO: add initializer map to knifecycle public API
111
+ const initializer = ($instance as any)._initializers.get(serviceName);
112
+
113
+ if (initializer && initializer[SPECIAL_PROPS.TYPE] === 'constant') {
114
+ log(
115
+ 'debug',
116
+ `🤖 - Reusing a constant initializer directly from the Knifecycle instance: "${serviceName}".`,
117
+ );
118
+ return {
119
+ initializer,
120
+ path: `instance://${serviceName}`,
121
+ };
122
+ }
123
+
124
+ if (serviceName.startsWith('OPERATION_API_')) {
125
+ const OPERATION_API = await getAPIOperation(serviceName);
126
+
127
+ return {
128
+ initializer: constant(serviceName, OPERATION_API),
129
+ path: `api://${serviceName}`,
130
+ };
131
+ }
132
+
133
+ if (BUILD_CONSTANTS[serviceName]) {
134
+ return {
135
+ initializer: constant(serviceName, BUILD_CONSTANTS[serviceName]),
136
+ path: `constant://${serviceName}`,
137
+ };
138
+ }
139
+
140
+ return $autoload(serviceName);
141
+ } catch (err) {
142
+ log('error', `Build error while loading "${serviceName}".`);
143
+ log('error-stack', (err as Error).stack || 'no_stack_trace');
144
+ throw err;
145
+ }
146
+ };
147
+ }) as any;
25
148
 
26
149
  /**
27
150
  * Wrap the _autoload service in order to build AWS
@@ -39,123 +162,5 @@ import type { WhookAPIOperationGCPFunctionConfig } from '..';
39
162
  */
40
163
  export default alsoInject(
41
164
  ['?BUILD_CONSTANTS', '$instance', '$injector', '?log'],
42
- wrapInitializer(
43
- async (
44
- {
45
- BUILD_CONSTANTS = {},
46
- $injector,
47
- $instance,
48
- log = noop,
49
- }: {
50
- BUILD_CONSTANTS?: WhookBuildConstantsService;
51
- $injector: Injector<Service>;
52
- $instance: Knifecycle<Dependencies>;
53
- log: LogService;
54
- },
55
- $autoload: Autoloader,
56
- ): Promise<
57
- (serviceName: string) => Promise<{
58
- initializer: Initializer<Dependencies, Service>;
59
- path: string;
60
- }>
61
- > => {
62
- let API: OpenAPIV3.Document;
63
- let OPERATION_APIS: WhookRawOperation<WhookAPIOperationGCPFunctionConfig>[];
64
- const getAPIOperation = (() => {
65
- return async (serviceName) => {
66
- // eslint-disable-next-line
67
- API = API || (await $injector(['API'])).API;
68
- // eslint-disable-next-line
69
- OPERATION_APIS =
70
- OPERATION_APIS ||
71
- getOpenAPIOperations<WhookAPIOperationGCPFunctionConfig>(API);
72
-
73
- const OPERATION = OPERATION_APIS.find(
74
- (operation) =>
75
- serviceName ===
76
- (((operation['x-whook'] || {}).sourceOperationId &&
77
- 'OPERATION_API_' +
78
- (operation['x-whook'] || {}).sourceOperationId) ||
79
- 'OPERATION_API_' + operation.operationId) +
80
- ((operation['x-whook'] || {}).suffix || ''),
81
- );
82
-
83
- if (!OPERATION) {
84
- log('error', '💥 - Unable to find a lambda operation definition!');
85
- throw new YError('E_OPERATION_NOT_FOUND', serviceName);
86
- }
87
-
88
- // eslint-disable-next-line
89
- const OPERATION_API = cleanupOpenAPI({
90
- ...API,
91
- paths: {
92
- [OPERATION.path]: {
93
- [OPERATION.method]: API.paths[OPERATION.path][OPERATION.method],
94
- },
95
- },
96
- });
97
-
98
- return {
99
- ...OPERATION_API,
100
- paths: {
101
- [OPERATION.path]: {
102
- [OPERATION.method]: (
103
- await dereferenceOpenAPIOperations(OPERATION_API, [
104
- {
105
- path: OPERATION.path,
106
- method: OPERATION.method,
107
- ...OPERATION_API.paths[OPERATION.path][OPERATION.method],
108
- parameters: OPERATION.parameters,
109
- },
110
- ])
111
- )[0],
112
- },
113
- },
114
- };
115
- };
116
- })();
117
-
118
- log('debug', '🤖 - Initializing the `$autoload` build wrapper.');
119
-
120
- return async (serviceName) => {
121
- try {
122
- // TODO: add initializer map to knifecycle public API
123
- const initializer = ($instance as any)._initializers.get(serviceName);
124
-
125
- if (initializer && initializer[SPECIAL_PROPS.TYPE] === 'constant') {
126
- log(
127
- 'debug',
128
- `🤖 - Reusing a constant initializer directly from the Knifecycle instance: "${serviceName}".`,
129
- );
130
- return {
131
- initializer,
132
- path: `instance://${serviceName}`,
133
- };
134
- }
135
-
136
- if (serviceName.startsWith('OPERATION_API_')) {
137
- const OPERATION_API = await getAPIOperation(serviceName);
138
-
139
- return {
140
- initializer: constant(serviceName, OPERATION_API),
141
- path: `api://${serviceName}`,
142
- };
143
- }
144
-
145
- if (BUILD_CONSTANTS[serviceName]) {
146
- return {
147
- initializer: constant(serviceName, BUILD_CONSTANTS[serviceName]),
148
- path: `constant://${serviceName}`,
149
- };
150
- }
151
-
152
- return $autoload(serviceName);
153
- } catch (err) {
154
- log('error', `Build error while loading "${serviceName}".`);
155
- log('stack', err.stack);
156
- }
157
- };
158
- },
159
- initAutoload,
160
- ),
165
+ wrapInitializer(initializerWrapper as any, initAutoload),
161
166
  );
@@ -1,7 +1,7 @@
1
- import initLogService from './log';
1
+ import initLogService from './log.js';
2
2
 
3
3
  describe('initLogService', () => {
4
4
  it('should work', async () => {
5
- await initLogService();
5
+ await initLogService({});
6
6
  });
7
7
  });
@@ -9,10 +9,10 @@ import {
9
9
  castParameters,
10
10
  } from '@whook/http-router';
11
11
  import { reuseSpecialProps, alsoInject } from 'knifecycle';
12
- import Ajv from 'ajv';
13
- import addAJVFormats from 'ajv-formats';
12
+ import { default as Ajv } from 'ajv';
13
+ import { default as addAJVFormats } from 'ajv-formats';
14
14
  import bytes from 'bytes';
15
- import HTTPError from 'yhttperror';
15
+ import { YHTTPError } from 'yhttperror';
16
16
  import {
17
17
  prepareParametersValidators,
18
18
  prepareBodyValidator,
@@ -88,7 +88,7 @@ export default function wrapHandlerForAWSHTTPFunction<
88
88
  ],
89
89
  reuseSpecialProps(
90
90
  initHandler,
91
- initHandlerForAWSHTTPFunction.bind(
91
+ (initHandlerForAWSHTTPFunction as any).bind(
92
92
  null,
93
93
  initHandler,
94
94
  ) as ServiceInitializer<D, S>,
@@ -97,7 +97,7 @@ export default function wrapHandlerForAWSHTTPFunction<
97
97
  }
98
98
 
99
99
  async function initHandlerForAWSHTTPFunction(
100
- initHandler: ServiceInitializer<unknown, WhookHandler>,
100
+ initHandler: ServiceInitializer<Dependencies<any>, WhookHandler>,
101
101
  {
102
102
  OPERATION_API,
103
103
  WRAPPERS,
@@ -125,9 +125,9 @@ async function initHandlerForAWSHTTPFunction(
125
125
  verbose: DEBUG_NODE_ENVS.includes(NODE_ENV),
126
126
  strict: true,
127
127
  logger: {
128
- log: (...args) => log('debug', ...args),
129
- warn: (...args) => log('warning', ...args),
130
- error: (...args) => log('error', ...args),
128
+ log: (...args) => log?.('debug', ...args),
129
+ warn: (...args) => log?.('warning', ...args),
130
+ error: (...args) => log?.('error', ...args),
131
131
  },
132
132
  useDefaults: true,
133
133
  coerceTypes: true,
@@ -213,10 +213,10 @@ async function handleForAWSHTTPFunction(
213
213
  req,
214
214
  res,
215
215
  ) {
216
- const debugging = DEBUG_NODE_ENVS.includes(NODE_ENV);
216
+ const debugging = (DEBUG_NODE_ENVS || []).includes(NODE_ENV);
217
217
  const bufferLimit = bytes.parse(BUFFER_LIMIT);
218
218
 
219
- log(
219
+ log?.(
220
220
  'info',
221
221
  'GCP_FUNCTIONS_REQUEST',
222
222
  JSON.stringify({
@@ -234,7 +234,7 @@ async function handleForAWSHTTPFunction(
234
234
  let responseLog;
235
235
  let responseSpec;
236
236
 
237
- log(
237
+ log?.(
238
238
  'debug',
239
239
  'REQUEST',
240
240
  JSON.stringify({
@@ -276,19 +276,21 @@ async function handleForAWSHTTPFunction(
276
276
  request.url.split(SEARCH_SEPARATOR)[0].length,
277
277
  );
278
278
 
279
- const pathParameters = OPERATION.path
280
- .split(PATH_SEPARATOR)
281
- .filter(identity)
282
- .map((part, index) => {
283
- const matches = /^\{([\d\w]+)\}$/i.exec(part);
284
-
285
- if (matches) {
286
- return {
287
- name: matches[1],
288
- value: parts[index],
289
- };
290
- }
291
- })
279
+ const pathParameters = (
280
+ OPERATION.path
281
+ .split(PATH_SEPARATOR)
282
+ .filter(identity)
283
+ .map((part, index) => {
284
+ const matches = /^\{([\d\w]+)\}$/i.exec(part);
285
+
286
+ if (matches) {
287
+ return {
288
+ name: matches[1],
289
+ value: parts[index],
290
+ };
291
+ }
292
+ }) as Array<{ name: string; value: string }>
293
+ )
292
294
  .filter(identity)
293
295
  .reduce(
294
296
  (accParameters, { name, value }) => ({
@@ -326,7 +328,7 @@ async function handleForAWSHTTPFunction(
326
328
  ...('undefined' !== typeof body ? { body } : {}),
327
329
  };
328
330
  } catch (err) {
329
- throw HTTPError.cast(err, 400);
331
+ throw YHTTPError.cast(err as Error, 400);
330
332
  }
331
333
 
332
334
  response = await executeHandler(operation, handler, parameters);
@@ -352,7 +354,7 @@ async function handleForAWSHTTPFunction(
352
354
  (responseSchema.type !== 'string' || responseSchema.format !== 'binary');
353
355
 
354
356
  if (responseHasSchema && !STRINGIFYERS[response.headers['content-type']]) {
355
- throw new HTTPError(
357
+ throw new YHTTPError(
356
358
  500,
357
359
  'E_STRINGIFYER_LACK',
358
360
  response.headers['content-type'],
@@ -366,9 +368,9 @@ async function handleForAWSHTTPFunction(
366
368
  type: 'success',
367
369
  status: response.status,
368
370
  };
369
- log('debug', JSON.stringify(responseLog));
371
+ log?.('debug', JSON.stringify(responseLog));
370
372
  } catch (err) {
371
- const castedError = HTTPError.cast(err);
373
+ const castedError = YHTTPError.cast(err as Error);
372
374
 
373
375
  responseLog = {
374
376
  type: 'error',
@@ -378,7 +380,7 @@ async function handleForAWSHTTPFunction(
378
380
  stack: castedError.stack,
379
381
  };
380
382
 
381
- log('error', JSON.stringify(responseLog));
383
+ log?.('error', JSON.stringify(responseLog));
382
384
  response = {
383
385
  status: castedError.httpCode,
384
386
  headers: {
@@ -396,7 +398,7 @@ async function handleForAWSHTTPFunction(
396
398
  };
397
399
  }
398
400
 
399
- log(
401
+ log?.(
400
402
  'debug',
401
403
  'RESPONSE',
402
404
  JSON.stringify({
@@ -441,8 +443,8 @@ async function pipeResponseInGCPFResponse(
441
443
  response: WhookResponse,
442
444
  res,
443
445
  ): Promise<void> {
444
- Object.keys(response.headers).forEach((headerName) => {
445
- res.set(headerName, response.headers[headerName]);
446
+ Object.keys(response.headers || {}).forEach((headerName) => {
447
+ res.set(headerName, response.headers?.[headerName]);
446
448
  });
447
449
  res.status(response.status);
448
450
 
@@ -1,136 +0,0 @@
1
- import { loadLambda } from '../libs/utils';
2
- import { extra, service as _service } from 'knifecycle';
3
- import { readArgs } from '@whook/cli';
4
- import YError from 'yerror';
5
- import { dereferenceOpenAPIOperations, getOpenAPIOperations } from '@whook/http-router';
6
- import stream from 'stream';
7
- import camelCase from 'camelcase';
8
- const SEARCH_SEPARATOR = '?';
9
- const PATH_SEPARATOR = '/';
10
- export const definition = {
11
- description: 'A command for testing AWS HTTP lambda',
12
- example: `whook testHTTPLambda --name getPing`,
13
- arguments: {
14
- type: 'object',
15
- additionalProperties: false,
16
- required: ['name'],
17
- properties: {
18
- name: {
19
- description: 'Name of the lamda to run',
20
- type: 'string'
21
- },
22
- type: {
23
- description: 'Type of lambda to test',
24
- type: 'string',
25
- enum: ['main', 'index'],
26
- default: 'index'
27
- },
28
- contentType: {
29
- description: 'Content type of the payload',
30
- type: 'string',
31
- default: 'application/json'
32
- },
33
- parameters: {
34
- description: 'The HTTP call parameters',
35
- type: 'string',
36
- default: '{}'
37
- }
38
- }
39
- }
40
- };
41
- export default extra(definition, _service(initTestHTTPLambdaCommand, "testHTTPLambdaCommand", ["NODE_ENV", "PROJECT_DIR", "API", "log", "args"]));
42
-
43
- async function initTestHTTPLambdaCommand({
44
- NODE_ENV,
45
- PROJECT_DIR,
46
- API,
47
- log,
48
- args
49
- }) {
50
- return async () => {
51
- const {
52
- name,
53
- type,
54
- contentType,
55
- parameters: rawParameters
56
- } = readArgs(definition.arguments, args);
57
- const handler = await loadLambda({
58
- PROJECT_DIR,
59
- log
60
- }, NODE_ENV, name, type);
61
- const OPERATION = (await dereferenceOpenAPIOperations(API, getOpenAPIOperations(API))).find(({
62
- operationId
63
- }) => operationId === name);
64
-
65
- if (!OPERATION) {
66
- throw new YError('E_OPERATION_NOT_FOUND');
67
- }
68
-
69
- const hasBody = !!OPERATION.requestBody;
70
- const parameters = JSON.parse(rawParameters);
71
- const search = (OPERATION.parameters || []).filter(p => p.in === 'query').reduce((accSearch, p) => {
72
- if (null != parameters[p.name]) {
73
- return accSearch + (accSearch ? '&' : '') + p.name + '=' + parameters[p.name];
74
- }
75
-
76
- return accSearch;
77
- }, '');
78
- const path = OPERATION.path.split(PATH_SEPARATOR).map(part => {
79
- const matches = /^\{([\d\w]+)\}$/i.exec(part);
80
-
81
- if (matches) {
82
- return parameters[matches[1]];
83
- }
84
-
85
- return part;
86
- }).join(PATH_SEPARATOR);
87
- const gcpfRequest = {
88
- method: OPERATION.method,
89
- originalUrl: path + (search ? SEARCH_SEPARATOR + search : ''),
90
- headers: (OPERATION.parameters || []).filter(p => p.in === 'header').reduce((headerParameters, p) => {
91
- headerParameters[p.name] = parameters[camelCase(p.name)];
92
- return headerParameters;
93
- }, {}),
94
- rawBody: Buffer.from(hasBody ? contentType === 'application/json' ? parameters.body ? JSON.stringify(parameters.body) : '' : parameters.body || '' : '')
95
- };
96
-
97
- if (hasBody) {
98
- gcpfRequest.headers['content-type'] = `${contentType};charset=UTF-8`;
99
- }
100
-
101
- log('info', 'GCPF_REQUEST:', gcpfRequest);
102
- const response = {
103
- status: 0,
104
- headers: {},
105
- data: ''
106
- };
107
- await new Promise((resolve, reject) => {
108
- const gcpfResponse = new stream.PassThrough();
109
-
110
- gcpfResponse.set = (name, value) => {
111
- response.headers[name] = value;
112
- };
113
-
114
- gcpfResponse.status = code => {
115
- response.status = code;
116
- };
117
-
118
- handler(gcpfRequest, gcpfResponse).catch(reject);
119
- const chunks = [];
120
- gcpfResponse.once('end', () => {
121
- response.data = Buffer.concat(chunks).toString();
122
- resolve();
123
- });
124
- gcpfResponse.once('error', reject);
125
- gcpfResponse.on('readable', () => {
126
- let data;
127
-
128
- while (data = gcpfResponse.read()) {
129
- chunks.push(data);
130
- }
131
- });
132
- });
133
- log('info', 'SUCCESS:', response);
134
- };
135
- }
136
- //# sourceMappingURL=testHTTPFunction.mjs.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/commands/testHTTPFunction.ts"],"names":["loadLambda","extra","autoService","readArgs","YError","dereferenceOpenAPIOperations","getOpenAPIOperations","stream","camelCase","SEARCH_SEPARATOR","PATH_SEPARATOR","definition","description","example","arguments","type","additionalProperties","required","properties","name","enum","default","contentType","parameters","initTestHTTPLambdaCommand","NODE_ENV","PROJECT_DIR","API","log","args","rawParameters","handler","OPERATION","find","operationId","hasBody","requestBody","JSON","parse","search","filter","p","in","reduce","accSearch","path","split","map","part","matches","exec","join","gcpfRequest","method","originalUrl","headers","headerParameters","rawBody","Buffer","from","body","stringify","response","status","data","Promise","resolve","reject","gcpfResponse","PassThrough","set","value","code","catch","chunks","once","concat","toString","on","read","push"],"mappings":"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","sourcesContent":["import { loadLambda } from '../libs/utils';\nimport { extra, autoService } from 'knifecycle';\nimport { readArgs } from '@whook/cli';\nimport YError from 'yerror';\nimport {\n dereferenceOpenAPIOperations,\n getOpenAPIOperations,\n} from '@whook/http-router';\nimport stream from 'stream';\nimport camelCase from 'camelcase';\nimport type {\n WhookCommandArgs,\n WhookCommandDefinition,\n WhookCommandNamedArgs,\n} from '@whook/cli';\nimport type { LogService } from 'common-services';\nimport type { OpenAPIV3 } from 'openapi-types';\n\nconst SEARCH_SEPARATOR = '?';\nconst PATH_SEPARATOR = '/';\n\nexport const definition: WhookCommandDefinition = {\n description: 'A command for testing AWS HTTP lambda',\n example: `whook testHTTPLambda --name getPing`,\n arguments: {\n type: 'object',\n additionalProperties: false,\n required: ['name'],\n properties: {\n name: {\n description: 'Name of the lamda to run',\n type: 'string',\n },\n type: {\n description: 'Type of lambda to test',\n type: 'string',\n enum: ['main', 'index'],\n default: 'index',\n },\n contentType: {\n description: 'Content type of the payload',\n type: 'string',\n default: 'application/json',\n },\n parameters: {\n description: 'The HTTP call parameters',\n type: 'string',\n default: '{}',\n },\n },\n },\n};\n\nexport default extra(definition, autoService(initTestHTTPLambdaCommand));\n\nasync function initTestHTTPLambdaCommand({\n NODE_ENV,\n PROJECT_DIR,\n API,\n log,\n args,\n}: {\n NODE_ENV: string;\n PROJECT_DIR: string;\n API: OpenAPIV3.Document;\n log: LogService;\n args: WhookCommandArgs;\n}) {\n return async () => {\n const {\n name,\n type,\n contentType,\n parameters: rawParameters,\n }: WhookCommandNamedArgs = readArgs(definition.arguments, args) as {\n name: string;\n type: string;\n contentType: string;\n parameters: string;\n };\n const handler = await loadLambda(\n { PROJECT_DIR, log },\n NODE_ENV,\n name,\n type,\n );\n const OPERATION = (\n await dereferenceOpenAPIOperations(API, getOpenAPIOperations(API))\n ).find(({ operationId }) => operationId === name);\n\n if (!OPERATION) {\n throw new YError('E_OPERATION_NOT_FOUND');\n }\n\n const hasBody = !!OPERATION.requestBody;\n const parameters = JSON.parse(rawParameters);\n const search = ((OPERATION.parameters || []) as OpenAPIV3.ParameterObject[])\n .filter((p) => p.in === 'query')\n .reduce((accSearch, p) => {\n if (null != parameters[p.name]) {\n return (\n accSearch +\n (accSearch ? '&' : '') +\n p.name +\n '=' +\n parameters[p.name]\n );\n }\n return accSearch;\n }, '');\n\n const path = OPERATION.path\n .split(PATH_SEPARATOR)\n\n .map((part) => {\n const matches = /^\\{([\\d\\w]+)\\}$/i.exec(part);\n\n if (matches) {\n return parameters[matches[1]];\n }\n return part;\n })\n .join(PATH_SEPARATOR);\n const gcpfRequest = {\n method: OPERATION.method,\n originalUrl: path + (search ? SEARCH_SEPARATOR + search : ''),\n headers: ((OPERATION.parameters || []) as OpenAPIV3.ParameterObject[])\n .filter((p) => p.in === 'header')\n .reduce((headerParameters, p) => {\n headerParameters[p.name] = parameters[camelCase(p.name)];\n return headerParameters;\n }, {}),\n rawBody: Buffer.from(\n hasBody\n ? contentType === 'application/json'\n ? parameters.body\n ? JSON.stringify(parameters.body)\n : ''\n : parameters.body || ''\n : '',\n ),\n };\n if (hasBody) {\n gcpfRequest.headers['content-type'] = `${contentType};charset=UTF-8`;\n }\n log('info', 'GCPF_REQUEST:', gcpfRequest);\n\n const response = {\n status: 0,\n headers: {},\n data: '',\n };\n await new Promise<void>((resolve, reject) => {\n const gcpfResponse: any = new stream.PassThrough();\n\n gcpfResponse.set = (name: string, value: string) => {\n response.headers[name] = value;\n };\n gcpfResponse.status = (code: number) => {\n response.status = code;\n };\n\n handler(gcpfRequest, gcpfResponse).catch(reject);\n\n const chunks = [];\n\n gcpfResponse.once('end', () => {\n response.data = Buffer.concat(chunks).toString();\n resolve();\n });\n gcpfResponse.once('error', reject);\n gcpfResponse.on('readable', () => {\n let data;\n while ((data = gcpfResponse.read())) {\n chunks.push(data);\n }\n });\n });\n log('info', 'SUCCESS:', response);\n };\n}\n"],"file":"testHTTPFunction.mjs"}