@whook/gcp-functions 8.3.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.
- package/LICENSE +20 -0
- package/README.md +187 -0
- package/dist/commands/testHTTPFunction.d.ts +12 -0
- package/dist/commands/testHTTPFunction.js +156 -0
- package/dist/commands/testHTTPFunction.js.map +1 -0
- package/dist/commands/testHTTPFunction.mjs +136 -0
- package/dist/commands/testHTTPFunction.mjs.map +1 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.js +299 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +265 -0
- package/dist/index.mjs.map +1 -0
- package/dist/libs/utils.d.ts +5 -0
- package/dist/libs/utils.js +39 -0
- package/dist/libs/utils.js.map +1 -0
- package/dist/libs/utils.mjs +27 -0
- package/dist/libs/utils.mjs.map +1 -0
- package/dist/services/_autoload.d.ts +17 -0
- package/dist/services/_autoload.js +121 -0
- package/dist/services/_autoload.js.map +1 -0
- package/dist/services/_autoload.mjs +107 -0
- package/dist/services/_autoload.mjs.map +1 -0
- package/dist/services/log.d.ts +2 -0
- package/dist/services/log.js +14 -0
- package/dist/services/log.js.map +1 -0
- package/dist/services/log.mjs +4 -0
- package/dist/services/log.mjs.map +1 -0
- package/dist/services/log.test.d.ts +1 -0
- package/dist/services/log.test.js +12 -0
- package/dist/services/log.test.js.map +1 -0
- package/dist/services/log.test.mjs +7 -0
- package/dist/services/log.test.mjs.map +1 -0
- package/dist/wrappers/googleHTTPFunction.d.ts +22 -0
- package/dist/wrappers/googleHTTPFunction.js +310 -0
- package/dist/wrappers/googleHTTPFunction.js.map +1 -0
- package/dist/wrappers/googleHTTPFunction.mjs +289 -0
- package/dist/wrappers/googleHTTPFunction.mjs.map +1 -0
- package/package.json +215 -0
- package/src/commands/testHTTPFunction.ts +181 -0
- package/src/index.ts +443 -0
- package/src/libs/utils.ts +43 -0
- package/src/services/_autoload.ts +161 -0
- package/src/services/log.test.ts +7 -0
- package/src/services/log.ts +4 -0
- package/src/wrappers/googleHTTPFunction.ts +468 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
The MIT License (MIT)
|
|
2
|
+
Copyright © 2017 Nicolas Froidure
|
|
3
|
+
|
|
4
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
5
|
+
of this software and associated documentation files (the “Software”), to deal
|
|
6
|
+
in the Software without restriction, including without limitation the rights
|
|
7
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
8
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
9
|
+
furnished to do so, subject to the following conditions:
|
|
10
|
+
|
|
11
|
+
The above copyright notice and this permission notice shall be included in
|
|
12
|
+
all copies or substantial portions of the Software.
|
|
13
|
+
|
|
14
|
+
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
15
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
16
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
17
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
18
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
19
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
20
|
+
THE SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
[//]: # ( )
|
|
2
|
+
[//]: # (This file is automatically generated by a `metapak`)
|
|
3
|
+
[//]: # (module. Do not change it except between the)
|
|
4
|
+
[//]: # (`content:start/end` flags, your changes would)
|
|
5
|
+
[//]: # (be overridden.)
|
|
6
|
+
[//]: # ( )
|
|
7
|
+
# @whook/gcp-functions
|
|
8
|
+
> Build and deploy to GCP Cloud Functions with Whook.
|
|
9
|
+
|
|
10
|
+
[](https://github.com/nfroidure/whook/blob/master/packages/whook-gcp-functions/LICENSE)
|
|
11
|
+
[](https://npmjs.org/package/@whook/gcp-functions)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
[//]: # (::contents:start)
|
|
15
|
+
|
|
16
|
+
This module is aimed to help you to build and deploy your
|
|
17
|
+
[Whook](https://github.com/nfroidure/whook) server to
|
|
18
|
+
[Google Cloud Functions](https://cloud.google.com/functions).
|
|
19
|
+
|
|
20
|
+
You can find a complete setup with a Terraform deployment example in
|
|
21
|
+
[this pull request](https://github.com/nfroidure/whook/pull/66).
|
|
22
|
+
|
|
23
|
+
## Quick setup
|
|
24
|
+
|
|
25
|
+
Install this module and its peer dependencies :
|
|
26
|
+
|
|
27
|
+
```sh
|
|
28
|
+
npm i @whook/gcp-functions;
|
|
29
|
+
npm i --save-dev @whook/http-transaction esbuild
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Add this module to your Whook plugins and tweak the 2 build functions in your
|
|
33
|
+
`build.ts` main file:
|
|
34
|
+
|
|
35
|
+
```diff
|
|
36
|
+
- import YError from 'yerror';
|
|
37
|
+
+import {
|
|
38
|
+
+ runBuild as runBaseBuild,
|
|
39
|
+
+ prepareBuildEnvironment as prepareBaseBuildEnvironment,
|
|
40
|
+
+} from '@whook/gcp-functions';
|
|
41
|
+
|
|
42
|
+
// (...)
|
|
43
|
+
|
|
44
|
+
export async function prepareEnvironment(
|
|
45
|
+
$: Knifecycle = new Knifecycle(),
|
|
46
|
+
): Promise<Knifecycle> {
|
|
47
|
+
|
|
48
|
+
// (...)
|
|
49
|
+
|
|
50
|
+
// Setup your own whook plugins or avoid whook defaults by leaving it empty
|
|
51
|
+
- $.register(constant('WHOOK_PLUGINS', ['@whook/cli', '@whook/whook']));
|
|
52
|
+
+ $.register(constant('WHOOK_PLUGINS', [
|
|
53
|
+
+ '@whook/gcp-functions',
|
|
54
|
+
+ '@whook/cli',
|
|
55
|
+
+ '@whook/whook',
|
|
56
|
+
+ ]));
|
|
57
|
+
|
|
58
|
+
// (...)
|
|
59
|
+
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// (...)
|
|
63
|
+
|
|
64
|
+
// The `runBuild` function is intended to build the
|
|
65
|
+
// project
|
|
66
|
+
export async function runBuild(
|
|
67
|
+
innerPrepareEnvironment = prepareBuildEnvironment,
|
|
68
|
+
): Promise<void> {
|
|
69
|
+
- throw new YError('E_NO_BUILD_IMPLEMENTED');
|
|
70
|
+
|
|
71
|
+
// Usually, here you call the installed build
|
|
72
|
+
- // return runBaseBuild(innerPrepareEnvironment);
|
|
73
|
+
+ return runBaseBuild(innerPrepareEnvironment);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// (...)
|
|
77
|
+
|
|
78
|
+
// The `prepareBuildEnvironment` create the build
|
|
79
|
+
// environment
|
|
80
|
+
export async function prepareBuildEnvironment(
|
|
81
|
+
$: Knifecycle = new Knifecycle(),
|
|
82
|
+
): Promise<Knifecycle> {
|
|
83
|
+
$ = await prepareEnvironment($);
|
|
84
|
+
|
|
85
|
+
// (...)
|
|
86
|
+
|
|
87
|
+
- // Usually, here you call the installed build env
|
|
88
|
+
- // $ = await prepareBaseBuildEnvironment($);
|
|
89
|
+
+ // Calling the GCP specific build env
|
|
90
|
+
+ $ = await prepareBaseBuildEnvironment($);
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
// The build often need to know were initializers
|
|
94
|
+
// can be found to create a static build and
|
|
95
|
+
// remove the need to create an injector
|
|
96
|
+
$.register(
|
|
97
|
+
constant('INITIALIZER_PATH_MAP', {
|
|
98
|
+
// (...)
|
|
99
|
+
obfuscator: '@whook/http-transaction/dist/services/obfuscator',
|
|
100
|
+
- log: 'common-services/dist/log',
|
|
101
|
+
+ log: '@whook/gcp-functions/dist/services/log',
|
|
102
|
+
time: 'common-services/dist/time',
|
|
103
|
+
delay: 'common-services/dist/delay',
|
|
104
|
+
}),
|
|
105
|
+
);
|
|
106
|
+
|
|
107
|
+
// (...)
|
|
108
|
+
|
|
109
|
+
}
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
And add the GCP Functions config (usually in `src/config/common/config.js`):
|
|
113
|
+
|
|
114
|
+
```diff
|
|
115
|
+
+ import type { WhookCompilerConfig } from '@whook/whook';
|
|
116
|
+
+ import type {
|
|
117
|
+
+ WhookAPIOperationGCPFunctionConfig
|
|
118
|
+
+ } from '@whook/gcp-functions';
|
|
119
|
+
|
|
120
|
+
// ...
|
|
121
|
+
|
|
122
|
+
export type AppConfigs = WhookConfigs &
|
|
123
|
+
+ WhookCompilerConfig &
|
|
124
|
+
APIConfig;
|
|
125
|
+
|
|
126
|
+
const CONFIG: AppConfigs = {
|
|
127
|
+
// ...
|
|
128
|
+
+ COMPILER_OPTIONS: {
|
|
129
|
+
+ externalModules: [],
|
|
130
|
+
+ ignoredModules: [],
|
|
131
|
+
+ target: '12', // Node 14 is in public review
|
|
132
|
+
+ },
|
|
133
|
+
};
|
|
134
|
+
|
|
135
|
+
// Export custom handlers definitions
|
|
136
|
+
export type APIHandlerDefinition = WhookAPIHandlerDefinition<
|
|
137
|
+
+ WhookAPIOperationGCPFunctionConfig &
|
|
138
|
+
WhookAPIOperationSwaggerConfig
|
|
139
|
+
>;
|
|
140
|
+
|
|
141
|
+
export default CONFIG;
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
# Build
|
|
145
|
+
|
|
146
|
+
To build your functions :
|
|
147
|
+
|
|
148
|
+
```sh
|
|
149
|
+
# Build all functions
|
|
150
|
+
npm run compile && npm run build
|
|
151
|
+
|
|
152
|
+
# Build only one function
|
|
153
|
+
npm run compile && npm run build -- getPing
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
# Debug
|
|
157
|
+
|
|
158
|
+
You can easily test your function builds by adding `@whook/gcp-functions` to
|
|
159
|
+
your `WHOOK_PLUGINS` list. It provides you some commands like the
|
|
160
|
+
`testHTTPFunction` one:
|
|
161
|
+
|
|
162
|
+
```sh
|
|
163
|
+
npx whook testHTTPFunction --name getPing
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
To get more insights when errors happens:
|
|
167
|
+
|
|
168
|
+
```sh
|
|
169
|
+
npm run whook-dev -- testHTTPFunction --name getPing
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
## Deployment
|
|
173
|
+
|
|
174
|
+
We recommend using [Terraform](https://terraform.io) to deploy your functions.
|
|
175
|
+
|
|
176
|
+
There is a complete example on how to deploy your functions
|
|
177
|
+
[in this pull request](https://github.com/nfroidure/whook/pull/54).
|
|
178
|
+
|
|
179
|
+
[//]: # (::contents:end)
|
|
180
|
+
|
|
181
|
+
# API
|
|
182
|
+
|
|
183
|
+
# Authors
|
|
184
|
+
- [Nicolas Froidure](http://insertafter.com/en/index.html)
|
|
185
|
+
|
|
186
|
+
# License
|
|
187
|
+
[MIT](https://github.com/nfroidure/whook/blob/master/packages/whook-gcp-functions/LICENSE)
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { WhookCommandArgs, WhookCommandDefinition } from '@whook/cli';
|
|
2
|
+
import type { LogService } from 'common-services';
|
|
3
|
+
import type { OpenAPIV3 } from 'openapi-types';
|
|
4
|
+
export declare const definition: WhookCommandDefinition;
|
|
5
|
+
declare const _default: import("knifecycle").ServiceInitializer<{
|
|
6
|
+
NODE_ENV: string;
|
|
7
|
+
PROJECT_DIR: string;
|
|
8
|
+
API: OpenAPIV3.Document<{}>;
|
|
9
|
+
log: LogService;
|
|
10
|
+
args: WhookCommandArgs;
|
|
11
|
+
}, () => Promise<void>>;
|
|
12
|
+
export default _default;
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.default = exports.definition = void 0;
|
|
7
|
+
|
|
8
|
+
var _utils = require("../libs/utils");
|
|
9
|
+
|
|
10
|
+
var _knifecycle = require("knifecycle");
|
|
11
|
+
|
|
12
|
+
var _cli = require("@whook/cli");
|
|
13
|
+
|
|
14
|
+
var _yerror = _interopRequireDefault(require("yerror"));
|
|
15
|
+
|
|
16
|
+
var _httpRouter = require("@whook/http-router");
|
|
17
|
+
|
|
18
|
+
var _stream = _interopRequireDefault(require("stream"));
|
|
19
|
+
|
|
20
|
+
var _camelcase = _interopRequireDefault(require("camelcase"));
|
|
21
|
+
|
|
22
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
23
|
+
|
|
24
|
+
const SEARCH_SEPARATOR = '?';
|
|
25
|
+
const PATH_SEPARATOR = '/';
|
|
26
|
+
const definition = {
|
|
27
|
+
description: 'A command for testing AWS HTTP lambda',
|
|
28
|
+
example: `whook testHTTPLambda --name getPing`,
|
|
29
|
+
arguments: {
|
|
30
|
+
type: 'object',
|
|
31
|
+
additionalProperties: false,
|
|
32
|
+
required: ['name'],
|
|
33
|
+
properties: {
|
|
34
|
+
name: {
|
|
35
|
+
description: 'Name of the lamda to run',
|
|
36
|
+
type: 'string'
|
|
37
|
+
},
|
|
38
|
+
type: {
|
|
39
|
+
description: 'Type of lambda to test',
|
|
40
|
+
type: 'string',
|
|
41
|
+
enum: ['main', 'index'],
|
|
42
|
+
default: 'index'
|
|
43
|
+
},
|
|
44
|
+
contentType: {
|
|
45
|
+
description: 'Content type of the payload',
|
|
46
|
+
type: 'string',
|
|
47
|
+
default: 'application/json'
|
|
48
|
+
},
|
|
49
|
+
parameters: {
|
|
50
|
+
description: 'The HTTP call parameters',
|
|
51
|
+
type: 'string',
|
|
52
|
+
default: '{}'
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
exports.definition = definition;
|
|
58
|
+
|
|
59
|
+
var _default = (0, _knifecycle.extra)(definition, (0, _knifecycle.service)(initTestHTTPLambdaCommand, "testHTTPLambdaCommand", ["NODE_ENV", "PROJECT_DIR", "API", "log", "args"]));
|
|
60
|
+
|
|
61
|
+
exports.default = _default;
|
|
62
|
+
|
|
63
|
+
async function initTestHTTPLambdaCommand({
|
|
64
|
+
NODE_ENV,
|
|
65
|
+
PROJECT_DIR,
|
|
66
|
+
API,
|
|
67
|
+
log,
|
|
68
|
+
args
|
|
69
|
+
}) {
|
|
70
|
+
return async () => {
|
|
71
|
+
const {
|
|
72
|
+
name,
|
|
73
|
+
type,
|
|
74
|
+
contentType,
|
|
75
|
+
parameters: rawParameters
|
|
76
|
+
} = (0, _cli.readArgs)(definition.arguments, args);
|
|
77
|
+
const handler = await (0, _utils.loadLambda)({
|
|
78
|
+
PROJECT_DIR,
|
|
79
|
+
log
|
|
80
|
+
}, NODE_ENV, name, type);
|
|
81
|
+
const OPERATION = (await (0, _httpRouter.dereferenceOpenAPIOperations)(API, (0, _httpRouter.getOpenAPIOperations)(API))).find(({
|
|
82
|
+
operationId
|
|
83
|
+
}) => operationId === name);
|
|
84
|
+
|
|
85
|
+
if (!OPERATION) {
|
|
86
|
+
throw new _yerror.default('E_OPERATION_NOT_FOUND');
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
const hasBody = !!OPERATION.requestBody;
|
|
90
|
+
const parameters = JSON.parse(rawParameters);
|
|
91
|
+
const search = (OPERATION.parameters || []).filter(p => p.in === 'query').reduce((accSearch, p) => {
|
|
92
|
+
if (null != parameters[p.name]) {
|
|
93
|
+
return accSearch + (accSearch ? '&' : '') + p.name + '=' + parameters[p.name];
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
return accSearch;
|
|
97
|
+
}, '');
|
|
98
|
+
const path = OPERATION.path.split(PATH_SEPARATOR).map(part => {
|
|
99
|
+
const matches = /^\{([\d\w]+)\}$/i.exec(part);
|
|
100
|
+
|
|
101
|
+
if (matches) {
|
|
102
|
+
return parameters[matches[1]];
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
return part;
|
|
106
|
+
}).join(PATH_SEPARATOR);
|
|
107
|
+
const gcpfRequest = {
|
|
108
|
+
method: OPERATION.method,
|
|
109
|
+
originalUrl: path + (search ? SEARCH_SEPARATOR + search : ''),
|
|
110
|
+
headers: (OPERATION.parameters || []).filter(p => p.in === 'header').reduce((headerParameters, p) => {
|
|
111
|
+
headerParameters[p.name] = parameters[(0, _camelcase.default)(p.name)];
|
|
112
|
+
return headerParameters;
|
|
113
|
+
}, {}),
|
|
114
|
+
rawBody: Buffer.from(hasBody ? contentType === 'application/json' ? parameters.body ? JSON.stringify(parameters.body) : '' : parameters.body || '' : '')
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
if (hasBody) {
|
|
118
|
+
gcpfRequest.headers['content-type'] = `${contentType};charset=UTF-8`;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
log('info', 'GCPF_REQUEST:', gcpfRequest);
|
|
122
|
+
const response = {
|
|
123
|
+
status: 0,
|
|
124
|
+
headers: {},
|
|
125
|
+
data: ''
|
|
126
|
+
};
|
|
127
|
+
await new Promise((resolve, reject) => {
|
|
128
|
+
const gcpfResponse = new _stream.default.PassThrough();
|
|
129
|
+
|
|
130
|
+
gcpfResponse.set = (name, value) => {
|
|
131
|
+
response.headers[name] = value;
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
gcpfResponse.status = code => {
|
|
135
|
+
response.status = code;
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
handler(gcpfRequest, gcpfResponse).catch(reject);
|
|
139
|
+
const chunks = [];
|
|
140
|
+
gcpfResponse.once('end', () => {
|
|
141
|
+
response.data = Buffer.concat(chunks).toString();
|
|
142
|
+
resolve();
|
|
143
|
+
});
|
|
144
|
+
gcpfResponse.once('error', reject);
|
|
145
|
+
gcpfResponse.on('readable', () => {
|
|
146
|
+
let data;
|
|
147
|
+
|
|
148
|
+
while (data = gcpfResponse.read()) {
|
|
149
|
+
chunks.push(data);
|
|
150
|
+
}
|
|
151
|
+
});
|
|
152
|
+
});
|
|
153
|
+
log('info', 'SUCCESS:', response);
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
//# sourceMappingURL=testHTTPFunction.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/commands/testHTTPFunction.ts"],"names":["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","YError","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","stream","PassThrough","set","value","code","catch","chunks","once","concat","toString","on","read","push"],"mappings":";;;;;;;AAAA;;AACA;;AACA;;AACA;;AACA;;AAIA;;AACA;;;;AASA,MAAMA,gBAAgB,GAAG,GAAzB;AACA,MAAMC,cAAc,GAAG,GAAvB;AAEO,MAAMC,UAAkC,GAAG;AAChDC,EAAAA,WAAW,EAAE,uCADmC;AAEhDC,EAAAA,OAAO,EAAG,qCAFsC;AAGhDC,EAAAA,SAAS,EAAE;AACTC,IAAAA,IAAI,EAAE,QADG;AAETC,IAAAA,oBAAoB,EAAE,KAFb;AAGTC,IAAAA,QAAQ,EAAE,CAAC,MAAD,CAHD;AAITC,IAAAA,UAAU,EAAE;AACVC,MAAAA,IAAI,EAAE;AACJP,QAAAA,WAAW,EAAE,0BADT;AAEJG,QAAAA,IAAI,EAAE;AAFF,OADI;AAKVA,MAAAA,IAAI,EAAE;AACJH,QAAAA,WAAW,EAAE,wBADT;AAEJG,QAAAA,IAAI,EAAE,QAFF;AAGJK,QAAAA,IAAI,EAAE,CAAC,MAAD,EAAS,OAAT,CAHF;AAIJC,QAAAA,OAAO,EAAE;AAJL,OALI;AAWVC,MAAAA,WAAW,EAAE;AACXV,QAAAA,WAAW,EAAE,6BADF;AAEXG,QAAAA,IAAI,EAAE,QAFK;AAGXM,QAAAA,OAAO,EAAE;AAHE,OAXH;AAgBVE,MAAAA,UAAU,EAAE;AACVX,QAAAA,WAAW,EAAE,0BADH;AAEVG,QAAAA,IAAI,EAAE,QAFI;AAGVM,QAAAA,OAAO,EAAE;AAHC;AAhBF;AAJH;AAHqC,CAA3C;;;eAgCQ,uBAAMV,UAAN,EAAkB,yBAAYa,yBAAZ,6EAAlB,C;;;;AAEf,eAAeA,yBAAf,CAAyC;AACvCC,EAAAA,QADuC;AAEvCC,EAAAA,WAFuC;AAGvCC,EAAAA,GAHuC;AAIvCC,EAAAA,GAJuC;AAKvCC,EAAAA;AALuC,CAAzC,EAYG;AACD,SAAO,YAAY;AACjB,UAAM;AACJV,MAAAA,IADI;AAEJJ,MAAAA,IAFI;AAGJO,MAAAA,WAHI;AAIJC,MAAAA,UAAU,EAAEO;AAJR,QAKqB,mBAASnB,UAAU,CAACG,SAApB,EAA+Be,IAA/B,CAL3B;AAWA,UAAME,OAAO,GAAG,MAAM,uBACpB;AAAEL,MAAAA,WAAF;AAAeE,MAAAA;AAAf,KADoB,EAEpBH,QAFoB,EAGpBN,IAHoB,EAIpBJ,IAJoB,CAAtB;AAMA,UAAMiB,SAAS,GAAG,CAChB,MAAM,8CAA6BL,GAA7B,EAAkC,sCAAqBA,GAArB,CAAlC,CADU,EAEhBM,IAFgB,CAEX,CAAC;AAAEC,MAAAA;AAAF,KAAD,KAAqBA,WAAW,KAAKf,IAF1B,CAAlB;;AAIA,QAAI,CAACa,SAAL,EAAgB;AACd,YAAM,IAAIG,eAAJ,CAAW,uBAAX,CAAN;AACD;;AAED,UAAMC,OAAO,GAAG,CAAC,CAACJ,SAAS,CAACK,WAA5B;AACA,UAAMd,UAAU,GAAGe,IAAI,CAACC,KAAL,CAAWT,aAAX,CAAnB;AACA,UAAMU,MAAM,GAAG,CAAER,SAAS,CAACT,UAAV,IAAwB,EAA1B,EACZkB,MADY,CACJC,CAAD,IAAOA,CAAC,CAACC,EAAF,KAAS,OADX,EAEZC,MAFY,CAEL,CAACC,SAAD,EAAYH,CAAZ,KAAkB;AACxB,UAAI,QAAQnB,UAAU,CAACmB,CAAC,CAACvB,IAAH,CAAtB,EAAgC;AAC9B,eACE0B,SAAS,IACRA,SAAS,GAAG,GAAH,GAAS,EADV,CAAT,GAEAH,CAAC,CAACvB,IAFF,GAGA,GAHA,GAIAI,UAAU,CAACmB,CAAC,CAACvB,IAAH,CALZ;AAOD;;AACD,aAAO0B,SAAP;AACD,KAbY,EAaV,EAbU,CAAf;AAeA,UAAMC,IAAI,GAAGd,SAAS,CAACc,IAAV,CACVC,KADU,CACJrC,cADI,EAGVsC,GAHU,CAGLC,IAAD,IAAU;AACb,YAAMC,OAAO,GAAG,mBAAmBC,IAAnB,CAAwBF,IAAxB,CAAhB;;AAEA,UAAIC,OAAJ,EAAa;AACX,eAAO3B,UAAU,CAAC2B,OAAO,CAAC,CAAD,CAAR,CAAjB;AACD;;AACD,aAAOD,IAAP;AACD,KAVU,EAWVG,IAXU,CAWL1C,cAXK,CAAb;AAYA,UAAM2C,WAAW,GAAG;AAClBC,MAAAA,MAAM,EAAEtB,SAAS,CAACsB,MADA;AAElBC,MAAAA,WAAW,EAAET,IAAI,IAAIN,MAAM,GAAG/B,gBAAgB,GAAG+B,MAAtB,GAA+B,EAAzC,CAFC;AAGlBgB,MAAAA,OAAO,EAAE,CAAExB,SAAS,CAACT,UAAV,IAAwB,EAA1B,EACNkB,MADM,CACEC,CAAD,IAAOA,CAAC,CAACC,EAAF,KAAS,QADjB,EAENC,MAFM,CAEC,CAACa,gBAAD,EAAmBf,CAAnB,KAAyB;AAC/Be,QAAAA,gBAAgB,CAACf,CAAC,CAACvB,IAAH,CAAhB,GAA2BI,UAAU,CAAC,wBAAUmB,CAAC,CAACvB,IAAZ,CAAD,CAArC;AACA,eAAOsC,gBAAP;AACD,OALM,EAKJ,EALI,CAHS;AASlBC,MAAAA,OAAO,EAAEC,MAAM,CAACC,IAAP,CACPxB,OAAO,GACHd,WAAW,KAAK,kBAAhB,GACEC,UAAU,CAACsC,IAAX,GACEvB,IAAI,CAACwB,SAAL,CAAevC,UAAU,CAACsC,IAA1B,CADF,GAEE,EAHJ,GAIEtC,UAAU,CAACsC,IAAX,IAAmB,EALlB,GAMH,EAPG;AATS,KAApB;;AAmBA,QAAIzB,OAAJ,EAAa;AACXiB,MAAAA,WAAW,CAACG,OAAZ,CAAoB,cAApB,IAAuC,GAAElC,WAAY,gBAArD;AACD;;AACDM,IAAAA,GAAG,CAAC,MAAD,EAAS,eAAT,EAA0ByB,WAA1B,CAAH;AAEA,UAAMU,QAAQ,GAAG;AACfC,MAAAA,MAAM,EAAE,CADO;AAEfR,MAAAA,OAAO,EAAE,EAFM;AAGfS,MAAAA,IAAI,EAAE;AAHS,KAAjB;AAKA,UAAM,IAAIC,OAAJ,CAAkB,CAACC,OAAD,EAAUC,MAAV,KAAqB;AAC3C,YAAMC,YAAiB,GAAG,IAAIC,gBAAOC,WAAX,EAA1B;;AAEAF,MAAAA,YAAY,CAACG,GAAb,GAAmB,CAACrD,IAAD,EAAesD,KAAf,KAAiC;AAClDV,QAAAA,QAAQ,CAACP,OAAT,CAAiBrC,IAAjB,IAAyBsD,KAAzB;AACD,OAFD;;AAGAJ,MAAAA,YAAY,CAACL,MAAb,GAAuBU,IAAD,IAAkB;AACtCX,QAAAA,QAAQ,CAACC,MAAT,GAAkBU,IAAlB;AACD,OAFD;;AAIA3C,MAAAA,OAAO,CAACsB,WAAD,EAAcgB,YAAd,CAAP,CAAmCM,KAAnC,CAAyCP,MAAzC;AAEA,YAAMQ,MAAM,GAAG,EAAf;AAEAP,MAAAA,YAAY,CAACQ,IAAb,CAAkB,KAAlB,EAAyB,MAAM;AAC7Bd,QAAAA,QAAQ,CAACE,IAAT,GAAgBN,MAAM,CAACmB,MAAP,CAAcF,MAAd,EAAsBG,QAAtB,EAAhB;AACAZ,QAAAA,OAAO;AACR,OAHD;AAIAE,MAAAA,YAAY,CAACQ,IAAb,CAAkB,OAAlB,EAA2BT,MAA3B;AACAC,MAAAA,YAAY,CAACW,EAAb,CAAgB,UAAhB,EAA4B,MAAM;AAChC,YAAIf,IAAJ;;AACA,eAAQA,IAAI,GAAGI,YAAY,CAACY,IAAb,EAAf,EAAqC;AACnCL,UAAAA,MAAM,CAACM,IAAP,CAAYjB,IAAZ;AACD;AACF,OALD;AAMD,KAzBK,CAAN;AA0BArC,IAAAA,GAAG,CAAC,MAAD,EAAS,UAAT,EAAqBmC,QAArB,CAAH;AACD,GA/GD;AAgHD","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.js"}
|
|
@@ -0,0 +1,136 @@
|
|
|
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
|
|
@@ -0,0 +1 @@
|
|
|
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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import Knifecycle from 'knifecycle';
|
|
2
|
+
import type { Dependencies } from 'knifecycle';
|
|
3
|
+
import type { WhookCompilerOptions } from '@whook/whook';
|
|
4
|
+
import type { BuildOptions } from 'knifecycle/dist/build';
|
|
5
|
+
export declare const DEFAULT_BUILD_PARALLELISM = 10;
|
|
6
|
+
export declare type WhookBuildConfig = {
|
|
7
|
+
BUILD_OPTIONS?: BuildOptions;
|
|
8
|
+
BUILD_PARALLELISM?: number;
|
|
9
|
+
};
|
|
10
|
+
export declare type WhookAPIOperationGCPFunctionConfig = {
|
|
11
|
+
type?: 'http';
|
|
12
|
+
sourceOperationId?: string;
|
|
13
|
+
staticFiles?: string[];
|
|
14
|
+
compilerOptions?: WhookCompilerOptions;
|
|
15
|
+
suffix?: string;
|
|
16
|
+
};
|
|
17
|
+
export declare function prepareBuildEnvironment<T extends Knifecycle<Dependencies>>($?: T): Promise<T>;
|
|
18
|
+
export declare function runBuild(aPrepareBuildEnvironment: typeof prepareBuildEnvironment): Promise<void>;
|