@interopio/gateway-server 0.6.1-beta → 0.7.0-beta

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.
@@ -1,43 +1,17 @@
1
1
  import {IOGateway} from '@interopio/gateway';
2
- import {FilePublisherConfig} from '@interopio/gateway/metrics/publisher/file';
3
-
2
+ import type {ServerCorsConfig, ServerConfigurer, ServerWebSocketOptions} from './types/web/server';
4
3
  export default GatewayServer.Factory;
5
4
 
6
5
  export namespace GatewayServer {
7
6
  export const Factory: (options: ServerConfig) => Promise<Server>
8
- export type SslConfig = { key?: string, cert?: string, ca?: string }
9
- export type AuthorizationRule = { access: 'permitted' | 'denied' | 'authenticated' }
10
- export type OriginFilters = {
11
- non_matched?: IOGateway.Filtering.Action
12
- missing?: IOGateway.Filtering.Action
13
- block?: IOGateway.Filtering.Matcher[]
14
- allow?: IOGateway.Filtering.Matcher[]
15
- /**
16
- * @deprecated
17
- * @see block
18
- */
19
- blacklist?: IOGateway.Filtering.Matcher[]
20
- /**
21
- * @deprecated
22
- * @see allow
23
- */
24
- whitelist?: IOGateway.Filtering.Matcher[]
25
- }
7
+ export type SslConfig = Readonly<{ key?: string, cert?: string, ca?: string }>
8
+
26
9
  export import LoggerConfig = IOGateway.Logging.LogConfig;
27
10
  export type AuthConfig = Readonly<{
28
11
  type: 'none' | 'basic' | 'oauth2',
29
12
  basic?: { user?: {name: string, password?: string}, realm?: string }
30
13
  oauth2?: { jwt: { issuerUri: string, issuer?: string, audience?: string | string[] } }
31
14
  }>;
32
- export type CorsConfig = Readonly<{
33
- allowOrigin?: '*' | IOGateway.Filtering.Matcher[]
34
- allowHeaders?: string[]
35
- allowMethods?: string[]
36
- exposeHeaders?: string[]
37
- allowCredentials?: boolean
38
- allowPrivateNetwork?: boolean
39
- maxAge?: number
40
- }>;
41
15
 
42
16
  export type ServerConfig = {
43
17
  /**
@@ -58,7 +32,7 @@ export namespace GatewayServer {
58
32
  /**
59
33
  * CORS configuration.
60
34
  */
61
- cors?: CorsConfig,
35
+ cors?: ServerCorsConfig,
62
36
 
63
37
  memory?: {
64
38
  memory_limit?: number
@@ -68,24 +42,12 @@ export namespace GatewayServer {
68
42
  max_backups?: number,
69
43
  },
70
44
 
71
- gateway?: IOGateway.GatewayConfig & {
45
+ app?: (configurer: ServerConfigurer, config: ServerConfig) => Promise<void>,
46
+ gateway?: IOGateway.GatewayConfig & ServerWebSocketOptions & {
72
47
  route?: string
73
- ping?: number
74
- origins?: OriginFilters
75
- limits?: {
76
- max_connections?: number
77
- },
78
- authorize?: AuthorizationRule
79
- }
80
- mesh?: {
48
+ },
49
+ mesh?: ServerWebSocketOptions & {
81
50
  timeout?: number // defaults to 60000
82
- ping?: number // defaults to 30000
83
- authorize?: AuthorizationRule
84
- origins?: OriginFilters
85
- }
86
- metrics?: {
87
- file: FilePublisherConfig
88
- authorize?: AuthorizationRule
89
51
  }
90
52
  }
91
53
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@interopio/gateway-server",
3
- "version": "0.6.1-beta",
3
+ "version": "0.7.0-beta",
4
4
  "keywords": [
5
5
  "gateway",
6
6
  "server",
@@ -32,6 +32,12 @@
32
32
  "node": "./dist/index.cjs",
33
33
  "require": "./dist/index.cjs"
34
34
  },
35
+ "./auth/api": {
36
+ "types": "./types/auth.d.ts"
37
+ },
38
+ "./web/server": {
39
+ "types": "./types/web/server.d.ts"
40
+ },
35
41
  "./metrics/publisher/rest": {
36
42
  "import": "./dist/metrics/publisher/rest.js",
37
43
  "node": "./dist/metrics/publisher/rest.cjs",
@@ -50,11 +56,11 @@
50
56
  "types": "gateway-server.d.ts",
51
57
  "type": "module",
52
58
  "engines": {
53
- "node": ">=20"
59
+ "node": ">=20.10 || >= 22.12 || >= 24"
54
60
  },
55
61
  "dependencies": {
56
- "@interopio/gateway": "^0.11.0-beta",
57
- "ws": "^8.18.2",
62
+ "@interopio/gateway": "^0.11.1-beta",
63
+ "ws": "^8.18.3",
58
64
  "http-cookie-agent": "^7.0.1",
59
65
  "undici": "^6.21.3",
60
66
  "tough-cookie": "^5.1.2"
package/readme.md CHANGED
@@ -28,9 +28,32 @@ const server: Server = await GatewayServer({
28
28
  ca: "intermediate.crt",
29
29
  key: "glue42.key"
30
30
  },
31
- metrics: {
32
- access: 'permitted'
33
- }
31
+ app: async (configurer) => {
32
+ configurer
33
+ .authorize(['/api/metrics', {access: 'permitted'}]) // or 'authenticated'
34
+ .cors(['/api/metrics', {allowMethods: ['GET', 'POST']}]) // ensure 'GET' and 'POST' methods are allowed for CORS
35
+ .handle(
36
+ [
37
+ {method: 'GET', path: '/api/metrics'},
38
+ async ({response}) => {
39
+ response.statusCode = 200; // OK
40
+ await response.end();
41
+ }
42
+ ],
43
+ [
44
+ {method: 'POST', path: '/api/metrics'},
45
+ async ({request, response}) => {
46
+ response.statusCode = 202; // Accepted
47
+ await response.end();
48
+ try {
49
+ const update = await request.json();
50
+ console.log(`${JSON.stringify(update)}`);
51
+ } catch (e) {
52
+ console.error('Error processing metrics:', e);
53
+ }
54
+ }
55
+ ]);
56
+ },
34
57
  });
35
58
 
36
59
  await server.close();
@@ -0,0 +1,5 @@
1
+ export type Principal = {
2
+ readonly name?: string
3
+ }
4
+
5
+ export type AuthorizationRule = { access: 'permitted' | 'denied' | 'authenticated' }
@@ -0,0 +1,64 @@
1
+
2
+
3
+ export type ReadonlyHeaderValue = string | undefined;
4
+ export type HeaderValue = number | ReadonlyHeaderValue;
5
+ export type ReadonlyHeaderValues = (readonly string[]) | ReadonlyHeaderValue
6
+ export type HeaderValues = (readonly string[]) | HeaderValue
7
+
8
+ export interface HttpHeaders {
9
+ get(name: string): HeaderValues
10
+ list(name: string): string[]
11
+ one(name: string): HeaderValue
12
+ has(name: string): boolean
13
+ keys(): IteratorObject<string>
14
+ }
15
+
16
+ export interface ReadonlyHttpHeaders extends HttpHeaders {
17
+ get(name: string): ReadonlyHeaderValues
18
+ one(name: string): string | undefined
19
+
20
+ }
21
+ export interface MutableHttpHeaders extends HttpHeaders {
22
+ get(name: string): HeaderValues
23
+ one(name: string): HeaderValue
24
+ set(name: string, value: HeaderValues): this
25
+ add(name: string, value: string | (readonly string[])): this
26
+ }
27
+
28
+ export type HttpMessage<Headers = HttpHeaders> = {
29
+ readonly headers: Headers
30
+ }
31
+ export type HttpMethod
32
+ = 'GET'
33
+ | 'HEAD'
34
+ | 'POST'
35
+ | 'PUT'
36
+ | 'DELETE'
37
+ | 'CONNECT'
38
+ | 'OPTIONS'
39
+ | 'TRACE'
40
+ | 'PATCH'
41
+ ;
42
+
43
+ export type HttpRequest<Headers = HttpHeaders> = HttpMessage<Headers> & {
44
+ readonly path: string,
45
+ readonly method?: HttpMethod
46
+ readonly URL: URL
47
+ readonly protocol: string
48
+ /**
49
+ * hostname[:port]
50
+ */
51
+ readonly host?: string
52
+ readonly body: Promise<Blob>
53
+ }
54
+
55
+ export type HttpResponse<Headers = HttpHeaders> = HttpMessage<Headers> & {
56
+ readonly statusCode: number
57
+ }
58
+
59
+ export type HttpCookie = {
60
+ name: string,
61
+ value: string
62
+ }
63
+
64
+
@@ -0,0 +1,108 @@
1
+ import type {
2
+ HttpCookie,
3
+ HttpMethod,
4
+ HttpRequest,
5
+ HttpResponse,
6
+ MutableHttpHeaders,
7
+ ReadonlyHttpHeaders
8
+ } from './http';
9
+ import type {WebSocketHandler} from './ws';
10
+ import type {Principal, AuthorizationRule} from '../auth';
11
+ import {IOGateway} from '@interopio/gateway';
12
+
13
+ export type OriginFilters = {
14
+ non_matched?: IOGateway.Filtering.Action
15
+ missing?: IOGateway.Filtering.Action
16
+ block?: IOGateway.Filtering.Matcher[]
17
+ allow?: IOGateway.Filtering.Matcher[]
18
+ /**
19
+ * @deprecated
20
+ * @see block
21
+ */
22
+ blacklist?: IOGateway.Filtering.Matcher[]
23
+ /**
24
+ * @deprecated
25
+ * @see allow
26
+ */
27
+ whitelist?: IOGateway.Filtering.Matcher[]
28
+ }
29
+
30
+ export type ServerHttpRequestMatcher = { method?: HttpMethod, path: IOGateway.Filtering.Matcher };
31
+
32
+ export type ServerCorsConfig = Readonly<{
33
+ allowOrigin?: '*' | IOGateway.Filtering.Matcher[]
34
+ allowHeaders?: string[]
35
+ allowMethods?: HttpMethod[]
36
+ exposeHeaders?: string[]
37
+ allowCredentials?: boolean
38
+ allowPrivateNetwork?: boolean
39
+ maxAge?: number
40
+ }>;
41
+
42
+ export type ServerExchangeOptions = {
43
+ authorize?: AuthorizationRule,
44
+ cors?: boolean | ServerCorsConfig,
45
+ origins?: OriginFilters,
46
+ }
47
+ export type ServerWebSocketOptions = ServerExchangeOptions & {
48
+ ping?: number,
49
+ maxConnections?: number
50
+ }
51
+
52
+ export type ServerConfigurerHandlerSpec<T extends string = string> = {
53
+ request: ServerHttpRequestMatcher, options?: ServerExchangeOptions
54
+ handler: (exchange: ServerWebExchange, variables: { [key in T]: string }) => Promise<void>,
55
+ }
56
+
57
+ export type ServerWebSocketHandler = WebSocketHandler & {
58
+ close?: () => Promise<void>
59
+ }
60
+
61
+ export type ServerConfigurerSocketSpec = {
62
+ path?: string, options?: ServerWebSocketOptions
63
+ factory: (server: { endpoint: string }) => Promise<ServerWebSocketHandler>,
64
+ }
65
+
66
+ export interface ServerConfigurer {
67
+ handle(...handler: Array<ServerConfigurerHandlerSpec>): void;
68
+
69
+ socket(...socket: Array<ServerConfigurerSocketSpec>): void;
70
+ }
71
+
72
+ export type Middleware<Request extends ServerHttpRequest = ServerHttpRequest, Response extends ServerHttpResponse = ServerHttpResponse> = ((context: ServerWebExchange<Request, Response>, next: () => Promise<void>) => Promise<void>)[];
73
+
74
+ export type ServerWebExchange<Request extends ServerHttpRequest = ServerHttpRequest, Response extends ServerHttpResponse = ServerHttpResponse> = {
75
+ readonly request: Request
76
+ readonly response: Response;
77
+ principal<P extends Principal>(): Promise<P | undefined>;
78
+ }
79
+
80
+ export type ResponseCookie = HttpCookie & {
81
+ maxAge: number,
82
+ domain?: string,
83
+ path?: string,
84
+ secure?: boolean,
85
+ httpOnly?: boolean,
86
+ sameSite?: 'strict' | 'lax' | 'none'
87
+ }
88
+
89
+ export type ServerHttpRequest = HttpRequest<ReadonlyHttpHeaders> & {
90
+ readonly cookies: HttpCookie[]
91
+ readonly formData: Promise<URLSearchParams>
92
+ // readonly text: Promise<string>
93
+ readonly json: Promise<unknown>
94
+ // readonly socket: http.IncomingMessage['socket']
95
+ // readonly _req: http.IncomingMessage
96
+ readonly upgrade: boolean
97
+ }
98
+
99
+ export interface ServerHttpResponse extends HttpResponse<MutableHttpHeaders> {
100
+ statusCode: number
101
+ statusMessage?: string
102
+
103
+ readonly cookies: ResponseCookie[]
104
+
105
+ addCookie(cookie: ResponseCookie): this
106
+
107
+ end(chunk?: unknown): Promise<boolean>
108
+ }
@@ -0,0 +1,19 @@
1
+ import type {WebSocket} from 'ws';
2
+ import type {ReadonlyHttpHeaders, HttpCookie} from './http';
3
+ import type {Principal} from '../auth';
4
+
5
+ type WebSocketHandshakeInfo = {
6
+ readonly url: URL;
7
+
8
+ // request headers for server and response headers for client
9
+ readonly headers: ReadonlyHttpHeaders;
10
+ readonly cookies: ReadonlyArray<HttpCookie>;
11
+ principal<P extends Principal>(): Promise<P | undefined>;
12
+ readonly protocol?: string;
13
+ readonly remoteAddress?: string;
14
+ readonly remoteFamily?: string;
15
+ readonly remotePort?: number;
16
+ readonly logPrefix?: string;
17
+ }
18
+
19
+ type WebSocketHandler = (socket: WebSocket, handshake: WebSocketHandshakeInfo) => Promise<void>