@zhin.js/gateway 0.0.1-bootstrap.0 → 1.1.2

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 (181) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +61 -0
  3. package/lib/config/ai-config-loader.d.ts +22 -0
  4. package/lib/config/ai-config-loader.js +96 -0
  5. package/lib/config/configuration-chat-policy.d.ts +57 -0
  6. package/lib/config/configuration-chat-policy.js +423 -0
  7. package/lib/config/configuration-patch.d.ts +16 -0
  8. package/lib/config/configuration-patch.js +105 -0
  9. package/lib/config/configuration-path.d.ts +6 -0
  10. package/lib/config/configuration-path.js +40 -0
  11. package/lib/config/configuration-projection.d.ts +6 -0
  12. package/lib/config/configuration-projection.js +28 -0
  13. package/lib/config/configuration-redaction.d.ts +18 -0
  14. package/lib/config/configuration-redaction.js +75 -0
  15. package/lib/config/configuration.d.ts +81 -0
  16. package/lib/config/configuration.js +686 -0
  17. package/lib/config/console-schema.d.ts +11 -0
  18. package/lib/config/console-schema.js +223 -0
  19. package/lib/config/environment-files.d.ts +3 -0
  20. package/lib/config/environment-files.js +14 -0
  21. package/lib/config/literal-secrets.d.ts +34 -0
  22. package/lib/config/literal-secrets.js +136 -0
  23. package/lib/config/plugin-package-map.d.ts +2 -0
  24. package/lib/config/plugin-package-map.js +14 -0
  25. package/lib/config/plugin-schema-catalog.d.ts +22 -0
  26. package/lib/config/plugin-schema-catalog.js +262 -0
  27. package/lib/config.d.ts +13 -0
  28. package/lib/config.js +13 -0
  29. package/lib/database/config.d.ts +22 -0
  30. package/lib/database/config.js +159 -0
  31. package/lib/database/index.d.ts +2 -0
  32. package/lib/database/index.js +2 -0
  33. package/lib/database/project-database.d.ts +31 -0
  34. package/lib/database/project-database.js +130 -0
  35. package/lib/database.d.ts +2 -0
  36. package/lib/database.js +2 -0
  37. package/lib/http/console-rpc.d.ts +27 -0
  38. package/lib/http/console-rpc.js +51 -0
  39. package/lib/http/gateway-console.d.ts +63 -0
  40. package/lib/http/gateway-console.js +309 -0
  41. package/lib/http/gateway-events.d.ts +40 -0
  42. package/lib/http/gateway-events.js +185 -0
  43. package/lib/http/gateway-http-server.d.ts +95 -0
  44. package/lib/http/gateway-http-server.js +522 -0
  45. package/lib/http/local-principal.d.ts +2 -0
  46. package/lib/http/local-principal.js +16 -0
  47. package/lib/http/plugin-switch-rpc.d.ts +19 -0
  48. package/lib/http/plugin-switch-rpc.js +214 -0
  49. package/lib/http/run-gateway.d.ts +43 -0
  50. package/lib/http/run-gateway.js +268 -0
  51. package/lib/http/start-gateway.d.ts +114 -0
  52. package/lib/http/start-gateway.js +226 -0
  53. package/lib/http-response.d.ts +6 -0
  54. package/lib/http-response.js +25 -0
  55. package/lib/http.d.ts +6 -0
  56. package/lib/http.js +6 -0
  57. package/lib/iam/crypto.d.ts +12 -0
  58. package/lib/iam/crypto.js +58 -0
  59. package/lib/iam/index.d.ts +8 -0
  60. package/lib/iam/index.js +8 -0
  61. package/lib/iam/install.d.ts +36 -0
  62. package/lib/iam/install.js +74 -0
  63. package/lib/iam/local-admin.d.ts +27 -0
  64. package/lib/iam/local-admin.js +102 -0
  65. package/lib/iam/rate-limit.d.ts +15 -0
  66. package/lib/iam/rate-limit.js +52 -0
  67. package/lib/iam/routes.d.ts +23 -0
  68. package/lib/iam/routes.js +157 -0
  69. package/lib/iam/rpc.d.ts +14 -0
  70. package/lib/iam/rpc.js +100 -0
  71. package/lib/iam/service.d.ts +203 -0
  72. package/lib/iam/service.js +784 -0
  73. package/lib/iam/setup-service.d.ts +83 -0
  74. package/lib/iam/setup-service.js +206 -0
  75. package/lib/iam/tables.d.ts +20 -0
  76. package/lib/iam/tables.js +82 -0
  77. package/lib/iam.d.ts +2 -0
  78. package/lib/iam.js +2 -0
  79. package/lib/index.d.ts +22 -0
  80. package/lib/index.js +22 -0
  81. package/lib/local/client.d.ts +71 -0
  82. package/lib/local/client.js +296 -0
  83. package/lib/local/handler.d.ts +30 -0
  84. package/lib/local/handler.js +86 -0
  85. package/lib/local/local-socket.d.ts +55 -0
  86. package/lib/local/local-socket.js +232 -0
  87. package/lib/local/paths.d.ts +34 -0
  88. package/lib/local/paths.js +58 -0
  89. package/lib/local/protocol.d.ts +140 -0
  90. package/lib/local/protocol.js +90 -0
  91. package/lib/local/state-file.d.ts +8 -0
  92. package/lib/local/state-file.js +45 -0
  93. package/lib/local.d.ts +10 -0
  94. package/lib/local.js +10 -0
  95. package/lib/onboarding/allowlist.d.ts +54 -0
  96. package/lib/onboarding/allowlist.js +106 -0
  97. package/lib/onboarding/errors.d.ts +7 -0
  98. package/lib/onboarding/errors.js +17 -0
  99. package/lib/onboarding/index.d.ts +6 -0
  100. package/lib/onboarding/index.js +6 -0
  101. package/lib/onboarding/install.d.ts +99 -0
  102. package/lib/onboarding/install.js +132 -0
  103. package/lib/onboarding/package-manager.d.ts +47 -0
  104. package/lib/onboarding/package-manager.js +179 -0
  105. package/lib/onboarding/service.d.ts +53 -0
  106. package/lib/onboarding/service.js +144 -0
  107. package/lib/onboarding/state-store.d.ts +26 -0
  108. package/lib/onboarding/state-store.js +97 -0
  109. package/lib/onboarding.d.ts +2 -0
  110. package/lib/onboarding.js +2 -0
  111. package/lib/packages/authorization.d.ts +24 -0
  112. package/lib/packages/authorization.js +128 -0
  113. package/lib/packages/errors.d.ts +11 -0
  114. package/lib/packages/errors.js +26 -0
  115. package/lib/packages/index.d.ts +5 -0
  116. package/lib/packages/index.js +5 -0
  117. package/lib/packages/rpc.d.ts +30 -0
  118. package/lib/packages/rpc.js +160 -0
  119. package/lib/packages/service.d.ts +139 -0
  120. package/lib/packages/service.js +504 -0
  121. package/lib/packages/snapshot.d.ts +14 -0
  122. package/lib/packages/snapshot.js +73 -0
  123. package/lib/packages.d.ts +2 -0
  124. package/lib/packages.js +2 -0
  125. package/lib/plugin-management/activity.d.ts +6 -0
  126. package/lib/plugin-management/activity.js +14 -0
  127. package/lib/plugin-management/config-explanation.d.ts +6 -0
  128. package/lib/plugin-management/config-explanation.js +113 -0
  129. package/lib/plugin-management/use-cases.d.ts +15 -0
  130. package/lib/plugin-management/use-cases.js +120 -0
  131. package/lib/plugin-management/workflow.d.ts +136 -0
  132. package/lib/plugin-management/workflow.js +878 -0
  133. package/lib/plugin-management.d.ts +5 -0
  134. package/lib/plugin-management.js +5 -0
  135. package/lib/project/config-file.d.ts +6 -0
  136. package/lib/project/config-file.js +58 -0
  137. package/lib/project/environment.d.ts +13 -0
  138. package/lib/project/environment.js +52 -0
  139. package/lib/project/instance-declarations.d.ts +55 -0
  140. package/lib/project/instance-declarations.js +542 -0
  141. package/lib/project/legacy-config.d.ts +25 -0
  142. package/lib/project/legacy-config.js +70 -0
  143. package/lib/project/node-requirements.d.ts +7 -0
  144. package/lib/project/node-requirements.js +20 -0
  145. package/lib/project/tsx-module-loader.d.ts +7 -0
  146. package/lib/project/tsx-module-loader.js +29 -0
  147. package/lib/project.d.ts +7 -0
  148. package/lib/project.js +7 -0
  149. package/lib/server.d.ts +11 -0
  150. package/lib/server.js +11 -0
  151. package/lib/supervisor/instance-logs.d.ts +39 -0
  152. package/lib/supervisor/instance-logs.js +152 -0
  153. package/lib/supervisor/instance-supervisor.d.ts +140 -0
  154. package/lib/supervisor/instance-supervisor.js +408 -0
  155. package/lib/supervisor/run-instance.d.ts +35 -0
  156. package/lib/supervisor/run-instance.js +161 -0
  157. package/lib/supervisor/terminal-state.d.ts +30 -0
  158. package/lib/supervisor/terminal-state.js +57 -0
  159. package/lib/supervisor.d.ts +4 -0
  160. package/lib/supervisor.js +4 -0
  161. package/lib/terminal/backends.d.ts +38 -0
  162. package/lib/terminal/backends.js +193 -0
  163. package/lib/terminal/config.d.ts +63 -0
  164. package/lib/terminal/config.js +237 -0
  165. package/lib/terminal/host.d.ts +26 -0
  166. package/lib/terminal/host.js +76 -0
  167. package/lib/terminal/index.d.ts +60 -0
  168. package/lib/terminal/index.js +135 -0
  169. package/lib/terminal/modules.d.ts +87 -0
  170. package/lib/terminal/modules.js +44 -0
  171. package/lib/terminal/service.d.ts +101 -0
  172. package/lib/terminal/service.js +455 -0
  173. package/lib/terminal/tickets.d.ts +46 -0
  174. package/lib/terminal/tickets.js +76 -0
  175. package/lib/terminal.d.ts +3 -0
  176. package/lib/terminal.js +3 -0
  177. package/lib/usage/aggregate.d.ts +87 -0
  178. package/lib/usage/aggregate.js +212 -0
  179. package/lib/usage.d.ts +2 -0
  180. package/lib/usage.js +2 -0
  181. package/package.json +117 -4
@@ -0,0 +1,185 @@
1
+ import { GATEWAY_PACKAGES_PROGRESS, GATEWAY_PACKAGES_PROGRESS_PATH } from '@zhin.js/console-protocol';
2
+ import { jsonResponse } from '@zhin.js/host-http';
3
+ const KEEPALIVE_MS = 15_000;
4
+ /** Console event the client reloads its entries on (`CONSOLE_ENTRY_LIFECYCLE_EVENTS`). */
5
+ export const PLUGIN_LIFECYCLE_UPDATED = 'plugin:lifecycle-updated';
6
+ /** Gateway frames held while an instance frame is half written. */
7
+ const MAX_PENDING_FRAMES = 1_024;
8
+ /** Chunks queued for a client that does not read; beyond it the stream ends (the client resumes). */
9
+ const MAX_QUEUED_CHUNKS = 4_096;
10
+ const SSE_HEADERS = Object.freeze({
11
+ 'content-type': 'text/event-stream; charset=utf-8',
12
+ 'cache-control': 'no-cache, no-transform',
13
+ 'x-accel-buffering': 'no',
14
+ });
15
+ export function gatewayEventFrame(type, data) {
16
+ return `event: ${type}\ndata: ${JSON.stringify(data)}\n\n`;
17
+ }
18
+ /** Registers the gateway's event routes; returns the unregister function. */
19
+ export function registerGatewayEventRoutes(options) {
20
+ const { server } = options;
21
+ const base = server.apiBase;
22
+ const keepAliveMs = options.keepAliveMs ?? KEEPALIVE_MS;
23
+ const encoder = new TextEncoder();
24
+ /** A client stream fed with gateway frames (plus, when merging, the instance's). */
25
+ const open = (request) => {
26
+ let controller;
27
+ let finished = false;
28
+ const cleanups = [];
29
+ const finish = () => {
30
+ if (finished)
31
+ return;
32
+ finished = true;
33
+ for (const cleanup of cleanups.splice(0)) {
34
+ try {
35
+ cleanup();
36
+ }
37
+ catch { /* keep closing */ }
38
+ }
39
+ try {
40
+ controller.close();
41
+ }
42
+ catch { /* already closed */ }
43
+ };
44
+ const stream = new ReadableStream({
45
+ start(value) { controller = value; },
46
+ cancel() { finish(); },
47
+ });
48
+ const write = (text) => {
49
+ if (finished)
50
+ return;
51
+ try {
52
+ if ((controller.desiredSize ?? 1) < -MAX_QUEUED_CHUNKS) {
53
+ finish();
54
+ return;
55
+ }
56
+ controller.enqueue(encoder.encode(text));
57
+ }
58
+ catch {
59
+ finish();
60
+ }
61
+ };
62
+ request.signal.addEventListener('abort', finish, { once: true });
63
+ const timer = setInterval(() => write(': keepalive\n\n'), keepAliveMs);
64
+ timer.unref?.();
65
+ cleanups.push(() => clearInterval(timer));
66
+ return { stream, write, finish, cleanups, get finished() { return finished; } };
67
+ };
68
+ /**
69
+ * Progress frames; on the Console event stream (`lifecycle`) a succeeded enable / disable that
70
+ * changed `disable_plugins` is followed by `plugin:lifecycle-updated` `{ instanceKey, enabled }`,
71
+ * the event the instance used to publish for the Console switch (the Console reloads its entries).
72
+ */
73
+ const subscribeProgress = (deliver, lifecycle = false) => options.packages?.subscribe((event) => {
74
+ deliver(gatewayEventFrame(GATEWAY_PACKAGES_PROGRESS, event));
75
+ const plugin = event.type === 'result' && event.result.ok ? event.result.plugin : undefined;
76
+ if (lifecycle && plugin?.changed) {
77
+ deliver(gatewayEventFrame(PLUGIN_LIFECYCLE_UPDATED, { instanceKey: plugin.instanceKey, enabled: plugin.enabled }));
78
+ }
79
+ });
80
+ const events = async (request, context) => {
81
+ if (!server.instanceReady)
82
+ return offlineStream(request);
83
+ const upstream = await server.forward(request, context);
84
+ const type = upstream.headers.get('content-type') ?? '';
85
+ // Errors (401 / 403 / 503 …) and non-SSE answers pass through unchanged.
86
+ if (!upstream.ok || !upstream.body || !type.includes('text/event-stream')) {
87
+ if (upstream.status === 503 && !server.instanceReady) {
88
+ await upstream.body?.cancel().catch(() => undefined);
89
+ return offlineStream(request);
90
+ }
91
+ return upstream;
92
+ }
93
+ const client = open(request);
94
+ const reader = upstream.body.getReader();
95
+ client.cleanups.push(() => { void reader.cancel().catch(() => undefined); });
96
+ // Gateway frames wait while an instance frame is half written.
97
+ const pending = [];
98
+ let partial = '';
99
+ const decoder = new TextDecoder();
100
+ const flushPending = () => {
101
+ for (const frame of pending.splice(0))
102
+ client.write(frame);
103
+ };
104
+ const stop = subscribeProgress((frame) => {
105
+ if (partial) {
106
+ if (pending.length < MAX_PENDING_FRAMES)
107
+ pending.push(frame);
108
+ return;
109
+ }
110
+ client.write(frame);
111
+ }, true);
112
+ if (stop)
113
+ client.cleanups.push(stop);
114
+ void (async () => {
115
+ try {
116
+ for (;;) {
117
+ const { done, value } = await reader.read();
118
+ if (done || client.finished)
119
+ break;
120
+ const text = decoder.decode(value, { stream: true });
121
+ client.write(text);
122
+ partial = trailingPartialFrame(partial + text);
123
+ if (!partial)
124
+ flushPending();
125
+ }
126
+ }
127
+ catch { /* instance side ended */ }
128
+ client.finish();
129
+ })();
130
+ const headers = new Headers(upstream.headers);
131
+ headers.delete('content-length');
132
+ return new Response(client.stream, { status: upstream.status, headers });
133
+ };
134
+ const offlineStream = (request) => {
135
+ const client = open(request);
136
+ client.write(': gateway\n\n');
137
+ const stop = subscribeProgress((frame) => client.write(frame), true);
138
+ if (stop)
139
+ client.cleanups.push(stop);
140
+ // Reconnect to the merged stream once the instance is back.
141
+ const unwatch = options.instance?.onChange(() => { if (server.instanceReady)
142
+ client.finish(); });
143
+ if (unwatch)
144
+ client.cleanups.push(unwatch);
145
+ return new Response(client.stream, { status: 200, headers: SSE_HEADERS });
146
+ };
147
+ const history = async (request, context) => {
148
+ if (server.instanceReady)
149
+ return server.forward(request, context);
150
+ const runtimeId = context.url.searchParams.get('runtimeId') ?? 'gateway';
151
+ const after = Number(context.url.searchParams.get('after') ?? 0);
152
+ const cursor = Number.isSafeInteger(after) && after >= 0 ? after : 0;
153
+ const page = Object.freeze({
154
+ runtimeId,
155
+ items: Object.freeze([]),
156
+ oldestAvailableEventId: null,
157
+ latestEventId: cursor,
158
+ nextAfter: cursor,
159
+ hasMore: false,
160
+ gap: false,
161
+ });
162
+ return jsonResponse(200, { success: true, data: page }, { 'cache-control': 'no-store' });
163
+ };
164
+ const progress = (request) => {
165
+ const client = open(request);
166
+ client.write(': gateway packages\n\n');
167
+ const stop = subscribeProgress((frame) => client.write(frame));
168
+ if (stop)
169
+ client.cleanups.push(stop);
170
+ return new Response(client.stream, { status: 200, headers: SSE_HEADERS });
171
+ };
172
+ const registrations = [
173
+ server.route('GET', `${base}/events`, events, { summary: 'Console SSE stream (instance events merged with gateway events)', tags: ['console'] }),
174
+ server.route('GET', `${base}/events/history`, history, { summary: 'Console event history (empty while the instance is offline)', tags: ['console'] }),
175
+ server.route('GET', `${base}${GATEWAY_PACKAGES_PROGRESS_PATH}`, progress, { summary: 'Package transaction progress (SSE)', tags: ['gateway'] }),
176
+ ];
177
+ return () => { for (const unregister of registrations)
178
+ unregister(); };
179
+ }
180
+ /** The text after the last complete SSE frame (empty when the buffer ends on a frame boundary). */
181
+ export function trailingPartialFrame(buffer) {
182
+ const normalized = buffer.replace(/\r\n/gu, '\n');
183
+ const boundary = normalized.lastIndexOf('\n\n');
184
+ return boundary < 0 ? normalized : normalized.slice(boundary + 2);
185
+ }
@@ -0,0 +1,95 @@
1
+ /**
2
+ * The gateway's HTTP server (ADR 0054 §2 / §3): the project's only listener.
3
+ *
4
+ * Request flow:
5
+ * 1. gateway-owned routes ({@link GatewayHttpServer.route} / `ws`) — health, `/auth/*`,
6
+ * terminal, the merged Console event stream, package progress; gateway-owned Console RPC
7
+ * (`gateway.*`, `iam.*`, `onboarding.update`) inside `POST {base}/console/request`;
8
+ * 2. `{base}/…` — authenticated and authorized here, then forwarded with the principal;
9
+ * 3. anything else (plugin webhooks, adapter reverse WebSockets, static pages) — forwarded as-is;
10
+ * those routes authenticate themselves.
11
+ *
12
+ * The instance being offline never takes gateway-owned routes down: forwarded requests get
13
+ * `503 { code: 'instance_unavailable', state }` with `Retry-After`; an instance that does not
14
+ * answer in time gives `504 { code: 'instance_timeout' }`, any other bridge failure
15
+ * `502 { code: 'instance_error' }` (mapped from {@link InstanceTransportError}).
16
+ */
17
+ import { TokenRegistry, type HttpHandler, type HttpHostAddress, type HttpRouteRegistration, type ResolvedHttpConfig, type RouteContext, type RouteMeta, type WsHandle, type WsRouteOptions } from '@zhin.js/host-http';
18
+ import { type InstanceTransport } from '@zhin.js/host-http/bridge';
19
+ import { type GatewayConsoleRpc, type GatewayRpcHandler } from './console-rpc.js';
20
+ export declare const DEFAULT_GATEWAY_RETRY_AFTER_SECONDS = 5;
21
+ /** Default cap on a forwarded request body (uploads go through the instance). */
22
+ export declare const DEFAULT_GATEWAY_MAX_REQUEST_BODY_BYTES: number;
23
+ /** Where the server finds the instance; both are read per request. */
24
+ export interface GatewayInstanceSource {
25
+ /** Current transport; undefined while no instance process exists. */
26
+ transport(): InstanceTransport | undefined;
27
+ /** Supervisor state reported in 503 bodies and `/pub/health` (e.g. `starting`, `crashed`). */
28
+ state(): string;
29
+ }
30
+ export interface GatewayHttpServerOptions {
31
+ /** Resolved `http.*` config: the primary listener plus `listeners` (extra ports, TLS). */
32
+ readonly http?: ResolvedHttpConfig;
33
+ readonly instance: GatewayInstanceSource;
34
+ /**
35
+ * Console authentication. The access provider (users, sessions, API tokens) is installed on it
36
+ * by the IAM module; defaults to a registry over `http.token`.
37
+ */
38
+ readonly tokenRegistry?: TokenRegistry;
39
+ readonly retryAfterSeconds?: number;
40
+ readonly maxRequestBodyBytes?: number;
41
+ /**
42
+ * Gateway-owned Console RPC (`gateway.*`) answered on `POST {base}/console/request`; every other
43
+ * RPC type on that route is forwarded to the instance unchanged.
44
+ */
45
+ readonly consoleRpc?: GatewayConsoleRpc;
46
+ }
47
+ /** One router, many listeners: every listener serves the same surface. */
48
+ export declare class GatewayHttpServer {
49
+ #private;
50
+ readonly tokenRegistry: TokenRegistry;
51
+ readonly apiBase: string;
52
+ constructor(options: GatewayHttpServerOptions);
53
+ /** Registers a gateway-owned route; it takes precedence over the instance's routes. */
54
+ route(method: string, path: string, handler: HttpHandler, meta?: RouteMeta): HttpRouteRegistration;
55
+ /** Registers a gateway-owned WebSocket route. */
56
+ ws(path: string, options?: WsRouteOptions): WsHandle;
57
+ /**
58
+ * Answers further RPC types on `POST {base}/console/request` (e.g. `iam.*`); the handler checks
59
+ * the per-RPC permission itself. Returns an unregister function.
60
+ */
61
+ useConsoleRpc(handler: GatewayRpcHandler): () => void;
62
+ /** Whether an instance is connected and serving its route table. */
63
+ get instanceReady(): boolean;
64
+ /**
65
+ * Forwards one request to the instance (the router already authenticated and authorized it):
66
+ * the instance's response, or the documented 502 / 503 / 504 / 413 gateway responses.
67
+ */
68
+ forward(request: Request, context: RouteContext): Promise<Response>;
69
+ /** Handles one request without a socket (tests, local socket bridge). */
70
+ handle(request: Request, info?: {
71
+ readonly remoteAddress?: string;
72
+ }): Promise<Response>;
73
+ /** Primary listener address. */
74
+ get address(): HttpHostAddress | undefined;
75
+ /** Addresses of every bound listener, primary first. */
76
+ get addresses(): readonly HttpHostAddress[];
77
+ listen(): Promise<HttpHostAddress>;
78
+ close(): Promise<void>;
79
+ /**
80
+ * A `{base}/…` request from the local control socket (`gateway.http.request`, ADR 0054 §6).
81
+ * Without `token` the socket's owner check is the authentication: the request runs as
82
+ * {@link LOCAL_OWNER_PRINCIPAL}. With `token` (an explicit `ZHIN_CONSOLE_TOKEN`) it is
83
+ * authenticated like an HTTP request with that Bearer credential and runs — and is audited — as
84
+ * its principal. Either way the request takes the HTTP route table: gateway-owned routes (e.g.
85
+ * `{base}/auth/me`), the `POST {base}/console/request` split, then the instance. Event streams
86
+ * cannot be carried in one socket reply; the socket handler refuses them. Only the path and query
87
+ * of `path` are used; paths outside `{base}` are refused.
88
+ */
89
+ localRequest(input: {
90
+ readonly method: string;
91
+ readonly path: string;
92
+ readonly body?: string;
93
+ readonly token?: string;
94
+ }): Promise<Response>;
95
+ }