@lunora/do 1.0.0-alpha.33 → 1.0.0-alpha.34
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
|
@@ -26,7 +26,7 @@ export { RLS_UNWRAP_SYMBOL, RlsRequiredError, guardWriter } from './packem_share
|
|
|
26
26
|
export { buildFtsMatch, ftsTableName, scoreDocument, stringifySearchText, tokenizeSearch } from './packem_shared/buildFtsMatch-BLEMawrp.mjs';
|
|
27
27
|
export { M as MIN_ADMIN_TOKEN_LENGTH, a as MIN_AUTH_SECRET_LENGTH, b as buildSecurityAudit } from './packem_shared/security-audit-CucgBice.mjs';
|
|
28
28
|
export { SESSION_DO_TTL_DEFAULT, SessionDO } from './packem_shared/SESSION_DO_TTL_DEFAULT-BnSKgVO4.mjs';
|
|
29
|
-
export { ROOT_DO_SIZE_WARN_BYTES, ROOT_SHARD_NAME, ShardDO } from './packem_shared/ROOT_DO_SIZE_WARN_BYTES-
|
|
29
|
+
export { ROOT_DO_SIZE_WARN_BYTES, ROOT_SHARD_NAME, ShardDO } from './packem_shared/ROOT_DO_SIZE_WARN_BYTES-B5c6kQIN.mjs';
|
|
30
30
|
export { SHARD_REGISTRY_DO_NAME, ShardRegistryDO } from './packem_shared/SHARD_REGISTRY_DO_NAME-D99roc-r.mjs';
|
|
31
31
|
export { MAX_SQL_ROWS, assertReadonly, runReadonlySql } from './packem_shared/MAX_SQL_ROWS-iFAA8FbD.mjs';
|
|
32
32
|
export { createSystemReader } from './packem_shared/createSystemReader-D12eNH13.mjs';
|
|
@@ -27,6 +27,30 @@ import { a as selectShapeMemberIds, s as selectShapeRows } from './ctx-db-shapes
|
|
|
27
27
|
|
|
28
28
|
const MAX_BATCH_ENTRIES = 500;
|
|
29
29
|
|
|
30
|
+
const BUFFER_LEVEL = {
|
|
31
|
+
debug: "debug",
|
|
32
|
+
error: "error",
|
|
33
|
+
fatal: "error",
|
|
34
|
+
info: "info",
|
|
35
|
+
log: "info",
|
|
36
|
+
trace: "debug",
|
|
37
|
+
warn: "warn"
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
const HEX_ONLY = /^[0-9a-f]+$/;
|
|
41
|
+
const parseTraceparent = (header) => {
|
|
42
|
+
if (header === null || header === void 0) {
|
|
43
|
+
return void 0;
|
|
44
|
+
}
|
|
45
|
+
const parts = header.trim().toLowerCase().split("-");
|
|
46
|
+
const [version, traceId, parentSpanId, flags] = parts;
|
|
47
|
+
if (parts.length < 4 || version === void 0 || version.length !== 2 || !HEX_ONLY.test(version) || version === "ff" || // Version 00 forbids trailing fields; only a future version may carry them.
|
|
48
|
+
version === "00" && parts.length !== 4 || traceId === void 0 || parentSpanId === void 0 || flags === void 0 || flags.length !== 2 || !HEX_ONLY.test(flags) || traceId.length !== 32 || parentSpanId.length !== 16 || !HEX_ONLY.test(traceId) || !HEX_ONLY.test(parentSpanId) || traceId === "00000000000000000000000000000000" || parentSpanId === "0000000000000000") {
|
|
49
|
+
return void 0;
|
|
50
|
+
}
|
|
51
|
+
return { parentSpanId, traceId };
|
|
52
|
+
};
|
|
53
|
+
|
|
30
54
|
const evictOldestEntry = (map, capacity) => {
|
|
31
55
|
if (map.size < capacity) {
|
|
32
56
|
return;
|
|
@@ -1158,6 +1182,35 @@ const createRelayLink = (host) => {
|
|
|
1158
1182
|
return parsed === void 0 ? new OwnerRelay(host, name) : new RelayMember(host, parsed.ownerKey, parsed.relayIndex);
|
|
1159
1183
|
};
|
|
1160
1184
|
|
|
1185
|
+
const stringifyFieldValue = (value) => {
|
|
1186
|
+
if (typeof value === "string") {
|
|
1187
|
+
return value;
|
|
1188
|
+
}
|
|
1189
|
+
try {
|
|
1190
|
+
return JSON.stringify(value) ?? String(value);
|
|
1191
|
+
} catch {
|
|
1192
|
+
return String(value);
|
|
1193
|
+
}
|
|
1194
|
+
};
|
|
1195
|
+
const coerceFieldValue = (value) => typeof value === "boolean" || typeof value === "number" || typeof value === "string" ? value : stringifyFieldValue(value);
|
|
1196
|
+
const normalizeLogFields = (perCall, bound) => {
|
|
1197
|
+
if (perCall === void 0 && bound === void 0) {
|
|
1198
|
+
return void 0;
|
|
1199
|
+
}
|
|
1200
|
+
const merged = {};
|
|
1201
|
+
if (bound !== void 0) {
|
|
1202
|
+
for (const [key, value] of Object.entries(bound)) {
|
|
1203
|
+
merged[key] = coerceFieldValue(value);
|
|
1204
|
+
}
|
|
1205
|
+
}
|
|
1206
|
+
if (perCall !== void 0) {
|
|
1207
|
+
for (const [key, value] of Object.entries(perCall)) {
|
|
1208
|
+
merged[key] = coerceFieldValue(value);
|
|
1209
|
+
}
|
|
1210
|
+
}
|
|
1211
|
+
return Object.keys(merged).length === 0 ? void 0 : merged;
|
|
1212
|
+
};
|
|
1213
|
+
|
|
1161
1214
|
const REQUEST_LOG_TABLE = "__lunora_reqlog__";
|
|
1162
1215
|
const REQUEST_LOG_RETENTION = 1e3;
|
|
1163
1216
|
const REQUEST_LOG_EVENT_SOURCE = "lunora";
|
|
@@ -1271,18 +1324,40 @@ const renderLogMessage = (args) => args.map((value) => {
|
|
|
1271
1324
|
return String(value);
|
|
1272
1325
|
}
|
|
1273
1326
|
}).join(" ");
|
|
1327
|
+
const isLogFields = (value) => {
|
|
1328
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
1329
|
+
return false;
|
|
1330
|
+
}
|
|
1331
|
+
const proto = Object.getPrototypeOf(value);
|
|
1332
|
+
return proto === Object.prototype || proto === null;
|
|
1333
|
+
};
|
|
1334
|
+
const parseLogArgs = (args, boundFields) => {
|
|
1335
|
+
if (args.length === 2 && typeof args[0] === "string" && isLogFields(args[1])) {
|
|
1336
|
+
return { fields: normalizeLogFields(args[1], boundFields), message: args[0] };
|
|
1337
|
+
}
|
|
1338
|
+
return { fields: normalizeLogFields(void 0, boundFields), message: renderLogMessage(args) };
|
|
1339
|
+
};
|
|
1274
1340
|
const emitLogEvent = (input) => {
|
|
1275
|
-
const
|
|
1341
|
+
const payload = {
|
|
1342
|
+
fields: input.fields,
|
|
1276
1343
|
function: input.functionPath,
|
|
1277
1344
|
level: input.level,
|
|
1278
1345
|
message: input.message,
|
|
1279
1346
|
shard: input.shardKey,
|
|
1280
1347
|
source: REQUEST_LOG_EVENT_SOURCE,
|
|
1348
|
+
spanId: input.spanId,
|
|
1349
|
+
traceId: input.traceId,
|
|
1281
1350
|
ts: input.ts,
|
|
1282
1351
|
type: LOG_EVENT_TYPE,
|
|
1283
1352
|
userId: input.userId
|
|
1284
|
-
}
|
|
1285
|
-
|
|
1353
|
+
};
|
|
1354
|
+
let line;
|
|
1355
|
+
try {
|
|
1356
|
+
line = JSON.stringify(payload);
|
|
1357
|
+
} catch {
|
|
1358
|
+
line = JSON.stringify({ ...payload, fields: void 0 });
|
|
1359
|
+
}
|
|
1360
|
+
if (input.level === "error" || input.level === "fatal") {
|
|
1286
1361
|
console.error(line);
|
|
1287
1362
|
} else if (input.level === "warn") {
|
|
1288
1363
|
console.warn(line);
|
|
@@ -4082,28 +4157,55 @@ class ShardDO {
|
|
|
4082
4157
|
* Unlike request-log args, `ctx.log` args are NOT redacted: the developer
|
|
4083
4158
|
* chose to log them, exactly like a raw `console.log`.
|
|
4084
4159
|
*/
|
|
4085
|
-
recordUserLog(functionPath, level, args, sink) {
|
|
4160
|
+
recordUserLog(functionPath, level, args, message, fields, sink) {
|
|
4161
|
+
const trace = parseTraceparent(this.getCurrentTraceparent());
|
|
4086
4162
|
const event = {
|
|
4087
4163
|
args,
|
|
4164
|
+
fields,
|
|
4088
4165
|
functionPath,
|
|
4089
4166
|
level,
|
|
4090
|
-
message
|
|
4167
|
+
message,
|
|
4091
4168
|
shardKey: this.state.id?.name,
|
|
4169
|
+
spanId: trace?.parentSpanId,
|
|
4170
|
+
traceId: trace?.traceId,
|
|
4092
4171
|
ts: Date.now(),
|
|
4093
4172
|
userId: this.getCurrentUserId()
|
|
4094
4173
|
};
|
|
4095
|
-
this.logs.push({ functionPath, level: level
|
|
4174
|
+
this.logs.push({ fields, functionPath, level: BUFFER_LEVEL[level], message, timestamp: event.ts });
|
|
4096
4175
|
try {
|
|
4097
4176
|
emitLogEvent(event);
|
|
4098
4177
|
} catch {
|
|
4099
4178
|
}
|
|
4100
4179
|
if (sink?.onLog) {
|
|
4101
4180
|
try {
|
|
4102
|
-
sink.onLog(event);
|
|
4181
|
+
sink.onLog(event, { waitUntil: this.state.waitUntil?.bind(this.state) });
|
|
4103
4182
|
} catch {
|
|
4104
4183
|
}
|
|
4105
4184
|
}
|
|
4106
4185
|
}
|
|
4186
|
+
/**
|
|
4187
|
+
* Build the `ctx.log` logger for one dispatched function. Each severity method
|
|
4188
|
+
* accepts either the structured form (`(message, fields)`) or console-style
|
|
4189
|
+
* varargs (see {@link parseLogArgs}); `with(fields)` returns a child that
|
|
4190
|
+
* stamps `fields` onto every line. The generated `buildCtx` calls this once
|
|
4191
|
+
* per dispatch and assigns the result to `ctx.log`.
|
|
4192
|
+
*/
|
|
4193
|
+
makeLogger(functionPath, sink, boundFields) {
|
|
4194
|
+
const emit = (level, args) => {
|
|
4195
|
+
const { fields, message } = parseLogArgs(args, boundFields);
|
|
4196
|
+
this.recordUserLog(functionPath, level, args, message, fields, sink);
|
|
4197
|
+
};
|
|
4198
|
+
return {
|
|
4199
|
+
debug: (...args) => emit("debug", args),
|
|
4200
|
+
error: (...args) => emit("error", args),
|
|
4201
|
+
fatal: (...args) => emit("fatal", args),
|
|
4202
|
+
info: (...args) => emit("info", args),
|
|
4203
|
+
log: (...args) => emit("log", args),
|
|
4204
|
+
trace: (...args) => emit("trace", args),
|
|
4205
|
+
warn: (...args) => emit("warn", args),
|
|
4206
|
+
with: (fields) => this.makeLogger(functionPath, sink, boundFields ? { ...boundFields, ...fields } : fields)
|
|
4207
|
+
};
|
|
4208
|
+
}
|
|
4107
4209
|
/**
|
|
4108
4210
|
* Assemble the per-socket {@link LifecycleDispatchInfo} from its attachment:
|
|
4109
4211
|
* the verified identity to replay and the {@link LifecycleEvent} the hooks
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lunora/do",
|
|
3
|
-
"version": "1.0.0-alpha.
|
|
3
|
+
"version": "1.0.0-alpha.34",
|
|
4
4
|
"description": "Lunora Durable Objects: ShardDO (SQLite, OCC, hibernated WebSocket subscriptions) and SessionDO",
|
|
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.
|
|
49
|
+
"@lunora/errors": "1.0.0-alpha.6",
|
|
50
50
|
"@lunora/fingerprint": "1.0.0-alpha.3",
|
|
51
51
|
"@visulima/redact": "3.0.0",
|
|
52
52
|
"drizzle-orm": "^0.45.2"
|