@valon-technologies/gestalt 0.0.1-alpha.1 → 0.0.1-alpha.9
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/README.md +8 -26
- package/gen/v1/{auth_pb.ts → authentication_pb.ts} +51 -17
- package/gen/v1/authorization_pb.ts +857 -0
- package/gen/v1/cache_pb.ts +32 -0
- package/gen/v1/datastore_pb.ts +62 -0
- package/gen/v1/plugin_pb.ts +216 -18
- package/gen/v1/runtime_pb.ts +27 -3
- package/gen/v1/s3_pb.ts +39 -0
- package/gen/v1/secrets_pb.ts +6 -0
- package/gen/v1/workflow_pb.ts +1372 -0
- package/package.json +12 -10
- package/src/api.ts +56 -0
- package/src/auth.ts +67 -16
- package/src/build.ts +37 -21
- package/src/cache.ts +32 -0
- package/src/catalog.ts +27 -0
- package/src/index.ts +87 -18
- package/src/indexeddb.ts +166 -0
- package/src/invoker.ts +124 -0
- package/src/plugin.ts +93 -38
- package/src/provider-kind.ts +107 -0
- package/src/provider.ts +32 -1
- package/src/runtime.ts +233 -218
- package/src/s3.ts +135 -20
- package/src/schema.ts +46 -0
- package/src/secrets.ts +12 -0
- package/src/target.ts +58 -60
- package/src/workflow-manager.ts +131 -0
- package/src/workflow.ts +479 -0
- package/tsconfig.json +1 -0
package/src/runtime.ts
CHANGED
|
@@ -4,17 +4,22 @@ import { dirname, resolve } from "node:path";
|
|
|
4
4
|
|
|
5
5
|
import { create } from "@bufbuild/protobuf";
|
|
6
6
|
import { EmptySchema } from "@bufbuild/protobuf/wkt";
|
|
7
|
-
import {
|
|
7
|
+
import {
|
|
8
|
+
Code,
|
|
9
|
+
ConnectError,
|
|
10
|
+
type ConnectRouter,
|
|
11
|
+
type ServiceImpl,
|
|
12
|
+
} from "@connectrpc/connect";
|
|
8
13
|
import { connectNodeAdapter } from "@connectrpc/connect-node";
|
|
9
14
|
|
|
10
15
|
import {
|
|
11
|
-
|
|
16
|
+
AuthenticationProvider as AuthenticationProviderService,
|
|
12
17
|
AuthSessionSettingsSchema,
|
|
13
18
|
AuthenticatedUserSchema,
|
|
14
19
|
BeginLoginResponseSchema,
|
|
15
20
|
type CompleteLoginRequest as AuthCompleteLoginRequest,
|
|
16
21
|
type ValidateExternalTokenRequest,
|
|
17
|
-
} from "../gen/v1/
|
|
22
|
+
} from "../gen/v1/authentication_pb.ts";
|
|
18
23
|
import {
|
|
19
24
|
Cache as CacheService,
|
|
20
25
|
CacheDeleteManyResponseSchema,
|
|
@@ -53,23 +58,33 @@ import {
|
|
|
53
58
|
type ConfigureProviderRequest,
|
|
54
59
|
} from "../gen/v1/runtime_pb.ts";
|
|
55
60
|
import { S3 as S3Service } from "../gen/v1/s3_pb.ts";
|
|
61
|
+
import { WorkflowProvider as WorkflowProviderService } from "../gen/v1/workflow_pb.ts";
|
|
56
62
|
import { errorMessage, type Request } from "./api.ts";
|
|
57
63
|
import {
|
|
58
|
-
|
|
59
|
-
|
|
64
|
+
AuthenticationProvider,
|
|
65
|
+
isAuthenticationProvider,
|
|
60
66
|
type AuthenticatedUser,
|
|
61
67
|
} from "./auth.ts";
|
|
62
68
|
import { CacheProvider, isCacheProvider } from "./cache.ts";
|
|
63
69
|
import { SecretsProvider, isSecretsProvider } from "./secrets.ts";
|
|
64
70
|
import { catalogToYaml, type Catalog } from "./catalog.ts";
|
|
65
71
|
import {
|
|
66
|
-
|
|
72
|
+
PluginProvider,
|
|
67
73
|
connectionModeToProtoValue,
|
|
68
74
|
connectionParamToProto,
|
|
69
|
-
|
|
75
|
+
isPluginProvider,
|
|
70
76
|
} from "./plugin.ts";
|
|
77
|
+
import {
|
|
78
|
+
providerKindLabel,
|
|
79
|
+
resolveDefaultProviderExport,
|
|
80
|
+
} from "./provider-kind.ts";
|
|
71
81
|
import { type ProviderKind, slugName } from "./provider.ts";
|
|
72
82
|
import { S3Provider, createS3Service, isS3Provider } from "./s3.ts";
|
|
83
|
+
import {
|
|
84
|
+
WorkflowProvider,
|
|
85
|
+
createWorkflowProviderService,
|
|
86
|
+
isWorkflowProvider,
|
|
87
|
+
} from "./workflow.ts";
|
|
73
88
|
import {
|
|
74
89
|
defaultProviderName,
|
|
75
90
|
formatProviderTarget,
|
|
@@ -79,24 +94,129 @@ import {
|
|
|
79
94
|
resolveProviderImportUrl,
|
|
80
95
|
} from "./target.ts";
|
|
81
96
|
|
|
97
|
+
/**
|
|
98
|
+
* Environment variable containing the Unix socket path for a running provider.
|
|
99
|
+
*/
|
|
82
100
|
export const ENV_PROVIDER_SOCKET = "GESTALT_PLUGIN_SOCKET";
|
|
101
|
+
/**
|
|
102
|
+
* Environment variable containing the parent process ID supplied by the host.
|
|
103
|
+
*/
|
|
83
104
|
export const ENV_PROVIDER_PARENT_PID = "GESTALT_PLUGIN_PARENT_PID";
|
|
105
|
+
/**
|
|
106
|
+
* Environment variable used to request static catalog generation.
|
|
107
|
+
*/
|
|
84
108
|
export const ENV_WRITE_CATALOG = "GESTALT_PLUGIN_WRITE_CATALOG";
|
|
85
|
-
|
|
109
|
+
/**
|
|
110
|
+
* Protocol version currently implemented by the TypeScript runtime.
|
|
111
|
+
*/
|
|
112
|
+
export const CURRENT_PROTOCOL_VERSION = 3;
|
|
113
|
+
/**
|
|
114
|
+
* Command-line usage for the runtime entrypoint.
|
|
115
|
+
*/
|
|
86
116
|
export const USAGE = "usage: bun run runtime.ts ROOT PROVIDER_TARGET";
|
|
117
|
+
export { createWorkflowProviderService } from "./workflow.ts";
|
|
87
118
|
|
|
119
|
+
/**
|
|
120
|
+
* Parsed arguments for the runtime entrypoint.
|
|
121
|
+
*/
|
|
88
122
|
export type RuntimeArgs = {
|
|
89
123
|
root: string;
|
|
90
124
|
target: string;
|
|
91
125
|
};
|
|
92
126
|
|
|
127
|
+
/**
|
|
128
|
+
* Provider implementations supported by the runtime host.
|
|
129
|
+
*/
|
|
93
130
|
export type LoadedProvider =
|
|
94
|
-
|
|
|
95
|
-
|
|
|
131
|
+
| PluginProvider
|
|
132
|
+
| AuthenticationProvider
|
|
96
133
|
| CacheProvider
|
|
97
134
|
| SecretsProvider
|
|
98
|
-
| S3Provider
|
|
135
|
+
| S3Provider
|
|
136
|
+
| WorkflowProvider;
|
|
137
|
+
|
|
138
|
+
type ProviderRuntimeEntry = {
|
|
139
|
+
isProvider: (value: unknown) => value is LoadedProvider;
|
|
140
|
+
protoKind: ProtoProviderKind;
|
|
141
|
+
registerService: (router: ConnectRouter, provider: LoadedProvider) => void;
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
const PROVIDER_RUNTIME_ENTRIES: Partial<
|
|
145
|
+
Record<ProviderKind, ProviderRuntimeEntry>
|
|
146
|
+
> = {
|
|
147
|
+
integration: {
|
|
148
|
+
isProvider: isPluginProvider as (value: unknown) => value is LoadedProvider,
|
|
149
|
+
protoKind: ProtoProviderKind.INTEGRATION,
|
|
150
|
+
registerService(router, provider) {
|
|
151
|
+
router.service(
|
|
152
|
+
IntegrationProviderService,
|
|
153
|
+
createProviderService(provider as PluginProvider),
|
|
154
|
+
);
|
|
155
|
+
},
|
|
156
|
+
},
|
|
157
|
+
authentication: {
|
|
158
|
+
isProvider:
|
|
159
|
+
isAuthenticationProvider as (value: unknown) => value is LoadedProvider,
|
|
160
|
+
protoKind: ProtoProviderKind.AUTHENTICATION,
|
|
161
|
+
registerService(router, provider) {
|
|
162
|
+
router.service(
|
|
163
|
+
AuthenticationProviderService,
|
|
164
|
+
createAuthenticationService(provider as AuthenticationProvider),
|
|
165
|
+
);
|
|
166
|
+
},
|
|
167
|
+
},
|
|
168
|
+
cache: {
|
|
169
|
+
isProvider: isCacheProvider as (value: unknown) => value is LoadedProvider,
|
|
170
|
+
protoKind: ProtoProviderKind.CACHE,
|
|
171
|
+
registerService(router, provider) {
|
|
172
|
+
router.service(
|
|
173
|
+
CacheService,
|
|
174
|
+
createCacheService(provider as CacheProvider),
|
|
175
|
+
);
|
|
176
|
+
},
|
|
177
|
+
},
|
|
178
|
+
secrets: {
|
|
179
|
+
isProvider: isSecretsProvider as (value: unknown) => value is LoadedProvider,
|
|
180
|
+
protoKind: ProtoProviderKind.SECRETS,
|
|
181
|
+
registerService(router, provider) {
|
|
182
|
+
router.service(
|
|
183
|
+
SecretsProviderService,
|
|
184
|
+
createSecretsService(provider as SecretsProvider),
|
|
185
|
+
);
|
|
186
|
+
},
|
|
187
|
+
},
|
|
188
|
+
s3: {
|
|
189
|
+
isProvider: isS3Provider as (value: unknown) => value is LoadedProvider,
|
|
190
|
+
protoKind: ProtoProviderKind.S3,
|
|
191
|
+
registerService(router, provider) {
|
|
192
|
+
router.service(S3Service, createS3Service(provider as S3Provider));
|
|
193
|
+
},
|
|
194
|
+
},
|
|
195
|
+
workflow: {
|
|
196
|
+
isProvider: isWorkflowProvider as (value: unknown) => value is LoadedProvider,
|
|
197
|
+
protoKind: ProtoProviderKind.WORKFLOW,
|
|
198
|
+
registerService(router, provider) {
|
|
199
|
+
router.service(
|
|
200
|
+
WorkflowProviderService,
|
|
201
|
+
createWorkflowProviderService(provider as WorkflowProvider),
|
|
202
|
+
);
|
|
203
|
+
},
|
|
204
|
+
},
|
|
205
|
+
};
|
|
206
|
+
|
|
207
|
+
function assertProtocolVersion(protocolVersion: number): void {
|
|
208
|
+
if (protocolVersion === CURRENT_PROTOCOL_VERSION) {
|
|
209
|
+
return;
|
|
210
|
+
}
|
|
211
|
+
throw new ConnectError(
|
|
212
|
+
`host requested protocol version ${protocolVersion}, provider requires ${CURRENT_PROTOCOL_VERSION}`,
|
|
213
|
+
Code.FailedPrecondition,
|
|
214
|
+
);
|
|
215
|
+
}
|
|
99
216
|
|
|
217
|
+
/**
|
|
218
|
+
* CLI entrypoint that loads a provider from source and starts serving it.
|
|
219
|
+
*/
|
|
100
220
|
export async function main(
|
|
101
221
|
argv: string[] = process.argv.slice(2),
|
|
102
222
|
): Promise<number> {
|
|
@@ -112,6 +232,9 @@ export async function main(
|
|
|
112
232
|
return 0;
|
|
113
233
|
}
|
|
114
234
|
|
|
235
|
+
/**
|
|
236
|
+
* Parses `gestalt-ts-runtime` CLI arguments.
|
|
237
|
+
*/
|
|
115
238
|
export function parseRuntimeArgs(argv: string[]): RuntimeArgs | undefined {
|
|
116
239
|
if (argv.length !== 2) {
|
|
117
240
|
return undefined;
|
|
@@ -122,87 +245,35 @@ export function parseRuntimeArgs(argv: string[]): RuntimeArgs | undefined {
|
|
|
122
245
|
};
|
|
123
246
|
}
|
|
124
247
|
|
|
248
|
+
/**
|
|
249
|
+
* Loads any supported provider kind from a package root and optional target.
|
|
250
|
+
*/
|
|
125
251
|
export async function loadProviderFromTarget(
|
|
126
252
|
root: string,
|
|
127
253
|
rawTarget?: string,
|
|
128
254
|
): Promise<LoadedProvider> {
|
|
129
255
|
const config = readPackageConfig(root);
|
|
130
|
-
const
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
const target = parseProviderTarget(targetValue);
|
|
256
|
+
const explicitTarget = rawTarget?.trim();
|
|
257
|
+
const target = explicitTarget
|
|
258
|
+
? parseProviderTarget(explicitTarget)
|
|
259
|
+
: config.providerTarget ?? readPackageProviderTarget(root);
|
|
260
|
+
const targetValue = explicitTarget || formatProviderTarget(target);
|
|
136
261
|
const module = await import(resolveProviderImportUrl(root, target));
|
|
137
262
|
const candidate =
|
|
138
|
-
(target.exportName ? module
|
|
139
|
-
|
|
263
|
+
(target.exportName ? Reflect.get(module, target.exportName) : undefined) ??
|
|
264
|
+
resolveDefaultProviderExport(module, target.kind);
|
|
140
265
|
|
|
141
266
|
const defaultName =
|
|
142
267
|
slugName(config.name ?? "") ||
|
|
143
268
|
slugName(dirname(resolve(root, target.modulePath)));
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
if (!isIntegrationProvider(candidate)) {
|
|
147
|
-
throw new Error(
|
|
148
|
-
`${targetValue} did not resolve to a Gestalt integration provider`,
|
|
149
|
-
);
|
|
150
|
-
}
|
|
151
|
-
candidate.resolveName(defaultName);
|
|
152
|
-
return candidate;
|
|
153
|
-
}
|
|
154
|
-
case "auth": {
|
|
155
|
-
if (!isAuthProvider(candidate)) {
|
|
156
|
-
throw new Error(
|
|
157
|
-
`${targetValue} did not resolve to a Gestalt auth provider`,
|
|
158
|
-
);
|
|
159
|
-
}
|
|
160
|
-
candidate.resolveName(defaultName);
|
|
161
|
-
return candidate;
|
|
162
|
-
}
|
|
163
|
-
case "cache": {
|
|
164
|
-
if (!isCacheProvider(candidate)) {
|
|
165
|
-
throw new Error(
|
|
166
|
-
`${targetValue} did not resolve to a Gestalt cache provider`,
|
|
167
|
-
);
|
|
168
|
-
}
|
|
169
|
-
candidate.resolveName(defaultName);
|
|
170
|
-
return candidate;
|
|
171
|
-
}
|
|
172
|
-
case "secrets": {
|
|
173
|
-
if (!isSecretsProvider(candidate)) {
|
|
174
|
-
throw new Error(
|
|
175
|
-
`${targetValue} did not resolve to a Gestalt secrets provider`,
|
|
176
|
-
);
|
|
177
|
-
}
|
|
178
|
-
candidate.resolveName(defaultName);
|
|
179
|
-
return candidate;
|
|
180
|
-
}
|
|
181
|
-
case "s3": {
|
|
182
|
-
if (!isS3Provider(candidate)) {
|
|
183
|
-
throw new Error(`${targetValue} did not resolve to a Gestalt s3 provider`);
|
|
184
|
-
}
|
|
185
|
-
candidate.resolveName(defaultName);
|
|
186
|
-
return candidate;
|
|
187
|
-
}
|
|
188
|
-
default:
|
|
189
|
-
throw new Error(
|
|
190
|
-
`TypeScript SDK does not yet support provider kind ${JSON.stringify(target.kind)}`,
|
|
191
|
-
);
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
export async function loadPluginFromTarget(
|
|
196
|
-
root: string,
|
|
197
|
-
rawTarget?: string,
|
|
198
|
-
): Promise<IntegrationProvider> {
|
|
199
|
-
const provider = await loadProviderFromTarget(root, rawTarget);
|
|
200
|
-
if (!isIntegrationProvider(provider)) {
|
|
201
|
-
throw new Error("target did not resolve to an integration provider");
|
|
202
|
-
}
|
|
269
|
+
const provider = resolveLoadedProvider(candidate, target.kind, targetValue);
|
|
270
|
+
provider.resolveName(defaultName);
|
|
203
271
|
return provider;
|
|
204
272
|
}
|
|
205
273
|
|
|
274
|
+
/**
|
|
275
|
+
* Runs a provider that has already been loaded into memory.
|
|
276
|
+
*/
|
|
206
277
|
export async function runLoadedProvider(
|
|
207
278
|
provider: LoadedProvider,
|
|
208
279
|
options: {
|
|
@@ -218,101 +289,34 @@ export async function runLoadedProvider(
|
|
|
218
289
|
|
|
219
290
|
const catalogPath = process.env[ENV_WRITE_CATALOG];
|
|
220
291
|
if (catalogPath) {
|
|
221
|
-
if (!
|
|
292
|
+
if (!isPluginProvider(provider)) {
|
|
222
293
|
throw new Error(
|
|
223
|
-
"static catalog generation is only supported for
|
|
294
|
+
"static catalog generation is only supported for plugin providers",
|
|
224
295
|
);
|
|
225
296
|
}
|
|
226
|
-
writeFileSync(catalogPath,
|
|
297
|
+
writeFileSync(catalogPath, catalogToYaml(provider.staticCatalog()), "utf8");
|
|
227
298
|
return;
|
|
228
299
|
}
|
|
229
300
|
|
|
230
301
|
await serve(provider);
|
|
231
302
|
}
|
|
232
303
|
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
root?: string;
|
|
237
|
-
pluginName?: string;
|
|
238
|
-
} = {},
|
|
239
|
-
): Promise<void> {
|
|
240
|
-
const runtimeOptions: {
|
|
241
|
-
root?: string;
|
|
242
|
-
providerName?: string;
|
|
243
|
-
} = {};
|
|
244
|
-
if (options.root !== undefined) {
|
|
245
|
-
runtimeOptions.root = options.root;
|
|
246
|
-
}
|
|
247
|
-
if (options.pluginName !== undefined) {
|
|
248
|
-
runtimeOptions.providerName = options.pluginName;
|
|
249
|
-
}
|
|
250
|
-
await runLoadedProvider(plugin, runtimeOptions);
|
|
251
|
-
}
|
|
252
|
-
|
|
304
|
+
/**
|
|
305
|
+
* Runs a bundled provider export after validating its provider kind.
|
|
306
|
+
*/
|
|
253
307
|
export async function runBundledProvider(
|
|
254
308
|
provider: unknown,
|
|
255
309
|
kind: ProviderKind,
|
|
256
310
|
providerName: string,
|
|
257
311
|
): Promise<void> {
|
|
258
|
-
|
|
259
|
-
switch (kind) {
|
|
260
|
-
case "integration":
|
|
261
|
-
if (!isIntegrationProvider(provider)) {
|
|
262
|
-
throw new Error(
|
|
263
|
-
"bundled target did not resolve to a Gestalt integration provider",
|
|
264
|
-
);
|
|
265
|
-
}
|
|
266
|
-
loaded = provider;
|
|
267
|
-
break;
|
|
268
|
-
case "auth":
|
|
269
|
-
if (!isAuthProvider(provider)) {
|
|
270
|
-
throw new Error(
|
|
271
|
-
"bundled target did not resolve to a Gestalt auth provider",
|
|
272
|
-
);
|
|
273
|
-
}
|
|
274
|
-
loaded = provider;
|
|
275
|
-
break;
|
|
276
|
-
case "cache":
|
|
277
|
-
if (!isCacheProvider(provider)) {
|
|
278
|
-
throw new Error(
|
|
279
|
-
"bundled target did not resolve to a Gestalt cache provider",
|
|
280
|
-
);
|
|
281
|
-
}
|
|
282
|
-
loaded = provider;
|
|
283
|
-
break;
|
|
284
|
-
case "secrets":
|
|
285
|
-
if (!isSecretsProvider(provider)) {
|
|
286
|
-
throw new Error(
|
|
287
|
-
"bundled target did not resolve to a Gestalt secrets provider",
|
|
288
|
-
);
|
|
289
|
-
}
|
|
290
|
-
loaded = provider;
|
|
291
|
-
break;
|
|
292
|
-
case "s3":
|
|
293
|
-
if (!isS3Provider(provider)) {
|
|
294
|
-
throw new Error("bundled target did not resolve to a Gestalt s3 provider");
|
|
295
|
-
}
|
|
296
|
-
loaded = provider;
|
|
297
|
-
break;
|
|
298
|
-
default:
|
|
299
|
-
throw new Error(
|
|
300
|
-
`TypeScript SDK does not yet support provider kind ${JSON.stringify(kind)}`,
|
|
301
|
-
);
|
|
302
|
-
}
|
|
303
|
-
loaded.name = slugName(providerName);
|
|
304
|
-
await runLoadedProvider(loaded, {
|
|
312
|
+
await runLoadedProvider(resolveLoadedProvider(provider, kind, "bundled target"), {
|
|
305
313
|
providerName,
|
|
306
314
|
});
|
|
307
315
|
}
|
|
308
316
|
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
): Promise<void> {
|
|
313
|
-
await runBundledProvider(plugin, "integration", pluginName);
|
|
314
|
-
}
|
|
315
|
-
|
|
317
|
+
/**
|
|
318
|
+
* Starts serving a provider over the Gestalt Unix socket transport.
|
|
319
|
+
*/
|
|
316
320
|
export async function serve(provider: LoadedProvider): Promise<void> {
|
|
317
321
|
const socketPath = process.env[ENV_PROVIDER_SOCKET];
|
|
318
322
|
if (!socketPath) {
|
|
@@ -328,20 +332,7 @@ export async function serve(provider: LoadedProvider): Promise<void> {
|
|
|
328
332
|
connect: false,
|
|
329
333
|
routes(router) {
|
|
330
334
|
router.service(ProviderLifecycle, createRuntimeService(provider));
|
|
331
|
-
|
|
332
|
-
router.service(
|
|
333
|
-
IntegrationProviderService,
|
|
334
|
-
createProviderService(provider),
|
|
335
|
-
);
|
|
336
|
-
} else if (isAuthProvider(provider)) {
|
|
337
|
-
router.service(AuthProviderService, createAuthService(provider));
|
|
338
|
-
} else if (isCacheProvider(provider)) {
|
|
339
|
-
router.service(CacheService, createCacheService(provider));
|
|
340
|
-
} else if (isS3Provider(provider)) {
|
|
341
|
-
router.service(S3Service, createS3Service(provider));
|
|
342
|
-
} else if (isSecretsProvider(provider)) {
|
|
343
|
-
router.service(SecretsProviderService, createSecretsService(provider));
|
|
344
|
-
}
|
|
335
|
+
registerProviderService(router, provider);
|
|
345
336
|
},
|
|
346
337
|
});
|
|
347
338
|
|
|
@@ -392,13 +383,18 @@ export async function serve(provider: LoadedProvider): Promise<void> {
|
|
|
392
383
|
}
|
|
393
384
|
}
|
|
394
385
|
|
|
386
|
+
/**
|
|
387
|
+
* Adapts the provider lifecycle service used during startup and health checks.
|
|
388
|
+
*
|
|
389
|
+
* @internal
|
|
390
|
+
*/
|
|
395
391
|
export function createRuntimeService(
|
|
396
392
|
provider: LoadedProvider,
|
|
397
393
|
): Partial<ServiceImpl<typeof ProviderLifecycle>> {
|
|
398
394
|
return {
|
|
399
395
|
async getProviderIdentity() {
|
|
400
396
|
return create(ProviderIdentitySchema, {
|
|
401
|
-
kind:
|
|
397
|
+
kind: providerRuntimeEntry(provider.kind).protoKind,
|
|
402
398
|
name: provider.name,
|
|
403
399
|
displayName: provider.displayName,
|
|
404
400
|
description: provider.description,
|
|
@@ -409,12 +405,7 @@ export function createRuntimeService(
|
|
|
409
405
|
});
|
|
410
406
|
},
|
|
411
407
|
async configureProvider(request: ConfigureProviderRequest) {
|
|
412
|
-
|
|
413
|
-
throw new ConnectError(
|
|
414
|
-
`host requested protocol version ${request.protocolVersion}, provider requires ${CURRENT_PROTOCOL_VERSION}`,
|
|
415
|
-
Code.FailedPrecondition,
|
|
416
|
-
);
|
|
417
|
-
}
|
|
408
|
+
assertProtocolVersion(request.protocolVersion);
|
|
418
409
|
try {
|
|
419
410
|
await provider.configureProvider(
|
|
420
411
|
request.name,
|
|
@@ -451,9 +442,17 @@ export function createRuntimeService(
|
|
|
451
442
|
};
|
|
452
443
|
}
|
|
453
444
|
|
|
445
|
+
/**
|
|
446
|
+
* Adapts a plugin provider to the shared protocol service implementation.
|
|
447
|
+
*
|
|
448
|
+
* @internal
|
|
449
|
+
*/
|
|
454
450
|
export function createProviderService(
|
|
455
|
-
provider:
|
|
451
|
+
provider: LoadedProvider,
|
|
456
452
|
): Partial<ServiceImpl<typeof IntegrationProviderService>> {
|
|
453
|
+
if (!isPluginProvider(provider)) {
|
|
454
|
+
throw new Error("provider is not a plugin provider");
|
|
455
|
+
}
|
|
457
456
|
return {
|
|
458
457
|
getMetadata() {
|
|
459
458
|
return create(ProviderMetadataSchema, {
|
|
@@ -478,6 +477,7 @@ export function createProviderService(
|
|
|
478
477
|
});
|
|
479
478
|
},
|
|
480
479
|
async startProvider(request: StartProviderRequest) {
|
|
480
|
+
assertProtocolVersion(request.protocolVersion);
|
|
481
481
|
try {
|
|
482
482
|
await provider.configureProvider(
|
|
483
483
|
request.name,
|
|
@@ -503,6 +503,7 @@ export function createProviderService(
|
|
|
503
503
|
request.token,
|
|
504
504
|
request.connectionParams,
|
|
505
505
|
request.context,
|
|
506
|
+
request.invocationToken,
|
|
506
507
|
),
|
|
507
508
|
),
|
|
508
509
|
);
|
|
@@ -542,9 +543,15 @@ export function createProviderService(
|
|
|
542
543
|
};
|
|
543
544
|
}
|
|
544
545
|
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
546
|
+
/**
|
|
547
|
+
* Adapts an authentication provider to the shared protocol service
|
|
548
|
+
* implementation.
|
|
549
|
+
*
|
|
550
|
+
* @internal
|
|
551
|
+
*/
|
|
552
|
+
export function createAuthenticationService(
|
|
553
|
+
provider: AuthenticationProvider,
|
|
554
|
+
): Partial<ServiceImpl<typeof AuthenticationProviderService>> {
|
|
548
555
|
return {
|
|
549
556
|
async beginLogin(request) {
|
|
550
557
|
const response = await provider.beginLogin({
|
|
@@ -557,7 +564,7 @@ export function createAuthService(
|
|
|
557
564
|
});
|
|
558
565
|
if (!response) {
|
|
559
566
|
throw new ConnectError(
|
|
560
|
-
"
|
|
567
|
+
"authentication provider returned nil response",
|
|
561
568
|
Code.Internal,
|
|
562
569
|
);
|
|
563
570
|
}
|
|
@@ -576,7 +583,7 @@ export function createAuthService(
|
|
|
576
583
|
});
|
|
577
584
|
if (!user) {
|
|
578
585
|
throw new ConnectError(
|
|
579
|
-
"
|
|
586
|
+
"authentication provider returned nil user",
|
|
580
587
|
Code.Internal,
|
|
581
588
|
);
|
|
582
589
|
}
|
|
@@ -585,7 +592,7 @@ export function createAuthService(
|
|
|
585
592
|
async validateExternalToken(request: ValidateExternalTokenRequest) {
|
|
586
593
|
if (!provider.supportsExternalTokenValidation()) {
|
|
587
594
|
throw new ConnectError(
|
|
588
|
-
"
|
|
595
|
+
"authentication provider does not support external token validation",
|
|
589
596
|
Code.Unimplemented,
|
|
590
597
|
);
|
|
591
598
|
}
|
|
@@ -598,7 +605,7 @@ export function createAuthService(
|
|
|
598
605
|
async getSessionSettings() {
|
|
599
606
|
if (!provider.supportsSessionSettings()) {
|
|
600
607
|
throw new ConnectError(
|
|
601
|
-
"
|
|
608
|
+
"authentication provider does not expose session settings",
|
|
602
609
|
Code.Unimplemented,
|
|
603
610
|
);
|
|
604
611
|
}
|
|
@@ -610,6 +617,11 @@ export function createAuthService(
|
|
|
610
617
|
};
|
|
611
618
|
}
|
|
612
619
|
|
|
620
|
+
/**
|
|
621
|
+
* Adapts a cache provider to the shared protocol service implementation.
|
|
622
|
+
*
|
|
623
|
+
* @internal
|
|
624
|
+
*/
|
|
613
625
|
export function createCacheService(
|
|
614
626
|
provider: CacheProvider,
|
|
615
627
|
): Partial<ServiceImpl<typeof CacheService>> {
|
|
@@ -674,6 +686,11 @@ export function createCacheService(
|
|
|
674
686
|
};
|
|
675
687
|
}
|
|
676
688
|
|
|
689
|
+
/**
|
|
690
|
+
* Adapts a secrets provider to the shared protocol service implementation.
|
|
691
|
+
*
|
|
692
|
+
* @internal
|
|
693
|
+
*/
|
|
677
694
|
export function createSecretsService(
|
|
678
695
|
provider: SecretsProvider,
|
|
679
696
|
): Partial<ServiceImpl<typeof SecretsProviderService>> {
|
|
@@ -687,14 +704,11 @@ export function createSecretsService(
|
|
|
687
704
|
};
|
|
688
705
|
}
|
|
689
706
|
|
|
690
|
-
export function pluginCatalogYaml(plugin: IntegrationProvider): string {
|
|
691
|
-
return catalogToYaml(plugin.staticCatalog());
|
|
692
|
-
}
|
|
693
|
-
|
|
694
707
|
function providerRequest(
|
|
695
708
|
token: string,
|
|
696
709
|
connectionParams: Record<string, string>,
|
|
697
710
|
requestContext?: ProtoRequestContext,
|
|
711
|
+
invocationToken = "",
|
|
698
712
|
): Request {
|
|
699
713
|
const subject = requestContext?.subject;
|
|
700
714
|
const credential = requestContext?.credential;
|
|
@@ -720,43 +734,44 @@ function providerRequest(
|
|
|
720
734
|
policy: access?.policy ?? "",
|
|
721
735
|
role: access?.role ?? "",
|
|
722
736
|
},
|
|
737
|
+
workflow: {
|
|
738
|
+
...(requestContext?.workflow ?? {}),
|
|
739
|
+
},
|
|
740
|
+
invocationToken,
|
|
723
741
|
};
|
|
724
742
|
}
|
|
725
743
|
|
|
726
|
-
function
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
case "secrets":
|
|
735
|
-
return ProtoProviderKind.SECRETS;
|
|
736
|
-
case "s3":
|
|
737
|
-
return ProtoProviderKind.S3;
|
|
738
|
-
case "telemetry":
|
|
739
|
-
return ProtoProviderKind.TELEMETRY;
|
|
740
|
-
default:
|
|
741
|
-
return ProtoProviderKind.UNSPECIFIED;
|
|
744
|
+
function providerRuntimeEntry(
|
|
745
|
+
kind: ProviderKind,
|
|
746
|
+
): ProviderRuntimeEntry {
|
|
747
|
+
const entry = PROVIDER_RUNTIME_ENTRIES[kind];
|
|
748
|
+
if (!entry) {
|
|
749
|
+
throw new Error(
|
|
750
|
+
`TypeScript SDK does not yet support provider kind ${JSON.stringify(kind)}`,
|
|
751
|
+
);
|
|
742
752
|
}
|
|
753
|
+
return entry;
|
|
743
754
|
}
|
|
744
755
|
|
|
745
|
-
function
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
case "s3":
|
|
756
|
-
return module.s3 ?? module.provider ?? module.default;
|
|
757
|
-
case "telemetry":
|
|
758
|
-
return module.telemetry ?? module.provider ?? module.default;
|
|
756
|
+
function resolveLoadedProvider(
|
|
757
|
+
candidate: unknown,
|
|
758
|
+
kind: ProviderKind,
|
|
759
|
+
source: string,
|
|
760
|
+
): LoadedProvider {
|
|
761
|
+
const entry = providerRuntimeEntry(kind);
|
|
762
|
+
if (!entry.isProvider(candidate)) {
|
|
763
|
+
throw new Error(
|
|
764
|
+
`${source} did not resolve to a Gestalt ${providerKindLabel(kind)}`,
|
|
765
|
+
);
|
|
759
766
|
}
|
|
767
|
+
return candidate;
|
|
768
|
+
}
|
|
769
|
+
|
|
770
|
+
function registerProviderService(
|
|
771
|
+
router: ConnectRouter,
|
|
772
|
+
provider: LoadedProvider,
|
|
773
|
+
): void {
|
|
774
|
+
providerRuntimeEntry(provider.kind).registerService(router, provider);
|
|
760
775
|
}
|
|
761
776
|
|
|
762
777
|
function objectFromUnknown(value: unknown): Record<string, unknown> {
|