@mionjs/platform-gcloud 0.8.8 → 0.13.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/.dist/cjs/index.cjs +8 -9
- package/.dist/cjs/src/constants.cjs +11 -4
- package/.dist/cjs/src/constants.cjs.map +1 -1
- package/.dist/cjs/src/constants.d.ts +1 -0
- package/.dist/cjs/src/googleCF.cjs +66 -91
- package/.dist/cjs/src/googleCF.cjs.map +1 -1
- package/.dist/cjs/src/headers.cjs +44 -43
- package/.dist/cjs/src/headers.cjs.map +1 -1
- package/.dist/cjs/src/types.cjs +0 -2
- package/.dist/cjs/src/types.d.ts +2 -2
- package/.dist/esm/index.js +2 -9
- package/.dist/esm/src/constants.d.ts +1 -0
- package/.dist/esm/src/constants.js +11 -6
- package/.dist/esm/src/constants.js.map +1 -1
- package/.dist/esm/src/googleCF.js +65 -94
- package/.dist/esm/src/googleCF.js.map +1 -1
- package/.dist/esm/src/headers.js +44 -45
- package/.dist/esm/src/headers.js.map +1 -1
- package/.dist/esm/src/types.d.ts +2 -2
- package/.dist/esm/src/types.js +0 -2
- package/LICENSE +1 -1
- package/README.md +4 -4
- package/package.json +18 -23
- package/.dist/cjs/index.cjs.map +0 -1
- package/.dist/cjs/index.d.ts.map +0 -1
- package/.dist/cjs/src/constants.d.ts.map +0 -1
- package/.dist/cjs/src/googleCF.d.ts.map +0 -1
- package/.dist/cjs/src/headers.d.ts.map +0 -1
- package/.dist/cjs/src/types.cjs.map +0 -1
- package/.dist/cjs/src/types.d.ts.map +0 -1
- package/.dist/esm/index.d.ts.map +0 -1
- package/.dist/esm/index.js.map +0 -1
- package/.dist/esm/src/constants.d.ts.map +0 -1
- package/.dist/esm/src/googleCF.d.ts.map +0 -1
- package/.dist/esm/src/headers.d.ts.map +0 -1
- package/.dist/esm/src/types.d.ts.map +0 -1
- package/.dist/esm/src/types.js.map +0 -1
- package/index.ts +0 -10
- package/src/constants.ts +0 -12
- package/src/googleCF.ts +0 -143
- package/src/headers.ts +0 -68
- package/src/types.ts +0 -13
package/src/googleCF.ts
DELETED
|
@@ -1,143 +0,0 @@
|
|
|
1
|
-
/* ########
|
|
2
|
-
* 2023 mion
|
|
3
|
-
* Author: Ma-jerez
|
|
4
|
-
* License: MIT
|
|
5
|
-
* The software is provided "as is", without warranty of any kind.
|
|
6
|
-
* ######## */
|
|
7
|
-
|
|
8
|
-
import {RpcError, SerializerModes} from '@mionjs/core';
|
|
9
|
-
import type {SerializerCode} from '@mionjs/core';
|
|
10
|
-
import {dispatchRoute, getRouterFatalErrorResponse, resetRouter, decodeQueryBody, setPlatformConfig} from '@mionjs/router';
|
|
11
|
-
import type {MionHeaders, MionResponse} from '@mionjs/router';
|
|
12
|
-
import {Request, Response} from 'express';
|
|
13
|
-
import {DEFAULT_GOOGLE_CF_OPTIONS} from './constants.ts';
|
|
14
|
-
import {GoogleCFOptions} from './types.ts';
|
|
15
|
-
import {headersFromIncomingMessage, headersFromServerResponse} from './headers.ts';
|
|
16
|
-
|
|
17
|
-
// ############# STATE #############
|
|
18
|
-
|
|
19
|
-
let googleCFOptions: Readonly<GoogleCFOptions> = {...DEFAULT_GOOGLE_CF_OPTIONS};
|
|
20
|
-
|
|
21
|
-
// ############# PUBLIC METHODS #############
|
|
22
|
-
|
|
23
|
-
export function resetGoogleCFOpts() {
|
|
24
|
-
googleCFOptions = {...DEFAULT_GOOGLE_CF_OPTIONS};
|
|
25
|
-
resetRouter();
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
export function setGoogleCFOpts(routerOptions?: Partial<GoogleCFOptions>) {
|
|
29
|
-
googleCFOptions = {
|
|
30
|
-
...googleCFOptions,
|
|
31
|
-
...routerOptions,
|
|
32
|
-
};
|
|
33
|
-
setPlatformConfig({...googleCFOptions});
|
|
34
|
-
return googleCFOptions;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
/** Creates a Google Cloud Functions handler with optional platform config */
|
|
38
|
-
export function createGoogleCFHandler(options?: Partial<GoogleCFOptions>) {
|
|
39
|
-
setGoogleCFOpts(options);
|
|
40
|
-
return googleCFHandler;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
export async function googleCFHandler(rawRequest: Request, rawResponse: Response): Promise<void> {
|
|
44
|
-
// Express in Google Cloud Functions might parse the body automatically when Content-Type is application/json
|
|
45
|
-
// We handle both cases: string body and already-parsed object body
|
|
46
|
-
// For binary requests, we need to handle the raw buffer
|
|
47
|
-
|
|
48
|
-
// TODO use its own express headers wrapper instead headers from record
|
|
49
|
-
rawResponse.setHeader('server', '@mionjs');
|
|
50
|
-
const reqHeaders = headersFromIncomingMessage(rawRequest);
|
|
51
|
-
const respHeaders = headersFromServerResponse(rawResponse, googleCFOptions.defaultResponseHeaders);
|
|
52
|
-
const contentType = rawRequest.headers['content-type'] || '';
|
|
53
|
-
const isBinary = contentType.startsWith('application/octet-stream');
|
|
54
|
-
let rawBody = isBinary ? (rawRequest as any).rawBody : rawRequest.body;
|
|
55
|
-
let reqBodyType: SerializerCode = isBinary
|
|
56
|
-
? SerializerModes.binary
|
|
57
|
-
: typeof rawBody === 'string'
|
|
58
|
-
? SerializerModes.stringifyJson
|
|
59
|
-
: SerializerModes.json;
|
|
60
|
-
// Extract query string from Express request
|
|
61
|
-
const urlQuery = rawRequest.originalUrl?.includes('?') ? rawRequest.originalUrl.split('?')[1] : undefined;
|
|
62
|
-
const queryBody = decodeQueryBody(urlQuery, rawBody);
|
|
63
|
-
if (queryBody) {
|
|
64
|
-
rawBody = queryBody.rawBody;
|
|
65
|
-
reqBodyType = queryBody.bodyType;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
try {
|
|
69
|
-
const routeResponse = await dispatchRoute(
|
|
70
|
-
rawRequest.path,
|
|
71
|
-
rawBody,
|
|
72
|
-
reqHeaders,
|
|
73
|
-
respHeaders,
|
|
74
|
-
rawRequest,
|
|
75
|
-
rawResponse,
|
|
76
|
-
reqBodyType,
|
|
77
|
-
urlQuery
|
|
78
|
-
);
|
|
79
|
-
reply(routeResponse, rawResponse);
|
|
80
|
-
} catch (err) {
|
|
81
|
-
const error =
|
|
82
|
-
err instanceof RpcError
|
|
83
|
-
? err
|
|
84
|
-
: new RpcError({
|
|
85
|
-
publicMessage: 'Internal Error',
|
|
86
|
-
originalError: err as Error,
|
|
87
|
-
type: 'unknown-error',
|
|
88
|
-
});
|
|
89
|
-
const routeResponse = getRouterFatalErrorResponse(error, respHeaders);
|
|
90
|
-
reply(routeResponse, rawResponse);
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
// ############# PRIVATE METHODS #############
|
|
95
|
-
|
|
96
|
-
function reply(mionResp: MionResponse, resp: Response): void {
|
|
97
|
-
resp.status(mionResp.statusCode);
|
|
98
|
-
const bodyType = mionResp.serializer;
|
|
99
|
-
switch (bodyType) {
|
|
100
|
-
case SerializerModes.stringifyJson: {
|
|
101
|
-
const buffer = Buffer.from(mionResp.rawBody as string, 'utf8');
|
|
102
|
-
resp.set('content-length', `${buffer.byteLength}`);
|
|
103
|
-
// content-type already set by serializer
|
|
104
|
-
resp.end(buffer);
|
|
105
|
-
break;
|
|
106
|
-
}
|
|
107
|
-
case SerializerModes.json: {
|
|
108
|
-
// Platform adapter stringifies the prepared body object
|
|
109
|
-
const jsonString = JSON.stringify(mionResp.body);
|
|
110
|
-
const buffer = Buffer.from(jsonString, 'utf8');
|
|
111
|
-
resp.set('content-type', 'application/json; charset=utf-8');
|
|
112
|
-
resp.set('content-length', `${buffer.byteLength}`);
|
|
113
|
-
resp.end(buffer);
|
|
114
|
-
break;
|
|
115
|
-
}
|
|
116
|
-
case SerializerModes.binary: {
|
|
117
|
-
const serializer = mionResp.binSerializer!;
|
|
118
|
-
resp.set('content-length', `${serializer.getLength()}`);
|
|
119
|
-
// content-type already set by serializer
|
|
120
|
-
resp.end(Buffer.from(serializer.getBufferView()));
|
|
121
|
-
|
|
122
|
-
// Release buffer when response is finished
|
|
123
|
-
const onFinish = () => serializer.markAsEnded();
|
|
124
|
-
resp.on('finish', onFinish);
|
|
125
|
-
resp.on('close', onFinish); // Fallback for aborted connection
|
|
126
|
-
break;
|
|
127
|
-
}
|
|
128
|
-
default: {
|
|
129
|
-
const error = new RpcError({
|
|
130
|
-
publicMessage: 'unknown-mion-response-format',
|
|
131
|
-
type: 'unknown-error',
|
|
132
|
-
errorData: {bodyType},
|
|
133
|
-
});
|
|
134
|
-
unexpectedFail(resp, mionResp.headers, error);
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
function unexpectedFail(resp: Response, respHeaders: MionHeaders, error: RpcError<string>) {
|
|
140
|
-
if (resp.writableEnded) return;
|
|
141
|
-
const routeResponse = getRouterFatalErrorResponse(error, respHeaders);
|
|
142
|
-
reply(routeResponse, resp);
|
|
143
|
-
}
|
package/src/headers.ts
DELETED
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
/* ########
|
|
2
|
-
* 2022 mion
|
|
3
|
-
* Author: Ma-jerez
|
|
4
|
-
* License: MIT
|
|
5
|
-
* The software is provided "as is", without warranty of any kind.
|
|
6
|
-
* ######## */
|
|
7
|
-
|
|
8
|
-
import {MionHeaders, headersFromRecord} from '@mionjs/router';
|
|
9
|
-
import {IncomingMessage, ServerResponse} from 'http';
|
|
10
|
-
|
|
11
|
-
export function headersFromIncomingMessage(rawRequest: IncomingMessage): MionHeaders {
|
|
12
|
-
return headersFromRecord(rawRequest.headers as Record<string, string>);
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* Reusable class for managing HTTP response headers with ServerResponse integration
|
|
17
|
-
* Provides a MionHeaders interface that wraps Node.js ServerResponse header methods
|
|
18
|
-
*/
|
|
19
|
-
class ServerResponseHeadersImpl implements MionHeaders {
|
|
20
|
-
constructor(private resp: ServerResponse) {}
|
|
21
|
-
|
|
22
|
-
append(name: string, value: string): void {
|
|
23
|
-
this.resp.appendHeader(name, value);
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
delete(name: string): void {
|
|
27
|
-
this.resp.removeHeader(name);
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
get(name: string): string | undefined | null {
|
|
31
|
-
const value = this.resp.getHeader(name);
|
|
32
|
-
if (Array.isArray(value)) return value.join(', ');
|
|
33
|
-
return value as string;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
has(name: string): boolean {
|
|
37
|
-
return this.resp.hasHeader(name);
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
set(name: string, value: string): void {
|
|
41
|
-
this.resp.setHeader(name, value);
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
entries(): IterableIterator<[string, string]> {
|
|
45
|
-
return getSingleHeadersObj(this.resp).entries();
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
keys(): IterableIterator<string> {
|
|
49
|
-
return new Set(this.resp.getHeaderNames()).values();
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
values(): IterableIterator<string> {
|
|
53
|
-
return getSingleHeadersObj(this.resp).values();
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
export function headersFromServerResponse(resp: ServerResponse, initialHeaders: Record<string, string> | null): MionHeaders {
|
|
58
|
-
if (initialHeaders) Object.entries(initialHeaders).forEach(([name, value]) => resp.setHeader(name, value));
|
|
59
|
-
return new ServerResponseHeadersImpl(resp);
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
function getSingleHeadersObj(resp: ServerResponse) {
|
|
63
|
-
const entries = Object.entries(resp.getHeaders()).map(([name, value]) => [
|
|
64
|
-
name,
|
|
65
|
-
Array.isArray(value) ? value.join(', ') : (value as string),
|
|
66
|
-
]);
|
|
67
|
-
return Object.fromEntries(entries);
|
|
68
|
-
}
|
package/src/types.ts
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
/* ########
|
|
2
|
-
* 2023 mion
|
|
3
|
-
* Author: Ma-jerez
|
|
4
|
-
* License: MIT
|
|
5
|
-
* The software is provided "as is", without warranty of any kind.
|
|
6
|
-
* ######## */
|
|
7
|
-
|
|
8
|
-
// type-google-cf-options-start
|
|
9
|
-
export interface GoogleCFOptions {
|
|
10
|
-
/** Set of default response header to add to every response*/
|
|
11
|
-
defaultResponseHeaders: Record<string, string>;
|
|
12
|
-
}
|
|
13
|
-
// type-google-cf-options-end
|