@lunora/runtime 1.0.0-alpha.28 → 1.0.0-alpha.29

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/dist/index.mjs CHANGED
@@ -1,10 +1,10 @@
1
1
  export { toAirbyteMessages, toFivetranResponse } from './packem_shared/toAirbyteMessages-DrHdplb4.mjs';
2
- export { composeWorker, createLunoraHandler, createWorker, defineRpcEnvelope, resolveLunoraOptions, withFrameworkWorker } from './packem_shared/composeWorker-B6Pzfwhg.mjs';
2
+ export { composeWorker, createLunoraHandler, createWorker, defineRpcEnvelope, resolveLunoraOptions, withFrameworkWorker } from './packem_shared/composeWorker-Br4_GgSW.mjs';
3
3
  export { createCrossShardRelationCapabilities } from './packem_shared/createCrossShardRelationCapabilities-CbcWjkAn.mjs';
4
4
  export { DEFAULT_REGISTRY_CACHE_TTL_MS, SHARD_REGISTRY_DO_NAME, createDynamicShardRegistry } from './packem_shared/DEFAULT_REGISTRY_CACHE_TTL_MS-B3pA7aXp.mjs';
5
5
  export { LunoraError, toErrorResponse } from './packem_shared/LunoraError-Bpb9EFJ3.mjs';
6
6
  export { emitLogEvent, emitRpcEvent } from './packem_shared/emitLogEvent-pEdtqAK8.mjs';
7
- export { analyticsEngineSink, combineSinks, consoleSink, otlpSink, sentrySink, webhookSink } from './packem_shared/analyticsEngineSink-F-5ZAdUA.mjs';
7
+ export { analyticsEngineSink, combineSinks, consoleSink, otlpSink, pipelineLogSink, sentrySink, webhookSink } from './packem_shared/analyticsEngineSink-DKZvbDFG.mjs';
8
8
  export { createQueryCoordinator, createStaticShardRegistry, mergeStrategyForAggregate } from './packem_shared/createQueryCoordinator-DNCJzOZE.mjs';
9
9
  export { applyJurisdiction, resolveShard } from './packem_shared/applyJurisdiction-BkZtTkct.mjs';
10
10
  export { decorateResponse, enforceOrigin, handleCorsPreflight, resolveSecurity } from './packem_shared/decorateResponse-DRWQFNhF.mjs';
@@ -1,4 +1,16 @@
1
- import { m as mergeHeaders, o as otlpRandomHex, w as wrapResourceSpans, a as wrapResourceLogs, e as encodeAttribute, O as OTLP_SEVERITY, c as otlpUnixNano } from './otlp-D_YzGXu1.mjs';
1
+ import { m as mergeHeaders, o as otlpRandomHex, w as wrapResourceSpans, e as encodeAttribute, a as wrapResourceLogs, O as OTLP_SEVERITY, c as otlpUnixNano } from './otlp-0FQT3AI8.mjs';
2
+
3
+ const stringifyFieldValue = (value) => {
4
+ if (typeof value === "string") {
5
+ return value;
6
+ }
7
+ try {
8
+ return JSON.stringify(value) ?? String(value);
9
+ } catch {
10
+ return String(value);
11
+ }
12
+ };
13
+ const coerceFieldValue = (value) => typeof value === "boolean" || typeof value === "number" || typeof value === "string" ? value : stringifyFieldValue(value);
2
14
 
3
15
  const shouldSkip = (event, onlyErrors) => onlyErrors === true && event.ok;
4
16
  const otlpTraceBody = (event, serviceName, endMs) => {
@@ -33,20 +45,32 @@ const otlpTraceBody = (event, serviceName, endMs) => {
33
45
  return wrapResourceSpans(span, "@lunora/runtime", serviceName);
34
46
  };
35
47
  const otlpLogBody = (event, serviceName) => {
36
- const attributes = [encodeAttribute("lunora.function_path", event.functionPath)];
48
+ const attributeByKey = /* @__PURE__ */ new Map();
49
+ attributeByKey.set("lunora.function_path", encodeAttribute("lunora.function_path", event.functionPath));
37
50
  if (event.shardKey !== void 0) {
38
- attributes.push(encodeAttribute("lunora.shard_key", event.shardKey));
51
+ attributeByKey.set("lunora.shard_key", encodeAttribute("lunora.shard_key", event.shardKey));
39
52
  }
40
53
  if (event.userId !== void 0) {
41
- attributes.push(encodeAttribute("lunora.user_id", event.userId));
54
+ attributeByKey.set("lunora.user_id", encodeAttribute("lunora.user_id", event.userId));
55
+ }
56
+ if (event.fields) {
57
+ for (const [key, value] of Object.entries(event.fields)) {
58
+ attributeByKey.set(key, encodeAttribute(key, coerceFieldValue(value)));
59
+ }
42
60
  }
43
61
  const logRecord = {
44
- attributes,
62
+ attributes: [...attributeByKey.values()],
45
63
  body: { stringValue: event.message },
46
64
  severityNumber: OTLP_SEVERITY[event.level],
47
65
  severityText: event.level.toUpperCase(),
48
66
  timeUnixNano: otlpUnixNano(event.ts)
49
67
  };
68
+ if (event.traceId !== void 0) {
69
+ logRecord.traceId = event.traceId;
70
+ }
71
+ if (event.spanId !== void 0) {
72
+ logRecord.spanId = event.spanId;
73
+ }
50
74
  return wrapResourceLogs(logRecord, "@lunora/runtime", serviceName);
51
75
  };
52
76
  const otlpPost = (url, body, headers, context) => {
@@ -63,7 +87,7 @@ const consoleSink = (options = {}) => {
63
87
  const { onlyErrors } = options;
64
88
  return {
65
89
  onLog: (event) => {
66
- if (event.level === "error") {
90
+ if (event.level === "error" || event.level === "fatal") {
67
91
  console.error("[lunora:log]", event.functionPath, event.message);
68
92
  } else {
69
93
  console.log("[lunora:log]", event.functionPath, event.message);
@@ -82,9 +106,33 @@ const consoleSink = (options = {}) => {
82
106
  };
83
107
  };
84
108
  const webhookSink = (options) => {
85
- const { headers, onlyErrors, transform, url } = options;
109
+ const { headers, onlyErrors, transform, transformLog, url } = options;
86
110
  const mergedHeaders = mergeHeaders({ "content-type": "application/json" }, headers);
111
+ const post = (payload, context) => {
112
+ try {
113
+ const sent = fetch(url, { body: JSON.stringify(payload), headers: mergedHeaders, method: "POST" }).catch(() => {
114
+ });
115
+ if (context?.waitUntil) {
116
+ context.waitUntil(sent);
117
+ }
118
+ } catch {
119
+ }
120
+ };
87
121
  return {
122
+ onLog: (event, context) => {
123
+ let payload = event;
124
+ if (transformLog) {
125
+ try {
126
+ payload = transformLog(event);
127
+ } catch {
128
+ return;
129
+ }
130
+ }
131
+ if (payload === null || payload === void 0) {
132
+ return;
133
+ }
134
+ post(payload, context);
135
+ },
88
136
  onRpc: (event, context) => {
89
137
  if (shouldSkip(event, onlyErrors)) {
90
138
  return;
@@ -101,24 +149,24 @@ const webhookSink = (options) => {
101
149
  if (payload === null || payload === void 0) {
102
150
  return;
103
151
  }
104
- const sent = fetch(url, {
105
- body: JSON.stringify(payload),
106
- headers: mergedHeaders,
107
- method: "POST"
108
- }).catch(() => {
109
- });
110
- if (context?.waitUntil) {
111
- context.waitUntil(sent);
112
- }
152
+ post(payload, context);
113
153
  } catch {
114
154
  }
115
155
  }
116
156
  };
117
157
  };
118
158
  const sentrySink = (options) => {
119
- const { capture } = options;
159
+ const { capture, captureLog } = options;
120
160
  const onlyErrors = options.onlyErrors ?? true;
121
161
  return {
162
+ // Only forward log lines when the caller wired `captureLog`; otherwise
163
+ // `ctx.log` output stays out of Sentry.
164
+ onLog: captureLog ? (event) => {
165
+ try {
166
+ captureLog(event);
167
+ } catch {
168
+ }
169
+ } : void 0,
122
170
  onRpc: (event) => {
123
171
  if (shouldSkip(event, onlyErrors)) {
124
172
  return;
@@ -148,6 +196,42 @@ const analyticsEngineSink = (options) => {
148
196
  }
149
197
  };
150
198
  };
199
+ const pipelineLogSink = (options) => {
200
+ const { pipeline } = options;
201
+ return {
202
+ onLog: (event, context) => {
203
+ try {
204
+ const record = {
205
+ functionPath: event.functionPath,
206
+ level: event.level,
207
+ message: event.message,
208
+ ts: event.ts
209
+ };
210
+ if (event.fields) {
211
+ record.fields = event.fields;
212
+ }
213
+ if (event.shardKey !== void 0) {
214
+ record.shardKey = event.shardKey;
215
+ }
216
+ if (event.userId !== void 0) {
217
+ record.userId = event.userId;
218
+ }
219
+ if (event.traceId !== void 0) {
220
+ record.traceId = event.traceId;
221
+ }
222
+ if (event.spanId !== void 0) {
223
+ record.spanId = event.spanId;
224
+ }
225
+ const sent = pipeline.send([record]).catch(() => {
226
+ });
227
+ if (context?.waitUntil) {
228
+ context.waitUntil(sent);
229
+ }
230
+ } catch {
231
+ }
232
+ }
233
+ };
234
+ };
151
235
  const otlpSink = (options) => {
152
236
  const { endpoint, headers, onlyErrors, token } = options;
153
237
  const serviceName = options.serviceName ?? "lunora";
@@ -197,4 +281,4 @@ const combineSinks = (...sinks) => {
197
281
  };
198
282
  };
199
283
 
200
- export { analyticsEngineSink, combineSinks, consoleSink, otlpSink, sentrySink, webhookSink };
284
+ export { analyticsEngineSink, combineSinks, consoleSink, otlpSink, pipelineLogSink, sentrySink, webhookSink };
@@ -1,6 +1,6 @@
1
1
  import { isLunoraError, toErrorBody } from '@lunora/errors';
2
2
  import { NOOP_EXECUTION_CONTEXT } from './NOOP_EXECUTION_CONTEXT-CCTu0Bf1.mjs';
3
- import { o as otlpRandomHex, b as buildTraceparent } from './otlp-D_YzGXu1.mjs';
3
+ import { o as otlpRandomHex, b as buildTraceparent } from './otlp-0FQT3AI8.mjs';
4
4
  import { LunoraError, toErrorResponse } from './LunoraError-Bpb9EFJ3.mjs';
5
5
  import { wrapResolverWithContract } from './composeIdentityResolvers-XGjO7V1J.mjs';
6
6
  export { composeIdentityResolvers, routeIdentityResolvers } from './composeIdentityResolvers-XGjO7V1J.mjs';
@@ -3,10 +3,14 @@ const OTLP_SEVERITY = {
3
3
  // DEBUG
4
4
  error: 17,
5
5
  // ERROR
6
+ fatal: 21,
7
+ // FATAL
6
8
  info: 9,
7
9
  // INFO
8
10
  log: 9,
9
11
  // INFO
12
+ trace: 1,
13
+ // TRACE
10
14
  warn: 13
11
15
  // WARN
12
16
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lunora/runtime",
3
- "version": "1.0.0-alpha.28",
3
+ "version": "1.0.0-alpha.29",
4
4
  "description": "Lunora Worker runtime: the RPC router, shard resolver, and query coordinator",
5
5
  "keywords": [
6
6
  "cloudflare",
@@ -46,7 +46,7 @@
46
46
  "access": "public"
47
47
  },
48
48
  "dependencies": {
49
- "@lunora/errors": "1.0.0-alpha.5"
49
+ "@lunora/errors": "1.0.0-alpha.6"
50
50
  },
51
51
  "engines": {
52
52
  "node": "^22.15.0 || >=24.11.0"