@richardmcquiston01/error-log-adapter 0.3.0 → 0.4.0
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.cjs +199 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +169 -1
- package/dist/index.d.ts +169 -1
- package/dist/index.mjs +195 -0
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -1
package/dist/index.cjs
CHANGED
|
@@ -22,19 +22,23 @@ var index_exports = {};
|
|
|
22
22
|
__export(index_exports, {
|
|
23
23
|
CompositeErrorAdapter: () => CompositeErrorAdapter,
|
|
24
24
|
ConsoleErrorAdapter: () => ConsoleErrorAdapter,
|
|
25
|
+
FirestoreErrorAdapter: () => FirestoreErrorAdapter,
|
|
25
26
|
FlatFileErrorAdapter: () => FlatFileErrorAdapter,
|
|
26
27
|
IndexedDbErrorAdapter: () => IndexedDbErrorAdapter,
|
|
27
28
|
JsonFileErrorAdapter: () => JsonFileErrorAdapter,
|
|
28
29
|
MongoDbErrorAdapter: () => MongoDbErrorAdapter,
|
|
29
30
|
MySqlErrorAdapter: () => MySqlErrorAdapter,
|
|
30
31
|
PostgresErrorAdapter: () => PostgresErrorAdapter,
|
|
32
|
+
RealtimeDatabaseErrorAdapter: () => RealtimeDatabaseErrorAdapter,
|
|
31
33
|
RedisErrorAdapter: () => RedisErrorAdapter,
|
|
32
34
|
S3ErrorAdapter: () => S3ErrorAdapter,
|
|
33
35
|
SqliteErrorAdapter: () => SqliteErrorAdapter,
|
|
36
|
+
SupabaseErrorAdapter: () => SupabaseErrorAdapter,
|
|
34
37
|
WebStorageErrorAdapter: () => WebStorageErrorAdapter,
|
|
35
38
|
WebhookErrorAdapter: () => WebhookErrorAdapter,
|
|
36
39
|
buildCreateErrorLogTableSql: () => buildCreateErrorLogTableSql,
|
|
37
40
|
buildErrorLogTableDdl: () => buildErrorLogTableDdl,
|
|
41
|
+
buildSupabaseSetupSql: () => buildSupabaseSetupSql,
|
|
38
42
|
createErrorLogStore: () => createErrorLogStore,
|
|
39
43
|
formatErrorLogLine: () => formatErrorLogLine,
|
|
40
44
|
serializeCause: () => serializeCause,
|
|
@@ -1029,23 +1033,218 @@ var S3ErrorAdapter = class {
|
|
|
1029
1033
|
};
|
|
1030
1034
|
}
|
|
1031
1035
|
};
|
|
1036
|
+
|
|
1037
|
+
// src/adapters/firebase-error-adapter.ts
|
|
1038
|
+
var DEFAULT_WRITE_TIMEOUT_MS = 1e4;
|
|
1039
|
+
function resolveTimeout(options, adapter) {
|
|
1040
|
+
const timeoutMs = options.timeoutMs ?? DEFAULT_WRITE_TIMEOUT_MS;
|
|
1041
|
+
if (Number.isNaN(timeoutMs) || timeoutMs <= 0) {
|
|
1042
|
+
throw new RangeError(
|
|
1043
|
+
`${adapter}: timeoutMs must be a positive number or Infinity, received ${String(options.timeoutMs)}.`
|
|
1044
|
+
);
|
|
1045
|
+
}
|
|
1046
|
+
return timeoutMs;
|
|
1047
|
+
}
|
|
1048
|
+
function waitForWrite(write, timeoutMs) {
|
|
1049
|
+
if (timeoutMs === Infinity) {
|
|
1050
|
+
return Promise.resolve(write);
|
|
1051
|
+
}
|
|
1052
|
+
return new Promise(
|
|
1053
|
+
(resolve, reject) => {
|
|
1054
|
+
const timer = setTimeout(() => {
|
|
1055
|
+
reject(
|
|
1056
|
+
new Error(
|
|
1057
|
+
`the write was not saved within ${timeoutMs} ms (the connection may be down; the SDK keeps the write queued and may still save it later)`
|
|
1058
|
+
)
|
|
1059
|
+
);
|
|
1060
|
+
}, timeoutMs);
|
|
1061
|
+
write.then(
|
|
1062
|
+
(value) => {
|
|
1063
|
+
clearTimeout(timer);
|
|
1064
|
+
resolve(value);
|
|
1065
|
+
},
|
|
1066
|
+
(reason) => {
|
|
1067
|
+
clearTimeout(timer);
|
|
1068
|
+
reject(reason);
|
|
1069
|
+
}
|
|
1070
|
+
);
|
|
1071
|
+
}
|
|
1072
|
+
);
|
|
1073
|
+
}
|
|
1074
|
+
function buildRecord(entry) {
|
|
1075
|
+
const serialized = serializeEntry(entry);
|
|
1076
|
+
const record = {
|
|
1077
|
+
id: crypto.randomUUID(),
|
|
1078
|
+
code: serialized.code,
|
|
1079
|
+
message: serialized.message,
|
|
1080
|
+
timestamp: serialized.timestamp
|
|
1081
|
+
};
|
|
1082
|
+
if (serialized.source !== void 0) {
|
|
1083
|
+
record.source = serialized.source;
|
|
1084
|
+
}
|
|
1085
|
+
if (serialized.cause !== void 0) {
|
|
1086
|
+
record.cause = JSON.stringify(serialized.cause);
|
|
1087
|
+
}
|
|
1088
|
+
return record;
|
|
1089
|
+
}
|
|
1090
|
+
var FirestoreErrorAdapter = class {
|
|
1091
|
+
/** @throws {RangeError} if `options.timeoutMs` is not a positive number or `Infinity`. */
|
|
1092
|
+
constructor(collection, options = {}) {
|
|
1093
|
+
this.collection = collection;
|
|
1094
|
+
this.prefix = options.prefix ?? "[error-log-adapter]";
|
|
1095
|
+
this.timeoutMs = resolveTimeout(options, "FirestoreErrorAdapter");
|
|
1096
|
+
}
|
|
1097
|
+
async log(entry) {
|
|
1098
|
+
try {
|
|
1099
|
+
const record = buildRecord(entry);
|
|
1100
|
+
await waitForWrite(
|
|
1101
|
+
this.collection.doc(record.id).set(record),
|
|
1102
|
+
this.timeoutMs
|
|
1103
|
+
);
|
|
1104
|
+
return { ok: true };
|
|
1105
|
+
} catch (error) {
|
|
1106
|
+
console.error(`${this.prefix} FirestoreErrorAdapter:`, error);
|
|
1107
|
+
return {
|
|
1108
|
+
ok: false,
|
|
1109
|
+
error: `FirestoreErrorAdapter failed to write the document: ${describeError(error)}`
|
|
1110
|
+
};
|
|
1111
|
+
}
|
|
1112
|
+
}
|
|
1113
|
+
};
|
|
1114
|
+
var RealtimeDatabaseErrorAdapter = class {
|
|
1115
|
+
/** @throws {RangeError} if `options.timeoutMs` is not a positive number or `Infinity`. */
|
|
1116
|
+
constructor(reference, options = {}) {
|
|
1117
|
+
this.reference = reference;
|
|
1118
|
+
this.prefix = options.prefix ?? "[error-log-adapter]";
|
|
1119
|
+
this.timeoutMs = resolveTimeout(options, "RealtimeDatabaseErrorAdapter");
|
|
1120
|
+
}
|
|
1121
|
+
async log(entry) {
|
|
1122
|
+
try {
|
|
1123
|
+
await waitForWrite(
|
|
1124
|
+
this.reference.push(buildRecord(entry)),
|
|
1125
|
+
this.timeoutMs
|
|
1126
|
+
);
|
|
1127
|
+
return { ok: true };
|
|
1128
|
+
} catch (error) {
|
|
1129
|
+
console.error(`${this.prefix} RealtimeDatabaseErrorAdapter:`, error);
|
|
1130
|
+
return {
|
|
1131
|
+
ok: false,
|
|
1132
|
+
error: `RealtimeDatabaseErrorAdapter failed to write the entry: ${describeError(error)}`
|
|
1133
|
+
};
|
|
1134
|
+
}
|
|
1135
|
+
}
|
|
1136
|
+
};
|
|
1137
|
+
|
|
1138
|
+
// src/adapters/supabase-error-adapter.ts
|
|
1139
|
+
var IDENTIFIER_PATTERN3 = /^[A-Za-z_][A-Za-z0-9_]*$/;
|
|
1140
|
+
function buildSupabaseSetupSql(tableName = DEFAULT_TABLE_NAME2, options = {}) {
|
|
1141
|
+
const insertRoles = options.insertRoles ?? [];
|
|
1142
|
+
for (const role of insertRoles) {
|
|
1143
|
+
if (!IDENTIFIER_PATTERN3.test(role)) {
|
|
1144
|
+
throw new RangeError(
|
|
1145
|
+
`buildSupabaseSetupSql: invalid role name "${role}". Use only letters, digits and underscores, and do not start with a digit.`
|
|
1146
|
+
);
|
|
1147
|
+
}
|
|
1148
|
+
}
|
|
1149
|
+
const statements = [
|
|
1150
|
+
...buildErrorLogTableDdl("postgres", tableName),
|
|
1151
|
+
`ALTER TABLE "${tableName}" ENABLE ROW LEVEL SECURITY`
|
|
1152
|
+
];
|
|
1153
|
+
if (insertRoles.length > 0) {
|
|
1154
|
+
const policy = `${tableName}_insert_only`;
|
|
1155
|
+
statements.push(
|
|
1156
|
+
`DROP POLICY IF EXISTS "${policy}" ON "${tableName}"`,
|
|
1157
|
+
`CREATE POLICY "${policy}" ON "${tableName}" FOR INSERT TO ${insertRoles.map((role) => `"${role}"`).join(", ")} WITH CHECK (true)`
|
|
1158
|
+
);
|
|
1159
|
+
}
|
|
1160
|
+
return statements;
|
|
1161
|
+
}
|
|
1162
|
+
function describeSupabaseError(result) {
|
|
1163
|
+
const error = result.error ?? { message: "" };
|
|
1164
|
+
const parts = [];
|
|
1165
|
+
if (error.message) {
|
|
1166
|
+
parts.push(error.message);
|
|
1167
|
+
} else if (result.status) {
|
|
1168
|
+
parts.push(
|
|
1169
|
+
`HTTP ${result.status}${result.statusText ? ` ${result.statusText}` : ""} with no error message (a 404 usually means the table does not exist or is not exposed by the API)`
|
|
1170
|
+
);
|
|
1171
|
+
} else {
|
|
1172
|
+
parts.push("unknown error with no message");
|
|
1173
|
+
}
|
|
1174
|
+
if (error.code) {
|
|
1175
|
+
parts.push(`code ${error.code}`);
|
|
1176
|
+
}
|
|
1177
|
+
const detailsLine = (error.details ?? "").split("\n")[0].trim();
|
|
1178
|
+
if (detailsLine && detailsLine !== error.message) {
|
|
1179
|
+
parts.push(`details: ${detailsLine}`);
|
|
1180
|
+
}
|
|
1181
|
+
if (error.hint) {
|
|
1182
|
+
parts.push(`hint: ${error.hint}`);
|
|
1183
|
+
}
|
|
1184
|
+
return parts.join("; ");
|
|
1185
|
+
}
|
|
1186
|
+
var SupabaseErrorAdapter = class {
|
|
1187
|
+
/** @throws {RangeError} if `options.tableName` is empty. */
|
|
1188
|
+
constructor(client, options = {}) {
|
|
1189
|
+
this.client = client;
|
|
1190
|
+
this.tableName = options.tableName ?? DEFAULT_TABLE_NAME2;
|
|
1191
|
+
if (this.tableName.trim() === "") {
|
|
1192
|
+
throw new RangeError(
|
|
1193
|
+
"SupabaseErrorAdapter: tableName must not be empty."
|
|
1194
|
+
);
|
|
1195
|
+
}
|
|
1196
|
+
this.prefix = options.prefix ?? "[error-log-adapter]";
|
|
1197
|
+
}
|
|
1198
|
+
async log(entry) {
|
|
1199
|
+
try {
|
|
1200
|
+
const serialized = serializeEntry(entry);
|
|
1201
|
+
const row = {
|
|
1202
|
+
id: crypto.randomUUID(),
|
|
1203
|
+
code: serialized.code,
|
|
1204
|
+
message: serialized.message,
|
|
1205
|
+
cause: serialized.cause === void 0 ? null : serialized.cause,
|
|
1206
|
+
source: serialized.source ?? null,
|
|
1207
|
+
occurred_at: serialized.timestamp
|
|
1208
|
+
};
|
|
1209
|
+
const result = await this.client.from(this.tableName).insert(row);
|
|
1210
|
+
if (result.error) {
|
|
1211
|
+
console.error(`${this.prefix} SupabaseErrorAdapter:`, result);
|
|
1212
|
+
return this.fail(describeSupabaseError(result));
|
|
1213
|
+
}
|
|
1214
|
+
return { ok: true };
|
|
1215
|
+
} catch (error) {
|
|
1216
|
+
console.error(`${this.prefix} SupabaseErrorAdapter:`, error);
|
|
1217
|
+
return this.fail(describeError(error));
|
|
1218
|
+
}
|
|
1219
|
+
}
|
|
1220
|
+
fail(reason) {
|
|
1221
|
+
return {
|
|
1222
|
+
ok: false,
|
|
1223
|
+
error: `SupabaseErrorAdapter failed to insert into table "${this.tableName}": ${reason}`
|
|
1224
|
+
};
|
|
1225
|
+
}
|
|
1226
|
+
};
|
|
1032
1227
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1033
1228
|
0 && (module.exports = {
|
|
1034
1229
|
CompositeErrorAdapter,
|
|
1035
1230
|
ConsoleErrorAdapter,
|
|
1231
|
+
FirestoreErrorAdapter,
|
|
1036
1232
|
FlatFileErrorAdapter,
|
|
1037
1233
|
IndexedDbErrorAdapter,
|
|
1038
1234
|
JsonFileErrorAdapter,
|
|
1039
1235
|
MongoDbErrorAdapter,
|
|
1040
1236
|
MySqlErrorAdapter,
|
|
1041
1237
|
PostgresErrorAdapter,
|
|
1238
|
+
RealtimeDatabaseErrorAdapter,
|
|
1042
1239
|
RedisErrorAdapter,
|
|
1043
1240
|
S3ErrorAdapter,
|
|
1044
1241
|
SqliteErrorAdapter,
|
|
1242
|
+
SupabaseErrorAdapter,
|
|
1045
1243
|
WebStorageErrorAdapter,
|
|
1046
1244
|
WebhookErrorAdapter,
|
|
1047
1245
|
buildCreateErrorLogTableSql,
|
|
1048
1246
|
buildErrorLogTableDdl,
|
|
1247
|
+
buildSupabaseSetupSql,
|
|
1049
1248
|
createErrorLogStore,
|
|
1050
1249
|
formatErrorLogLine,
|
|
1051
1250
|
serializeCause,
|