service-bridge 0.1.4
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 +989 -0
- package/biome.json +28 -0
- package/bun.lock +249 -0
- package/dist/express.d.ts +51 -0
- package/dist/express.js +129 -0
- package/dist/fastify.d.ts +43 -0
- package/dist/fastify.js +122 -0
- package/dist/index.js +34507 -0
- package/dist/trace.d.ts +19 -0
- package/http/dist/express.d.ts +51 -0
- package/http/dist/express.d.ts.map +1 -0
- package/http/dist/express.test.d.ts +2 -0
- package/http/dist/express.test.d.ts.map +1 -0
- package/http/dist/fastify.d.ts +43 -0
- package/http/dist/fastify.d.ts.map +1 -0
- package/http/dist/fastify.test.d.ts +2 -0
- package/http/dist/fastify.test.d.ts.map +1 -0
- package/http/dist/index.d.ts +7 -0
- package/http/dist/index.d.ts.map +1 -0
- package/http/dist/trace.d.ts +19 -0
- package/http/dist/trace.d.ts.map +1 -0
- package/http/dist/trace.test.d.ts +2 -0
- package/http/dist/trace.test.d.ts.map +1 -0
- package/http/package.json +49 -0
- package/http/src/express.test.ts +125 -0
- package/http/src/express.ts +209 -0
- package/http/src/fastify.test.ts +142 -0
- package/http/src/fastify.ts +159 -0
- package/http/src/index.ts +10 -0
- package/http/src/sdk-augment.d.ts +11 -0
- package/http/src/servicebridge.d.ts +23 -0
- package/http/src/trace.test.ts +97 -0
- package/http/src/trace.ts +56 -0
- package/http/tsconfig.json +17 -0
- package/http/tsconfig.test.json +6 -0
- package/package.json +113 -0
- package/sdk/dist/generated/servicebridge-package-definition.d.ts +4912 -0
- package/sdk/dist/grpc-client.d.ts +344 -0
- package/sdk/dist/grpc-client.test.d.ts +1 -0
- package/sdk/dist/index.d.ts +2 -0
- package/sdk/package.json +31 -0
- package/sdk/scripts/generate-proto.ts +65 -0
- package/sdk/src/generated/servicebridge-package-definition.ts +5423 -0
- package/sdk/src/grpc-client.d.ts +332 -0
- package/sdk/src/grpc-client.d.ts.map +1 -0
- package/sdk/src/grpc-client.test.ts +422 -0
- package/sdk/src/grpc-client.ts +3088 -0
- package/sdk/src/index.d.ts +3 -0
- package/sdk/src/index.d.ts.map +1 -0
- package/sdk/src/index.ts +31 -0
- package/sdk/tsconfig.json +13 -0
|
@@ -0,0 +1,344 @@
|
|
|
1
|
+
export interface TraceCtx {
|
|
2
|
+
traceId: string;
|
|
3
|
+
spanId: string;
|
|
4
|
+
}
|
|
5
|
+
export declare function getTraceContext(): TraceCtx | undefined;
|
|
6
|
+
export declare function runWithTraceContext<T>(ctx: TraceCtx, fn: () => T): T;
|
|
7
|
+
/** Тип поля Protobuf-сообщения */
|
|
8
|
+
export type RpcFieldType = "string" | "int32" | "int64" | "uint32" | "uint64" | "float" | "double" | "bool" | "bytes";
|
|
9
|
+
/** Определение одного поля схемы */
|
|
10
|
+
export interface RpcFieldDef {
|
|
11
|
+
/** Тип поля */
|
|
12
|
+
type: RpcFieldType;
|
|
13
|
+
/** Уникальный номер поля (field number в proto) */
|
|
14
|
+
id: number;
|
|
15
|
+
/** Повторяющееся поле (массив) */
|
|
16
|
+
repeated?: boolean;
|
|
17
|
+
}
|
|
18
|
+
/** Схема сообщения: имя поля → определение */
|
|
19
|
+
export type RpcSchema = Record<string, RpcFieldDef>;
|
|
20
|
+
/** Входная и выходная схемы для RPC-функции */
|
|
21
|
+
export interface RpcSchemaOpts {
|
|
22
|
+
input?: RpcSchema;
|
|
23
|
+
output?: RpcSchema;
|
|
24
|
+
}
|
|
25
|
+
export interface RetryPolicy {
|
|
26
|
+
retries?: number;
|
|
27
|
+
retryDelay?: number;
|
|
28
|
+
}
|
|
29
|
+
export type WorkerTransport = "tls";
|
|
30
|
+
export interface WorkerTLSOpts {
|
|
31
|
+
caCert?: string | Buffer;
|
|
32
|
+
cert?: string | Buffer;
|
|
33
|
+
key?: string | Buffer;
|
|
34
|
+
serverName?: string;
|
|
35
|
+
}
|
|
36
|
+
export interface ServiceBridgeOpts extends RetryPolicy {
|
|
37
|
+
timeout?: number;
|
|
38
|
+
/** @deprecated No longer used — discovery is now lazy via LookupFunction. */
|
|
39
|
+
discoveryTimeout?: number;
|
|
40
|
+
/**
|
|
41
|
+
* How often (ms) each SbResolver re-polls LookupFunction to discover new replicas.
|
|
42
|
+
* Dead replicas are detected instantly by gRPC subchannel health monitoring.
|
|
43
|
+
* Default: 10 000 ms.
|
|
44
|
+
*/
|
|
45
|
+
discoveryRefreshMs?: number;
|
|
46
|
+
queueMaxSize?: number;
|
|
47
|
+
queueOverflow?: "drop-oldest" | "drop-newest" | "error";
|
|
48
|
+
heartbeatIntervalMs?: number;
|
|
49
|
+
workerTransport?: WorkerTransport;
|
|
50
|
+
/**
|
|
51
|
+
* Explicit mTLS cert materials for the worker gRPC server.
|
|
52
|
+
* When omitted, they are provisioned automatically from the server on `serve()`:
|
|
53
|
+
* the SDK generates a key pair locally and posts the public key to
|
|
54
|
+
* `POST /api/tls/provision` — the private key never leaves the process.
|
|
55
|
+
*/
|
|
56
|
+
workerTLS?: WorkerTLSOpts;
|
|
57
|
+
/**
|
|
58
|
+
* Base URL for the HTTP admin API used for auto-provisioning and management.
|
|
59
|
+
* Defaults to the gRPC host on port 14444 (e.g. "http://127.0.0.1:14444").
|
|
60
|
+
*/
|
|
61
|
+
adminUrl?: string;
|
|
62
|
+
/**
|
|
63
|
+
* Optional admin session cookie for browser-authenticated HTTP API endpoints
|
|
64
|
+
* (for example, DELETE /api/workflow-runs/:id).
|
|
65
|
+
*/
|
|
66
|
+
adminSessionCookie?: string;
|
|
67
|
+
/**
|
|
68
|
+
* Optional CSRF token paired with adminSessionCookie for unsafe HTTP methods.
|
|
69
|
+
*/
|
|
70
|
+
adminCsrfToken?: string;
|
|
71
|
+
/**
|
|
72
|
+
* Optional Origin header value required by CSRF/origin checks on admin endpoints.
|
|
73
|
+
*/
|
|
74
|
+
adminOrigin?: string;
|
|
75
|
+
/**
|
|
76
|
+
* When `true` (default), automatically patches `console.log / .info / .warn / .error / .debug`
|
|
77
|
+
* so that all console output is also shipped to ServiceBridge as structured log entries.
|
|
78
|
+
* Original console output is preserved (pass-through).
|
|
79
|
+
* Set to `false` to opt out.
|
|
80
|
+
*/
|
|
81
|
+
captureLogs?: boolean;
|
|
82
|
+
}
|
|
83
|
+
export interface RpcOpts extends RetryPolicy {
|
|
84
|
+
timeout?: number;
|
|
85
|
+
traceId?: string;
|
|
86
|
+
parentSpanId?: string;
|
|
87
|
+
}
|
|
88
|
+
export interface EventOpts {
|
|
89
|
+
traceId?: string;
|
|
90
|
+
parentSpanId?: string;
|
|
91
|
+
idempotencyKey?: string;
|
|
92
|
+
headers?: Record<string, string>;
|
|
93
|
+
}
|
|
94
|
+
export interface HandleEventOpts {
|
|
95
|
+
/** Maximum number of concurrent event deliveries to process simultaneously. */
|
|
96
|
+
concurrency?: number;
|
|
97
|
+
/** Number of messages to prefetch from the server ahead of processing. */
|
|
98
|
+
prefetch?: number;
|
|
99
|
+
groupName?: string;
|
|
100
|
+
retryPolicyJson?: string;
|
|
101
|
+
/** Server-side filter expression. Syntax: comma-separated AND conditions.
|
|
102
|
+
* Examples: "status=paid", "amount>100", "status=paid,amount>100", "region!=us-east" */
|
|
103
|
+
filterExpr?: string;
|
|
104
|
+
}
|
|
105
|
+
export interface HandleRpcOpts {
|
|
106
|
+
timeout?: number;
|
|
107
|
+
retryable?: boolean;
|
|
108
|
+
concurrency?: number;
|
|
109
|
+
/** Схема для авто-валидации и бинарного кодирования payload */
|
|
110
|
+
schema?: RpcSchemaOpts;
|
|
111
|
+
/**
|
|
112
|
+
* Whitelist of service names allowed to call this function.
|
|
113
|
+
* When set, the worker rejects Handle requests from services not in this list.
|
|
114
|
+
* Corresponds to the allowed_callers field on the service key.
|
|
115
|
+
* When mTLS is used, the x-caller-service header is cryptographically backed by the cert CN.
|
|
116
|
+
*/
|
|
117
|
+
allowedCallers?: string[];
|
|
118
|
+
}
|
|
119
|
+
export interface ServeOpts {
|
|
120
|
+
host?: string;
|
|
121
|
+
instanceId?: string;
|
|
122
|
+
weight?: number;
|
|
123
|
+
transport?: WorkerTransport;
|
|
124
|
+
tls?: WorkerTLSOpts;
|
|
125
|
+
}
|
|
126
|
+
export interface ScheduleOpts {
|
|
127
|
+
cron?: string;
|
|
128
|
+
delay?: number;
|
|
129
|
+
timezone?: string;
|
|
130
|
+
misfire?: "fire_now" | "skip";
|
|
131
|
+
via?: "event" | "rpc" | "workflow";
|
|
132
|
+
retryPolicyJson?: string;
|
|
133
|
+
}
|
|
134
|
+
/** StreamWriter allows handlers to push incremental chunks during execution. */
|
|
135
|
+
export interface StreamWriter {
|
|
136
|
+
/**
|
|
137
|
+
* Append a chunk to the run's named stream.
|
|
138
|
+
* @param data - any JSON-serializable value
|
|
139
|
+
* @param key - stream key (default: "default"). Use named keys for multiple streams
|
|
140
|
+
* (e.g. "output", "log", "progress").
|
|
141
|
+
*/
|
|
142
|
+
write(data: unknown, key?: string): Promise<void>;
|
|
143
|
+
/** Node.js only. No-op placeholder for API symmetry; the stream lifecycle is managed by the runtime. */
|
|
144
|
+
end(key?: string): Promise<void>;
|
|
145
|
+
}
|
|
146
|
+
export interface EventContext {
|
|
147
|
+
traceId: string;
|
|
148
|
+
spanId: string;
|
|
149
|
+
refs: {
|
|
150
|
+
topic: string;
|
|
151
|
+
groupName: string;
|
|
152
|
+
messageId: string;
|
|
153
|
+
attempt: number;
|
|
154
|
+
headers: Record<string, string>;
|
|
155
|
+
};
|
|
156
|
+
retry(delayMs?: number): void;
|
|
157
|
+
reject(reason: string): void;
|
|
158
|
+
/** Real-time stream writer. Use ctx.stream.write(data) to push chunks to subscribers. */
|
|
159
|
+
stream: StreamWriter;
|
|
160
|
+
}
|
|
161
|
+
/** Context passed as optional second argument to RPC handlers. */
|
|
162
|
+
export interface RpcContext {
|
|
163
|
+
traceId: string;
|
|
164
|
+
spanId: string;
|
|
165
|
+
/** Real-time stream writer. Use ctx.stream.write(data) to push chunks to subscribers. */
|
|
166
|
+
stream: StreamWriter;
|
|
167
|
+
}
|
|
168
|
+
type EventHandler = (payload: unknown, ctx: EventContext) => void | Promise<void>;
|
|
169
|
+
type FnHandler = (payload: unknown, ctx?: RpcContext) => unknown | Promise<unknown>;
|
|
170
|
+
export interface HttpSpan {
|
|
171
|
+
traceId: string;
|
|
172
|
+
spanId: string;
|
|
173
|
+
end(opts: {
|
|
174
|
+
statusCode?: number;
|
|
175
|
+
success?: boolean;
|
|
176
|
+
error?: string;
|
|
177
|
+
}): void;
|
|
178
|
+
}
|
|
179
|
+
export interface RunStreamEvent {
|
|
180
|
+
type: "chunk" | "run_complete";
|
|
181
|
+
runId: string;
|
|
182
|
+
key: string;
|
|
183
|
+
sequence: number;
|
|
184
|
+
data: unknown;
|
|
185
|
+
runStatus?: string;
|
|
186
|
+
}
|
|
187
|
+
export interface RunWorkflowResult {
|
|
188
|
+
runId: string;
|
|
189
|
+
traceId: string;
|
|
190
|
+
}
|
|
191
|
+
export interface RunWorkflowOpts {
|
|
192
|
+
/** Override the trace ID for this workflow run. */
|
|
193
|
+
traceId?: string;
|
|
194
|
+
}
|
|
195
|
+
export interface WorkflowOpts {
|
|
196
|
+
/** Maximum serialized state size in bytes. Defaults to 262144 (256 KB). */
|
|
197
|
+
stateLimitBytes?: number;
|
|
198
|
+
/** Default per-step timeout in milliseconds. Defaults to 30000 (30 s). */
|
|
199
|
+
stepTimeoutMs?: number;
|
|
200
|
+
}
|
|
201
|
+
export interface WatchRunOpts {
|
|
202
|
+
/** Filter by stream key. Empty = all keys. */
|
|
203
|
+
key?: string;
|
|
204
|
+
/** Replay chunks with sequence strictly greater than this value. 0 = full replay. */
|
|
205
|
+
fromSequence?: number;
|
|
206
|
+
}
|
|
207
|
+
export type ServiceBridgeErrorSeverity = "fatal" | "retriable" | "ignorable";
|
|
208
|
+
export declare class ServiceBridgeError extends Error {
|
|
209
|
+
code?: number;
|
|
210
|
+
component: string;
|
|
211
|
+
operation: string;
|
|
212
|
+
severity: ServiceBridgeErrorSeverity;
|
|
213
|
+
retryable: boolean;
|
|
214
|
+
cause?: unknown;
|
|
215
|
+
constructor(opts: {
|
|
216
|
+
message: string;
|
|
217
|
+
code?: number;
|
|
218
|
+
component: string;
|
|
219
|
+
operation: string;
|
|
220
|
+
severity: ServiceBridgeErrorSeverity;
|
|
221
|
+
cause?: unknown;
|
|
222
|
+
});
|
|
223
|
+
}
|
|
224
|
+
/**
|
|
225
|
+
* A single node in a workflow DAG.
|
|
226
|
+
*
|
|
227
|
+
* - `id` — unique step identifier; used in `deps` of other steps.
|
|
228
|
+
* - `deps` — IDs of steps that must succeed before this step runs.
|
|
229
|
+
* Empty array (default) = root step; receives the workflow input directly.
|
|
230
|
+
* - `if` — optional filter expression (same syntax as event filters).
|
|
231
|
+
* If it evaluates to false the step is skipped.
|
|
232
|
+
*/
|
|
233
|
+
export type WorkflowStep = {
|
|
234
|
+
id: string;
|
|
235
|
+
type: "rpc";
|
|
236
|
+
ref: string;
|
|
237
|
+
deps?: string[];
|
|
238
|
+
if?: string;
|
|
239
|
+
timeoutMs?: number;
|
|
240
|
+
} | {
|
|
241
|
+
id: string;
|
|
242
|
+
type: "event";
|
|
243
|
+
ref: string;
|
|
244
|
+
deps?: string[];
|
|
245
|
+
if?: string;
|
|
246
|
+
} | {
|
|
247
|
+
id: string;
|
|
248
|
+
type: "event_wait";
|
|
249
|
+
ref: string;
|
|
250
|
+
deps?: string[];
|
|
251
|
+
if?: string;
|
|
252
|
+
timeoutMs?: number;
|
|
253
|
+
} | {
|
|
254
|
+
id: string;
|
|
255
|
+
type: "sleep";
|
|
256
|
+
durationMs: number;
|
|
257
|
+
deps?: string[];
|
|
258
|
+
if?: string;
|
|
259
|
+
} | {
|
|
260
|
+
id: string;
|
|
261
|
+
type: "workflow";
|
|
262
|
+
ref: string;
|
|
263
|
+
deps?: string[];
|
|
264
|
+
if?: string;
|
|
265
|
+
};
|
|
266
|
+
export interface ServiceBridgeService {
|
|
267
|
+
rpc<T = unknown>(fn: string, payload?: unknown, opts?: RpcOpts): Promise<T>;
|
|
268
|
+
event(topic: string, payload?: unknown, opts?: EventOpts): Promise<string>;
|
|
269
|
+
job(target: string, opts: ScheduleOpts): Promise<string>;
|
|
270
|
+
workflow(name: string, steps: WorkflowStep[], opts?: WorkflowOpts): Promise<string>;
|
|
271
|
+
runWorkflow(name: string, input?: unknown, opts?: RunWorkflowOpts): Promise<RunWorkflowResult>;
|
|
272
|
+
cancelWorkflowRun(runId: string): Promise<void>;
|
|
273
|
+
/**
|
|
274
|
+
* Регистрирует обработчик RPC-функции.
|
|
275
|
+
* Если передан `opts.schema`, payload автоматически валидируется и
|
|
276
|
+
* кодируется/декодируется в бинарный Protobuf-формат вместо JSON.
|
|
277
|
+
* Схема также публикуется в server registry и используется вызывающей стороной.
|
|
278
|
+
*/
|
|
279
|
+
handleRpc(fn: string, handler: FnHandler, opts?: HandleRpcOpts): ServiceBridgeService;
|
|
280
|
+
handleEvent(pattern: string, handler: EventHandler, opts?: HandleEventOpts): ServiceBridgeService;
|
|
281
|
+
serve(opts?: ServeOpts): Promise<void>;
|
|
282
|
+
stop(): void;
|
|
283
|
+
startHttpSpan(opts: {
|
|
284
|
+
method: string;
|
|
285
|
+
path: string;
|
|
286
|
+
traceId?: string;
|
|
287
|
+
parentSpanId?: string;
|
|
288
|
+
}): HttpSpan;
|
|
289
|
+
/**
|
|
290
|
+
* Register an HTTP endpoint in the ServiceBridge catalog.
|
|
291
|
+
* Call this once per route after your HTTP server is configured.
|
|
292
|
+
* The Express and Fastify adapters call this automatically — you only need
|
|
293
|
+
* this when integrating a different HTTP framework.
|
|
294
|
+
*
|
|
295
|
+
* @example
|
|
296
|
+
* await sb.registerHttpEndpoint({ method: 'GET', route: '/users/:id' });
|
|
297
|
+
*/
|
|
298
|
+
registerHttpEndpoint(opts: {
|
|
299
|
+
/** HTTP method: GET, POST, PUT, PATCH, DELETE, HEAD, OPTIONS */
|
|
300
|
+
method: string;
|
|
301
|
+
/** Route pattern including parameter placeholders, e.g. "/users/:id" */
|
|
302
|
+
route: string;
|
|
303
|
+
/** Stable identifier for this process instance. Defaults to a per-SDK UUID. */
|
|
304
|
+
instanceId?: string;
|
|
305
|
+
/** Address where this service can be reached, e.g. "http://10.0.0.1:3000" */
|
|
306
|
+
endpoint?: string;
|
|
307
|
+
/** Service names allowed to call this endpoint (RBAC). Default: [] (all allowed) */
|
|
308
|
+
allowedCallers?: string[];
|
|
309
|
+
/** Optional JSON schema string for request validation metadata. */
|
|
310
|
+
requestSchemaJson?: string;
|
|
311
|
+
/** Optional JSON schema string for response validation metadata. */
|
|
312
|
+
responseSchemaJson?: string;
|
|
313
|
+
/** Optional transport label for the endpoint instance (e.g. "http", "https"). */
|
|
314
|
+
transport?: string;
|
|
315
|
+
}): Promise<void>;
|
|
316
|
+
/**
|
|
317
|
+
* Subscribe to a run's real-time stream.
|
|
318
|
+
* Replays existing chunks then forwards new ones until the run completes or the caller breaks.
|
|
319
|
+
*
|
|
320
|
+
* @example
|
|
321
|
+
* const stream = sb.watchRun(runId, { key: "output" });
|
|
322
|
+
* for await (const chunk of stream) {
|
|
323
|
+
* process.stdout.write(chunk.data.token);
|
|
324
|
+
* }
|
|
325
|
+
*/
|
|
326
|
+
watchRun(runId: string, opts?: WatchRunOpts): AsyncIterable<RunStreamEvent>;
|
|
327
|
+
/** @internal Used by captureConsole to forward intercepted log lines. */
|
|
328
|
+
readonly _log: (level: string, msg: string, attrs?: Record<string, string>) => void;
|
|
329
|
+
}
|
|
330
|
+
export declare function servicebridge(url: string, serviceKey: string, service?: string, globalOpts?: ServiceBridgeOpts): ServiceBridgeService;
|
|
331
|
+
/**
|
|
332
|
+
* Intercepts `console.log / .info / .warn / .error / .debug` so that every
|
|
333
|
+
* call is **also** shipped to ServiceBridge as a structured log entry.
|
|
334
|
+
*
|
|
335
|
+
* Original console output is preserved (pass-through) — nothing changes on
|
|
336
|
+
* the terminal side. Trace correlation works automatically via AsyncLocalStorage.
|
|
337
|
+
*
|
|
338
|
+
* @example
|
|
339
|
+
* const svc = servicebridge("localhost:14445", "my-key", "orders");
|
|
340
|
+
* captureConsole(svc); // call once at startup
|
|
341
|
+
* console.log("order created"); // appears on stdout AND in ServiceBridge
|
|
342
|
+
*/
|
|
343
|
+
export declare function captureConsole(svc: ServiceBridgeService): void;
|
|
344
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
export type { EventContext, EventOpts, HandleEventOpts, HandleRpcOpts, HttpSpan, RetryPolicy, RpcContext, RpcFieldDef, RpcFieldType, RpcOpts, RpcSchema, RpcSchemaOpts, RunStreamEvent, RunWorkflowOpts, ScheduleOpts, ServeOpts, ServiceBridgeErrorSeverity, ServiceBridgeOpts, ServiceBridgeService, StreamWriter, TraceCtx, WatchRunOpts, WorkflowOpts, } from "./grpc-client";
|
|
2
|
+
export { getTraceContext, runWithTraceContext, ServiceBridgeError, servicebridge, } from "./grpc-client";
|
package/sdk/package.json
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@servicebridge/sdk-node",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"license": "SEE LICENSE IN LICENSE",
|
|
6
|
+
"publishConfig": {
|
|
7
|
+
"access": "public"
|
|
8
|
+
},
|
|
9
|
+
"main": "dist/index.js",
|
|
10
|
+
"types": "dist/index.d.ts",
|
|
11
|
+
"exports": {
|
|
12
|
+
".": {
|
|
13
|
+
"import": "./dist/index.js",
|
|
14
|
+
"types": "./dist/index.d.ts"
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
"scripts": {
|
|
18
|
+
"generate:proto": "bun run scripts/generate-proto.ts",
|
|
19
|
+
"build": "bun run generate:proto && bun build src/index.ts --outdir=dist --target=node",
|
|
20
|
+
"test": "bun test"
|
|
21
|
+
},
|
|
22
|
+
"dependencies": {
|
|
23
|
+
"@grpc/grpc-js": "^1.9.0",
|
|
24
|
+
"@grpc/proto-loader": "^0.7.10",
|
|
25
|
+
"protobufjs": "^8.0.0"
|
|
26
|
+
},
|
|
27
|
+
"devDependencies": {
|
|
28
|
+
"@types/bun": "latest",
|
|
29
|
+
"typescript": "^5.3.0"
|
|
30
|
+
}
|
|
31
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { mkdir, writeFile } from "node:fs/promises";
|
|
2
|
+
import { dirname, join } from "node:path";
|
|
3
|
+
import { fileURLToPath } from "node:url";
|
|
4
|
+
import * as protoLoader from "@grpc/proto-loader";
|
|
5
|
+
|
|
6
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
7
|
+
const rootDir = join(__dirname, "..");
|
|
8
|
+
const sdkRepoRoot = join(rootDir, "..", "..");
|
|
9
|
+
const protoPath = join(sdkRepoRoot, "proto", "servicebridge.proto");
|
|
10
|
+
const outPath = join(
|
|
11
|
+
rootDir,
|
|
12
|
+
"src",
|
|
13
|
+
"generated",
|
|
14
|
+
"servicebridge-package-definition.ts",
|
|
15
|
+
);
|
|
16
|
+
|
|
17
|
+
const packageDefinition = protoLoader.loadSync(protoPath, {
|
|
18
|
+
keepCase: true,
|
|
19
|
+
longs: String,
|
|
20
|
+
enums: String,
|
|
21
|
+
defaults: true,
|
|
22
|
+
oneofs: true,
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
function serialize(value: unknown): string {
|
|
26
|
+
if (Buffer.isBuffer(value)) {
|
|
27
|
+
return `Buffer.from([${Array.from(value).join(", ")}])`;
|
|
28
|
+
}
|
|
29
|
+
if (Array.isArray(value)) {
|
|
30
|
+
if (value.length === 0) {
|
|
31
|
+
return "[]";
|
|
32
|
+
}
|
|
33
|
+
return `[\n${value.map((item) => indent(serialize(item))).join(",\n")}\n]`;
|
|
34
|
+
}
|
|
35
|
+
if (value && typeof value === "object") {
|
|
36
|
+
const entries = Object.entries(value);
|
|
37
|
+
if (entries.length === 0) {
|
|
38
|
+
return "{}";
|
|
39
|
+
}
|
|
40
|
+
return `{\n${entries
|
|
41
|
+
.map(
|
|
42
|
+
([key, item]) => `${indent(JSON.stringify(key))}: ${serialize(item)}`,
|
|
43
|
+
)
|
|
44
|
+
.join(",\n")}\n}`;
|
|
45
|
+
}
|
|
46
|
+
return JSON.stringify(value);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function indent(value: string): string {
|
|
50
|
+
return value
|
|
51
|
+
.split("\n")
|
|
52
|
+
.map((line) => ` ${line}`)
|
|
53
|
+
.join("\n");
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
await mkdir(dirname(outPath), { recursive: true });
|
|
57
|
+
await writeFile(
|
|
58
|
+
outPath,
|
|
59
|
+
`/* eslint-disable */
|
|
60
|
+
/* auto-generated by packages/sdk/scripts/generate-proto.ts */
|
|
61
|
+
|
|
62
|
+
export const servicebridgePackageDefinition = ${serialize(packageDefinition)} as const;
|
|
63
|
+
`,
|
|
64
|
+
"utf8",
|
|
65
|
+
);
|