easy-ping 0.8.1 → 0.10.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/README.md +17 -11
- package/dist/adapter-C3uFRpEN.d.cts +10 -0
- package/dist/adapter-DoCRPi9I.d.ts +10 -0
- package/dist/adapters/drizzle.cjs +6 -4
- package/dist/adapters/drizzle.cjs.map +1 -1
- package/dist/adapters/drizzle.js +7 -5
- package/dist/adapters/drizzle.js.map +1 -1
- package/dist/adapters/mongodb.cjs.map +1 -1
- package/dist/adapters/mongodb.d.cts +1 -1
- package/dist/adapters/mongodb.d.ts +1 -1
- package/dist/adapters/mongodb.js +1 -1
- package/dist/adapters/mysql.cjs +7 -4
- package/dist/adapters/mysql.cjs.map +1 -1
- package/dist/adapters/mysql.d.cts +4 -3
- package/dist/adapters/mysql.d.ts +4 -3
- package/dist/adapters/mysql.js +3 -3
- package/dist/adapters/postgres.cjs +3 -3
- package/dist/adapters/postgres.cjs.map +1 -1
- package/dist/adapters/postgres.d.cts +2 -2
- package/dist/adapters/postgres.d.ts +2 -2
- package/dist/adapters/postgres.js +7 -7
- package/dist/adapters/postgres.js.map +1 -1
- package/dist/adapters/sqlite.cjs +8 -5
- package/dist/adapters/sqlite.cjs.map +1 -1
- package/dist/adapters/sqlite.d.cts +4 -3
- package/dist/adapters/sqlite.d.ts +4 -3
- package/dist/adapters/sqlite.js +3 -3
- package/dist/chunk-A4HX5YTG.js +413 -0
- package/dist/chunk-A4HX5YTG.js.map +1 -0
- package/dist/{chunk-JOVIZXO6.js → chunk-CFLVAF2R.js} +20 -6
- package/dist/chunk-CFLVAF2R.js.map +1 -0
- package/dist/{chunk-2EYKPF5A.js → chunk-CMWOIYVQ.js} +3 -3
- package/dist/{chunk-2EYKPF5A.js.map → chunk-CMWOIYVQ.js.map} +1 -1
- package/dist/{chunk-HY47TQMY.js → chunk-HSB5T3LD.js} +11 -8
- package/dist/chunk-HSB5T3LD.js.map +1 -0
- package/dist/{chunk-E4IZ2CQC.js → chunk-JN3UCQBP.js} +2 -2
- package/dist/chunk-JN3UCQBP.js.map +1 -0
- package/dist/{chunk-3VOQOGDR.js → chunk-O2PBBL5X.js} +24 -6
- package/dist/chunk-O2PBBL5X.js.map +1 -0
- package/dist/{chunk-M4R77BJD.js → chunk-UM2L26PV.js} +10 -7
- package/dist/chunk-UM2L26PV.js.map +1 -0
- package/dist/dialect-CvBJSydR.d.cts +10 -0
- package/dist/dialect-CvBJSydR.d.ts +10 -0
- package/dist/index.cjs +74 -10
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +4 -2
- package/dist/index.d.ts +4 -2
- package/dist/index.js +39 -7
- package/dist/index.js.map +1 -1
- package/dist/node.cjs +14 -2
- package/dist/node.cjs.map +1 -1
- package/dist/node.js +15 -3
- package/dist/node.js.map +1 -1
- package/dist/{plugin-C4fikLl7.d.ts → plugin-Bp68CCnd.d.ts} +1 -0
- package/dist/{plugin-6S8tpH0n.d.cts → plugin-p4HS8yjS.d.cts} +1 -0
- package/dist/plugins/digests.cjs +19 -12
- package/dist/plugins/digests.cjs.map +1 -1
- package/dist/plugins/digests.d.cts +1 -1
- package/dist/plugins/digests.d.ts +1 -1
- package/dist/plugins/digests.js +5 -12
- package/dist/plugins/digests.js.map +1 -1
- package/dist/plugins/mobile-push.cjs +2 -1
- package/dist/plugins/mobile-push.cjs.map +1 -1
- package/dist/plugins/mobile-push.d.cts +1 -1
- package/dist/plugins/mobile-push.d.ts +1 -1
- package/dist/plugins/mobile-push.js +3 -2
- package/dist/plugins/mobile-push.js.map +1 -1
- package/dist/plugins/preferences-client.cjs.map +1 -1
- package/dist/plugins/preferences-client.d.cts +1 -1
- package/dist/plugins/preferences-client.d.ts +1 -1
- package/dist/plugins/preferences-client.js +1 -1
- package/dist/plugins/preferences.cjs.map +1 -1
- package/dist/plugins/preferences.d.cts +1 -1
- package/dist/plugins/preferences.d.ts +1 -1
- package/dist/plugins/preferences.js +1 -1
- package/dist/plugins/push.cjs.map +1 -1
- package/dist/plugins/push.d.cts +1 -1
- package/dist/plugins/push.d.ts +1 -1
- package/dist/plugins/push.js +1 -1
- package/dist/plugins/telegram.cjs +22 -1
- package/dist/plugins/telegram.cjs.map +1 -1
- package/dist/plugins/telegram.d.cts +1 -1
- package/dist/plugins/telegram.d.ts +1 -1
- package/dist/plugins/telegram.js +23 -2
- package/dist/plugins/telegram.js.map +1 -1
- package/dist/providers/expo-push.cjs +1 -1
- package/dist/providers/expo-push.cjs.map +1 -1
- package/dist/providers/expo-push.js +1 -1
- package/dist/providers/expo-push.js.map +1 -1
- package/dist/providers/web-push.cjs +3 -7
- package/dist/providers/web-push.cjs.map +1 -1
- package/dist/providers/web-push.d.cts +1 -1
- package/dist/providers/web-push.d.ts +1 -1
- package/dist/providers/web-push.js +3 -7
- package/dist/providers/web-push.js.map +1 -1
- package/dist/react-native.cjs +20 -2
- package/dist/react-native.cjs.map +1 -1
- package/dist/react-native.js +20 -2
- package/dist/react-native.js.map +1 -1
- package/dist/react.cjs +20 -2
- package/dist/react.cjs.map +1 -1
- package/dist/react.js +20 -2
- package/dist/react.js.map +1 -1
- package/dist/schema.cjs +336 -123
- package/dist/schema.cjs.map +1 -1
- package/dist/schema.d.cts +28 -2
- package/dist/schema.d.ts +28 -2
- package/dist/schema.js +3 -3
- package/package.json +1 -1
- package/dist/adapter-B7R4rXtJ.d.cts +0 -17
- package/dist/adapter-B7R4rXtJ.d.ts +0 -17
- package/dist/chunk-3VOQOGDR.js.map +0 -1
- package/dist/chunk-E4IZ2CQC.js.map +0 -1
- package/dist/chunk-HY47TQMY.js.map +0 -1
- package/dist/chunk-JOVIZXO6.js.map +0 -1
- package/dist/chunk-M4R77BJD.js.map +0 -1
- package/dist/chunk-XIDVLYNQ.js +0 -209
- package/dist/chunk-XIDVLYNQ.js.map +0 -1
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
type Row = Record<string, unknown>;
|
|
2
|
+
type SqlResult = {
|
|
3
|
+
rows: readonly Row[];
|
|
4
|
+
/** Rows an INSERT/UPDATE/DELETE touched; drivers without RETURNING report through this. */
|
|
5
|
+
affectedRows: number;
|
|
6
|
+
};
|
|
7
|
+
/** The whole driver contract for the MySQL and SQLite adapters. */
|
|
8
|
+
type SqlExec = (text: string, params: readonly unknown[]) => Promise<SqlResult>;
|
|
9
|
+
|
|
10
|
+
export type { SqlExec as S, SqlResult as a };
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
type Row = Record<string, unknown>;
|
|
2
|
+
type SqlResult = {
|
|
3
|
+
rows: readonly Row[];
|
|
4
|
+
/** Rows an INSERT/UPDATE/DELETE touched; drivers without RETURNING report through this. */
|
|
5
|
+
affectedRows: number;
|
|
6
|
+
};
|
|
7
|
+
/** The whole driver contract for the MySQL and SQLite adapters. */
|
|
8
|
+
type SqlExec = (text: string, params: readonly unknown[]) => Promise<SqlResult>;
|
|
9
|
+
|
|
10
|
+
export type { SqlExec as S, SqlResult as a };
|
package/dist/index.cjs
CHANGED
|
@@ -209,6 +209,7 @@ function createScopedSigner(secret, pluginId, purposes, onViolation) {
|
|
|
209
209
|
var STREAM_HIGH_WATER_MARK = 256;
|
|
210
210
|
var MAX_BODY_BYTES = 64 * 1024;
|
|
211
211
|
var MAX_READ_IDS = 200;
|
|
212
|
+
var SESSION_ERROR = /* @__PURE__ */ Symbol("session-error");
|
|
212
213
|
var PRIVATE_HEADERS = {
|
|
213
214
|
"cache-control": "private, no-store",
|
|
214
215
|
"x-content-type-options": "nosniff"
|
|
@@ -308,13 +309,26 @@ function csrfCheck(request, url, trusted) {
|
|
|
308
309
|
function createHandler(deps) {
|
|
309
310
|
const trustedOrigins = deps.trustedOrigins ?? [];
|
|
310
311
|
const maxBodyBytes = deps.maxBodyBytes ?? MAX_BODY_BYTES;
|
|
312
|
+
let warnedBadUserId = false;
|
|
311
313
|
async function resolveUserId(request) {
|
|
314
|
+
let id;
|
|
312
315
|
try {
|
|
313
|
-
|
|
316
|
+
id = await deps.session.getUserId(request);
|
|
314
317
|
} catch (error) {
|
|
315
318
|
deps.logger.error("session.getUserId threw", { error });
|
|
316
|
-
return
|
|
319
|
+
return SESSION_ERROR;
|
|
317
320
|
}
|
|
321
|
+
if (id === null || id === void 0) return null;
|
|
322
|
+
if (typeof id !== "string" || id === "") {
|
|
323
|
+
if (!warnedBadUserId) {
|
|
324
|
+
warnedBadUserId = true;
|
|
325
|
+
deps.logger.warn(
|
|
326
|
+
`session.getUserId returned ${id === "" ? "an empty string" : typeof id}; treating the request as unauthenticated. Return a non-empty string or null.`
|
|
327
|
+
);
|
|
328
|
+
}
|
|
329
|
+
return null;
|
|
330
|
+
}
|
|
331
|
+
return id;
|
|
318
332
|
}
|
|
319
333
|
async function bearerMatches(request, secret) {
|
|
320
334
|
if (!secret) return false;
|
|
@@ -337,7 +351,7 @@ function createHandler(deps) {
|
|
|
337
351
|
if (rejected) return rejected;
|
|
338
352
|
}
|
|
339
353
|
const userId = await resolveUserId(request);
|
|
340
|
-
if (userId ===
|
|
354
|
+
if (userId === SESSION_ERROR) return empty(500);
|
|
341
355
|
if (userId === null) return empty(401);
|
|
342
356
|
return harden(await route2.handler({ request, userId, claims: null, params: {} }));
|
|
343
357
|
}
|
|
@@ -378,7 +392,7 @@ function createHandler(deps) {
|
|
|
378
392
|
if (rejected) return rejected;
|
|
379
393
|
}
|
|
380
394
|
const userId = await resolveUserId(request);
|
|
381
|
-
if (userId ===
|
|
395
|
+
if (userId === SESSION_ERROR) return empty(500);
|
|
382
396
|
if (userId === null) return empty(401);
|
|
383
397
|
if (request.method === "GET" && path === "/events") {
|
|
384
398
|
if (!deps.events) return empty(404);
|
|
@@ -582,12 +596,23 @@ var ESCAPES = {
|
|
|
582
596
|
var escapeHtml = (value) => String(value ?? "").replace(/[&<>"']/g, (char) => ESCAPES[char] ?? char);
|
|
583
597
|
|
|
584
598
|
// src/core/rate-limit.ts
|
|
599
|
+
var UNKEYED = "\0unkeyed";
|
|
585
600
|
var clientAddress = (request) => {
|
|
586
601
|
const headers = request.headers;
|
|
587
602
|
return headers.get("cf-connecting-ip") ?? headers.get("x-real-ip") ?? headers.get("x-forwarded-for")?.split(",")[0]?.trim() ?? null;
|
|
588
603
|
};
|
|
589
604
|
function createRateLimiter(config) {
|
|
590
|
-
|
|
605
|
+
let warned = false;
|
|
606
|
+
const keyOf = config.key ?? ((request) => {
|
|
607
|
+
const address = clientAddress(request);
|
|
608
|
+
if (address !== null) return address;
|
|
609
|
+
if (!warned) {
|
|
610
|
+
warned = true;
|
|
611
|
+
config.onUnkeyed?.();
|
|
612
|
+
}
|
|
613
|
+
return UNKEYED;
|
|
614
|
+
});
|
|
615
|
+
const maxKeys = Math.max(1, config.maxKeys ?? 1e4);
|
|
591
616
|
const buckets = /* @__PURE__ */ new Map();
|
|
592
617
|
let lastSweep = 0;
|
|
593
618
|
return (request) => {
|
|
@@ -600,7 +625,12 @@ function createRateLimiter(config) {
|
|
|
600
625
|
}
|
|
601
626
|
let bucket = buckets.get(key);
|
|
602
627
|
if (!bucket || bucket.resetAt <= now) {
|
|
628
|
+
if (!bucket && buckets.size >= maxKeys) {
|
|
629
|
+
const oldest = buckets.keys().next().value;
|
|
630
|
+
if (oldest !== void 0) buckets.delete(oldest);
|
|
631
|
+
}
|
|
603
632
|
bucket = { count: 0, resetAt: now + config.windowMs };
|
|
633
|
+
buckets.delete(key);
|
|
604
634
|
buckets.set(key, bucket);
|
|
605
635
|
}
|
|
606
636
|
bucket.count += 1;
|
|
@@ -1095,6 +1125,22 @@ function createPluginStore(pluginId, schema, storage, prefix) {
|
|
|
1095
1125
|
}
|
|
1096
1126
|
return declaration;
|
|
1097
1127
|
}
|
|
1128
|
+
function writable(table) {
|
|
1129
|
+
const declaration = resolve(table);
|
|
1130
|
+
if (declaration.readOnly) {
|
|
1131
|
+
throw new ConfigError(
|
|
1132
|
+
`plugin "${pluginId}" tried to write "${table}", which it declares readOnly.`
|
|
1133
|
+
);
|
|
1134
|
+
}
|
|
1135
|
+
return declaration;
|
|
1136
|
+
}
|
|
1137
|
+
function notEverything(table, where, action) {
|
|
1138
|
+
if (Object.keys(where).length === 0) {
|
|
1139
|
+
throw new ConfigError(
|
|
1140
|
+
`plugin "${pluginId}" called ${action}("${table}", {}), which would touch every row. Pass a condition.`
|
|
1141
|
+
);
|
|
1142
|
+
}
|
|
1143
|
+
}
|
|
1098
1144
|
function checkFields(table, fields, context) {
|
|
1099
1145
|
for (const field of fields) {
|
|
1100
1146
|
const spec = Object.hasOwn(table.fields, field) ? table.fields[field] : void 0;
|
|
@@ -1153,7 +1199,7 @@ function createPluginStore(pluginId, schema, storage, prefix) {
|
|
|
1153
1199
|
});
|
|
1154
1200
|
},
|
|
1155
1201
|
async insert(table, rows) {
|
|
1156
|
-
const declaration =
|
|
1202
|
+
const declaration = writable(table);
|
|
1157
1203
|
for (const row of rows) checkRow(declaration, row, "insert");
|
|
1158
1204
|
return storage.insertRows(
|
|
1159
1205
|
qualified(declaration),
|
|
@@ -1161,7 +1207,7 @@ function createPluginStore(pluginId, schema, storage, prefix) {
|
|
|
1161
1207
|
);
|
|
1162
1208
|
},
|
|
1163
1209
|
async upsert(table, rows, options) {
|
|
1164
|
-
const declaration =
|
|
1210
|
+
const declaration = writable(table);
|
|
1165
1211
|
for (const row of rows) checkRow(declaration, row, "upsert");
|
|
1166
1212
|
checkFields(declaration, options.onConflict, "onConflict");
|
|
1167
1213
|
return storage.insertRows(
|
|
@@ -1171,14 +1217,16 @@ function createPluginStore(pluginId, schema, storage, prefix) {
|
|
|
1171
1217
|
);
|
|
1172
1218
|
},
|
|
1173
1219
|
async update(table, where, set) {
|
|
1174
|
-
const declaration =
|
|
1220
|
+
const declaration = writable(table);
|
|
1175
1221
|
checkWhere(declaration, where);
|
|
1222
|
+
notEverything(table, where, "update");
|
|
1176
1223
|
checkRow(declaration, set, "update");
|
|
1177
1224
|
return storage.updateRows(qualified(declaration), where, serialize(declaration, set));
|
|
1178
1225
|
},
|
|
1179
1226
|
async remove(table, where) {
|
|
1180
|
-
const declaration =
|
|
1227
|
+
const declaration = writable(table);
|
|
1181
1228
|
checkWhere(declaration, where);
|
|
1229
|
+
notEverything(table, where, "remove");
|
|
1182
1230
|
return storage.deleteRows(qualified(declaration), where);
|
|
1183
1231
|
}
|
|
1184
1232
|
};
|
|
@@ -1257,7 +1305,18 @@ function validate(config, plugins) {
|
|
|
1257
1305
|
}
|
|
1258
1306
|
}
|
|
1259
1307
|
}
|
|
1308
|
+
const core = new Set(CORE_ROUTES.map((route) => `${route.method} ${route.path}`));
|
|
1260
1309
|
const routes = /* @__PURE__ */ new Set();
|
|
1310
|
+
for (const plugin of plugins) {
|
|
1311
|
+
for (const route of plugin.routes ?? []) {
|
|
1312
|
+
const signature = `${route.method} ${route.path}`;
|
|
1313
|
+
if (core.has(signature)) {
|
|
1314
|
+
throw new ConfigError(
|
|
1315
|
+
`plugin "${plugin.id}" registers "${signature}", which is a core route. Pick another path.`
|
|
1316
|
+
);
|
|
1317
|
+
}
|
|
1318
|
+
}
|
|
1319
|
+
}
|
|
1261
1320
|
for (const plugin of plugins) {
|
|
1262
1321
|
for (const route of plugin.routes ?? []) {
|
|
1263
1322
|
const signature = `${route.method} ${route.path}`;
|
|
@@ -1374,7 +1433,12 @@ function easyPing(config) {
|
|
|
1374
1433
|
trustedOrigins: config.trustedOrigins,
|
|
1375
1434
|
onRequest: config.onRequest,
|
|
1376
1435
|
maxBodyBytes: config.maxBodyBytes,
|
|
1377
|
-
rateLimit: config.rateLimit ? createRateLimiter(
|
|
1436
|
+
rateLimit: config.rateLimit ? createRateLimiter({
|
|
1437
|
+
onUnkeyed: () => logger.warn(
|
|
1438
|
+
"rateLimit: a request arrived with no cf-connecting-ip, x-real-ip or x-forwarded-for header, so every such request shares one bucket. Put the app behind a proxy that sets one of them, or pass rateLimit.key (a session or API key)."
|
|
1439
|
+
),
|
|
1440
|
+
...config.rateLimit
|
|
1441
|
+
}) : void 0,
|
|
1378
1442
|
cronMaxSweeps: config.cron?.maxSweeps,
|
|
1379
1443
|
...config.cron?.secret ? { cronSecret: config.cron.secret } : {},
|
|
1380
1444
|
...config.machineSecret ?? config.cron?.secret ? { machineSecret: config.machineSecret ?? config.cron?.secret } : {}
|