@valon-technologies/gestalt 0.0.1-alpha.13 → 0.0.1-alpha.14
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/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 +44 -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,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { rmSync, writeFileSync } from "node:fs";
|
|
2
2
|
import { createServer } from "node:http2";
|
|
3
3
|
import { dirname, resolve } from "node:path";
|
|
4
4
|
|
|
@@ -48,7 +48,7 @@ import {
|
|
|
48
48
|
OperationResultSchema,
|
|
49
49
|
ProviderMetadataSchema,
|
|
50
50
|
type HTTPSubjectRequest as ProtoHTTPSubjectRequest,
|
|
51
|
-
type
|
|
51
|
+
type PostConnectCredential as ProtoPostConnectCredential,
|
|
52
52
|
type RequestContext as ProtoRequestContext,
|
|
53
53
|
type ResolveHTTPSubjectRequest as ProtoResolveHTTPSubjectRequest,
|
|
54
54
|
IntegrationProvider as IntegrationProviderService,
|
|
@@ -57,12 +57,16 @@ import {
|
|
|
57
57
|
type GetSessionCatalogRequest,
|
|
58
58
|
type StartProviderRequest,
|
|
59
59
|
} from "../gen/v1/plugin_pb.ts";
|
|
60
|
+
import {
|
|
61
|
+
PluginRuntimeProvider as PluginRuntimeProviderService,
|
|
62
|
+
} from "../gen/v1/pluginruntime_pb.ts";
|
|
60
63
|
import {
|
|
61
64
|
ConfigureProviderResponseSchema,
|
|
62
65
|
HealthCheckResponseSchema,
|
|
63
66
|
ProviderIdentitySchema,
|
|
64
67
|
ProviderKind as ProtoProviderKind,
|
|
65
68
|
ProviderLifecycle,
|
|
69
|
+
StartRuntimeProviderResponseSchema,
|
|
66
70
|
type ConfigureProviderRequest,
|
|
67
71
|
} from "../gen/v1/runtime_pb.ts";
|
|
68
72
|
import { S3 as S3Service } from "../gen/v1/s3_pb.ts";
|
|
@@ -93,6 +97,11 @@ import {
|
|
|
93
97
|
connectionParamToProto,
|
|
94
98
|
isPluginProvider,
|
|
95
99
|
} from "./plugin.ts";
|
|
100
|
+
import {
|
|
101
|
+
PluginRuntimeProvider,
|
|
102
|
+
createPluginRuntimeProviderService,
|
|
103
|
+
isPluginRuntimeProvider,
|
|
104
|
+
} from "./pluginruntime.ts";
|
|
96
105
|
import {
|
|
97
106
|
providerKindLabel,
|
|
98
107
|
resolveDefaultProviderExport,
|
|
@@ -125,11 +134,6 @@ export const ENV_PROVIDER_PARENT_PID = "GESTALT_PLUGIN_PARENT_PID";
|
|
|
125
134
|
* Environment variable used to request static catalog generation.
|
|
126
135
|
*/
|
|
127
136
|
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
137
|
/**
|
|
134
138
|
* Protocol version currently implemented by the TypeScript runtime.
|
|
135
139
|
*/
|
|
@@ -139,6 +143,7 @@ export const CURRENT_PROTOCOL_VERSION = 3;
|
|
|
139
143
|
*/
|
|
140
144
|
export const USAGE = "usage: bun run runtime.ts ROOT PROVIDER_TARGET";
|
|
141
145
|
export { createAgentProviderService } from "./agent.ts";
|
|
146
|
+
export { createPluginRuntimeProviderService } from "./pluginruntime.ts";
|
|
142
147
|
export { createWorkflowProviderService } from "./workflow.ts";
|
|
143
148
|
|
|
144
149
|
/**
|
|
@@ -158,6 +163,7 @@ export type LoadedProvider =
|
|
|
158
163
|
| CacheProvider
|
|
159
164
|
| SecretsProvider
|
|
160
165
|
| S3Provider
|
|
166
|
+
| PluginRuntimeProvider
|
|
161
167
|
| AgentProvider
|
|
162
168
|
| WorkflowProvider;
|
|
163
169
|
|
|
@@ -218,6 +224,17 @@ const PROVIDER_RUNTIME_ENTRIES: Partial<
|
|
|
218
224
|
router.service(S3Service, createS3Service(provider as S3Provider));
|
|
219
225
|
},
|
|
220
226
|
},
|
|
227
|
+
runtime: {
|
|
228
|
+
isProvider:
|
|
229
|
+
isPluginRuntimeProvider as (value: unknown) => value is LoadedProvider,
|
|
230
|
+
protoKind: ProtoProviderKind.RUNTIME,
|
|
231
|
+
registerService(router, provider) {
|
|
232
|
+
router.service(
|
|
233
|
+
PluginRuntimeProviderService,
|
|
234
|
+
createPluginRuntimeProviderService(provider as PluginRuntimeProvider),
|
|
235
|
+
);
|
|
236
|
+
},
|
|
237
|
+
},
|
|
221
238
|
agent: {
|
|
222
239
|
isProvider: isAgentProvider as (value: unknown) => value is LoadedProvider,
|
|
223
240
|
protoKind: ProtoProviderKind.AGENT,
|
|
@@ -324,19 +341,11 @@ export async function runLoadedProvider(
|
|
|
324
341
|
}
|
|
325
342
|
|
|
326
343
|
const catalogPath = process.env[ENV_WRITE_CATALOG];
|
|
327
|
-
|
|
328
|
-
if (catalogPath || manifestMetadataPath) {
|
|
344
|
+
if (catalogPath) {
|
|
329
345
|
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);
|
|
346
|
+
throw new Error("static catalog generation is only supported for plugin providers");
|
|
339
347
|
}
|
|
348
|
+
writeFileSync(catalogPath, catalogToYaml(provider.staticCatalog()), "utf8");
|
|
340
349
|
return;
|
|
341
350
|
}
|
|
342
351
|
|
|
@@ -364,9 +373,7 @@ export async function serve(provider: LoadedProvider): Promise<void> {
|
|
|
364
373
|
if (!socketPath) {
|
|
365
374
|
throw new Error(`${ENV_PROVIDER_SOCKET} is required`);
|
|
366
375
|
}
|
|
367
|
-
|
|
368
|
-
rmSync(socketPath);
|
|
369
|
-
}
|
|
376
|
+
rmSync(socketPath, { force: true });
|
|
370
377
|
|
|
371
378
|
const handler = connectNodeAdapter({
|
|
372
379
|
grpc: true,
|
|
@@ -393,9 +400,7 @@ export async function serve(provider: LoadedProvider): Promise<void> {
|
|
|
393
400
|
server.close(() => resolveClose());
|
|
394
401
|
});
|
|
395
402
|
} finally {
|
|
396
|
-
|
|
397
|
-
rmSync(socketPath);
|
|
398
|
-
}
|
|
403
|
+
rmSync(socketPath, { force: true });
|
|
399
404
|
}
|
|
400
405
|
}
|
|
401
406
|
})();
|
|
@@ -482,6 +487,16 @@ export function createRuntimeService(
|
|
|
482
487
|
});
|
|
483
488
|
}
|
|
484
489
|
},
|
|
490
|
+
async startProvider() {
|
|
491
|
+
try {
|
|
492
|
+
await provider.startProvider();
|
|
493
|
+
} catch (error) {
|
|
494
|
+
throw providerRuntimeError("start provider", error);
|
|
495
|
+
}
|
|
496
|
+
return create(StartRuntimeProviderResponseSchema, {
|
|
497
|
+
protocolVersion: CURRENT_PROTOCOL_VERSION,
|
|
498
|
+
});
|
|
499
|
+
},
|
|
485
500
|
};
|
|
486
501
|
}
|
|
487
502
|
|
|
@@ -548,6 +563,7 @@ export function createProviderService(
|
|
|
548
563
|
request.connectionParams,
|
|
549
564
|
request.context,
|
|
550
565
|
request.invocationToken,
|
|
566
|
+
request.idempotencyKey,
|
|
551
567
|
),
|
|
552
568
|
),
|
|
553
569
|
);
|
|
@@ -801,6 +817,7 @@ function providerRequest(
|
|
|
801
817
|
connectionParams: Record<string, string>,
|
|
802
818
|
requestContext?: ProtoRequestContext,
|
|
803
819
|
invocationToken = "",
|
|
820
|
+
idempotencyKey = "",
|
|
804
821
|
): Request {
|
|
805
822
|
const subject = requestContext?.subject;
|
|
806
823
|
const credential = requestContext?.credential;
|
|
@@ -830,6 +847,7 @@ function providerRequest(
|
|
|
830
847
|
...(requestContext?.workflow ?? {}),
|
|
831
848
|
},
|
|
832
849
|
invocationToken,
|
|
850
|
+
idempotencyKey: idempotencyKey.trim(),
|
|
833
851
|
};
|
|
834
852
|
}
|
|
835
853
|
|
|
@@ -866,12 +884,12 @@ function providerHTTPSubjectResolutionContext(
|
|
|
866
884
|
}
|
|
867
885
|
|
|
868
886
|
function providerConnectedToken(
|
|
869
|
-
token?:
|
|
887
|
+
token?: ProtoPostConnectCredential,
|
|
870
888
|
): ConnectedToken {
|
|
871
889
|
const metadataJson = token?.metadataJson ?? "";
|
|
872
890
|
return {
|
|
873
891
|
id: token?.id ?? "",
|
|
874
|
-
subjectId: token?.
|
|
892
|
+
subjectId: token?.subjectId ?? "",
|
|
875
893
|
integration: token?.integration ?? "",
|
|
876
894
|
connection: token?.connection ?? "",
|
|
877
895
|
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): {
|