@orkestrel/middleware 0.0.5 → 0.0.7

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.
@@ -34,25 +34,24 @@ export declare interface BearerOptions {
34
34
  * `context.state` once a token verifies.
35
35
  *
36
36
  * @remarks
37
- * `token` is optional-mutable: absent until `createBearer` runs, then
38
- * written in place the pattern every stateful battery's slice follows so a
37
+ * `token` is an optional readonly state contract: absent until
38
+ * `createBearer` runs, then installed on the request-owned state object. A
39
39
  * consumer intersects only the slices it mounts into its own `TState`.
40
40
  */
41
41
  export declare interface BearerState {
42
- token?: string;
42
+ readonly token?: string;
43
43
  }
44
44
 
45
45
  /**
46
46
  * The body state slice `createBody` stashes.
47
47
  *
48
48
  * @remarks
49
- * `body` holds the same value the cached `context.body()` resolved to
50
- * (`undefined` when the request declared no body, or a body `createBody`
51
- * did not reject) a mid-handler read without a second `context.body()`
52
- * await.
49
+ * `body` holds the same defined value the cached `context.body()` resolved
50
+ * to a mid-handler read without a second `context.body()` await. The
51
+ * property remains absent when the body resolves `undefined`.
53
52
  */
54
53
  export declare interface BodyState {
55
- body?: unknown;
54
+ readonly body?: unknown;
56
55
  }
57
56
 
58
57
  /**
@@ -147,9 +146,25 @@ export declare interface ClientInfo {
147
146
  * The client-facts state slice `createForwarded` stashes.
148
147
  */
149
148
  export declare interface ClientState {
150
- client?: ClientInfo;
149
+ readonly client?: ClientInfo;
151
150
  }
152
151
 
152
+ /**
153
+ * Compress bytes with the host-independent `CompressionStream` primitive.
154
+ *
155
+ * @param bytes - The uncompressed response bytes
156
+ * @param encoding - The negotiated actionable coding
157
+ * @returns The compressed bytes, or the original bytes when the platform
158
+ * stream unexpectedly has no readable body
159
+ *
160
+ * @example
161
+ * ```ts
162
+ * const bytes = new TextEncoder().encode('compress me')
163
+ * const compressed = await compressBytes(bytes, 'gzip')
164
+ * ```
165
+ */
166
+ export declare function compressBytes(bytes: Uint8Array<ArrayBuffer>, encoding: Exclude<Encoding, 'identity'>): Promise<Uint8Array<ArrayBuffer>>;
167
+
153
168
  /**
154
169
  * Options for `createCompression` — response-body compression.
155
170
  *
@@ -576,7 +591,7 @@ export declare interface CSRFOptions {
576
591
  * response exposes for a subsequent mutating request to submit back.
577
592
  */
578
593
  export declare interface CSRFState {
579
- csrf?: string;
594
+ readonly csrf?: string;
580
595
  }
581
596
 
582
597
  /**
@@ -835,7 +850,7 @@ export declare interface HeaderTransportOptions {
835
850
  * `identifier` option is enabled.
836
851
  */
837
852
  export declare interface IdentifierState {
838
- identifier?: string;
853
+ readonly identifier?: string;
839
854
  }
840
855
 
841
856
  /**
@@ -1114,7 +1129,7 @@ export declare interface MultipartFile {
1114
1129
  * cached body has nothing left to read.
1115
1130
  */
1116
1131
  export declare interface MultipartState {
1117
- multipart?: MultipartBody;
1132
+ readonly multipart?: MultipartBody;
1118
1133
  }
1119
1134
 
1120
1135
  /**
@@ -1312,17 +1327,19 @@ export declare class Session implements SessionInterface {
1312
1327
  }
1313
1328
 
1314
1329
  /**
1315
- * The `@orkestrel/database` column shape for a {@link SessionRow} table — pass
1316
- * as-is to `createDatabase({ tables: { sessions: sessionColumns } })` so an
1317
- * app declaring a durable session table never hand-writes the shape.
1330
+ * The `@orkestrel/database` column shape for a
1331
+ * {@link import('./types.js').SessionRow} table pass as-is to
1332
+ * `createDatabase({ tables: { sessions: sessionColumns } })` so an app
1333
+ * declaring a durable session table never hand-writes the shape.
1318
1334
  *
1319
1335
  * @remarks
1320
- * `lastSeen`/`createdAt` are `integerShape({ min: 0 })` — the table VALIDATES
1321
- * them as integers, so `DatabaseSessionStore`'s `now` clock must yield
1322
- * integer milliseconds (`Date.now()`, the implicit default `createSession`
1323
- * clock). A fractional clock (`performance.now()`) fails the write with a
1324
- * validation error; `MemorySessionStore` carries no such column shape and
1325
- * accepts a fractional clock without complaint.
1336
+ * `lastSeen`/`createdAt` are `integerShape({ min: 0 })` — the table validates
1337
+ * them as integers, so
1338
+ * {@link import('./stores/DatabaseSessionStore.js').DatabaseSessionStore}'s
1339
+ * `now` clock must yield integer milliseconds (`Date.now()`, the implicit
1340
+ * default `createSession` clock). A fractional clock (`performance.now()`)
1341
+ * fails the write with a validation error; `MemorySessionStore` carries no
1342
+ * such column shape and accepts a fractional clock without complaint.
1326
1343
  *
1327
1344
  * @example
1328
1345
  * ```ts
@@ -1449,8 +1466,8 @@ export declare interface SessionRow {
1449
1466
  * `control` is present whenever `session` is (the handle to act on it).
1450
1467
  */
1451
1468
  export declare interface SessionState {
1452
- session?: SessionInterface;
1453
- control?: SessionControlInterface;
1469
+ readonly session?: SessionInterface;
1470
+ readonly control?: SessionControlInterface;
1454
1471
  }
1455
1472
 
1456
1473
  /**
@@ -34,25 +34,24 @@ export declare interface BearerOptions {
34
34
  * `context.state` once a token verifies.
35
35
  *
36
36
  * @remarks
37
- * `token` is optional-mutable: absent until `createBearer` runs, then
38
- * written in place the pattern every stateful battery's slice follows so a
37
+ * `token` is an optional readonly state contract: absent until
38
+ * `createBearer` runs, then installed on the request-owned state object. A
39
39
  * consumer intersects only the slices it mounts into its own `TState`.
40
40
  */
41
41
  export declare interface BearerState {
42
- token?: string;
42
+ readonly token?: string;
43
43
  }
44
44
 
45
45
  /**
46
46
  * The body state slice `createBody` stashes.
47
47
  *
48
48
  * @remarks
49
- * `body` holds the same value the cached `context.body()` resolved to
50
- * (`undefined` when the request declared no body, or a body `createBody`
51
- * did not reject) a mid-handler read without a second `context.body()`
52
- * await.
49
+ * `body` holds the same defined value the cached `context.body()` resolved
50
+ * to a mid-handler read without a second `context.body()` await. The
51
+ * property remains absent when the body resolves `undefined`.
53
52
  */
54
53
  export declare interface BodyState {
55
- body?: unknown;
54
+ readonly body?: unknown;
56
55
  }
57
56
 
58
57
  /**
@@ -147,9 +146,25 @@ export declare interface ClientInfo {
147
146
  * The client-facts state slice `createForwarded` stashes.
148
147
  */
149
148
  export declare interface ClientState {
150
- client?: ClientInfo;
149
+ readonly client?: ClientInfo;
151
150
  }
152
151
 
152
+ /**
153
+ * Compress bytes with the host-independent `CompressionStream` primitive.
154
+ *
155
+ * @param bytes - The uncompressed response bytes
156
+ * @param encoding - The negotiated actionable coding
157
+ * @returns The compressed bytes, or the original bytes when the platform
158
+ * stream unexpectedly has no readable body
159
+ *
160
+ * @example
161
+ * ```ts
162
+ * const bytes = new TextEncoder().encode('compress me')
163
+ * const compressed = await compressBytes(bytes, 'gzip')
164
+ * ```
165
+ */
166
+ export declare function compressBytes(bytes: Uint8Array<ArrayBuffer>, encoding: Exclude<Encoding, 'identity'>): Promise<Uint8Array<ArrayBuffer>>;
167
+
153
168
  /**
154
169
  * Options for `createCompression` — response-body compression.
155
170
  *
@@ -576,7 +591,7 @@ export declare interface CSRFOptions {
576
591
  * response exposes for a subsequent mutating request to submit back.
577
592
  */
578
593
  export declare interface CSRFState {
579
- csrf?: string;
594
+ readonly csrf?: string;
580
595
  }
581
596
 
582
597
  /**
@@ -835,7 +850,7 @@ export declare interface HeaderTransportOptions {
835
850
  * `identifier` option is enabled.
836
851
  */
837
852
  export declare interface IdentifierState {
838
- identifier?: string;
853
+ readonly identifier?: string;
839
854
  }
840
855
 
841
856
  /**
@@ -1114,7 +1129,7 @@ export declare interface MultipartFile {
1114
1129
  * cached body has nothing left to read.
1115
1130
  */
1116
1131
  export declare interface MultipartState {
1117
- multipart?: MultipartBody;
1132
+ readonly multipart?: MultipartBody;
1118
1133
  }
1119
1134
 
1120
1135
  /**
@@ -1312,17 +1327,19 @@ export declare class Session implements SessionInterface {
1312
1327
  }
1313
1328
 
1314
1329
  /**
1315
- * The `@orkestrel/database` column shape for a {@link SessionRow} table — pass
1316
- * as-is to `createDatabase({ tables: { sessions: sessionColumns } })` so an
1317
- * app declaring a durable session table never hand-writes the shape.
1330
+ * The `@orkestrel/database` column shape for a
1331
+ * {@link import('./types.js').SessionRow} table pass as-is to
1332
+ * `createDatabase({ tables: { sessions: sessionColumns } })` so an app
1333
+ * declaring a durable session table never hand-writes the shape.
1318
1334
  *
1319
1335
  * @remarks
1320
- * `lastSeen`/`createdAt` are `integerShape({ min: 0 })` — the table VALIDATES
1321
- * them as integers, so `DatabaseSessionStore`'s `now` clock must yield
1322
- * integer milliseconds (`Date.now()`, the implicit default `createSession`
1323
- * clock). A fractional clock (`performance.now()`) fails the write with a
1324
- * validation error; `MemorySessionStore` carries no such column shape and
1325
- * accepts a fractional clock without complaint.
1336
+ * `lastSeen`/`createdAt` are `integerShape({ min: 0 })` — the table validates
1337
+ * them as integers, so
1338
+ * {@link import('./stores/DatabaseSessionStore.js').DatabaseSessionStore}'s
1339
+ * `now` clock must yield integer milliseconds (`Date.now()`, the implicit
1340
+ * default `createSession` clock). A fractional clock (`performance.now()`)
1341
+ * fails the write with a validation error; `MemorySessionStore` carries no
1342
+ * such column shape and accepts a fractional clock without complaint.
1326
1343
  *
1327
1344
  * @example
1328
1345
  * ```ts
@@ -1449,8 +1466,8 @@ export declare interface SessionRow {
1449
1466
  * `control` is present whenever `session` is (the handle to act on it).
1450
1467
  */
1451
1468
  export declare interface SessionState {
1452
- session?: SessionInterface;
1453
- control?: SessionControlInterface;
1469
+ readonly session?: SessionInterface;
1470
+ readonly control?: SessionControlInterface;
1454
1471
  }
1455
1472
 
1456
1473
  /**
@@ -305,6 +305,26 @@ function detectEncodings(candidates) {
305
305
  return supported;
306
306
  }
307
307
  /**
308
+ * Compress bytes with the host-independent `CompressionStream` primitive.
309
+ *
310
+ * @param bytes - The uncompressed response bytes
311
+ * @param encoding - The negotiated actionable coding
312
+ * @returns The compressed bytes, or the original bytes when the platform
313
+ * stream unexpectedly has no readable body
314
+ *
315
+ * @example
316
+ * ```ts
317
+ * const bytes = new TextEncoder().encode('compress me')
318
+ * const compressed = await compressBytes(bytes, 'gzip')
319
+ * ```
320
+ */
321
+ async function compressBytes(bytes, encoding) {
322
+ const source = new Response(bytes).body;
323
+ if (source === null) return bytes;
324
+ const compressed = await new Response(source.pipeThrough(new CompressionStream(encoding))).arrayBuffer();
325
+ return new Uint8Array(compressed);
326
+ }
327
+ /**
308
328
  * Whether a response is eligible for the compression/ETag buffering pipeline
309
329
  * (ruling J) — the shared cheap-skip predicate both batteries apply before
310
330
  * ever touching `response.arrayBuffer()`.
@@ -568,7 +588,7 @@ function isPreflight(method, headers) {
568
588
  * ```
569
589
  */
570
590
  function buildClientInfo(ip) {
571
- return { ip };
591
+ return { ...ip !== void 0 ? { ip } : {} };
572
592
  }
573
593
  /**
574
594
  * Constant-time string equality — `createCSRF`'s double-submit token
@@ -664,6 +684,34 @@ function restoreSession(value) {
664
684
  return session;
665
685
  }
666
686
  //#endregion
687
+ //#region src/core/shapers.ts
688
+ /**
689
+ * The `@orkestrel/database` column shape for a
690
+ * {@link import('./types.js').SessionRow} table — pass as-is to
691
+ * `createDatabase({ tables: { sessions: sessionColumns } })` so an app
692
+ * declaring a durable session table never hand-writes the shape.
693
+ *
694
+ * @remarks
695
+ * `lastSeen`/`createdAt` are `integerShape({ min: 0 })` — the table validates
696
+ * them as integers, so
697
+ * {@link import('./stores/DatabaseSessionStore.js').DatabaseSessionStore}'s
698
+ * `now` clock must yield integer milliseconds (`Date.now()`, the implicit
699
+ * default `createSession` clock). A fractional clock (`performance.now()`)
700
+ * fails the write with a validation error; `MemorySessionStore` carries no
701
+ * such column shape and accepts a fractional clock without complaint.
702
+ *
703
+ * @example
704
+ * ```ts
705
+ * const db = createDatabase({ driver, tables: { sessions: sessionColumns } })
706
+ * ```
707
+ */
708
+ var sessionColumns = {
709
+ id: stringShape(),
710
+ session: jsonShape(),
711
+ lastSeen: integerShape({ min: 0 }),
712
+ createdAt: integerShape({ min: 0 })
713
+ };
714
+ //#endregion
667
715
  //#region src/core/stores/MemorySessionStore.ts
668
716
  /**
669
717
  * The default in-process {@link SessionStoreInterface} — a `Map`-backed store
@@ -741,8 +789,8 @@ var MemorySessionStore = class {
741
789
  }
742
790
  #expired(entry, now) {
743
791
  return sessionExpired(entry, now, {
744
- ttl: this.#ttl,
745
- lifetime: this.#lifetime
792
+ ...this.#ttl !== void 0 ? { ttl: this.#ttl } : {},
793
+ ...this.#lifetime !== void 0 ? { lifetime: this.#lifetime } : {}
746
794
  });
747
795
  }
748
796
  #reserve(now) {
@@ -815,8 +863,8 @@ var DatabaseSessionStore = class {
815
863
  const row = await this.#table.get(id);
816
864
  if (row === void 0) return void 0;
817
865
  if (sessionExpired(row, now, {
818
- ttl: this.#ttl,
819
- lifetime: this.#lifetime
866
+ ...this.#ttl !== void 0 ? { ttl: this.#ttl } : {},
867
+ ...this.#lifetime !== void 0 ? { lifetime: this.#lifetime } : {}
820
868
  })) {
821
869
  await this.#table.remove(id);
822
870
  return;
@@ -931,18 +979,12 @@ function createCompression(options) {
931
979
  const threshold = options?.threshold ?? 1024;
932
980
  const encodings = detectEncodings(options?.encodings ?? DEFAULT_COMPRESSION_ENCODINGS);
933
981
  const filter = options?.filter;
934
- const compress = async (bytes, encoding) => {
935
- const source = new Response(bytes).body;
936
- if (source === null) return bytes;
937
- const compressed = await new Response(source.pipeThrough(new CompressionStream(encoding))).arrayBuffer();
938
- return new Uint8Array(compressed);
939
- };
940
982
  return async (request, context, next) => {
941
983
  return compressResponse(request, context, await next(), {
942
984
  threshold,
943
- filter,
985
+ ...filter !== void 0 ? { filter } : {},
944
986
  encodings,
945
- compress
987
+ compress: compressBytes
946
988
  });
947
989
  };
948
990
  }
@@ -988,7 +1030,7 @@ function createSecurity(options) {
988
1030
  if (identifierEnabled) {
989
1031
  const incoming = request.headers.get(DEFAULT_IDENTIFIER_HEADER);
990
1032
  identifier = trust && incoming !== null && isValidRequestId(incoming) ? incoming : crypto.randomUUID();
991
- context.state.identifier = identifier;
1033
+ Object.assign(context.state, { identifier });
992
1034
  }
993
1035
  const response = await next();
994
1036
  response.headers.set("x-content-type-options", "nosniff");
@@ -1121,7 +1163,7 @@ function createForwarded(options) {
1121
1163
  const trust = hasProxies ? { proxies: options.proxies } : { trusted: options.trusted };
1122
1164
  return async (request, context, next) => {
1123
1165
  const ip = resolveForwardedFor(request.headers.get("x-forwarded-for") ?? void 0, trust) ?? context.state.connection?.ip;
1124
- context.state.client = buildClientInfo(ip);
1166
+ Object.assign(context.state, { client: buildClientInfo(ip) });
1125
1167
  return next();
1126
1168
  };
1127
1169
  }
@@ -1195,7 +1237,7 @@ function createBearer(options) {
1195
1237
  }
1196
1238
  const verified = await verifyToken(candidate, secret);
1197
1239
  if (verified === void 0) throw new HTTPError(401, "invalid token");
1198
- context.state.token = verified;
1240
+ Object.assign(context.state, { token: verified });
1199
1241
  return next();
1200
1242
  };
1201
1243
  }
@@ -1224,20 +1266,14 @@ function createLimiter(options) {
1224
1266
  const max = options.max;
1225
1267
  const window = options.window;
1226
1268
  const capacity = options.capacity ?? 1e4;
1227
- const deriveKey = options.key ?? ((context) => resolveKey(context.state));
1269
+ const deriveKey = options.key;
1228
1270
  const message = options.message ?? "rate limit exceeded";
1229
1271
  const clock = options.clock ?? Date.now;
1230
1272
  const policy = options.policy ?? false;
1231
1273
  const evict = options.evict;
1232
- const notify = (evictedKey) => {
1233
- if (evict === void 0) return;
1234
- try {
1235
- evict(evictedKey);
1236
- } catch {}
1237
- };
1238
1274
  const buckets = /* @__PURE__ */ new Map();
1239
1275
  return async (request, context, next) => {
1240
- const key = deriveKey(context);
1276
+ const key = deriveKey === void 0 ? resolveKey(context.state) : deriveKey(context);
1241
1277
  const now = clock();
1242
1278
  let bucket = buckets.get(key);
1243
1279
  if (bucket === void 0) {
@@ -1245,13 +1281,15 @@ function createLimiter(options) {
1245
1281
  const oldest = buckets.keys().next().value;
1246
1282
  if (oldest !== void 0) {
1247
1283
  buckets.delete(oldest);
1248
- notify(oldest);
1284
+ if (evict !== void 0) try {
1285
+ evict(oldest);
1286
+ } catch {}
1249
1287
  }
1250
1288
  }
1251
1289
  bucket = {
1252
1290
  budget: createBudget({
1253
1291
  max,
1254
- consume: (value) => value
1292
+ consume: Number
1255
1293
  }),
1256
1294
  resetAt: now + window
1257
1295
  };
@@ -1305,7 +1343,7 @@ function createLimiter(options) {
1305
1343
  function createBody() {
1306
1344
  return async (request, context, next) => {
1307
1345
  const body = await context.body();
1308
- context.state.body = body;
1346
+ if (body !== void 0) Object.assign(context.state, { body });
1309
1347
  const contentType = request.headers.get("content-type");
1310
1348
  if (contentType !== null && contentType.toLowerCase().startsWith("application/json") && body === void 0) throw new HTTPError(400, "invalid json");
1311
1349
  return next();
@@ -1340,12 +1378,12 @@ function createSession(options) {
1340
1378
  const transport = options.transport;
1341
1379
  const clock = options.clock ?? Date.now;
1342
1380
  const store = options.store ?? new MemorySessionStore({
1343
- ttl: options.ttl,
1344
- lifetime: options.lifetime,
1345
- capacity: options.capacity,
1346
- evict: options.evict
1381
+ ...options.ttl !== void 0 ? { ttl: options.ttl } : {},
1382
+ ...options.lifetime !== void 0 ? { lifetime: options.lifetime } : {},
1383
+ ...options.capacity !== void 0 ? { capacity: options.capacity } : {},
1384
+ ...options.evict !== void 0 ? { evict: options.evict } : {}
1347
1385
  });
1348
- const create = options.create ?? ((id) => new Session(id));
1386
+ const create = options.create;
1349
1387
  const mint = options.mint;
1350
1388
  const requireSession = options.require ?? false;
1351
1389
  const ends = options.ends ?? false;
@@ -1362,18 +1400,19 @@ function createSession(options) {
1362
1400
  if (session === void 0) {
1363
1401
  if (mint !== void 0 ? await mint(context) : true) {
1364
1402
  const id = crypto.randomUUID();
1365
- session = create(id);
1403
+ session = create === void 0 ? new Session(id) : create(id);
1366
1404
  minted = true;
1367
1405
  } else if (requireSession) throw new HTTPError(404, "session required");
1368
1406
  }
1369
1407
  let destroyed = false;
1370
1408
  let regenerated;
1371
1409
  const activeSession = session;
1372
- if (activeSession !== void 0) {
1373
- const control = {
1410
+ if (activeSession !== void 0) Object.assign(context.state, {
1411
+ session: activeSession,
1412
+ control: {
1374
1413
  regenerate() {
1375
1414
  if (destroyed) return;
1376
- const newSession = create(crypto.randomUUID());
1415
+ const newSession = create === void 0 ? new Session(crypto.randomUUID()) : create(crypto.randomUUID());
1377
1416
  transferSessionData(activeSession, newSession);
1378
1417
  regenerated = newSession;
1379
1418
  },
@@ -1381,10 +1420,8 @@ function createSession(options) {
1381
1420
  destroyed = true;
1382
1421
  regenerated = void 0;
1383
1422
  }
1384
- };
1385
- context.state.session = activeSession;
1386
- context.state.control = control;
1387
- }
1423
+ }
1424
+ });
1388
1425
  const response = await next();
1389
1426
  if (activeSession !== void 0) if (destroyed) {
1390
1427
  await store.delete(activeSession.id);
@@ -1427,8 +1464,9 @@ function createCSRF(options) {
1427
1464
  const safe = options.safe ?? DEFAULT_CSRF_SAFE_METHODS;
1428
1465
  return async (request, context, next) => {
1429
1466
  if (safe.includes(context.method)) {
1430
- const token = await signToken(context.state.session?.id ?? crypto.randomUUID(), { secret });
1431
- context.state.csrf = token;
1467
+ const bound = context.state.session?.id ?? crypto.randomUUID();
1468
+ const token = await signToken(bound, { secret });
1469
+ Object.assign(context.state, { csrf: token });
1432
1470
  const response = await next();
1433
1471
  const secure = resolveSecure(void 0, context.state.connection?.encrypted ?? false);
1434
1472
  await writeSignedCookie(response.headers, cookieName, token, secret, {
@@ -1586,30 +1624,6 @@ function createMemorySessionStore(options) {
1586
1624
  return new MemorySessionStore(options);
1587
1625
  }
1588
1626
  /**
1589
- * The `@orkestrel/database` column shape for a {@link SessionRow} table — pass
1590
- * as-is to `createDatabase({ tables: { sessions: sessionColumns } })` so an
1591
- * app declaring a durable session table never hand-writes the shape.
1592
- *
1593
- * @remarks
1594
- * `lastSeen`/`createdAt` are `integerShape({ min: 0 })` — the table VALIDATES
1595
- * them as integers, so `DatabaseSessionStore`'s `now` clock must yield
1596
- * integer milliseconds (`Date.now()`, the implicit default `createSession`
1597
- * clock). A fractional clock (`performance.now()`) fails the write with a
1598
- * validation error; `MemorySessionStore` carries no such column shape and
1599
- * accepts a fractional clock without complaint.
1600
- *
1601
- * @example
1602
- * ```ts
1603
- * const db = createDatabase({ driver, tables: { sessions: sessionColumns } })
1604
- * ```
1605
- */
1606
- var sessionColumns = {
1607
- id: stringShape(),
1608
- session: jsonShape(),
1609
- lastSeen: integerShape({ min: 0 }),
1610
- createdAt: integerShape({ min: 0 })
1611
- };
1612
- /**
1613
1627
  * Create a {@link DatabaseSessionStore} as a {@link SessionStoreInterface} —
1614
1628
  * the durable counterpart to `createMemorySessionStore`, over a caller-opened
1615
1629
  * `@orkestrel/database` table (declare it with {@link sessionColumns}).
@@ -1634,6 +1648,6 @@ function createDatabaseSessionStore(table, is, options) {
1634
1648
  return new DatabaseSessionStore(table, is, options);
1635
1649
  }
1636
1650
  //#endregion
1637
- export { DEFAULT_BEARER_HEADER, DEFAULT_BEARER_SCHEME, DEFAULT_CLUSTER, DEFAULT_COEP, DEFAULT_COMPRESSION_ENCODINGS, DEFAULT_COMPRESSION_THRESHOLD, DEFAULT_COOP, DEFAULT_CORP, DEFAULT_CORS_HEADERS, DEFAULT_CORS_METHODS, DEFAULT_CSP, DEFAULT_CSRF_COOKIE, DEFAULT_CSRF_FIELD, DEFAULT_CSRF_HEADER, DEFAULT_CSRF_SAFE_METHODS, DEFAULT_DEADLINE_STATUS, DEFAULT_FRAME_OPTIONS, DEFAULT_HSTS, DEFAULT_IDENTIFIER_HEADER, DEFAULT_LIMITER_CAPACITY, DEFAULT_LIMITER_MESSAGE, DEFAULT_PERMISSIONS_POLICY, DEFAULT_REFERRER_POLICY, DEFAULT_SESSION_CAPACITY, DEFAULT_SESSION_COOKIE, DEFAULT_SESSION_HEADER, DatabaseSessionStore, MemorySessionStore, Session, buildClientInfo, buildRateLimitField, buildRateLimitPolicyField, buildRetryAfter, compressResponse, createBearer, createBody, createBoundary, createCSRF, createCompression, createCookieTransport, createCors, createDatabaseSessionStore, createDeadline, createETag, createForwarded, createHeaderTransport, createLimiter, createMemorySessionStore, createSecurity, createSession, createTelemetry, detectEncodings, equalsConstantTime, except, isBufferingIneligible, isCompressionNegotiated, isMultipartBody, isMultipartFile, isPreflight, isSession, isSessionControl, matchesTrustedEntry, only, rebuildResponse, resolveForwardedFor, resolveKey, resolveOptInHeader, restoreSession, sessionColumns, sessionExpired, snapshotSession, transferSessionData };
1651
+ export { DEFAULT_BEARER_HEADER, DEFAULT_BEARER_SCHEME, DEFAULT_CLUSTER, DEFAULT_COEP, DEFAULT_COMPRESSION_ENCODINGS, DEFAULT_COMPRESSION_THRESHOLD, DEFAULT_COOP, DEFAULT_CORP, DEFAULT_CORS_HEADERS, DEFAULT_CORS_METHODS, DEFAULT_CSP, DEFAULT_CSRF_COOKIE, DEFAULT_CSRF_FIELD, DEFAULT_CSRF_HEADER, DEFAULT_CSRF_SAFE_METHODS, DEFAULT_DEADLINE_STATUS, DEFAULT_FRAME_OPTIONS, DEFAULT_HSTS, DEFAULT_IDENTIFIER_HEADER, DEFAULT_LIMITER_CAPACITY, DEFAULT_LIMITER_MESSAGE, DEFAULT_PERMISSIONS_POLICY, DEFAULT_REFERRER_POLICY, DEFAULT_SESSION_CAPACITY, DEFAULT_SESSION_COOKIE, DEFAULT_SESSION_HEADER, DatabaseSessionStore, MemorySessionStore, Session, buildClientInfo, buildRateLimitField, buildRateLimitPolicyField, buildRetryAfter, compressBytes, compressResponse, createBearer, createBody, createBoundary, createCSRF, createCompression, createCookieTransport, createCors, createDatabaseSessionStore, createDeadline, createETag, createForwarded, createHeaderTransport, createLimiter, createMemorySessionStore, createSecurity, createSession, createTelemetry, detectEncodings, equalsConstantTime, except, isBufferingIneligible, isCompressionNegotiated, isMultipartBody, isMultipartFile, isPreflight, isSession, isSessionControl, matchesTrustedEntry, only, rebuildResponse, resolveForwardedFor, resolveKey, resolveOptInHeader, restoreSession, sessionColumns, sessionExpired, snapshotSession, transferSessionData };
1638
1652
 
1639
1653
  //# sourceMappingURL=index.js.map