@valon-technologies/gestalt 0.0.1-alpha.13 → 0.0.1-alpha.16
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/gen/google/rpc/status_pb.ts +76 -0
- package/gen/v1/agent_pb.ts +561 -65
- package/gen/v1/datastore_pb.ts +457 -2
- package/gen/v1/plugin_pb.ts +31 -14
- package/gen/v1/pluginruntime_pb.ts +120 -81
- package/gen/v1/runtime_pb.ts +29 -1
- package/gen/v1/s3_pb.ts +101 -1
- package/gen/v1/workflow_pb.ts +644 -58
- package/package.json +5 -3
- package/src/agent.ts +168 -15
- package/src/api.ts +4 -1
- package/src/build.ts +2 -0
- package/src/index.ts +69 -18
- package/src/indexeddb.ts +481 -1
- package/src/invoker.ts +3 -0
- package/src/plugin.ts +3 -184
- package/src/pluginruntime.ts +220 -0
- package/src/provider-kind.ts +6 -0
- package/src/provider.ts +16 -0
- package/src/runtime-log-host.ts +244 -0
- package/src/runtime.ts +46 -26
- package/src/s3.ts +81 -0
- package/src/telemetry.ts +429 -0
- package/src/workflow-manager.ts +11 -0
- package/src/manifest-metadata.ts +0 -107
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
import { connect } from "node:net";
|
|
2
|
+
import { Writable } from "node:stream";
|
|
3
|
+
|
|
4
|
+
import type { MessageInitShape } from "@bufbuild/protobuf";
|
|
5
|
+
import {
|
|
6
|
+
createClient,
|
|
7
|
+
type Client,
|
|
8
|
+
type Interceptor,
|
|
9
|
+
} from "@connectrpc/connect";
|
|
10
|
+
import { createGrpcTransport } from "@connectrpc/connect-node";
|
|
11
|
+
|
|
12
|
+
import {
|
|
13
|
+
AppendPluginRuntimeLogsRequestSchema,
|
|
14
|
+
type AppendPluginRuntimeLogsResponse,
|
|
15
|
+
PluginRuntimeLogHost as PluginRuntimeLogHostService,
|
|
16
|
+
PluginRuntimeLogStream,
|
|
17
|
+
} from "../gen/v1/pluginruntime_pb.ts";
|
|
18
|
+
|
|
19
|
+
export const ENV_RUNTIME_LOG_HOST_SOCKET = "GESTALT_RUNTIME_LOG_SOCKET";
|
|
20
|
+
export const ENV_RUNTIME_LOG_HOST_SOCKET_TOKEN = `${ENV_RUNTIME_LOG_HOST_SOCKET}_TOKEN`;
|
|
21
|
+
export const ENV_RUNTIME_SESSION_ID = "GESTALT_RUNTIME_SESSION_ID";
|
|
22
|
+
|
|
23
|
+
const RUNTIME_LOG_RELAY_TOKEN_HEADER = "x-gestalt-host-service-relay-token";
|
|
24
|
+
|
|
25
|
+
export type RuntimeLogStreamName = "stdout" | "stderr" | "runtime";
|
|
26
|
+
export type RuntimeLogStreamInput =
|
|
27
|
+
| RuntimeLogStreamName
|
|
28
|
+
| PluginRuntimeLogStream;
|
|
29
|
+
export type RuntimeLogAppendLogsInput = MessageInitShape<
|
|
30
|
+
typeof AppendPluginRuntimeLogsRequestSchema
|
|
31
|
+
>;
|
|
32
|
+
export type RuntimeLogAppendResponseMessage = AppendPluginRuntimeLogsResponse;
|
|
33
|
+
|
|
34
|
+
export interface RuntimeLogAppendInput {
|
|
35
|
+
sessionId?: string;
|
|
36
|
+
message: string | Uint8Array;
|
|
37
|
+
stream?: RuntimeLogStreamInput;
|
|
38
|
+
observedAt?: Date;
|
|
39
|
+
sourceSeq?: number | bigint;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export interface RuntimeLogWriterOptions {
|
|
43
|
+
sessionId?: string;
|
|
44
|
+
stream?: RuntimeLogStreamInput;
|
|
45
|
+
sourceSeqStart?: number | bigint;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export class RuntimeLogHost {
|
|
49
|
+
private readonly client: Client<typeof PluginRuntimeLogHostService>;
|
|
50
|
+
private sourceSeq = 0n;
|
|
51
|
+
|
|
52
|
+
constructor() {
|
|
53
|
+
const target = process.env[ENV_RUNTIME_LOG_HOST_SOCKET];
|
|
54
|
+
if (!target) {
|
|
55
|
+
throw new Error(
|
|
56
|
+
`runtime log host: ${ENV_RUNTIME_LOG_HOST_SOCKET} is not set`,
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
const relayToken =
|
|
60
|
+
process.env[ENV_RUNTIME_LOG_HOST_SOCKET_TOKEN]?.trim() ?? "";
|
|
61
|
+
const transportOptions = runtimeLogTransportOptions(target);
|
|
62
|
+
const transport = createGrpcTransport({
|
|
63
|
+
...transportOptions,
|
|
64
|
+
...(transportOptions.nodeOptions
|
|
65
|
+
? {
|
|
66
|
+
nodeOptions: {
|
|
67
|
+
createConnection: () =>
|
|
68
|
+
connect(transportOptions.nodeOptions!.path),
|
|
69
|
+
},
|
|
70
|
+
}
|
|
71
|
+
: {}),
|
|
72
|
+
interceptors: relayToken
|
|
73
|
+
? [runtimeLogRelayTokenInterceptor(relayToken)]
|
|
74
|
+
: [],
|
|
75
|
+
});
|
|
76
|
+
this.client = createClient(PluginRuntimeLogHostService, transport);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
async appendLogs(
|
|
80
|
+
request: RuntimeLogAppendLogsInput,
|
|
81
|
+
): Promise<RuntimeLogAppendResponseMessage> {
|
|
82
|
+
return await this.client.appendLogs(request);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
async append(
|
|
86
|
+
input: RuntimeLogAppendInput,
|
|
87
|
+
): Promise<RuntimeLogAppendResponseMessage> {
|
|
88
|
+
const sourceSeq =
|
|
89
|
+
input.sourceSeq === undefined
|
|
90
|
+
? (this.sourceSeq += 1n)
|
|
91
|
+
: BigInt(input.sourceSeq);
|
|
92
|
+
if (sourceSeq > this.sourceSeq) {
|
|
93
|
+
this.sourceSeq = sourceSeq;
|
|
94
|
+
}
|
|
95
|
+
return await this.appendLogs({
|
|
96
|
+
sessionId: runtimeSessionId(input.sessionId),
|
|
97
|
+
logs: [
|
|
98
|
+
{
|
|
99
|
+
stream: runtimeLogStream(input.stream ?? "runtime"),
|
|
100
|
+
message: runtimeLogMessage(input.message),
|
|
101
|
+
observedAt: toProtoTimestamp(input.observedAt ?? new Date()),
|
|
102
|
+
sourceSeq,
|
|
103
|
+
},
|
|
104
|
+
],
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
writer(options?: RuntimeLogWriterOptions): Writable;
|
|
109
|
+
writer(sessionId: string, options?: RuntimeLogWriterOptions): Writable;
|
|
110
|
+
writer(
|
|
111
|
+
sessionIdOrOptions: string | RuntimeLogWriterOptions = {},
|
|
112
|
+
options: RuntimeLogWriterOptions = {},
|
|
113
|
+
): Writable {
|
|
114
|
+
const writerOptions =
|
|
115
|
+
typeof sessionIdOrOptions === "string"
|
|
116
|
+
? options
|
|
117
|
+
: sessionIdOrOptions;
|
|
118
|
+
const sessionId = runtimeSessionId(
|
|
119
|
+
typeof sessionIdOrOptions === "string"
|
|
120
|
+
? sessionIdOrOptions
|
|
121
|
+
: writerOptions.sessionId,
|
|
122
|
+
);
|
|
123
|
+
const stream = writerOptions.stream ?? "stdout";
|
|
124
|
+
let sourceSeq = BigInt(writerOptions.sourceSeqStart ?? 0);
|
|
125
|
+
|
|
126
|
+
return new Writable({
|
|
127
|
+
write: (chunk: Buffer | string, encoding, callback) => {
|
|
128
|
+
const actualEncoding = (
|
|
129
|
+
String(encoding) === "buffer" ? "utf8" : encoding
|
|
130
|
+
) as BufferEncoding;
|
|
131
|
+
const message =
|
|
132
|
+
typeof chunk === "string"
|
|
133
|
+
? chunk
|
|
134
|
+
: Buffer.from(chunk).toString(actualEncoding);
|
|
135
|
+
sourceSeq += 1n;
|
|
136
|
+
this.append({
|
|
137
|
+
sessionId,
|
|
138
|
+
stream,
|
|
139
|
+
message,
|
|
140
|
+
sourceSeq,
|
|
141
|
+
}).then(
|
|
142
|
+
() => callback(),
|
|
143
|
+
(error: unknown) => callback(toError(error)),
|
|
144
|
+
);
|
|
145
|
+
},
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
function runtimeSessionId(sessionId?: string): string {
|
|
151
|
+
const value = (sessionId ?? process.env[ENV_RUNTIME_SESSION_ID] ?? "").trim();
|
|
152
|
+
if (!value) {
|
|
153
|
+
throw new Error(`runtime session: ${ENV_RUNTIME_SESSION_ID} is not set`);
|
|
154
|
+
}
|
|
155
|
+
return value;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
function runtimeLogTransportOptions(rawTarget: string): {
|
|
159
|
+
baseUrl: string;
|
|
160
|
+
nodeOptions?: { path: string };
|
|
161
|
+
} {
|
|
162
|
+
const target = rawTarget.trim();
|
|
163
|
+
if (!target) {
|
|
164
|
+
throw new Error("runtime log host: transport target is required");
|
|
165
|
+
}
|
|
166
|
+
if (target.startsWith("tcp://")) {
|
|
167
|
+
const address = target.slice("tcp://".length).trim();
|
|
168
|
+
if (!address) {
|
|
169
|
+
throw new Error(
|
|
170
|
+
`runtime log host: tcp target ${JSON.stringify(rawTarget)} is missing host:port`,
|
|
171
|
+
);
|
|
172
|
+
}
|
|
173
|
+
return { baseUrl: `http://${address}` };
|
|
174
|
+
}
|
|
175
|
+
if (target.startsWith("tls://")) {
|
|
176
|
+
const address = target.slice("tls://".length).trim();
|
|
177
|
+
if (!address) {
|
|
178
|
+
throw new Error(
|
|
179
|
+
`runtime log host: tls target ${JSON.stringify(rawTarget)} is missing host:port`,
|
|
180
|
+
);
|
|
181
|
+
}
|
|
182
|
+
return { baseUrl: `https://${address}` };
|
|
183
|
+
}
|
|
184
|
+
if (target.startsWith("unix://")) {
|
|
185
|
+
const socketPath = target.slice("unix://".length).trim();
|
|
186
|
+
if (!socketPath) {
|
|
187
|
+
throw new Error(
|
|
188
|
+
`runtime log host: unix target ${JSON.stringify(rawTarget)} is missing a socket path`,
|
|
189
|
+
);
|
|
190
|
+
}
|
|
191
|
+
return { baseUrl: "http://localhost", nodeOptions: { path: socketPath } };
|
|
192
|
+
}
|
|
193
|
+
if (target.includes("://")) {
|
|
194
|
+
const parsed = new URL(target);
|
|
195
|
+
throw new Error(
|
|
196
|
+
`runtime log host: unsupported target scheme ${JSON.stringify(parsed.protocol.replace(/:$/, ""))}`,
|
|
197
|
+
);
|
|
198
|
+
}
|
|
199
|
+
return { baseUrl: "http://localhost", nodeOptions: { path: target } };
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
function runtimeLogRelayTokenInterceptor(token: string): Interceptor {
|
|
203
|
+
return (next) => async (req) => {
|
|
204
|
+
req.header.set(RUNTIME_LOG_RELAY_TOKEN_HEADER, token);
|
|
205
|
+
return await next(req);
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
function runtimeLogStream(stream: RuntimeLogStreamInput): PluginRuntimeLogStream {
|
|
210
|
+
if (typeof stream === "number") {
|
|
211
|
+
return stream;
|
|
212
|
+
}
|
|
213
|
+
switch (stream.trim().toLowerCase()) {
|
|
214
|
+
case "stdout":
|
|
215
|
+
return PluginRuntimeLogStream.STDOUT;
|
|
216
|
+
case "stderr":
|
|
217
|
+
return PluginRuntimeLogStream.STDERR;
|
|
218
|
+
case "runtime":
|
|
219
|
+
return PluginRuntimeLogStream.RUNTIME;
|
|
220
|
+
default:
|
|
221
|
+
throw new Error(`unsupported runtime log stream ${JSON.stringify(stream)}`);
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
function runtimeLogMessage(message: string | Uint8Array): string {
|
|
226
|
+
if (typeof message === "string") {
|
|
227
|
+
return message;
|
|
228
|
+
}
|
|
229
|
+
return Buffer.from(message).toString("utf8");
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
function toProtoTimestamp(value: Date): { seconds: bigint; nanos: number } {
|
|
233
|
+
const millis = value.getTime();
|
|
234
|
+
const seconds = Math.floor(millis / 1000);
|
|
235
|
+
const nanos = Math.trunc((millis - (seconds * 1000)) * 1_000_000);
|
|
236
|
+
return {
|
|
237
|
+
seconds: BigInt(seconds),
|
|
238
|
+
nanos,
|
|
239
|
+
};
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
function toError(error: unknown): Error {
|
|
243
|
+
return error instanceof Error ? error : new Error(String(error));
|
|
244
|
+
}
|
package/src/runtime.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
|
|
3
|
+
import { rmSync, writeFileSync } from "node:fs";
|
|
2
4
|
import { createServer } from "node:http2";
|
|
3
5
|
import { dirname, resolve } from "node:path";
|
|
4
6
|
|
|
@@ -48,7 +50,7 @@ import {
|
|
|
48
50
|
OperationResultSchema,
|
|
49
51
|
ProviderMetadataSchema,
|
|
50
52
|
type HTTPSubjectRequest as ProtoHTTPSubjectRequest,
|
|
51
|
-
type
|
|
53
|
+
type PostConnectCredential as ProtoPostConnectCredential,
|
|
52
54
|
type RequestContext as ProtoRequestContext,
|
|
53
55
|
type ResolveHTTPSubjectRequest as ProtoResolveHTTPSubjectRequest,
|
|
54
56
|
IntegrationProvider as IntegrationProviderService,
|
|
@@ -57,12 +59,16 @@ import {
|
|
|
57
59
|
type GetSessionCatalogRequest,
|
|
58
60
|
type StartProviderRequest,
|
|
59
61
|
} from "../gen/v1/plugin_pb.ts";
|
|
62
|
+
import {
|
|
63
|
+
PluginRuntimeProvider as PluginRuntimeProviderService,
|
|
64
|
+
} from "../gen/v1/pluginruntime_pb.ts";
|
|
60
65
|
import {
|
|
61
66
|
ConfigureProviderResponseSchema,
|
|
62
67
|
HealthCheckResponseSchema,
|
|
63
68
|
ProviderIdentitySchema,
|
|
64
69
|
ProviderKind as ProtoProviderKind,
|
|
65
70
|
ProviderLifecycle,
|
|
71
|
+
StartRuntimeProviderResponseSchema,
|
|
66
72
|
type ConfigureProviderRequest,
|
|
67
73
|
} from "../gen/v1/runtime_pb.ts";
|
|
68
74
|
import { S3 as S3Service } from "../gen/v1/s3_pb.ts";
|
|
@@ -93,6 +99,11 @@ import {
|
|
|
93
99
|
connectionParamToProto,
|
|
94
100
|
isPluginProvider,
|
|
95
101
|
} from "./plugin.ts";
|
|
102
|
+
import {
|
|
103
|
+
PluginRuntimeProvider,
|
|
104
|
+
createPluginRuntimeProviderService,
|
|
105
|
+
isPluginRuntimeProvider,
|
|
106
|
+
} from "./pluginruntime.ts";
|
|
96
107
|
import {
|
|
97
108
|
providerKindLabel,
|
|
98
109
|
resolveDefaultProviderExport,
|
|
@@ -125,11 +136,6 @@ export const ENV_PROVIDER_PARENT_PID = "GESTALT_PLUGIN_PARENT_PID";
|
|
|
125
136
|
* Environment variable used to request static catalog generation.
|
|
126
137
|
*/
|
|
127
138
|
export const ENV_WRITE_CATALOG = "GESTALT_PLUGIN_WRITE_CATALOG";
|
|
128
|
-
/**
|
|
129
|
-
* Environment variable used to request generated manifest metadata export.
|
|
130
|
-
*/
|
|
131
|
-
export const ENV_WRITE_MANIFEST_METADATA =
|
|
132
|
-
"GESTALT_PLUGIN_WRITE_MANIFEST_METADATA";
|
|
133
139
|
/**
|
|
134
140
|
* Protocol version currently implemented by the TypeScript runtime.
|
|
135
141
|
*/
|
|
@@ -139,6 +145,7 @@ export const CURRENT_PROTOCOL_VERSION = 3;
|
|
|
139
145
|
*/
|
|
140
146
|
export const USAGE = "usage: bun run runtime.ts ROOT PROVIDER_TARGET";
|
|
141
147
|
export { createAgentProviderService } from "./agent.ts";
|
|
148
|
+
export { createPluginRuntimeProviderService } from "./pluginruntime.ts";
|
|
142
149
|
export { createWorkflowProviderService } from "./workflow.ts";
|
|
143
150
|
|
|
144
151
|
/**
|
|
@@ -158,6 +165,7 @@ export type LoadedProvider =
|
|
|
158
165
|
| CacheProvider
|
|
159
166
|
| SecretsProvider
|
|
160
167
|
| S3Provider
|
|
168
|
+
| PluginRuntimeProvider
|
|
161
169
|
| AgentProvider
|
|
162
170
|
| WorkflowProvider;
|
|
163
171
|
|
|
@@ -218,6 +226,17 @@ const PROVIDER_RUNTIME_ENTRIES: Partial<
|
|
|
218
226
|
router.service(S3Service, createS3Service(provider as S3Provider));
|
|
219
227
|
},
|
|
220
228
|
},
|
|
229
|
+
runtime: {
|
|
230
|
+
isProvider:
|
|
231
|
+
isPluginRuntimeProvider as (value: unknown) => value is LoadedProvider,
|
|
232
|
+
protoKind: ProtoProviderKind.RUNTIME,
|
|
233
|
+
registerService(router, provider) {
|
|
234
|
+
router.service(
|
|
235
|
+
PluginRuntimeProviderService,
|
|
236
|
+
createPluginRuntimeProviderService(provider as PluginRuntimeProvider),
|
|
237
|
+
);
|
|
238
|
+
},
|
|
239
|
+
},
|
|
221
240
|
agent: {
|
|
222
241
|
isProvider: isAgentProvider as (value: unknown) => value is LoadedProvider,
|
|
223
242
|
protoKind: ProtoProviderKind.AGENT,
|
|
@@ -324,19 +343,11 @@ export async function runLoadedProvider(
|
|
|
324
343
|
}
|
|
325
344
|
|
|
326
345
|
const catalogPath = process.env[ENV_WRITE_CATALOG];
|
|
327
|
-
|
|
328
|
-
if (catalogPath || manifestMetadataPath) {
|
|
346
|
+
if (catalogPath) {
|
|
329
347
|
if (!isPluginProvider(provider)) {
|
|
330
|
-
throw new Error(
|
|
331
|
-
"static catalog and manifest metadata generation are only supported for plugin providers",
|
|
332
|
-
);
|
|
333
|
-
}
|
|
334
|
-
if (catalogPath) {
|
|
335
|
-
writeFileSync(catalogPath, catalogToYaml(provider.staticCatalog()), "utf8");
|
|
336
|
-
}
|
|
337
|
-
if (manifestMetadataPath && provider.supportsManifestMetadata()) {
|
|
338
|
-
provider.writeManifestMetadata(manifestMetadataPath);
|
|
348
|
+
throw new Error("static catalog generation is only supported for plugin providers");
|
|
339
349
|
}
|
|
350
|
+
writeFileSync(catalogPath, catalogToYaml(provider.staticCatalog()), "utf8");
|
|
340
351
|
return;
|
|
341
352
|
}
|
|
342
353
|
|
|
@@ -364,9 +375,7 @@ export async function serve(provider: LoadedProvider): Promise<void> {
|
|
|
364
375
|
if (!socketPath) {
|
|
365
376
|
throw new Error(`${ENV_PROVIDER_SOCKET} is required`);
|
|
366
377
|
}
|
|
367
|
-
|
|
368
|
-
rmSync(socketPath);
|
|
369
|
-
}
|
|
378
|
+
rmSync(socketPath, { force: true });
|
|
370
379
|
|
|
371
380
|
const handler = connectNodeAdapter({
|
|
372
381
|
grpc: true,
|
|
@@ -393,9 +402,7 @@ export async function serve(provider: LoadedProvider): Promise<void> {
|
|
|
393
402
|
server.close(() => resolveClose());
|
|
394
403
|
});
|
|
395
404
|
} finally {
|
|
396
|
-
|
|
397
|
-
rmSync(socketPath);
|
|
398
|
-
}
|
|
405
|
+
rmSync(socketPath, { force: true });
|
|
399
406
|
}
|
|
400
407
|
}
|
|
401
408
|
})();
|
|
@@ -482,6 +489,16 @@ export function createRuntimeService(
|
|
|
482
489
|
});
|
|
483
490
|
}
|
|
484
491
|
},
|
|
492
|
+
async startProvider() {
|
|
493
|
+
try {
|
|
494
|
+
await provider.startProvider();
|
|
495
|
+
} catch (error) {
|
|
496
|
+
throw providerRuntimeError("start provider", error);
|
|
497
|
+
}
|
|
498
|
+
return create(StartRuntimeProviderResponseSchema, {
|
|
499
|
+
protocolVersion: CURRENT_PROTOCOL_VERSION,
|
|
500
|
+
});
|
|
501
|
+
},
|
|
485
502
|
};
|
|
486
503
|
}
|
|
487
504
|
|
|
@@ -548,6 +565,7 @@ export function createProviderService(
|
|
|
548
565
|
request.connectionParams,
|
|
549
566
|
request.context,
|
|
550
567
|
request.invocationToken,
|
|
568
|
+
request.idempotencyKey,
|
|
551
569
|
),
|
|
552
570
|
),
|
|
553
571
|
);
|
|
@@ -801,6 +819,7 @@ function providerRequest(
|
|
|
801
819
|
connectionParams: Record<string, string>,
|
|
802
820
|
requestContext?: ProtoRequestContext,
|
|
803
821
|
invocationToken = "",
|
|
822
|
+
idempotencyKey = "",
|
|
804
823
|
): Request {
|
|
805
824
|
const subject = requestContext?.subject;
|
|
806
825
|
const credential = requestContext?.credential;
|
|
@@ -830,6 +849,7 @@ function providerRequest(
|
|
|
830
849
|
...(requestContext?.workflow ?? {}),
|
|
831
850
|
},
|
|
832
851
|
invocationToken,
|
|
852
|
+
idempotencyKey: idempotencyKey.trim(),
|
|
833
853
|
};
|
|
834
854
|
}
|
|
835
855
|
|
|
@@ -866,12 +886,12 @@ function providerHTTPSubjectResolutionContext(
|
|
|
866
886
|
}
|
|
867
887
|
|
|
868
888
|
function providerConnectedToken(
|
|
869
|
-
token?:
|
|
889
|
+
token?: ProtoPostConnectCredential,
|
|
870
890
|
): ConnectedToken {
|
|
871
891
|
const metadataJson = token?.metadataJson ?? "";
|
|
872
892
|
return {
|
|
873
893
|
id: token?.id ?? "",
|
|
874
|
-
subjectId: token?.
|
|
894
|
+
subjectId: token?.subjectId ?? "",
|
|
875
895
|
integration: token?.integration ?? "",
|
|
876
896
|
connection: token?.connection ?? "",
|
|
877
897
|
instance: token?.instance ?? "",
|
package/src/s3.ts
CHANGED
|
@@ -20,6 +20,7 @@ import {
|
|
|
20
20
|
PresignObjectResponseSchema,
|
|
21
21
|
ReadObjectChunkSchema,
|
|
22
22
|
S3 as S3Service,
|
|
23
|
+
S3ObjectAccess as S3ObjectAccessService,
|
|
23
24
|
type ByteRange as ProtoByteRange,
|
|
24
25
|
type ReadObjectRequest as ProtoReadObjectRequest,
|
|
25
26
|
type S3ObjectMeta as ProtoS3ObjectMeta,
|
|
@@ -198,6 +199,16 @@ export interface PresignResult {
|
|
|
198
199
|
headers: Record<string, string>;
|
|
199
200
|
}
|
|
200
201
|
|
|
202
|
+
/**
|
|
203
|
+
* Options used when creating a host-mediated object-access URL.
|
|
204
|
+
*/
|
|
205
|
+
export type ObjectAccessURLOptions = PresignOptions;
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* Result returned by {@link S3.createObjectAccessURL} or {@link S3Object.createAccessURL}.
|
|
209
|
+
*/
|
|
210
|
+
export type ObjectAccessURL = PresignResult;
|
|
211
|
+
|
|
201
212
|
/**
|
|
202
213
|
* Accepted write body sources for the S3 client.
|
|
203
214
|
*/
|
|
@@ -509,7 +520,9 @@ export function createS3Service(
|
|
|
509
520
|
* ```
|
|
510
521
|
*/
|
|
511
522
|
export class S3 {
|
|
523
|
+
private readonly transport: ReturnType<typeof createGrpcTransport>;
|
|
512
524
|
private readonly client: Client<typeof S3Service>;
|
|
525
|
+
private objectAccessClient?: Client<typeof S3ObjectAccessService>;
|
|
513
526
|
|
|
514
527
|
constructor(name?: string) {
|
|
515
528
|
const envName = s3SocketEnv(name);
|
|
@@ -538,6 +551,7 @@ export class S3 {
|
|
|
538
551
|
: {}),
|
|
539
552
|
interceptors,
|
|
540
553
|
});
|
|
554
|
+
this.transport = transport;
|
|
541
555
|
this.client = createClient(S3Service, transport);
|
|
542
556
|
}
|
|
543
557
|
|
|
@@ -654,6 +668,62 @@ export class S3 {
|
|
|
654
668
|
}
|
|
655
669
|
return result;
|
|
656
670
|
}
|
|
671
|
+
|
|
672
|
+
async createObjectAccessURL(
|
|
673
|
+
ref: ObjectRef,
|
|
674
|
+
options?: ObjectAccessURLOptions,
|
|
675
|
+
): Promise<ObjectAccessURL> {
|
|
676
|
+
const requestedMethod = options?.method ?? PresignMethod.Get;
|
|
677
|
+
const response = await s3Rpc(() =>
|
|
678
|
+
this.s3ObjectAccessClient().createObjectAccessURL({
|
|
679
|
+
ref: toProtoObjectRef(ref),
|
|
680
|
+
method: toProtoPresignMethod(requestedMethod),
|
|
681
|
+
expiresSeconds: normalizeProtoInt(options?.expiresSeconds),
|
|
682
|
+
contentType: options?.contentType ?? "",
|
|
683
|
+
contentDisposition: options?.contentDisposition ?? "",
|
|
684
|
+
headers: cloneStringMap(options?.headers),
|
|
685
|
+
}),
|
|
686
|
+
);
|
|
687
|
+
const result: ObjectAccessURL = {
|
|
688
|
+
url: response.url,
|
|
689
|
+
method: response.method === ProtoPresignMethod.UNSPECIFIED
|
|
690
|
+
? requestedMethod
|
|
691
|
+
: fromProtoPresignMethod(response.method),
|
|
692
|
+
headers: cloneStringMap(response.headers),
|
|
693
|
+
};
|
|
694
|
+
if (response.expiresAt) {
|
|
695
|
+
result.expiresAt = fromProtoTimestamp(response.expiresAt);
|
|
696
|
+
}
|
|
697
|
+
return result;
|
|
698
|
+
}
|
|
699
|
+
|
|
700
|
+
private s3ObjectAccessClient(): Client<typeof S3ObjectAccessService> {
|
|
701
|
+
if (!this.objectAccessClient) {
|
|
702
|
+
this.objectAccessClient = createClient(S3ObjectAccessService, this.transport);
|
|
703
|
+
}
|
|
704
|
+
return this.objectAccessClient;
|
|
705
|
+
}
|
|
706
|
+
|
|
707
|
+
async createObjectAccessUrl(
|
|
708
|
+
ref: ObjectRef,
|
|
709
|
+
options?: ObjectAccessURLOptions,
|
|
710
|
+
): Promise<ObjectAccessURL> {
|
|
711
|
+
return await this.createObjectAccessURL(ref, options);
|
|
712
|
+
}
|
|
713
|
+
|
|
714
|
+
async createAccessURL(
|
|
715
|
+
ref: ObjectRef,
|
|
716
|
+
options?: ObjectAccessURLOptions,
|
|
717
|
+
): Promise<ObjectAccessURL> {
|
|
718
|
+
return await this.createObjectAccessURL(ref, options);
|
|
719
|
+
}
|
|
720
|
+
|
|
721
|
+
async createAccessUrl(
|
|
722
|
+
ref: ObjectRef,
|
|
723
|
+
options?: ObjectAccessURLOptions,
|
|
724
|
+
): Promise<ObjectAccessURL> {
|
|
725
|
+
return await this.createObjectAccessURL(ref, options);
|
|
726
|
+
}
|
|
657
727
|
}
|
|
658
728
|
|
|
659
729
|
/**
|
|
@@ -768,6 +838,17 @@ export class S3Object {
|
|
|
768
838
|
async presign(options?: PresignOptions): Promise<PresignResult> {
|
|
769
839
|
return await this.client.presignObject(this.ref, options);
|
|
770
840
|
}
|
|
841
|
+
|
|
842
|
+
/**
|
|
843
|
+
* Creates a host-mediated object-access URL for the referenced object.
|
|
844
|
+
*/
|
|
845
|
+
async createAccessURL(options?: ObjectAccessURLOptions): Promise<ObjectAccessURL> {
|
|
846
|
+
return await this.client.createObjectAccessURL(this.ref, options);
|
|
847
|
+
}
|
|
848
|
+
|
|
849
|
+
async createAccessUrl(options?: ObjectAccessURLOptions): Promise<ObjectAccessURL> {
|
|
850
|
+
return await this.createAccessURL(options);
|
|
851
|
+
}
|
|
771
852
|
}
|
|
772
853
|
|
|
773
854
|
function s3TransportOptions(rawTarget: string): {
|