service-bridge 1.8.4-dev.45 → 1.8.4-dev.46

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.js +60 -60
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -841,11 +841,11 @@ function ensureSbResolverRegistered() {
841
841
  }
842
842
  registerResolver("sb", SbResolver);
843
843
  }
844
- function servicebridge(url, serviceKey, serviceOrOpts = {}, maybeGlobalOpts = {}) {
845
- const service = typeof serviceOrOpts === "string" ? serviceOrOpts.trim() : "";
846
- const globalOpts = typeof serviceOrOpts === "string" ? maybeGlobalOpts : serviceOrOpts ?? {};
844
+ function servicebridge(url, serviceKey, opts = {}) {
847
845
  const parsedServiceKey = parseServiceKeyV2(serviceKey);
848
- const defaultConsumerPrefix = parsedServiceKey.keyId || "consumer";
846
+ const service = parsedServiceKey.keyId || "";
847
+ const globalOpts = opts;
848
+ const defaultConsumerPrefix = service || "consumer";
849
849
  const meta = new grpc.Metadata;
850
850
  meta.add("x-service-key", serviceKey);
851
851
  const rawUrl = url.trim();
@@ -2097,7 +2097,7 @@ function servicebridge(url, serviceKey, serviceOrOpts = {}, maybeGlobalOpts = {}
2097
2097
  }
2098
2098
  }
2099
2099
  const svc = {
2100
- async rpc(targetService, fn, payload, opts) {
2100
+ async rpc(targetService, fn, payload, opts2) {
2101
2101
  try {
2102
2102
  await _controlReady;
2103
2103
  } catch (err) {
@@ -2110,10 +2110,10 @@ function servicebridge(url, serviceKey, serviceOrOpts = {}, maybeGlobalOpts = {}
2110
2110
  }
2111
2111
  const lookupKey = `${svcName}/${fname}`;
2112
2112
  const tc = traceStorage.getStore();
2113
- const traceId = opts?.traceId ?? tc?.traceId ?? crypto.randomUUID();
2114
- const maxRetries = normalizeNonNegativeInt(opts?.retries ?? globalOpts.retries ?? 3, 3);
2115
- const baseDelay = normalizePositiveInt(opts?.retryDelay ?? globalOpts.retryDelay ?? 300, 300);
2116
- const timeout = normalizePositiveInt(opts?.timeout ?? globalOpts.timeout ?? 30000, 30000);
2113
+ const traceId = opts2?.traceId ?? tc?.traceId ?? crypto.randomUUID();
2114
+ const maxRetries = normalizeNonNegativeInt(opts2?.retries ?? globalOpts.retries ?? 3, 3);
2115
+ const baseDelay = normalizePositiveInt(opts2?.retryDelay ?? globalOpts.retryDelay ?? 300, 300);
2116
+ const timeout = normalizePositiveInt(opts2?.timeout ?? globalOpts.timeout ?? 30000, 30000);
2117
2117
  let functionKey = resolveFunctionKey(lookupKey);
2118
2118
  if (!functionKey) {
2119
2119
  await doLookupFunction(lookupKey);
@@ -2132,12 +2132,12 @@ function servicebridge(url, serviceKey, serviceOrOpts = {}, maybeGlobalOpts = {}
2132
2132
  const rpcFnName = fname;
2133
2133
  const rpcServiceName = svcName;
2134
2134
  const rootSpanId = crypto.randomUUID();
2135
- const parentSpanId = opts?.parentSpanId ?? tc?.spanId ?? "";
2135
+ const parentSpanId = opts2?.parentSpanId ?? tc?.spanId ?? "";
2136
2136
  const rootStartedAt = Date.now();
2137
2137
  const hasRetries = maxRetries > 0;
2138
2138
  reportCallStartAsync(traceId, rootSpanId, parentSpanId, rpcFnName, rootStartedAt, telemetryInputBuf, 1, "rpc", rpcServiceName);
2139
2139
  return traceStorage.run({ traceId, spanId: rootSpanId }, async () => {
2140
- if (opts?.mode === "proxy") {
2140
+ if (opts2?.mode === "proxy") {
2141
2141
  return await new Promise((resolve, reject) => {
2142
2142
  stub.ProxyCall({
2143
2143
  function_name: functionKey,
@@ -2248,9 +2248,9 @@ function servicebridge(url, serviceKey, serviceOrOpts = {}, maybeGlobalOpts = {}
2248
2248
  throw normalizeServiceError(lastError, lookupKey, "worker");
2249
2249
  });
2250
2250
  },
2251
- event(topic, payload, opts) {
2251
+ event(topic, payload, opts2) {
2252
2252
  if (!isOnline) {
2253
- enqueueOffline({ type: "event", topic, payload, opts });
2253
+ enqueueOffline({ type: "event", topic, payload, opts: opts2 });
2254
2254
  return Promise.resolve("");
2255
2255
  }
2256
2256
  const tc = traceStorage.getStore();
@@ -2258,15 +2258,15 @@ function servicebridge(url, serviceKey, serviceOrOpts = {}, maybeGlobalOpts = {}
2258
2258
  stub.Publish({
2259
2259
  topic,
2260
2260
  payload: toJsonBuffer(payload),
2261
- headers: toWireStringMap(opts?.headers),
2262
- trace_id: opts?.traceId ?? tc?.traceId ?? "",
2263
- parent_span_id: opts?.parentSpanId ?? tc?.spanId ?? "",
2261
+ headers: toWireStringMap(opts2?.headers),
2262
+ trace_id: opts2?.traceId ?? tc?.traceId ?? "",
2263
+ parent_span_id: opts2?.parentSpanId ?? tc?.spanId ?? "",
2264
2264
  producer_service: defaultConsumerPrefix,
2265
- idempotency_key: opts?.idempotencyKey ?? ""
2265
+ idempotency_key: opts2?.idempotencyKey ?? ""
2266
2266
  }, meta, unaryDeadlineOptions(), (err, res) => err ? reject(normalizeServiceError(err, `publish:${topic}`)) : resolve(res?.message_id ?? ""));
2267
2267
  });
2268
2268
  },
2269
- publishEvent(topic, payload, opts) {
2269
+ publishEvent(topic, payload, opts2) {
2270
2270
  const stream = workerSessionStream;
2271
2271
  if (!stream) {
2272
2272
  return Promise.reject(new Error("publishEvent requires an active worker session (call serve() first)"));
@@ -2277,9 +2277,9 @@ function servicebridge(url, serviceKey, serviceOrOpts = {}, maybeGlobalOpts = {}
2277
2277
  request_id: requestId,
2278
2278
  topic,
2279
2279
  payload: toJsonBuffer(payload),
2280
- headers: toWireStringMap(opts?.headers),
2281
- trace_id: opts?.traceId ?? tc?.traceId ?? "",
2282
- parent_span_id: opts?.parentSpanId ?? tc?.spanId ?? ""
2280
+ headers: toWireStringMap(opts2?.headers),
2281
+ trace_id: opts2?.traceId ?? tc?.traceId ?? "",
2282
+ parent_span_id: opts2?.parentSpanId ?? tc?.spanId ?? ""
2283
2283
  };
2284
2284
  return new Promise((resolve, reject) => {
2285
2285
  const timer = setTimeout(() => {
@@ -2296,12 +2296,12 @@ function servicebridge(url, serviceKey, serviceOrOpts = {}, maybeGlobalOpts = {}
2296
2296
  }
2297
2297
  });
2298
2298
  },
2299
- handleRpc(fn, handler, opts) {
2300
- fnHandlers.set(fn, { handler, opts: opts ?? {} });
2299
+ handleRpc(fn, handler, opts2) {
2300
+ fnHandlers.set(fn, { handler, opts: opts2 ?? {} });
2301
2301
  return svc;
2302
2302
  },
2303
- handleEvent(pattern, handler, opts) {
2304
- const normalizedOpts = opts ?? {};
2303
+ handleEvent(pattern, handler, opts2) {
2304
+ const normalizedOpts = opts2 ?? {};
2305
2305
  const groupName = `${defaultConsumerPrefix}.${pattern}`;
2306
2306
  if (eventHandlers.has(groupName)) {
2307
2307
  throw new Error(`Duplicate event consumer group "${groupName}". ` + "Use handleEvent() with a unique topic pattern per handler.");
@@ -2314,13 +2314,13 @@ function servicebridge(url, serviceKey, serviceOrOpts = {}, maybeGlobalOpts = {}
2314
2314
  });
2315
2315
  return svc;
2316
2316
  },
2317
- async serve(opts = {}) {
2317
+ async serve(opts2 = {}) {
2318
2318
  if (workerServer)
2319
2319
  throw new Error("serve() already called");
2320
2320
  if (fnHandlers.size === 0 && eventHandlers.size === 0) {
2321
2321
  throw new Error("No handlers registered. Call handleRpc() or handleEvent() before serve().");
2322
2322
  }
2323
- if (opts.maxInFlight != null && (!Number.isInteger(opts.maxInFlight) || opts.maxInFlight < 1)) {
2323
+ if (opts2.maxInFlight != null && (!Number.isInteger(opts2.maxInFlight) || opts2.maxInFlight < 1)) {
2324
2324
  throw new Error("serve() maxInFlight must be a positive integer");
2325
2325
  }
2326
2326
  try {
@@ -2329,10 +2329,10 @@ function servicebridge(url, serviceKey, serviceOrOpts = {}, maybeGlobalOpts = {}
2329
2329
  Handle: handleRpc,
2330
2330
  Deliver: handleDeliver
2331
2331
  });
2332
- const host = opts.host || "localhost";
2332
+ const host = opts2.host || "localhost";
2333
2333
  const isWildcardBind = host === "0.0.0.0" || host === "::";
2334
2334
  const advertiseHost = isWildcardBind ? await outboundIP() || host : host;
2335
- const tlsOpts = opts.tls ?? effectiveWorkerTLS ?? undefined;
2335
+ const tlsOpts = opts2.tls ?? effectiveWorkerTLS ?? undefined;
2336
2336
  let effectiveCert = toPemBuffer(tlsOpts?.cert);
2337
2337
  let effectiveKey = toPemBuffer(tlsOpts?.key);
2338
2338
  const explicitWorkerCACert = toPemBuffer(tlsOpts?.caCert);
@@ -2344,7 +2344,7 @@ function servicebridge(url, serviceKey, serviceOrOpts = {}, maybeGlobalOpts = {}
2344
2344
  validateWorkerCertAndKeyPair(effectiveCert, effectiveKey);
2345
2345
  }
2346
2346
  if (!effectiveCert || !effectiveKey) {
2347
- const instanceIdForCert = opts.instanceId || Array.from(crypto.getRandomValues(new Uint8Array(3))).map((b) => b.toString(16).padStart(2, "0")).join("");
2347
+ const instanceIdForCert = opts2.instanceId || Array.from(crypto.getRandomValues(new Uint8Array(3))).map((b) => b.toString(16).padStart(2, "0")).join("");
2348
2348
  const provisioned = await provisionWorkerTLS(stub, meta, service, instanceIdForCert, isWildcardBind && advertiseHost !== host ? advertiseHost : undefined, isWildcardBind && advertiseHost !== host ? [advertiseHost] : undefined);
2349
2349
  effectiveCert = provisioned.cert;
2350
2350
  effectiveKey = provisioned.key;
@@ -2368,13 +2368,13 @@ function servicebridge(url, serviceKey, serviceOrOpts = {}, maybeGlobalOpts = {}
2368
2368
  server.bindAsync(`${host}:0`, serverCreds, (err, p) => err ? reject(err) : resolve(p));
2369
2369
  });
2370
2370
  const endpoint = `${advertiseHost}:${port}`;
2371
- const instanceId = opts.instanceId || Array.from(crypto.getRandomValues(new Uint8Array(3))).map((b) => b.toString(16).padStart(2, "0")).join("");
2371
+ const instanceId = opts2.instanceId || Array.from(crypto.getRandomValues(new Uint8Array(3))).map((b) => b.toString(16).padStart(2, "0")).join("");
2372
2372
  serveState = {
2373
2373
  endpoint,
2374
2374
  transport: "tls",
2375
- opts,
2375
+ opts: opts2,
2376
2376
  instanceId,
2377
- maxInFlight: Math.max(1, Math.trunc(opts.maxInFlight ?? 128))
2377
+ maxInFlight: Math.max(1, Math.trunc(opts2.maxInFlight ?? 128))
2378
2378
  };
2379
2379
  if (effectiveCACert && effectiveCert && effectiveKey) {
2380
2380
  effectiveWorkerTLS = {
@@ -2430,47 +2430,47 @@ function servicebridge(url, serviceKey, serviceOrOpts = {}, maybeGlobalOpts = {}
2430
2430
  },
2431
2431
  async job(serviceOrTarget, fnOrOpts, optsOrUndefined) {
2432
2432
  let target2;
2433
- let opts;
2433
+ let opts2;
2434
2434
  if (typeof fnOrOpts === "string") {
2435
2435
  const service2 = serviceOrTarget.trim();
2436
2436
  const fn = fnOrOpts.trim();
2437
- opts = optsOrUndefined ?? { via: "rpc" };
2437
+ opts2 = optsOrUndefined ?? { via: "rpc" };
2438
2438
  if (!service2 || !fn) {
2439
2439
  throw new Error("job: service and fn are required for RPC jobs");
2440
2440
  }
2441
- if (opts.via !== "rpc") {
2441
+ if (opts2.via !== "rpc") {
2442
2442
  throw new Error("job: via must be 'rpc' when using (service, fn) form");
2443
2443
  }
2444
2444
  target2 = `${service2}/${fn}`;
2445
2445
  } else {
2446
2446
  target2 = serviceOrTarget;
2447
- opts = fnOrOpts;
2448
- if (opts.via === "rpc") {
2447
+ opts2 = fnOrOpts;
2448
+ if (opts2.via === "rpc") {
2449
2449
  throw new Error("job: use job(service, fn, opts) form for RPC jobs");
2450
2450
  }
2451
2451
  }
2452
- jobRegistrations.set(target2, { target: target2, opts });
2452
+ jobRegistrations.set(target2, { target: target2, opts: opts2 });
2453
2453
  if (isOnline) {
2454
2454
  await reconcileRegistrations(`job:${target2}`).catch((err) => {
2455
2455
  reportSDKError(`register-job:${target2}`, err);
2456
2456
  });
2457
2457
  } else {
2458
- enqueueOffline({ type: "job", target: target2, opts });
2458
+ enqueueOffline({ type: "job", target: target2, opts: opts2 });
2459
2459
  }
2460
2460
  return target2;
2461
2461
  },
2462
- async workflow(name, steps, opts) {
2463
- workflowRegistrations.set(name, { name, steps, opts });
2462
+ async workflow(name, steps, opts2) {
2463
+ workflowRegistrations.set(name, { name, steps, opts: opts2 });
2464
2464
  if (isOnline) {
2465
2465
  await reconcileRegistrations(`workflow:${name}`).catch((err) => {
2466
2466
  reportSDKError(`register-workflow:${name}`, err);
2467
2467
  });
2468
2468
  } else {
2469
- enqueueOffline({ type: "workflow", name, steps, opts });
2469
+ enqueueOffline({ type: "workflow", name, steps, opts: opts2 });
2470
2470
  }
2471
2471
  return name;
2472
2472
  },
2473
- async executeWorkflow(service2, name, input, opts) {
2473
+ async executeWorkflow(service2, name, input, opts2) {
2474
2474
  await _controlReady;
2475
2475
  const svc2 = service2.trim();
2476
2476
  const wfName = name.trim();
@@ -2510,14 +2510,14 @@ function servicebridge(url, serviceKey, serviceOrOpts = {}, maybeGlobalOpts = {}
2510
2510
  });
2511
2511
  });
2512
2512
  },
2513
- startHttpSpan(opts) {
2513
+ startHttpSpan(opts2) {
2514
2514
  const tc = traceStorage.getStore();
2515
- const traceId = opts.traceId ?? tc?.traceId ?? crypto.randomUUID();
2515
+ const traceId = opts2.traceId ?? tc?.traceId ?? crypto.randomUUID();
2516
2516
  const spanId = crypto.randomUUID();
2517
- const parentSpanId = opts.parentSpanId ?? tc?.spanId ?? "";
2518
- const fn = `${opts.method} ${opts.path}`;
2517
+ const parentSpanId = opts2.parentSpanId ?? tc?.spanId ?? "";
2518
+ const fn = `${opts2.method} ${opts2.path}`;
2519
2519
  const startedAt = Date.now();
2520
- const inputBuf = toJsonBuffer({ method: opts.method, path: opts.path });
2520
+ const inputBuf = toJsonBuffer({ method: opts2.method, path: opts2.path });
2521
2521
  reportCallStartAsync(traceId, spanId, parentSpanId, fn, startedAt, inputBuf, 1, "http");
2522
2522
  return {
2523
2523
  traceId,
@@ -2532,17 +2532,17 @@ function servicebridge(url, serviceKey, serviceOrOpts = {}, maybeGlobalOpts = {}
2532
2532
  }
2533
2533
  };
2534
2534
  },
2535
- async registerHttpEndpoint(opts) {
2535
+ async registerHttpEndpoint(opts2) {
2536
2536
  await _controlReady;
2537
2537
  if (serveState) {
2538
- const existing = httpRegistrations.get(`${opts.method}:${opts.route}`);
2538
+ const existing = httpRegistrations.get(`${opts2.method}:${opts2.route}`);
2539
2539
  if (!existing) {
2540
- httpRegistrations.set(`${opts.method}:${opts.route}`, {
2541
- method: opts.method,
2542
- route: opts.route,
2543
- allowedCallers: opts.allowedCallers,
2544
- requestSchemaJson: opts.requestSchemaJson,
2545
- responseSchemaJson: opts.responseSchemaJson
2540
+ httpRegistrations.set(`${opts2.method}:${opts2.route}`, {
2541
+ method: opts2.method,
2542
+ route: opts2.route,
2543
+ allowedCallers: opts2.allowedCallers,
2544
+ requestSchemaJson: opts2.requestSchemaJson,
2545
+ responseSchemaJson: opts2.responseSchemaJson
2546
2546
  });
2547
2547
  reconcileRegistrations("http-register").catch((err) => {
2548
2548
  reportSDKError("register-http-endpoint", err);
@@ -2550,9 +2550,9 @@ function servicebridge(url, serviceKey, serviceOrOpts = {}, maybeGlobalOpts = {}
2550
2550
  }
2551
2551
  }
2552
2552
  },
2553
- watchTrace(traceId, opts) {
2554
- const key = opts?.key ?? "";
2555
- const fromSeq = opts?.fromSequence ?? 0;
2553
+ watchTrace(traceId, opts2) {
2554
+ const key = opts2?.key ?? "";
2555
+ const fromSeq = opts2?.fromSequence ?? 0;
2556
2556
  const WATCH_TRACE_QUEUE_LIMIT = 256;
2557
2557
  const WATCH_TRACE_RETRY_MIN_MS = 500;
2558
2558
  const WATCH_TRACE_RETRY_MAX_MS = 5000;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "service-bridge",
3
- "version": "1.8.4-dev.45",
3
+ "version": "1.8.4-dev.46",
4
4
  "type": "module",
5
5
  "description": "ServiceBridge SDK for Node.js — one self-hosted runtime for RPC, events, workflows, and jobs without a service mesh or sidecars. Direct gRPC between workers; durable events, jobs, tracing, auto mTLS. One Go runtime + PostgreSQL.",
6
6
  "keywords": [