tempest-express-sdk 0.10.0 → 0.20.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 +10 -7
- package/dist/chunk-2OYRCWG5.js +106 -0
- package/dist/chunk-2OYRCWG5.js.map +1 -0
- package/dist/cli.cjs +157 -10
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +72 -11
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +1925 -49
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1705 -10
- package/dist/index.d.ts +1705 -10
- package/dist/index.js +1828 -136
- package/dist/index.js.map +1 -1
- package/package.json +5 -1
- package/dist/chunk-U3SXT3KR.js +0 -6
- package/dist/chunk-U3SXT3KR.js.map +0 -1
package/dist/index.d.cts
CHANGED
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
export { z } from 'zod';
|
|
3
3
|
import * as tempest_db_js from 'tempest-db-js';
|
|
4
|
-
import { Model, ModelClass, BaseRepository,
|
|
4
|
+
import { Model, ModelClass, BaseRepository, WhereInput, InferModel, InferInsert, PaginationFilter as PaginationFilter$1, PaginationResult, AsyncDriver, AsyncEngine, AsyncSession } from 'tempest-db-js';
|
|
5
5
|
export { AsyncDriver, AsyncEngine, AsyncResult, AsyncSession, BaseRepository, BelongsTo, ColType, Column, ColumnFlags, CompiledQuery, CondNode, Condition, DeleteBuilder, DeleteNode, Dialect, EngineOptions, Executable, HasMany, InferInsert, InferModel, InsertBuilder, InsertNode, Model, ModelClass, NoResultError, NodeSqliteDriver, Operator, OrderTerm, PaginationResult, ParsedDatabaseUrl, PostgresDialect, QueryNode, RecordNotFound, Relation, RelationValue, PaginationFilter as RepositoryPaginationFilter, Returning, RowOf, SelectBuilder, SelectNode, SortDirection, SqliteDialect, SyncEngine, SyncSession, UpdateBuilder, UpdateNode, WhereArg, WhereInput, WithRelations, and, belongsTo, column, columnsOf, createEngine, createSyncEngine, del, detectDialect, getDialect, hasMany, insert, join, loadRelations, not, or, parseDatabaseUrl, select, sql, update } from 'tempest-db-js';
|
|
6
|
-
import { Request,
|
|
6
|
+
import { Request, Response as Response$1, RequestHandler, Router, ErrorRequestHandler, Express } from 'express';
|
|
7
7
|
import * as ws from 'ws';
|
|
8
8
|
import { Server } from 'node:http';
|
|
9
|
+
import { Readable } from 'node:stream';
|
|
9
10
|
import { OpenAPIRegistry } from '@asteasolutions/zod-to-openapi';
|
|
10
11
|
export { OpenAPIRegistry } from '@asteasolutions/zod-to-openapi';
|
|
12
|
+
import { BinaryLike } from 'node:crypto';
|
|
11
13
|
|
|
12
14
|
/**
|
|
13
15
|
* Request-scoped context propagation via `AsyncLocalStorage`.
|
|
@@ -57,6 +59,17 @@ declare const HTTP_500_MARKER = "http_500";
|
|
|
57
59
|
type LogLevel = "debug" | "info" | "warning" | "error";
|
|
58
60
|
/** Free-form structured context merged into the emitted record. */
|
|
59
61
|
type LogExtra = Record<string, unknown>;
|
|
62
|
+
/** A sink receiving every emitted record (for file routing, shipping, …). */
|
|
63
|
+
type LogSink = (level: LogLevel, record: Record<string, unknown>) => void;
|
|
64
|
+
/**
|
|
65
|
+
* Register a sink invoked for every record every {@link JSONLogger} emits (in
|
|
66
|
+
* addition to the stdout/stderr line). Used by `configureFileLogging` to route
|
|
67
|
+
* records into per-level + `500.log` files.
|
|
68
|
+
*
|
|
69
|
+
* @param sink - The sink callback. Errors thrown by it are swallowed.
|
|
70
|
+
* @returns A function that removes the sink.
|
|
71
|
+
*/
|
|
72
|
+
declare function addLogSink(sink: LogSink): () => void;
|
|
60
73
|
/** A minimal structured logger writing one JSON line per record. */
|
|
61
74
|
declare class JSONLogger {
|
|
62
75
|
private readonly name;
|
|
@@ -487,6 +500,173 @@ declare function encodeCursor(payload: Record<string, unknown>): string;
|
|
|
487
500
|
*/
|
|
488
501
|
declare function decodeCursor(cursor: string): Record<string, unknown>;
|
|
489
502
|
|
|
503
|
+
/**
|
|
504
|
+
* Ready-made, validated Zod field types, mirroring `utils.fields`.
|
|
505
|
+
*
|
|
506
|
+
* Reusable building blocks for DTOs so you don't re-derive the same constraint
|
|
507
|
+
* everywhere: money in cents, a price string, a percentage, a latitude, a slug,
|
|
508
|
+
* a hex color. Compose them into schemas with `z.object({ price: priceField })`.
|
|
509
|
+
*/
|
|
510
|
+
|
|
511
|
+
/** A strictly positive integer (`> 0`). */
|
|
512
|
+
declare const positiveIntField: z.ZodNumber;
|
|
513
|
+
/** A non-negative integer (`>= 0`). */
|
|
514
|
+
declare const nonNegativeIntField: z.ZodNumber;
|
|
515
|
+
/** A monetary amount in the smallest unit (cents), `>= 0`. Avoids float drift. */
|
|
516
|
+
declare const centsField: z.ZodNumber;
|
|
517
|
+
/** A TCP port (`1..65535`). */
|
|
518
|
+
declare const portField: z.ZodNumber;
|
|
519
|
+
/** A 0–5 star rating. */
|
|
520
|
+
declare const ratingField: z.ZodNumber;
|
|
521
|
+
/** A strictly positive float (`> 0`). */
|
|
522
|
+
declare const positiveFloatField: z.ZodNumber;
|
|
523
|
+
/** A non-negative float (`>= 0`). */
|
|
524
|
+
declare const nonNegativeFloatField: z.ZodNumber;
|
|
525
|
+
/** A percentage (`0..100`). */
|
|
526
|
+
declare const percentField: z.ZodNumber;
|
|
527
|
+
/** A ratio (`0..1`). */
|
|
528
|
+
declare const ratioField: z.ZodNumber;
|
|
529
|
+
/** A WGS-84 latitude (`-90..90`). */
|
|
530
|
+
declare const latitudeField: z.ZodNumber;
|
|
531
|
+
/** A WGS-84 longitude (`-180..180`). */
|
|
532
|
+
declare const longitudeField: z.ZodNumber;
|
|
533
|
+
/** A non-empty string; whitespace is trimmed before the length check. */
|
|
534
|
+
declare const nonEmptyStrField: z.ZodPipeline<z.ZodEffects<z.ZodString, string, string>, z.ZodString>;
|
|
535
|
+
/** A URL slug: lowercase alphanumerics separated by single hyphens. */
|
|
536
|
+
declare const slugField: z.ZodString;
|
|
537
|
+
/** A hex color: `#rgb` or `#rrggbb`. */
|
|
538
|
+
declare const hexColorField: z.ZodString;
|
|
539
|
+
/**
|
|
540
|
+
* A money amount as an exact decimal **string** with up to two decimal places
|
|
541
|
+
* (e.g. `"19.90"`). Mirrors `PriceField` — `tempest-db-js` `numeric` columns map
|
|
542
|
+
* to strings, so money stays exact instead of drifting through a float.
|
|
543
|
+
*/
|
|
544
|
+
declare const priceField: z.ZodString;
|
|
545
|
+
|
|
546
|
+
/**
|
|
547
|
+
* Delta-sync pagination schemas, mirroring `schemas.pagination` (Sync* half).
|
|
548
|
+
*
|
|
549
|
+
* For offline-first clients that pull "everything changed since my last sync".
|
|
550
|
+
* The client sends the `serverTime` from the previous page back as `since`;
|
|
551
|
+
* using the **server** clock as the watermark avoids clock-skew gaps.
|
|
552
|
+
*/
|
|
553
|
+
|
|
554
|
+
/**
|
|
555
|
+
* Filter schema for a delta-sync pull. Extend with `.extend` to add domain
|
|
556
|
+
* filters; the sync keys stay reserved.
|
|
557
|
+
*/
|
|
558
|
+
declare const syncFilterSchema: z.ZodObject<{
|
|
559
|
+
since: z.ZodOptional<z.ZodDate>;
|
|
560
|
+
cursor: z.ZodOptional<z.ZodString>;
|
|
561
|
+
limit: z.ZodDefault<z.ZodNumber>;
|
|
562
|
+
includeDeleted: z.ZodDefault<z.ZodBoolean>;
|
|
563
|
+
}, "strip", z.ZodTypeAny, {
|
|
564
|
+
limit: number;
|
|
565
|
+
includeDeleted: boolean;
|
|
566
|
+
cursor?: string | undefined;
|
|
567
|
+
since?: Date | undefined;
|
|
568
|
+
}, {
|
|
569
|
+
cursor?: string | undefined;
|
|
570
|
+
limit?: number | undefined;
|
|
571
|
+
since?: Date | undefined;
|
|
572
|
+
includeDeleted?: boolean | undefined;
|
|
573
|
+
}>;
|
|
574
|
+
/** The parsed shape of {@link syncFilterSchema}. */
|
|
575
|
+
type SyncFilter = z.infer<typeof syncFilterSchema>;
|
|
576
|
+
/**
|
|
577
|
+
* Build the delta-sync response envelope for a given item schema. Persist
|
|
578
|
+
* `serverTime` on the client and send it back as the next `since`.
|
|
579
|
+
*
|
|
580
|
+
* @param item - The zod schema for a single item.
|
|
581
|
+
* @returns A zod object `{ items, nextCursor, hasMore, limit, serverTime }`.
|
|
582
|
+
*/
|
|
583
|
+
declare function syncPaginationSchema<T extends z.ZodTypeAny>(item: T): z.ZodObject<{
|
|
584
|
+
items: z.ZodArray<T, "many">;
|
|
585
|
+
nextCursor: z.ZodNullable<z.ZodString>;
|
|
586
|
+
hasMore: z.ZodBoolean;
|
|
587
|
+
limit: z.ZodNumber;
|
|
588
|
+
serverTime: z.ZodDate;
|
|
589
|
+
}, "strip", z.ZodTypeAny, {
|
|
590
|
+
items: T["_output"][];
|
|
591
|
+
limit: number;
|
|
592
|
+
nextCursor: string | null;
|
|
593
|
+
hasMore: boolean;
|
|
594
|
+
serverTime: Date;
|
|
595
|
+
}, {
|
|
596
|
+
items: T["_input"][];
|
|
597
|
+
limit: number;
|
|
598
|
+
nextCursor: string | null;
|
|
599
|
+
hasMore: boolean;
|
|
600
|
+
serverTime: Date;
|
|
601
|
+
}>;
|
|
602
|
+
|
|
603
|
+
/**
|
|
604
|
+
* RFC-5988 pagination `Link` header builder, mirroring `schemas.link_headers`.
|
|
605
|
+
*
|
|
606
|
+
* Emits the `first` / `prev` / `next` / `last` rels GitHub-style clients expect.
|
|
607
|
+
* `prev`/`next` are omitted at the ends. Assign the result to
|
|
608
|
+
* `res.setHeader("Link", value)`.
|
|
609
|
+
*/
|
|
610
|
+
/** Options for {@link buildPaginationLinkHeader}. */
|
|
611
|
+
interface PaginationLinkOptions {
|
|
612
|
+
/** Absolute or relative collection URL; existing query params are preserved. */
|
|
613
|
+
baseUrl: string;
|
|
614
|
+
/** Current page (1-based). */
|
|
615
|
+
page: number;
|
|
616
|
+
/** Page size. */
|
|
617
|
+
pageSize: number;
|
|
618
|
+
/** Total number of pages. */
|
|
619
|
+
pages: number;
|
|
620
|
+
/** Extra query params to preserve on every link (filters, sort). */
|
|
621
|
+
extraParams?: Record<string, string>;
|
|
622
|
+
/** Query param name for the page index. Default `"page"`. */
|
|
623
|
+
pageParam?: string;
|
|
624
|
+
/** Query param name for the page size. Default `"pageSize"`. */
|
|
625
|
+
sizeParam?: string;
|
|
626
|
+
}
|
|
627
|
+
/**
|
|
628
|
+
* Build a `Link` header value for an offset-paginated collection.
|
|
629
|
+
*
|
|
630
|
+
* @param options - Base URL, current page, page size, total pages and param names.
|
|
631
|
+
* @returns The `Link` header value, or `""` when there's nothing to link (single page).
|
|
632
|
+
*/
|
|
633
|
+
declare function buildPaginationLinkHeader(options: PaginationLinkOptions): string;
|
|
634
|
+
|
|
635
|
+
/**
|
|
636
|
+
* `logEntrySchema` — the shape of one structured log record, mirroring
|
|
637
|
+
* `schemas.logs.LogEntrySchema`.
|
|
638
|
+
*
|
|
639
|
+
* Matches the JSON `JSONLogger` emits. It is intentionally open (`.passthrough()`)
|
|
640
|
+
* so arbitrary `extra` keys (`path`, `requestId`, `http_500`, …) survive instead
|
|
641
|
+
* of being dropped — useful when a logs endpoint parses and returns records.
|
|
642
|
+
*/
|
|
643
|
+
|
|
644
|
+
/** One structured log record; extra keys pass through unchanged. */
|
|
645
|
+
declare const logEntrySchema: z.ZodObject<{
|
|
646
|
+
timestamp: z.ZodString;
|
|
647
|
+
level: z.ZodString;
|
|
648
|
+
logger: z.ZodString;
|
|
649
|
+
message: z.ZodString;
|
|
650
|
+
requestId: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
651
|
+
stack: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
652
|
+
}, "passthrough", z.ZodTypeAny, z.objectOutputType<{
|
|
653
|
+
timestamp: z.ZodString;
|
|
654
|
+
level: z.ZodString;
|
|
655
|
+
logger: z.ZodString;
|
|
656
|
+
message: z.ZodString;
|
|
657
|
+
requestId: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
658
|
+
stack: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
659
|
+
}, z.ZodTypeAny, "passthrough">, z.objectInputType<{
|
|
660
|
+
timestamp: z.ZodString;
|
|
661
|
+
level: z.ZodString;
|
|
662
|
+
logger: z.ZodString;
|
|
663
|
+
message: z.ZodString;
|
|
664
|
+
requestId: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
665
|
+
stack: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
666
|
+
}, z.ZodTypeAny, "passthrough">>;
|
|
667
|
+
/** The parsed shape of {@link logEntrySchema} (plus any extra keys). */
|
|
668
|
+
type LogEntry = z.infer<typeof logEntrySchema>;
|
|
669
|
+
|
|
490
670
|
/**
|
|
491
671
|
* Environment-driven settings, mirroring `settings.base.BaseAppSettings`.
|
|
492
672
|
*
|
|
@@ -559,6 +739,155 @@ type BaseAppSettings = z.infer<typeof baseAppSettingsSchema>;
|
|
|
559
739
|
*/
|
|
560
740
|
declare function loadSettings<S extends z.ZodTypeAny>(schema: S, env?: NodeJS.ProcessEnv): Readonly<z.infer<S>>;
|
|
561
741
|
|
|
742
|
+
/**
|
|
743
|
+
* Composable settings fragments covering common service dependencies,
|
|
744
|
+
* mirroring `settings.mixins`.
|
|
745
|
+
*
|
|
746
|
+
* Each fragment is a plain object of zod fields keyed by the **environment
|
|
747
|
+
* variable name** (matched case-sensitively, no prefix), with the same defaults
|
|
748
|
+
* as the FastAPI SDK. Compose the ones a service needs onto
|
|
749
|
+
* {@link baseAppSettingsShape} and parse with {@link loadSettings}:
|
|
750
|
+
*
|
|
751
|
+
* ```ts
|
|
752
|
+
* import { baseAppSettingsShape, jwtSettingsShape, loadSettings, z } from "tempest-express-sdk";
|
|
753
|
+
*
|
|
754
|
+
* const settings = loadSettings(
|
|
755
|
+
* z.object({ ...baseAppSettingsShape, ...jwtSettingsShape }),
|
|
756
|
+
* );
|
|
757
|
+
* settings.JWT_SECRET; // typed
|
|
758
|
+
* ```
|
|
759
|
+
*
|
|
760
|
+
* Nothing here reads `process.env` on its own — `loadSettings` does, so the
|
|
761
|
+
* fragments stay pure and testable.
|
|
762
|
+
*/
|
|
763
|
+
|
|
764
|
+
/**
|
|
765
|
+
* Parse an environment string into a boolean. Unlike `z.coerce.boolean()`
|
|
766
|
+
* (which treats every non-empty string — including `"false"` — as `true`), this
|
|
767
|
+
* reads the usual truthy tokens and treats everything else as `false`.
|
|
768
|
+
*
|
|
769
|
+
* @param defaultValue - The value when the variable is absent.
|
|
770
|
+
* @returns A zod schema coercing `"true"`/`"1"`/`"yes"`/`"on"` to `true`.
|
|
771
|
+
*/
|
|
772
|
+
declare function envBoolean(defaultValue: boolean): z.ZodEffects<z.ZodDefault<z.ZodUnion<[z.ZodBoolean, z.ZodString]>>, boolean, string | boolean | undefined>;
|
|
773
|
+
/**
|
|
774
|
+
* Parse a comma-separated environment string into a trimmed, non-empty list.
|
|
775
|
+
*
|
|
776
|
+
* @param defaultValue - The default CSV string when the variable is absent.
|
|
777
|
+
* @returns A zod schema producing `string[]`.
|
|
778
|
+
*/
|
|
779
|
+
declare function envList(defaultValue?: string): z.ZodEffects<z.ZodDefault<z.ZodString>, string[], string | undefined>;
|
|
780
|
+
/** Structured logging configuration. */
|
|
781
|
+
declare const logSettingsShape: {
|
|
782
|
+
readonly LOG_LEVEL: z.ZodDefault<z.ZodEnum<["DEBUG", "INFO", "WARNING", "ERROR"]>>;
|
|
783
|
+
readonly LOG_JSON: z.ZodEffects<z.ZodDefault<z.ZodUnion<[z.ZodBoolean, z.ZodString]>>, boolean, string | boolean | undefined>;
|
|
784
|
+
readonly LOG_DIR: z.ZodDefault<z.ZodString>;
|
|
785
|
+
};
|
|
786
|
+
/** Redis connection settings (cache / sessions / SSE broker). */
|
|
787
|
+
declare const redisSettingsShape: {
|
|
788
|
+
readonly REDIS_URL: z.ZodDefault<z.ZodString>;
|
|
789
|
+
};
|
|
790
|
+
/** RabbitMQ connection settings (queue broker). */
|
|
791
|
+
declare const rabbitmqSettingsShape: {
|
|
792
|
+
readonly RABBITMQ_URL: z.ZodDefault<z.ZodString>;
|
|
793
|
+
readonly RABBITMQ_PREFETCH_COUNT: z.ZodDefault<z.ZodNumber>;
|
|
794
|
+
};
|
|
795
|
+
/** JWT signing/verification settings. */
|
|
796
|
+
declare const jwtSettingsShape: {
|
|
797
|
+
readonly JWT_SECRET: z.ZodDefault<z.ZodString>;
|
|
798
|
+
readonly JWT_ALGORITHM: z.ZodDefault<z.ZodString>;
|
|
799
|
+
readonly JWT_ACCESS_TTL_SECONDS: z.ZodDefault<z.ZodNumber>;
|
|
800
|
+
readonly JWT_REFRESH_TTL_SECONDS: z.ZodDefault<z.ZodNumber>;
|
|
801
|
+
readonly JWT_ISSUER: z.ZodOptional<z.ZodString>;
|
|
802
|
+
};
|
|
803
|
+
/** Opaque shared-secret token settings (`X-Token` guards). */
|
|
804
|
+
declare const tokenSettingsShape: {
|
|
805
|
+
readonly TOKEN_SECRET: z.ZodDefault<z.ZodString>;
|
|
806
|
+
};
|
|
807
|
+
/** SMTP email transport settings. */
|
|
808
|
+
declare const emailSettingsShape: {
|
|
809
|
+
readonly SMTP_HOST: z.ZodDefault<z.ZodString>;
|
|
810
|
+
readonly SMTP_PORT: z.ZodDefault<z.ZodNumber>;
|
|
811
|
+
readonly SMTP_USERNAME: z.ZodOptional<z.ZodString>;
|
|
812
|
+
readonly SMTP_PASSWORD: z.ZodOptional<z.ZodString>;
|
|
813
|
+
readonly SMTP_FROM_ADDR: z.ZodDefault<z.ZodString>;
|
|
814
|
+
readonly SMTP_USE_TLS: z.ZodEffects<z.ZodDefault<z.ZodUnion<[z.ZodBoolean, z.ZodString]>>, boolean, string | boolean | undefined>;
|
|
815
|
+
readonly SMTP_USE_SSL: z.ZodEffects<z.ZodDefault<z.ZodUnion<[z.ZodBoolean, z.ZodString]>>, boolean, string | boolean | undefined>;
|
|
816
|
+
readonly SMTP_TIMEOUT_SECONDS: z.ZodDefault<z.ZodNumber>;
|
|
817
|
+
};
|
|
818
|
+
/** Local upload storage settings. */
|
|
819
|
+
declare const uploadSettingsShape: {
|
|
820
|
+
readonly UPLOAD_DIR: z.ZodDefault<z.ZodString>;
|
|
821
|
+
readonly UPLOAD_MAX_SIZE_BYTES: z.ZodDefault<z.ZodNumber>;
|
|
822
|
+
readonly UPLOAD_ALLOWED_EXTENSIONS: z.ZodEffects<z.ZodDefault<z.ZodString>, string[], string | undefined>;
|
|
823
|
+
readonly UPLOAD_ALLOWED_MIMETYPES: z.ZodEffects<z.ZodDefault<z.ZodString>, string[], string | undefined>;
|
|
824
|
+
};
|
|
825
|
+
/** MinIO / S3 object-storage settings. */
|
|
826
|
+
declare const minioSettingsShape: {
|
|
827
|
+
readonly MINIO_ENDPOINT: z.ZodDefault<z.ZodString>;
|
|
828
|
+
readonly MINIO_ACCESS_KEY: z.ZodDefault<z.ZodString>;
|
|
829
|
+
readonly MINIO_SECRET_KEY: z.ZodDefault<z.ZodString>;
|
|
830
|
+
readonly MINIO_SECURE: z.ZodEffects<z.ZodDefault<z.ZodUnion<[z.ZodBoolean, z.ZodString]>>, boolean, string | boolean | undefined>;
|
|
831
|
+
readonly MINIO_REGION: z.ZodDefault<z.ZodString>;
|
|
832
|
+
readonly MINIO_DEFAULT_BUCKET: z.ZodDefault<z.ZodString>;
|
|
833
|
+
readonly MINIO_PUBLIC_ENDPOINT: z.ZodOptional<z.ZodString>;
|
|
834
|
+
readonly MINIO_PUBLIC_SECURE: z.ZodEffects<z.ZodOptional<z.ZodUnion<[z.ZodBoolean, z.ZodString]>>, boolean | undefined, string | boolean | undefined>;
|
|
835
|
+
};
|
|
836
|
+
/** Web Push (VAPID) settings. */
|
|
837
|
+
declare const webPushSettingsShape: {
|
|
838
|
+
readonly VAPID_PUBLIC_KEY: z.ZodDefault<z.ZodString>;
|
|
839
|
+
readonly VAPID_PRIVATE_KEY: z.ZodDefault<z.ZodString>;
|
|
840
|
+
readonly VAPID_SUBJECT: z.ZodDefault<z.ZodString>;
|
|
841
|
+
readonly WEBPUSH_DEFAULT_TTL_SECONDS: z.ZodDefault<z.ZodNumber>;
|
|
842
|
+
};
|
|
843
|
+
/** Server-side session settings (cookie + TTL). */
|
|
844
|
+
declare const sessionSettingsShape: {
|
|
845
|
+
readonly SESSION_TTL_SECONDS: z.ZodDefault<z.ZodNumber>;
|
|
846
|
+
readonly SESSION_SLIDING: z.ZodEffects<z.ZodDefault<z.ZodUnion<[z.ZodBoolean, z.ZodString]>>, boolean, string | boolean | undefined>;
|
|
847
|
+
readonly SESSION_COOKIE_NAME: z.ZodDefault<z.ZodString>;
|
|
848
|
+
readonly SESSION_COOKIE_DOMAIN: z.ZodOptional<z.ZodString>;
|
|
849
|
+
readonly SESSION_COOKIE_PATH: z.ZodDefault<z.ZodString>;
|
|
850
|
+
readonly SESSION_COOKIE_SECURE: z.ZodEffects<z.ZodDefault<z.ZodUnion<[z.ZodBoolean, z.ZodString]>>, boolean, string | boolean | undefined>;
|
|
851
|
+
readonly SESSION_COOKIE_HTTPONLY: z.ZodEffects<z.ZodDefault<z.ZodUnion<[z.ZodBoolean, z.ZodString]>>, boolean, string | boolean | undefined>;
|
|
852
|
+
readonly SESSION_COOKIE_SAMESITE: z.ZodDefault<z.ZodEnum<["lax", "strict", "none"]>>;
|
|
853
|
+
readonly SESSION_ROTATE_ON_LOGIN: z.ZodEffects<z.ZodDefault<z.ZodUnion<[z.ZodBoolean, z.ZodString]>>, boolean, string | boolean | undefined>;
|
|
854
|
+
};
|
|
855
|
+
/** WebSocket hub tuning. */
|
|
856
|
+
declare const webSocketSettingsShape: {
|
|
857
|
+
readonly WS_HEARTBEAT_SECONDS: z.ZodDefault<z.ZodNumber>;
|
|
858
|
+
readonly WS_HEARTBEAT_TIMEOUT_SECONDS: z.ZodDefault<z.ZodNumber>;
|
|
859
|
+
readonly WS_MAX_CONNECTIONS_PER_USER: z.ZodDefault<z.ZodNumber>;
|
|
860
|
+
readonly WS_MAX_MESSAGE_BYTES: z.ZodDefault<z.ZodNumber>;
|
|
861
|
+
};
|
|
862
|
+
/**
|
|
863
|
+
* Authentication flow settings (signup/activation/reset/MFA + token delivery).
|
|
864
|
+
* The FastAPI SDK's HTML-template fields (SSR activation/reset pages) are
|
|
865
|
+
* omitted — this SDK ships the JSON auth API and defers rendering to a
|
|
866
|
+
* decoupled frontend.
|
|
867
|
+
*/
|
|
868
|
+
declare const authSettingsShape: {
|
|
869
|
+
readonly AUTH_AUTO_ACTIVATE: z.ZodEffects<z.ZodDefault<z.ZodUnion<[z.ZodBoolean, z.ZodString]>>, boolean, string | boolean | undefined>;
|
|
870
|
+
readonly AUTH_RETURN_TOKEN_IN_RESPONSE: z.ZodEffects<z.ZodDefault<z.ZodUnion<[z.ZodBoolean, z.ZodString]>>, boolean, string | boolean | undefined>;
|
|
871
|
+
readonly AUTH_ACTIVATION_TTL_SECONDS: z.ZodDefault<z.ZodNumber>;
|
|
872
|
+
readonly AUTH_PASSWORD_RESET_TTL_SECONDS: z.ZodDefault<z.ZodNumber>;
|
|
873
|
+
readonly AUTH_ACTIVATION_URL_TEMPLATE: z.ZodDefault<z.ZodString>;
|
|
874
|
+
readonly AUTH_PASSWORD_RESET_URL_TEMPLATE: z.ZodDefault<z.ZodString>;
|
|
875
|
+
readonly AUTH_PASSWORD_MIN_LENGTH: z.ZodDefault<z.ZodNumber>;
|
|
876
|
+
readonly AUTH_PASSWORD_REQUIRE_COMPLEXITY: z.ZodEffects<z.ZodDefault<z.ZodUnion<[z.ZodBoolean, z.ZodString]>>, boolean, string | boolean | undefined>;
|
|
877
|
+
readonly AUTH_DEFAULT_LOCALE: z.ZodDefault<z.ZodString>;
|
|
878
|
+
readonly AUTH_MFA_ENABLED: z.ZodEffects<z.ZodDefault<z.ZodUnion<[z.ZodBoolean, z.ZodString]>>, boolean, string | boolean | undefined>;
|
|
879
|
+
readonly AUTH_MFA_ISSUER: z.ZodDefault<z.ZodString>;
|
|
880
|
+
readonly AUTH_MFA_RECOVERY_CODES_COUNT: z.ZodDefault<z.ZodNumber>;
|
|
881
|
+
readonly AUTH_MFA_TOKEN_TTL_SECONDS: z.ZodDefault<z.ZodNumber>;
|
|
882
|
+
readonly AUTH_MFA_VERIFY_WINDOW: z.ZodDefault<z.ZodNumber>;
|
|
883
|
+
readonly AUTH_TOKEN_DELIVERY: z.ZodDefault<z.ZodEnum<["bearer", "cookie", "both"]>>;
|
|
884
|
+
readonly AUTH_COOKIE_SECURE: z.ZodEffects<z.ZodDefault<z.ZodUnion<[z.ZodBoolean, z.ZodString]>>, boolean, string | boolean | undefined>;
|
|
885
|
+
readonly AUTH_COOKIE_SAMESITE: z.ZodDefault<z.ZodEnum<["lax", "strict", "none"]>>;
|
|
886
|
+
readonly AUTH_COOKIE_DOMAIN: z.ZodOptional<z.ZodString>;
|
|
887
|
+
readonly AUTH_ACCESS_COOKIE_NAME: z.ZodDefault<z.ZodString>;
|
|
888
|
+
readonly AUTH_REFRESH_COOKIE_NAME: z.ZodDefault<z.ZodString>;
|
|
889
|
+
};
|
|
890
|
+
|
|
562
891
|
/**
|
|
563
892
|
* Derive a conventional table name from a model class name: the trailing
|
|
564
893
|
* `Model` suffix is stripped and the rest snake-cased (`UserModel` → `user`).
|
|
@@ -626,6 +955,378 @@ declare function createdByColumn(): tempest_db_js.Column<string, tempest_db_js.C
|
|
|
626
955
|
*/
|
|
627
956
|
declare function updatedByColumn(): tempest_db_js.Column<string, tempest_db_js.ColumnFlags>;
|
|
628
957
|
|
|
958
|
+
/**
|
|
959
|
+
* Base for an authenticated user. Subclass it, set `tablename`, and add domain
|
|
960
|
+
* columns (name, avatar, …):
|
|
961
|
+
*
|
|
962
|
+
* ```ts
|
|
963
|
+
* class UserModel extends BaseUserModel {
|
|
964
|
+
* static tablename = tableNameFor("UserModel"); // "user"
|
|
965
|
+
* name = column.text().notNull();
|
|
966
|
+
* }
|
|
967
|
+
* ```
|
|
968
|
+
*/
|
|
969
|
+
declare abstract class BaseUserModel extends BaseModel {
|
|
970
|
+
/** Login identifier; enforce uniqueness with a unique index in a migration. */
|
|
971
|
+
email: tempest_db_js.Column<string, tempest_db_js.ColumnFlags & {
|
|
972
|
+
notNull: true;
|
|
973
|
+
}>;
|
|
974
|
+
/** The password hash (never the plaintext) — see `PasswordUtils`. */
|
|
975
|
+
hashedPassword: tempest_db_js.Column<string, tempest_db_js.ColumnFlags & {
|
|
976
|
+
notNull: true;
|
|
977
|
+
}>;
|
|
978
|
+
/** Whether the user has administrative privileges. */
|
|
979
|
+
isAdmin: tempest_db_js.Column<boolean, tempest_db_js.ColumnFlags & {
|
|
980
|
+
notNull: true;
|
|
981
|
+
} & {
|
|
982
|
+
hasDefault: true;
|
|
983
|
+
}>;
|
|
984
|
+
/** Timestamp of the last successful login, or `null` if never. */
|
|
985
|
+
lastLoginAt: tempest_db_js.Column<Date, tempest_db_js.ColumnFlags>;
|
|
986
|
+
}
|
|
987
|
+
/** Purpose of a single-use user token. */
|
|
988
|
+
declare const UserTokenPurpose: {
|
|
989
|
+
readonly ACTIVATION: "activation";
|
|
990
|
+
readonly PASSWORD_RESET: "password_reset";
|
|
991
|
+
readonly EMAIL_VERIFICATION: "email_verification";
|
|
992
|
+
readonly EMAIL_CHANGE: "email_change";
|
|
993
|
+
};
|
|
994
|
+
/** A `UserTokenPurpose` value. */
|
|
995
|
+
type UserTokenPurpose = (typeof UserTokenPurpose)[keyof typeof UserTokenPurpose];
|
|
996
|
+
/**
|
|
997
|
+
* Base for a single-use, hashed user token (activation, password reset, email
|
|
998
|
+
* verification/change). Store only the **hash** of the token; compare hashes on
|
|
999
|
+
* redemption.
|
|
1000
|
+
*/
|
|
1001
|
+
declare abstract class BaseUserTokenModel extends BaseModel {
|
|
1002
|
+
/** Owning user id. */
|
|
1003
|
+
userId: tempest_db_js.Column<string, tempest_db_js.ColumnFlags & {
|
|
1004
|
+
notNull: true;
|
|
1005
|
+
}>;
|
|
1006
|
+
/** Hash of the opaque token value. */
|
|
1007
|
+
tokenHash: tempest_db_js.Column<string, tempest_db_js.ColumnFlags & {
|
|
1008
|
+
notNull: true;
|
|
1009
|
+
}>;
|
|
1010
|
+
/** Purpose discriminator (a {@link UserTokenPurpose} value). */
|
|
1011
|
+
purpose: tempest_db_js.Column<string, tempest_db_js.ColumnFlags & {
|
|
1012
|
+
notNull: true;
|
|
1013
|
+
}>;
|
|
1014
|
+
/** When the token stops being valid. */
|
|
1015
|
+
expiresAt: tempest_db_js.Column<Date, tempest_db_js.ColumnFlags & {
|
|
1016
|
+
notNull: true;
|
|
1017
|
+
}>;
|
|
1018
|
+
/** When the token was consumed, or `null` while still usable. */
|
|
1019
|
+
usedAt: tempest_db_js.Column<Date, tempest_db_js.ColumnFlags>;
|
|
1020
|
+
/** Optional JSON payload carried with the token (e.g. the pending email). */
|
|
1021
|
+
payload: tempest_db_js.Column<Record<string, unknown>, tempest_db_js.ColumnFlags>;
|
|
1022
|
+
}
|
|
1023
|
+
/**
|
|
1024
|
+
* Base for a rotating refresh token. Rotation revokes the used token and issues
|
|
1025
|
+
* a new one in the same `familyId`; reuse of a revoked token in a family is the
|
|
1026
|
+
* signal to revoke the whole family (theft detection).
|
|
1027
|
+
*/
|
|
1028
|
+
declare abstract class BaseUserRefreshTokenModel extends BaseModel {
|
|
1029
|
+
/** Owning user id. */
|
|
1030
|
+
userId: tempest_db_js.Column<string, tempest_db_js.ColumnFlags & {
|
|
1031
|
+
notNull: true;
|
|
1032
|
+
}>;
|
|
1033
|
+
/** Hash of the opaque refresh token. */
|
|
1034
|
+
tokenHash: tempest_db_js.Column<string, tempest_db_js.ColumnFlags & {
|
|
1035
|
+
notNull: true;
|
|
1036
|
+
}>;
|
|
1037
|
+
/** Rotation family — all tokens descended from one login share it. */
|
|
1038
|
+
familyId: tempest_db_js.Column<string, tempest_db_js.ColumnFlags & {
|
|
1039
|
+
notNull: true;
|
|
1040
|
+
} & {
|
|
1041
|
+
hasDefault: true;
|
|
1042
|
+
}>;
|
|
1043
|
+
/** When the token expires. */
|
|
1044
|
+
expiresAt: tempest_db_js.Column<Date, tempest_db_js.ColumnFlags & {
|
|
1045
|
+
notNull: true;
|
|
1046
|
+
}>;
|
|
1047
|
+
/** When the token was rotated/consumed, or `null`. */
|
|
1048
|
+
usedAt: tempest_db_js.Column<Date, tempest_db_js.ColumnFlags>;
|
|
1049
|
+
/** When the token was revoked, or `null` while active. */
|
|
1050
|
+
revokedAt: tempest_db_js.Column<Date, tempest_db_js.ColumnFlags>;
|
|
1051
|
+
}
|
|
1052
|
+
|
|
1053
|
+
/** The kind of mutation an audit entry records. */
|
|
1054
|
+
declare const AuditAction: {
|
|
1055
|
+
readonly CREATE: "create";
|
|
1056
|
+
readonly UPDATE: "update";
|
|
1057
|
+
readonly DELETE: "delete";
|
|
1058
|
+
};
|
|
1059
|
+
/** An `AuditAction` value. */
|
|
1060
|
+
type AuditAction = (typeof AuditAction)[keyof typeof AuditAction];
|
|
1061
|
+
/** A per-field before/after change. */
|
|
1062
|
+
interface FieldChange {
|
|
1063
|
+
before: unknown;
|
|
1064
|
+
after: unknown;
|
|
1065
|
+
}
|
|
1066
|
+
/**
|
|
1067
|
+
* Freeze a row (ORM instance or plain object) into a plain, comparable record,
|
|
1068
|
+
* dropping keys whose value is a function.
|
|
1069
|
+
*
|
|
1070
|
+
* @param row - The row to snapshot.
|
|
1071
|
+
* @param exclude - Field names to omit (e.g. `["hashedPassword"]`).
|
|
1072
|
+
* @returns A plain record of the row's own enumerable data fields.
|
|
1073
|
+
*/
|
|
1074
|
+
declare function snapshot(row: Record<string, unknown>, exclude?: readonly string[]): Record<string, unknown>;
|
|
1075
|
+
/**
|
|
1076
|
+
* Compute the changed-field diff between two snapshots.
|
|
1077
|
+
*
|
|
1078
|
+
* @param before - The snapshot before the change.
|
|
1079
|
+
* @param after - The snapshot after the change.
|
|
1080
|
+
* @returns A map of changed field → `{ before, after }`; empty when nothing
|
|
1081
|
+
* changed. Keys present in only one side count as a change.
|
|
1082
|
+
*/
|
|
1083
|
+
declare function diffSnapshots(before: Record<string, unknown>, after: Record<string, unknown>): Record<string, FieldChange>;
|
|
1084
|
+
/**
|
|
1085
|
+
* Base for an append-only audit log. Subclass it, set `tablename`, add indexes
|
|
1086
|
+
* on `entity` / `entityId` / `actor` in a migration.
|
|
1087
|
+
*/
|
|
1088
|
+
declare abstract class BaseAuditLogModel extends BaseModel {
|
|
1089
|
+
/** Changed model name (e.g. `"UserModel"`). */
|
|
1090
|
+
entity: tempest_db_js.Column<string, tempest_db_js.ColumnFlags & {
|
|
1091
|
+
notNull: true;
|
|
1092
|
+
}>;
|
|
1093
|
+
/** Changed row id, stored as text. */
|
|
1094
|
+
entityId: tempest_db_js.Column<string, tempest_db_js.ColumnFlags & {
|
|
1095
|
+
notNull: true;
|
|
1096
|
+
}>;
|
|
1097
|
+
/** Mutation kind (an {@link AuditAction} value). */
|
|
1098
|
+
action: tempest_db_js.Column<string, tempest_db_js.ColumnFlags & {
|
|
1099
|
+
notNull: true;
|
|
1100
|
+
}>;
|
|
1101
|
+
/** Who performed the change, or `null` for system/anonymous. */
|
|
1102
|
+
actor: tempest_db_js.Column<string, tempest_db_js.ColumnFlags>;
|
|
1103
|
+
/** Before/after diff, serialized as JSON. */
|
|
1104
|
+
changes: tempest_db_js.Column<Record<string, FieldChange>, tempest_db_js.ColumnFlags & {
|
|
1105
|
+
notNull: true;
|
|
1106
|
+
}>;
|
|
1107
|
+
/** Optional extra metadata (request id, ip, reason, …). */
|
|
1108
|
+
context: tempest_db_js.Column<Record<string, unknown>, tempest_db_js.ColumnFlags>;
|
|
1109
|
+
}
|
|
1110
|
+
|
|
1111
|
+
/**
|
|
1112
|
+
* `TenantScopedRepository` — a `BaseRepository` that can't leak across tenants,
|
|
1113
|
+
* mirroring `db.tenant`.
|
|
1114
|
+
*
|
|
1115
|
+
* In a shared-schema multi-tenant database every tenant's rows live in the same
|
|
1116
|
+
* table, told apart by a `tenantId` column. Forget one `WHERE tenant_id = ?` and
|
|
1117
|
+
* tenant A reads (or deletes) tenant B's data. This repository binds a tenant id
|
|
1118
|
+
* at construction and injects it into every read filter and every write — the
|
|
1119
|
+
* scoping is invisible at the call site.
|
|
1120
|
+
*/
|
|
1121
|
+
|
|
1122
|
+
/**
|
|
1123
|
+
* A repository whose every operation is scoped to a single tenant. Use it
|
|
1124
|
+
* exactly like {@link BaseRepository}.
|
|
1125
|
+
*
|
|
1126
|
+
* ```ts
|
|
1127
|
+
* const repo = new TenantScopedRepository(OrderModel, session, tenantId);
|
|
1128
|
+
* await repo.list(); // WHERE tenant_id = tenantId
|
|
1129
|
+
* await repo.create({ total: "10" }); // tenant_id stamped automatically
|
|
1130
|
+
* ```
|
|
1131
|
+
*
|
|
1132
|
+
* @typeParam C - the model class (must declare the tenant column).
|
|
1133
|
+
*/
|
|
1134
|
+
declare class TenantScopedRepository<C extends ModelClass, TF extends string = "tenantId"> extends BaseRepository<C> {
|
|
1135
|
+
private readonly tenantId;
|
|
1136
|
+
private readonly tenantField;
|
|
1137
|
+
private readonly modelClass;
|
|
1138
|
+
/**
|
|
1139
|
+
* @param model - The model class (must have the `tenantField` column).
|
|
1140
|
+
* @param session - The async session.
|
|
1141
|
+
* @param tenantId - The tenant every operation is scoped to.
|
|
1142
|
+
* @param tenantField - Name of the tenant column. Default `"tenantId"`.
|
|
1143
|
+
*/
|
|
1144
|
+
constructor(model: C, session: ConstructorParameters<typeof BaseRepository<C>>[1], tenantId: unknown, tenantField?: TF);
|
|
1145
|
+
/** Merge the tenant predicate into a filter object. */
|
|
1146
|
+
private scoped;
|
|
1147
|
+
/** Stamp the tenant id onto an insert payload. */
|
|
1148
|
+
private stamped;
|
|
1149
|
+
list(filters?: WhereInput<InferModel<C>>): Promise<InferModel<C>[]>;
|
|
1150
|
+
first(filters?: WhereInput<InferModel<C>>): Promise<InferModel<C> | null>;
|
|
1151
|
+
exists(filters: WhereInput<InferModel<C>>): Promise<boolean>;
|
|
1152
|
+
count(filters?: WhereInput<InferModel<C>>): Promise<number>;
|
|
1153
|
+
/** Fetch by id **within the tenant**; throws `RecordNotFound` across tenants. */
|
|
1154
|
+
getById(id: unknown): Promise<InferModel<C>>;
|
|
1155
|
+
getByIdOrNull(id: unknown): Promise<InferModel<C> | null>;
|
|
1156
|
+
/** Insert one row; the tenant id is stamped for you (don't pass it). */
|
|
1157
|
+
create(data: Omit<InferInsert<C>, TF>): Promise<InferModel<C>>;
|
|
1158
|
+
/** Insert many rows; the tenant id is stamped onto each. */
|
|
1159
|
+
createMany(data: readonly Omit<InferInsert<C>, TF>[]): Promise<InferModel<C>[]>;
|
|
1160
|
+
update(filters: WhereInput<InferModel<C>>, set: Partial<InferModel<C>>): Promise<number>;
|
|
1161
|
+
delete(filters: WhereInput<InferModel<C>>): Promise<number>;
|
|
1162
|
+
paginate(filter?: PaginationFilter$1<InferModel<C>>): Promise<PaginationResult<InferModel<C>>>;
|
|
1163
|
+
}
|
|
1164
|
+
|
|
1165
|
+
/** Delivery state of an outbox event. */
|
|
1166
|
+
declare const OutboxStatus: {
|
|
1167
|
+
readonly PENDING: "pending";
|
|
1168
|
+
readonly SENT: "sent";
|
|
1169
|
+
readonly FAILED: "failed";
|
|
1170
|
+
};
|
|
1171
|
+
/** An `OutboxStatus` value. */
|
|
1172
|
+
type OutboxStatus = (typeof OutboxStatus)[keyof typeof OutboxStatus];
|
|
1173
|
+
/**
|
|
1174
|
+
* Base for a transactional outbox row. Subclass it and set `tablename`. Insert a
|
|
1175
|
+
* row in the same transaction as the write it describes.
|
|
1176
|
+
*/
|
|
1177
|
+
declare abstract class BaseOutboxModel extends BaseModel {
|
|
1178
|
+
/** Destination topic / routing key. */
|
|
1179
|
+
topic: tempest_db_js.Column<string, tempest_db_js.ColumnFlags & {
|
|
1180
|
+
notNull: true;
|
|
1181
|
+
}>;
|
|
1182
|
+
/** The event body, serialized as JSON. */
|
|
1183
|
+
payload: tempest_db_js.Column<Record<string, unknown>, tempest_db_js.ColumnFlags & {
|
|
1184
|
+
notNull: true;
|
|
1185
|
+
}>;
|
|
1186
|
+
/** Delivery state (an {@link OutboxStatus} value). */
|
|
1187
|
+
status: tempest_db_js.Column<string, tempest_db_js.ColumnFlags & {
|
|
1188
|
+
notNull: true;
|
|
1189
|
+
} & {
|
|
1190
|
+
hasDefault: true;
|
|
1191
|
+
}>;
|
|
1192
|
+
/** How many delivery attempts have been made. */
|
|
1193
|
+
attempts: tempest_db_js.Column<number, tempest_db_js.ColumnFlags & {
|
|
1194
|
+
notNull: true;
|
|
1195
|
+
} & {
|
|
1196
|
+
hasDefault: true;
|
|
1197
|
+
}>;
|
|
1198
|
+
/** Give up (mark `failed`) after this many attempts. */
|
|
1199
|
+
maxAttempts: tempest_db_js.Column<number, tempest_db_js.ColumnFlags & {
|
|
1200
|
+
notNull: true;
|
|
1201
|
+
} & {
|
|
1202
|
+
hasDefault: true;
|
|
1203
|
+
}>;
|
|
1204
|
+
/** Earliest time the row may be delivered (drives retry backoff). */
|
|
1205
|
+
availableAt: tempest_db_js.Column<Date, tempest_db_js.ColumnFlags & {
|
|
1206
|
+
notNull: true;
|
|
1207
|
+
} & {
|
|
1208
|
+
hasDefault: true;
|
|
1209
|
+
}>;
|
|
1210
|
+
/** When the row was successfully delivered, or `null`. */
|
|
1211
|
+
sentAt: tempest_db_js.Column<Date, tempest_db_js.ColumnFlags>;
|
|
1212
|
+
/** The last delivery error message, or `null`. */
|
|
1213
|
+
lastError: tempest_db_js.Column<string, tempest_db_js.ColumnFlags>;
|
|
1214
|
+
}
|
|
1215
|
+
/** Publishes one event to the broker; throws to signal a delivery failure. */
|
|
1216
|
+
type OutboxPublisher = (topic: string, payload: Record<string, unknown>) => Promise<void>;
|
|
1217
|
+
/** Options for {@link OutboxRelay}. */
|
|
1218
|
+
interface OutboxRelayOptions {
|
|
1219
|
+
/** Max rows to drain per pass. Default `100`. */
|
|
1220
|
+
batchSize?: number;
|
|
1221
|
+
/** Base backoff (seconds) between retries; scaled by attempt count. Default `30`. */
|
|
1222
|
+
retryBackoffSeconds?: number;
|
|
1223
|
+
}
|
|
1224
|
+
/**
|
|
1225
|
+
* Polls a `BaseOutboxModel` table and publishes pending events with retries.
|
|
1226
|
+
*
|
|
1227
|
+
* @typeParam C - the concrete outbox model class.
|
|
1228
|
+
*/
|
|
1229
|
+
declare class OutboxRelay<C extends ModelClass> {
|
|
1230
|
+
private readonly repository;
|
|
1231
|
+
private readonly publish;
|
|
1232
|
+
private readonly logger;
|
|
1233
|
+
private readonly batchSize;
|
|
1234
|
+
private readonly retryBackoffSeconds;
|
|
1235
|
+
private running;
|
|
1236
|
+
/**
|
|
1237
|
+
* @param repository - Repository over the outbox model.
|
|
1238
|
+
* @param publish - Callback that delivers one event to the broker.
|
|
1239
|
+
* @param options - Batch size and retry backoff.
|
|
1240
|
+
*/
|
|
1241
|
+
constructor(repository: BaseRepository<C>, publish: OutboxPublisher, options?: OutboxRelayOptions);
|
|
1242
|
+
/**
|
|
1243
|
+
* Deliver one batch of due pending events.
|
|
1244
|
+
*
|
|
1245
|
+
* @param now - The current time (injectable for tests). Defaults to `new Date()`.
|
|
1246
|
+
* @returns The number of events successfully delivered.
|
|
1247
|
+
*/
|
|
1248
|
+
drainOnce(now?: Date): Promise<number>;
|
|
1249
|
+
private markFailure;
|
|
1250
|
+
/**
|
|
1251
|
+
* Run `drainOnce` on an interval until {@link stop} is called.
|
|
1252
|
+
*
|
|
1253
|
+
* @param intervalMs - Delay between passes in milliseconds. Default `1000`.
|
|
1254
|
+
*/
|
|
1255
|
+
run(intervalMs?: number): Promise<void>;
|
|
1256
|
+
/** Stop the {@link run} loop after the current pass. */
|
|
1257
|
+
stop(): void;
|
|
1258
|
+
}
|
|
1259
|
+
|
|
1260
|
+
/**
|
|
1261
|
+
* Slow-query logging, mirroring `db.slow_query`.
|
|
1262
|
+
*
|
|
1263
|
+
* `tempest-db-js` exposes an `onQuery` hook with the SQL + params but **no
|
|
1264
|
+
* duration**, so timing has to happen at the driver boundary. This wraps an
|
|
1265
|
+
* `AsyncDriver` so every statement is timed and any that meets or exceeds a
|
|
1266
|
+
* threshold is logged — including statements run inside a reserved transaction.
|
|
1267
|
+
*
|
|
1268
|
+
* ```ts
|
|
1269
|
+
* import { AsyncEngine, NodeSqliteDriver } from "tempest-express-sdk";
|
|
1270
|
+
* import { wrapWithSlowQueryLog } from "tempest-express-sdk";
|
|
1271
|
+
*
|
|
1272
|
+
* const sync = NodeSqliteDriver.open("app.db");
|
|
1273
|
+
* const timed = wrapWithSlowQueryLog(
|
|
1274
|
+
* { execute: (s, p) => Promise.resolve(sync.execute(s, p)), close: async () => sync.close() },
|
|
1275
|
+
* { thresholdMs: 200 },
|
|
1276
|
+
* );
|
|
1277
|
+
* const engine = new AsyncEngine(timed, "sqlite");
|
|
1278
|
+
* ```
|
|
1279
|
+
*/
|
|
1280
|
+
|
|
1281
|
+
/** Options for {@link wrapWithSlowQueryLog}. */
|
|
1282
|
+
interface SlowQueryOptions {
|
|
1283
|
+
/** Statements at or above this many ms are logged. Default `500`. */
|
|
1284
|
+
thresholdMs?: number;
|
|
1285
|
+
/** Level for the slow-query lines. Default `"warning"`. */
|
|
1286
|
+
level?: LogLevel;
|
|
1287
|
+
/** Include the bound params in the log line. **Dev only** — may carry PII. */
|
|
1288
|
+
logParameters?: boolean;
|
|
1289
|
+
/** Logger name. Default `tempest_express_sdk.db.slow_query`. */
|
|
1290
|
+
loggerName?: string;
|
|
1291
|
+
}
|
|
1292
|
+
/**
|
|
1293
|
+
* Wrap an `AsyncDriver` so slow statements are logged. The returned driver is a
|
|
1294
|
+
* drop-in for {@link AsyncEngine}; `iterate` and `reserve` (transactions) are
|
|
1295
|
+
* preserved and their statements timed too.
|
|
1296
|
+
*
|
|
1297
|
+
* @param driver - The driver to wrap.
|
|
1298
|
+
* @param options - Threshold, level and whether to log params.
|
|
1299
|
+
* @returns A timing driver delegating to `driver`.
|
|
1300
|
+
*/
|
|
1301
|
+
declare function wrapWithSlowQueryLog(driver: AsyncDriver, options?: SlowQueryOptions): AsyncDriver;
|
|
1302
|
+
|
|
1303
|
+
/**
|
|
1304
|
+
* Database backup helper, mirroring `db.backup`.
|
|
1305
|
+
*
|
|
1306
|
+
* `backupDatabase` detects the dialect from the URL and produces a backup file:
|
|
1307
|
+
* a `pg_dump` for PostgreSQL, a file copy for SQLite. It shells out to `pg_dump`
|
|
1308
|
+
* for Postgres (must be on `PATH`), so the heavy lifting stays with the battle-
|
|
1309
|
+
* tested tool rather than a hand-rolled dump.
|
|
1310
|
+
*/
|
|
1311
|
+
/** Options for {@link backupDatabase}. */
|
|
1312
|
+
interface BackupOptions {
|
|
1313
|
+
/** Path to the `pg_dump` binary. Default `"pg_dump"` (resolved on `PATH`). */
|
|
1314
|
+
pgDumpPath?: string;
|
|
1315
|
+
/** Extra `pg_dump` arguments (e.g. `["--no-owner", "-Fc"]`). */
|
|
1316
|
+
pgDumpArgs?: string[];
|
|
1317
|
+
}
|
|
1318
|
+
/**
|
|
1319
|
+
* Back up a database to `destPath`.
|
|
1320
|
+
*
|
|
1321
|
+
* @param databaseUrl - The connection URL (SQLite or PostgreSQL).
|
|
1322
|
+
* @param destPath - Where to write the backup.
|
|
1323
|
+
* @param options - `pg_dump` binary path and extra args (Postgres only).
|
|
1324
|
+
* @returns The `destPath` on success.
|
|
1325
|
+
* @throws {Error} For in-memory SQLite, an unsupported dialect, or a non-zero
|
|
1326
|
+
* `pg_dump` exit.
|
|
1327
|
+
*/
|
|
1328
|
+
declare function backupDatabase(databaseUrl: string, destPath: string, options?: BackupOptions): Promise<string>;
|
|
1329
|
+
|
|
629
1330
|
/**
|
|
630
1331
|
* Generic async service over a `tempest-db-js` repository.
|
|
631
1332
|
*
|
|
@@ -1155,6 +1856,93 @@ interface ClientIpOptions {
|
|
|
1155
1856
|
*/
|
|
1156
1857
|
declare function getClientIp(req: Request, options?: ClientIpOptions): string;
|
|
1157
1858
|
|
|
1859
|
+
/**
|
|
1860
|
+
* File-download helpers, mirroring `utils.download`.
|
|
1861
|
+
*
|
|
1862
|
+
* Serve a file from disk with HTTP Range support (resumable / seekable
|
|
1863
|
+
* downloads → `206 Partial Content`) or send in-memory bytes, both with a
|
|
1864
|
+
* correct `Content-Disposition`. Path resolution is traversal-safe.
|
|
1865
|
+
*/
|
|
1866
|
+
|
|
1867
|
+
/**
|
|
1868
|
+
* Resolve a client-supplied relative path under a root, refusing traversal
|
|
1869
|
+
* outside it.
|
|
1870
|
+
*
|
|
1871
|
+
* @param root - The directory downloads are confined to.
|
|
1872
|
+
* @param relativePath - The (untrusted) relative path.
|
|
1873
|
+
* @param subdir - Optional sub-directory under `root`.
|
|
1874
|
+
* @returns The absolute, validated path.
|
|
1875
|
+
* @throws {Error} When the resolved path escapes `root`.
|
|
1876
|
+
*/
|
|
1877
|
+
declare function resolveDownloadPath(root: string, relativePath: string, subdir?: string): string;
|
|
1878
|
+
/** Options for {@link sendFileDownload} / {@link sendBytesDownload}. */
|
|
1879
|
+
interface DownloadOptions {
|
|
1880
|
+
/** Download filename; defaults to the file's basename. */
|
|
1881
|
+
filename?: string;
|
|
1882
|
+
/** MIME type. Default `application/octet-stream`. */
|
|
1883
|
+
contentType?: string;
|
|
1884
|
+
/** Serve inline (view in browser) instead of forcing a download. */
|
|
1885
|
+
inline?: boolean;
|
|
1886
|
+
}
|
|
1887
|
+
/**
|
|
1888
|
+
* Stream a file from disk as a download, honoring a `Range` request header
|
|
1889
|
+
* (responds `206` with `Content-Range` for a partial request, else `200`).
|
|
1890
|
+
*
|
|
1891
|
+
* @param req - The request (read for the `Range` header).
|
|
1892
|
+
* @param res - The response.
|
|
1893
|
+
* @param absolutePath - The absolute file path (validate it first — see
|
|
1894
|
+
* {@link resolveDownloadPath}).
|
|
1895
|
+
* @param options - Filename, content type and inline flag.
|
|
1896
|
+
* @returns Resolves once the response stream is wired up.
|
|
1897
|
+
*/
|
|
1898
|
+
declare function sendFileDownload(req: Request, res: Response$1, absolutePath: string, options?: DownloadOptions): Promise<void>;
|
|
1899
|
+
/**
|
|
1900
|
+
* Send in-memory bytes as a download.
|
|
1901
|
+
*
|
|
1902
|
+
* @param res - The response.
|
|
1903
|
+
* @param data - The bytes to send.
|
|
1904
|
+
* @param options - Filename, content type and inline flag.
|
|
1905
|
+
*/
|
|
1906
|
+
declare function sendBytesDownload(res: Response$1, data: Uint8Array, options?: DownloadOptions): void;
|
|
1907
|
+
|
|
1908
|
+
/**
|
|
1909
|
+
* File-based log routing, mirroring `utils.log` / the `core.logging` file sink.
|
|
1910
|
+
*
|
|
1911
|
+
* `configureFileLogging` installs a {@link LogSink} that appends every record
|
|
1912
|
+
* emitted by any {@link JSONLogger} to a per-level file (`info.log`,
|
|
1913
|
+
* `error.log`, …) and, additionally, routes records flagged as captured HTTP
|
|
1914
|
+
* 500s to a dedicated `500.log` — so uncaught-error triage has its own stream.
|
|
1915
|
+
*/
|
|
1916
|
+
|
|
1917
|
+
/** Per-level log file names. */
|
|
1918
|
+
declare const LEVEL_LOG_FILES: Record<LogLevel, string>;
|
|
1919
|
+
/** The dedicated file for captured HTTP 500 records. */
|
|
1920
|
+
declare const HTTP_500_LOG_FILE = "500.log";
|
|
1921
|
+
/** A handle to detach file logging and close the open streams. */
|
|
1922
|
+
interface FileLoggingHandle {
|
|
1923
|
+
/** Remove the sink and close every open file stream. */
|
|
1924
|
+
close(): void;
|
|
1925
|
+
}
|
|
1926
|
+
/** Options for {@link configureFileLogging}. */
|
|
1927
|
+
interface FileLoggingOptions {
|
|
1928
|
+
/** Directory the log files are written under (created if missing). */
|
|
1929
|
+
dir: string;
|
|
1930
|
+
}
|
|
1931
|
+
/**
|
|
1932
|
+
* Route every emitted log record into per-level files + `500.log`.
|
|
1933
|
+
*
|
|
1934
|
+
* @param options - The log directory.
|
|
1935
|
+
* @returns A handle whose `close()` detaches the sink and closes the streams.
|
|
1936
|
+
*
|
|
1937
|
+
* @example
|
|
1938
|
+
* ```ts
|
|
1939
|
+
* const logs = configureFileLogging({ dir: "logs" });
|
|
1940
|
+
* // ... on shutdown:
|
|
1941
|
+
* logs.close();
|
|
1942
|
+
* ```
|
|
1943
|
+
*/
|
|
1944
|
+
declare function configureFileLogging(options: FileLoggingOptions): FileLoggingHandle;
|
|
1945
|
+
|
|
1158
1946
|
/**
|
|
1159
1947
|
* TOTP (RFC 6238) helper for MFA, mirroring `utils.totp.TOTPHelper`.
|
|
1160
1948
|
*
|
|
@@ -2269,6 +3057,61 @@ declare class LocalUploadStorage implements UploadStorage {
|
|
|
2269
3057
|
*/
|
|
2270
3058
|
declare function buildContentDisposition(filename: string, inline?: boolean): string;
|
|
2271
3059
|
|
|
3060
|
+
/**
|
|
3061
|
+
* S3 / MinIO-backed {@link UploadStorage}, mirroring `utils.storage_backends`.
|
|
3062
|
+
*
|
|
3063
|
+
* Implements the same narrow `UploadStorage` interface as
|
|
3064
|
+
* {@link LocalUploadStorage} over a MinIO/S3 client, so services swap backends
|
|
3065
|
+
* without touching call sites. The `minio` client is an **optional** peer
|
|
3066
|
+
* dependency, lazy-loaded on first use (or inject your own client for tests /
|
|
3067
|
+
* a custom SDK).
|
|
3068
|
+
*/
|
|
3069
|
+
|
|
3070
|
+
/** Minimal MinIO/S3 client surface used by {@link S3UploadStorage}. */
|
|
3071
|
+
interface S3ClientLike {
|
|
3072
|
+
putObject(bucket: string, key: string, data: Buffer, size?: number, metaData?: Record<string, string>): Promise<unknown>;
|
|
3073
|
+
getObject(bucket: string, key: string): Promise<Readable>;
|
|
3074
|
+
removeObject(bucket: string, key: string): Promise<void>;
|
|
3075
|
+
}
|
|
3076
|
+
/** Options for {@link S3UploadStorage}. */
|
|
3077
|
+
interface S3UploadStorageOptions {
|
|
3078
|
+
/** Target bucket. */
|
|
3079
|
+
bucket: string;
|
|
3080
|
+
/** Public base URL for {@link S3UploadStorage.url} (e.g. a CDN or the endpoint). */
|
|
3081
|
+
publicBaseUrl?: string;
|
|
3082
|
+
/** Inject a ready client (e.g. a `minio` `Client`, or a mock). */
|
|
3083
|
+
client?: S3ClientLike;
|
|
3084
|
+
/** MinIO/S3 endpoint host (used only when `client` is not injected). */
|
|
3085
|
+
endPoint?: string;
|
|
3086
|
+
/** Endpoint port. */
|
|
3087
|
+
port?: number;
|
|
3088
|
+
/** Whether to use TLS. */
|
|
3089
|
+
useSSL?: boolean;
|
|
3090
|
+
/** Access key. */
|
|
3091
|
+
accessKey?: string;
|
|
3092
|
+
/** Secret key. */
|
|
3093
|
+
secretKey?: string;
|
|
3094
|
+
/** Region. */
|
|
3095
|
+
region?: string;
|
|
3096
|
+
}
|
|
3097
|
+
/** {@link UploadStorage} over a MinIO/S3 client. */
|
|
3098
|
+
declare class S3UploadStorage implements UploadStorage {
|
|
3099
|
+
private readonly bucket;
|
|
3100
|
+
private readonly publicBaseUrl;
|
|
3101
|
+
private client;
|
|
3102
|
+
private readonly options;
|
|
3103
|
+
/**
|
|
3104
|
+
* @param options - Bucket, public URL and either a client or connection config.
|
|
3105
|
+
*/
|
|
3106
|
+
constructor(options: S3UploadStorageOptions);
|
|
3107
|
+
/** Resolve the client, lazy-loading `minio` when one wasn't injected. */
|
|
3108
|
+
private getClient;
|
|
3109
|
+
save(key: string, data: Uint8Array, options?: SaveOptions): Promise<UploadResult>;
|
|
3110
|
+
read(key: string): Promise<Buffer>;
|
|
3111
|
+
delete(key: string): Promise<void>;
|
|
3112
|
+
url(key: string): string;
|
|
3113
|
+
}
|
|
3114
|
+
|
|
2272
3115
|
/** Web Push DTOs (Zod), mirroring `webpush.schemas`. */
|
|
2273
3116
|
|
|
2274
3117
|
/** The browser-provided push subscription keys. */
|
|
@@ -2316,13 +3159,13 @@ declare const webPushPayloadSchema: z.ZodObject<{
|
|
|
2316
3159
|
data: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
2317
3160
|
}, "strip", z.ZodTypeAny, {
|
|
2318
3161
|
title: string;
|
|
2319
|
-
url?: string | undefined;
|
|
2320
3162
|
data?: Record<string, unknown> | undefined;
|
|
3163
|
+
url?: string | undefined;
|
|
2321
3164
|
body?: string | undefined;
|
|
2322
3165
|
}, {
|
|
2323
3166
|
title: string;
|
|
2324
|
-
url?: string | undefined;
|
|
2325
3167
|
data?: Record<string, unknown> | undefined;
|
|
3168
|
+
url?: string | undefined;
|
|
2326
3169
|
body?: string | undefined;
|
|
2327
3170
|
}>;
|
|
2328
3171
|
type WebPushKeys = z.infer<typeof webPushKeysSchema>;
|
|
@@ -2424,16 +3267,16 @@ declare const inboundMessageSchema: z.ZodObject<{
|
|
|
2424
3267
|
direction: z.ZodOptional<z.ZodEnum<["incoming", "outgoing"]>>;
|
|
2425
3268
|
}, "strip", z.ZodTypeAny, {
|
|
2426
3269
|
from: string;
|
|
3270
|
+
timestamp: string;
|
|
2427
3271
|
messageId: string;
|
|
2428
3272
|
mediaType: "image" | "video" | "audio" | "document" | "sticker" | null;
|
|
2429
|
-
timestamp: string;
|
|
2430
3273
|
text?: string | undefined;
|
|
2431
3274
|
direction?: "incoming" | "outgoing" | undefined;
|
|
2432
3275
|
}, {
|
|
2433
3276
|
from: string;
|
|
3277
|
+
timestamp: string;
|
|
2434
3278
|
messageId: string;
|
|
2435
3279
|
mediaType: "image" | "video" | "audio" | "document" | "sticker" | null;
|
|
2436
|
-
timestamp: string;
|
|
2437
3280
|
text?: string | undefined;
|
|
2438
3281
|
direction?: "incoming" | "outgoing" | undefined;
|
|
2439
3282
|
}>;
|
|
@@ -2686,6 +3529,87 @@ declare class EmailProvider implements MessagingProvider {
|
|
|
2686
3529
|
status(): Promise<string>;
|
|
2687
3530
|
}
|
|
2688
3531
|
|
|
3532
|
+
/**
|
|
3533
|
+
* Broadcast + multi-channel helpers over {@link MessagingProvider}.
|
|
3534
|
+
*
|
|
3535
|
+
* {@link broadcastText} fans one message out to many recipients through a single
|
|
3536
|
+
* provider, with bounded concurrency and a per-recipient result (one failure
|
|
3537
|
+
* never aborts the rest). {@link MessagingHub} keeps named providers so app code
|
|
3538
|
+
* sends by channel name and can broadcast across all of them.
|
|
3539
|
+
*/
|
|
3540
|
+
|
|
3541
|
+
/** The outcome of a single recipient's send within a broadcast. */
|
|
3542
|
+
interface BroadcastResult {
|
|
3543
|
+
/** The recipient address/handle. */
|
|
3544
|
+
to: string;
|
|
3545
|
+
/** Whether the send succeeded. */
|
|
3546
|
+
ok: boolean;
|
|
3547
|
+
/** The provider result, when successful. */
|
|
3548
|
+
result?: OutboundResult;
|
|
3549
|
+
/** The error message, when failed. */
|
|
3550
|
+
error?: string;
|
|
3551
|
+
}
|
|
3552
|
+
/** Options for {@link broadcastText}. */
|
|
3553
|
+
interface BroadcastOptions extends SendOptions {
|
|
3554
|
+
/** Maximum concurrent sends. Default 10. */
|
|
3555
|
+
concurrency?: number;
|
|
3556
|
+
}
|
|
3557
|
+
/**
|
|
3558
|
+
* Send `text` to every recipient through `provider`, bounded by concurrency.
|
|
3559
|
+
*
|
|
3560
|
+
* A failed recipient is captured in its {@link BroadcastResult} (`ok: false`)
|
|
3561
|
+
* rather than aborting the batch.
|
|
3562
|
+
*
|
|
3563
|
+
* @param provider - The channel to send through.
|
|
3564
|
+
* @param recipients - Recipient addresses/handles.
|
|
3565
|
+
* @param text - The message body.
|
|
3566
|
+
* @param options - Concurrency + send options.
|
|
3567
|
+
* @returns One result per recipient, in input order.
|
|
3568
|
+
*/
|
|
3569
|
+
declare function broadcastText(provider: MessagingProvider, recipients: string[], text: string, options?: BroadcastOptions): Promise<BroadcastResult[]>;
|
|
3570
|
+
/** A registry of named messaging channels. */
|
|
3571
|
+
declare class MessagingHub {
|
|
3572
|
+
private readonly channels;
|
|
3573
|
+
/**
|
|
3574
|
+
* Register a provider under a channel name.
|
|
3575
|
+
*
|
|
3576
|
+
* @param name - The channel name (e.g. `"whatsapp"`, `"sms"`).
|
|
3577
|
+
* @param provider - The provider implementation.
|
|
3578
|
+
* @returns The hub (chainable).
|
|
3579
|
+
*/
|
|
3580
|
+
register(name: string, provider: MessagingProvider): this;
|
|
3581
|
+
/**
|
|
3582
|
+
* Get a registered provider, throwing when the channel is unknown.
|
|
3583
|
+
*
|
|
3584
|
+
* @param name - The channel name.
|
|
3585
|
+
* @returns The provider.
|
|
3586
|
+
* @throws {Error} When no provider is registered under `name`.
|
|
3587
|
+
*/
|
|
3588
|
+
get(name: string): MessagingProvider;
|
|
3589
|
+
/** The registered channel names. */
|
|
3590
|
+
channelNames(): string[];
|
|
3591
|
+
/**
|
|
3592
|
+
* Send text through a named channel.
|
|
3593
|
+
*
|
|
3594
|
+
* @param channel - The channel name.
|
|
3595
|
+
* @param to - The recipient.
|
|
3596
|
+
* @param text - The message body.
|
|
3597
|
+
* @param options - Send options.
|
|
3598
|
+
* @returns The provider result.
|
|
3599
|
+
*/
|
|
3600
|
+
send(channel: string, to: string, text: string, options?: SendOptions): Promise<OutboundResult>;
|
|
3601
|
+
/**
|
|
3602
|
+
* Broadcast text to many recipients on a named channel.
|
|
3603
|
+
*
|
|
3604
|
+
* @param channel - The channel name.
|
|
3605
|
+
* @param recipients - Recipient addresses/handles.
|
|
3606
|
+
* @param text - The message body.
|
|
3607
|
+
* @param options - Broadcast + send options.
|
|
3608
|
+
* @returns One result per recipient.
|
|
3609
|
+
*/
|
|
3610
|
+
broadcast(channel: string, recipients: string[], text: string, options?: BroadcastOptions): Promise<BroadcastResult[]>;
|
|
3611
|
+
}
|
|
3612
|
+
|
|
2689
3613
|
/**
|
|
2690
3614
|
* Admin site + resource registry, mirroring `admin.site` / `admin.config`.
|
|
2691
3615
|
*
|
|
@@ -3459,6 +4383,62 @@ interface AuthRouterOptions {
|
|
|
3459
4383
|
*/
|
|
3460
4384
|
declare function makeAuthRouter(options: AuthRouterOptions): Router;
|
|
3461
4385
|
|
|
4386
|
+
/**
|
|
4387
|
+
* Optional server-rendered HTML pages for the bundled auth flows, mirroring the
|
|
4388
|
+
* FastAPI SDK's activation/reset templates.
|
|
4389
|
+
*
|
|
4390
|
+
* This SDK favors the JSON auth API + a decoupled frontend, but a link in an
|
|
4391
|
+
* email (activation, password reset) sometimes has to land on a *server* page —
|
|
4392
|
+
* there's no SPA to route to. These helpers render small, self-contained,
|
|
4393
|
+
* theme-aware HTML pages (no template engine, no external assets) for exactly
|
|
4394
|
+
* those landings.
|
|
4395
|
+
*/
|
|
4396
|
+
/** Options for {@link renderAuthResultPage}. */
|
|
4397
|
+
interface AuthResultPageOptions {
|
|
4398
|
+
/** `true` renders a success state, `false` an error state. */
|
|
4399
|
+
ok: boolean;
|
|
4400
|
+
/** Page + heading title. */
|
|
4401
|
+
title: string;
|
|
4402
|
+
/** Body message. */
|
|
4403
|
+
message: string;
|
|
4404
|
+
/** Optional call-to-action link. */
|
|
4405
|
+
cta?: {
|
|
4406
|
+
href: string;
|
|
4407
|
+
label: string;
|
|
4408
|
+
};
|
|
4409
|
+
}
|
|
4410
|
+
/**
|
|
4411
|
+
* Render a success/error result page (e.g. "account activated", "link
|
|
4412
|
+
* expired").
|
|
4413
|
+
*
|
|
4414
|
+
* @param options - Success flag, title, message and an optional CTA.
|
|
4415
|
+
* @returns A complete HTML document.
|
|
4416
|
+
*/
|
|
4417
|
+
declare function renderAuthResultPage(options: AuthResultPageOptions): string;
|
|
4418
|
+
/** Options for {@link renderPasswordResetFormPage}. */
|
|
4419
|
+
interface PasswordResetFormOptions {
|
|
4420
|
+
/** Form POST target. */
|
|
4421
|
+
action: string;
|
|
4422
|
+
/** The reset token, embedded as a hidden field. */
|
|
4423
|
+
token: string;
|
|
4424
|
+
/** Page + heading title. Default `"Redefinir senha"`. */
|
|
4425
|
+
title?: string;
|
|
4426
|
+
/** Name of the hidden token field. Default `"token"`. */
|
|
4427
|
+
tokenField?: string;
|
|
4428
|
+
/** Name of the password field. Default `"password"`. */
|
|
4429
|
+
passwordField?: string;
|
|
4430
|
+
/** Submit button label. Default `"Redefinir senha"`. */
|
|
4431
|
+
submitLabel?: string;
|
|
4432
|
+
}
|
|
4433
|
+
/**
|
|
4434
|
+
* Render a "set a new password" form that POSTs the token + new password to
|
|
4435
|
+
* `action`.
|
|
4436
|
+
*
|
|
4437
|
+
* @param options - Form action, token and field/label overrides.
|
|
4438
|
+
* @returns A complete HTML document.
|
|
4439
|
+
*/
|
|
4440
|
+
declare function renderPasswordResetFormPage(options: PasswordResetFormOptions): string;
|
|
4441
|
+
|
|
3462
4442
|
/**
|
|
3463
4443
|
* Express error handling, mirroring `api.handlers`.
|
|
3464
4444
|
*
|
|
@@ -3474,8 +4454,8 @@ declare const REQUEST_ID_HEADER = "X-Request-ID";
|
|
|
3474
4454
|
/**
|
|
3475
4455
|
* Middleware that establishes a request id and binds the request context.
|
|
3476
4456
|
*
|
|
3477
|
-
* Reuses an inbound `X-Request-ID` when present
|
|
3478
|
-
* it on the response, and runs the rest of the chain inside
|
|
4457
|
+
* Reuses an inbound `X-Request-ID` when present **and well-formed**, otherwise
|
|
4458
|
+
* generates one, sets it on the response, and runs the rest of the chain inside
|
|
3479
4459
|
* {@link runWithRequestContext} so loggers and handlers can read it.
|
|
3480
4460
|
*
|
|
3481
4461
|
* @returns The configured middleware.
|
|
@@ -3715,7 +4695,722 @@ interface RunServerOptions {
|
|
|
3715
4695
|
*/
|
|
3716
4696
|
declare function runServer(app: Express, options?: RunServerOptions): Promise<Server>;
|
|
3717
4697
|
|
|
4698
|
+
/**
|
|
4699
|
+
* `bodySizeLimitMiddleware` — reject oversize request bodies early, mirroring
|
|
4700
|
+
* `api.middlewares.body_size`.
|
|
4701
|
+
*
|
|
4702
|
+
* Without an upstream limit a client can stream gigabytes before body parsers
|
|
4703
|
+
* reject it — wasting bandwidth and RAM. This middleware short-circuits the
|
|
4704
|
+
* moment `Content-Length` exceeds the cap, and defensively tracks streamed
|
|
4705
|
+
* bytes for chunked/unknown-length uploads.
|
|
4706
|
+
*/
|
|
4707
|
+
|
|
4708
|
+
/** Options for {@link bodySizeLimitMiddleware}. */
|
|
4709
|
+
interface BodySizeLimitOptions {
|
|
4710
|
+
/** Hard cap on the request body in bytes. */
|
|
4711
|
+
maxBytes: number;
|
|
4712
|
+
/** Path prefixes that bypass the check (e.g. an upload endpoint). */
|
|
4713
|
+
excludePaths?: string[];
|
|
4714
|
+
}
|
|
4715
|
+
/**
|
|
4716
|
+
* Build a middleware enforcing `maxBytes` per request. A `Content-Length` over
|
|
4717
|
+
* the cap is rejected immediately with `413`; chunked bodies are aborted once
|
|
4718
|
+
* the streamed size crosses the cap.
|
|
4719
|
+
*
|
|
4720
|
+
* @param options - The cap and path exclusions.
|
|
4721
|
+
* @returns An Express middleware.
|
|
4722
|
+
*/
|
|
4723
|
+
declare function bodySizeLimitMiddleware(options: BodySizeLimitOptions): RequestHandler;
|
|
4724
|
+
|
|
4725
|
+
/**
|
|
4726
|
+
* `csrfMiddleware` — double-submit cookie protection for state changes,
|
|
4727
|
+
* mirroring `api.middlewares.csrf`.
|
|
4728
|
+
*
|
|
4729
|
+
* CSRF lets a third-party site trigger authenticated mutating requests through
|
|
4730
|
+
* a victim's browser, because cookies ride along automatically. The
|
|
4731
|
+
* double-submit defense: issue a random `csrf_token` cookie, have the frontend
|
|
4732
|
+
* echo it in an `X-CSRF-Token` header, and reject mutating requests where the
|
|
4733
|
+
* header is missing or does not match the cookie. A cross-site page can't read
|
|
4734
|
+
* the cookie (same-origin policy), so it can't forge the header.
|
|
4735
|
+
*
|
|
4736
|
+
* JWT bearer auth (`Authorization: Bearer …`) is **not** subject to CSRF (the
|
|
4737
|
+
* browser doesn't auto-attach it), so `/api/` routes are typically excluded.
|
|
4738
|
+
*/
|
|
4739
|
+
|
|
4740
|
+
/** Default cookie holding the CSRF token. */
|
|
4741
|
+
declare const CSRF_COOKIE_NAME = "csrf_token";
|
|
4742
|
+
/** Default header the client echoes the cookie value into. */
|
|
4743
|
+
declare const CSRF_HEADER_NAME = "X-CSRF-Token";
|
|
4744
|
+
/**
|
|
4745
|
+
* Generate a URL-safe random CSRF token.
|
|
4746
|
+
*
|
|
4747
|
+
* @param nBytes - Entropy bytes (32 → a 43-char token). Default `32`.
|
|
4748
|
+
* @returns A URL-safe base64 token without padding.
|
|
4749
|
+
*/
|
|
4750
|
+
declare function generateCsrfToken(nBytes?: number): string;
|
|
4751
|
+
/** Options for {@link csrfMiddleware}. */
|
|
4752
|
+
interface CsrfOptions {
|
|
4753
|
+
/** Name of the CSRF cookie. Default `csrf_token`. */
|
|
4754
|
+
cookieName?: string;
|
|
4755
|
+
/** Name of the CSRF header. Default `X-CSRF-Token`. */
|
|
4756
|
+
headerName?: string;
|
|
4757
|
+
/** Path prefixes that bypass the check (e.g. `["/api/", "/webhooks/"]`). */
|
|
4758
|
+
excludePaths?: string[];
|
|
4759
|
+
}
|
|
4760
|
+
/**
|
|
4761
|
+
* Build a double-submit CSRF middleware. Safe methods (GET/HEAD/OPTIONS) pass;
|
|
4762
|
+
* unsafe methods must carry a matching cookie + header or get `403`.
|
|
4763
|
+
*
|
|
4764
|
+
* @param options - Cookie/header names and excluded path prefixes.
|
|
4765
|
+
* @returns An Express middleware.
|
|
4766
|
+
*/
|
|
4767
|
+
declare function csrfMiddleware(options?: CsrfOptions): RequestHandler;
|
|
4768
|
+
|
|
4769
|
+
/**
|
|
4770
|
+
* `GracefulShutdown` — track in-flight requests and drain on shutdown,
|
|
4771
|
+
* mirroring `api.middlewares.graceful`.
|
|
4772
|
+
*
|
|
4773
|
+
* Wire {@link GracefulShutdown.middleware} into the app, then on `SIGTERM`
|
|
4774
|
+
* call {@link GracefulShutdown.beginDrain} (new non-exempt requests get `503`)
|
|
4775
|
+
* and `await` {@link GracefulShutdown.waitDrained} before closing the server —
|
|
4776
|
+
* so a rolling deploy never cuts an in-flight request mid-response.
|
|
4777
|
+
*/
|
|
4778
|
+
|
|
4779
|
+
/** Options for {@link GracefulShutdown}. */
|
|
4780
|
+
interface GracefulShutdownOptions {
|
|
4781
|
+
/** Max seconds to wait for in-flight requests to finish. Default `30`. */
|
|
4782
|
+
drainTimeoutSeconds?: number;
|
|
4783
|
+
/** `Retry-After` seconds on the 503 served while draining. Default `5`. */
|
|
4784
|
+
retryAfterSeconds?: number;
|
|
4785
|
+
/** Exact paths that keep being served while draining. */
|
|
4786
|
+
exemptPaths?: string[];
|
|
4787
|
+
}
|
|
4788
|
+
/** In-flight request tracker with a drain gate. */
|
|
4789
|
+
declare class GracefulShutdown {
|
|
4790
|
+
private readonly drainTimeoutSeconds;
|
|
4791
|
+
private readonly retryAfterSeconds;
|
|
4792
|
+
private readonly exempt;
|
|
4793
|
+
private inFlightCount;
|
|
4794
|
+
private draining;
|
|
4795
|
+
private idleResolvers;
|
|
4796
|
+
constructor(options?: GracefulShutdownOptions);
|
|
4797
|
+
/** Number of requests currently being served. */
|
|
4798
|
+
get inFlight(): number;
|
|
4799
|
+
/** Whether draining has begun. */
|
|
4800
|
+
get isDraining(): boolean;
|
|
4801
|
+
/** The Express middleware: counts in-flight requests, 503s while draining. */
|
|
4802
|
+
middleware(): RequestHandler;
|
|
4803
|
+
private release;
|
|
4804
|
+
/** Flip into draining mode (idempotent). New non-exempt requests get 503. */
|
|
4805
|
+
beginDrain(): void;
|
|
4806
|
+
/**
|
|
4807
|
+
* Wait until in-flight requests finish or the drain timeout elapses.
|
|
4808
|
+
*
|
|
4809
|
+
* @returns `true` if everything drained in time, `false` on timeout.
|
|
4810
|
+
*/
|
|
4811
|
+
waitDrained(): Promise<boolean>;
|
|
4812
|
+
}
|
|
4813
|
+
|
|
4814
|
+
/**
|
|
4815
|
+
* `idempotencyMiddleware` — cache responses by `Idempotency-Key`, mirroring
|
|
4816
|
+
* `api.middlewares.idempotency`.
|
|
4817
|
+
*
|
|
4818
|
+
* A client retrying a mutating request with the same `Idempotency-Key` gets the
|
|
4819
|
+
* original response back instead of a duplicate side effect (a second charge, a
|
|
4820
|
+
* second order). Only mutating verbs are eligible; the key is scoped per
|
|
4821
|
+
* `(method, path, key)` so the same key on different endpoints never collides.
|
|
4822
|
+
*/
|
|
4823
|
+
|
|
4824
|
+
/** The canonical header (Stripe / AWS / GitHub all use it). */
|
|
4825
|
+
declare const IDEMPOTENCY_HEADER = "Idempotency-Key";
|
|
4826
|
+
/** A serialized response stored under an idempotency key. */
|
|
4827
|
+
interface CachedResponse {
|
|
4828
|
+
statusCode: number;
|
|
4829
|
+
headers: Array<[string, string]>;
|
|
4830
|
+
body: string;
|
|
4831
|
+
contentType: string | null;
|
|
4832
|
+
}
|
|
4833
|
+
/** Backend every idempotency cache implements. */
|
|
4834
|
+
interface IdempotencyStore {
|
|
4835
|
+
/** Return the cached response for `key`, or `null` when missing/expired. */
|
|
4836
|
+
get(key: string): Promise<CachedResponse | null>;
|
|
4837
|
+
/** Store `response` under `key` with a TTL. */
|
|
4838
|
+
set(key: string, response: CachedResponse, ttlSeconds: number): Promise<void>;
|
|
4839
|
+
}
|
|
4840
|
+
/** In-process {@link IdempotencyStore} with lazy TTL eviction (single-replica). */
|
|
4841
|
+
declare class MemoryIdempotencyStore implements IdempotencyStore {
|
|
4842
|
+
private readonly store;
|
|
4843
|
+
get(key: string): Promise<CachedResponse | null>;
|
|
4844
|
+
set(key: string, response: CachedResponse, ttlSeconds: number): Promise<void>;
|
|
4845
|
+
}
|
|
4846
|
+
/** Minimal async Redis surface used by {@link RedisIdempotencyStore}. */
|
|
4847
|
+
interface IdempotencyRedisLike {
|
|
4848
|
+
get(key: string): Promise<string | null>;
|
|
4849
|
+
set(key: string, value: string, options: {
|
|
4850
|
+
EX: number;
|
|
4851
|
+
}): Promise<unknown>;
|
|
4852
|
+
}
|
|
4853
|
+
/** {@link IdempotencyStore} backed by an async Redis client (multi-replica). */
|
|
4854
|
+
declare class RedisIdempotencyStore implements IdempotencyStore {
|
|
4855
|
+
private readonly client;
|
|
4856
|
+
private readonly prefix;
|
|
4857
|
+
constructor(client: IdempotencyRedisLike, options?: {
|
|
4858
|
+
prefix?: string;
|
|
4859
|
+
});
|
|
4860
|
+
get(key: string): Promise<CachedResponse | null>;
|
|
4861
|
+
set(key: string, response: CachedResponse, ttlSeconds: number): Promise<void>;
|
|
4862
|
+
}
|
|
4863
|
+
/** Options for {@link idempotencyMiddleware}. */
|
|
4864
|
+
interface IdempotencyOptions {
|
|
4865
|
+
/** The cache backend (memory or Redis). */
|
|
4866
|
+
store: IdempotencyStore;
|
|
4867
|
+
/** Time-to-live for a cached response, in seconds. Default 24h. */
|
|
4868
|
+
ttlSeconds?: number;
|
|
4869
|
+
/** Header carrying the key. Default `Idempotency-Key`. */
|
|
4870
|
+
headerName?: string;
|
|
4871
|
+
}
|
|
4872
|
+
/**
|
|
4873
|
+
* Build an idempotency middleware. On a cache hit it replays the stored
|
|
4874
|
+
* response; on a miss it captures the response, stores it, and forwards.
|
|
4875
|
+
*
|
|
4876
|
+
* @param options - Store, TTL and header name.
|
|
4877
|
+
* @returns An Express middleware.
|
|
4878
|
+
*/
|
|
4879
|
+
declare function idempotencyMiddleware(options: IdempotencyOptions): RequestHandler;
|
|
4880
|
+
|
|
4881
|
+
/**
|
|
4882
|
+
* `HttpMetrics` + `prometheusMiddleware` — per-request Prometheus metrics,
|
|
4883
|
+
* mirroring the FastAPI `PrometheusMiddleware`.
|
|
4884
|
+
*
|
|
4885
|
+
* Complements the system `/metrics` router (`MetricsUtils.toPrometheus`, which
|
|
4886
|
+
* reports process/host gauges) with **per-request** instrumentation: a request
|
|
4887
|
+
* counter labelled by method/path/status and a latency histogram. Everything is
|
|
4888
|
+
* in-process and dependency-free; expose it with {@link HttpMetrics.render}.
|
|
4889
|
+
*/
|
|
4890
|
+
|
|
4891
|
+
/**
|
|
4892
|
+
* In-process HTTP request metrics: a labelled request counter and a latency
|
|
4893
|
+
* histogram, rendered as Prometheus text.
|
|
4894
|
+
*/
|
|
4895
|
+
declare class HttpMetrics {
|
|
4896
|
+
private readonly buckets;
|
|
4897
|
+
/** `method|status` → count. */
|
|
4898
|
+
private readonly requestTotals;
|
|
4899
|
+
/** `method|route` → histogram. */
|
|
4900
|
+
private readonly durations;
|
|
4901
|
+
constructor(options?: {
|
|
4902
|
+
buckets?: number[];
|
|
4903
|
+
});
|
|
4904
|
+
/**
|
|
4905
|
+
* Record one completed request.
|
|
4906
|
+
*
|
|
4907
|
+
* @param method - HTTP method.
|
|
4908
|
+
* @param route - The route pattern (or path) — keep cardinality bounded.
|
|
4909
|
+
* @param status - Response status code.
|
|
4910
|
+
* @param durationSeconds - Wall-clock request duration in seconds.
|
|
4911
|
+
*/
|
|
4912
|
+
observe(method: string, route: string, status: number, durationSeconds: number): void;
|
|
4913
|
+
/** Render the collected metrics as Prometheus exposition text. */
|
|
4914
|
+
render(): string;
|
|
4915
|
+
/**
|
|
4916
|
+
* Build the middleware that records each request into this collector.
|
|
4917
|
+
*
|
|
4918
|
+
* @param options - Optional exempt paths (e.g. the metrics route itself).
|
|
4919
|
+
* @returns An Express middleware.
|
|
4920
|
+
*/
|
|
4921
|
+
middleware(options?: {
|
|
4922
|
+
exemptPaths?: string[];
|
|
4923
|
+
}): RequestHandler;
|
|
4924
|
+
}
|
|
4925
|
+
/**
|
|
4926
|
+
* Convenience factory: a fresh {@link HttpMetrics} plus its middleware.
|
|
4927
|
+
*
|
|
4928
|
+
* @param options - Histogram buckets and exempt paths.
|
|
4929
|
+
* @returns The collector and its middleware.
|
|
4930
|
+
*/
|
|
4931
|
+
declare function prometheusMiddleware(options?: {
|
|
4932
|
+
buckets?: number[];
|
|
4933
|
+
exemptPaths?: string[];
|
|
4934
|
+
}): {
|
|
4935
|
+
metrics: HttpMetrics;
|
|
4936
|
+
middleware: RequestHandler;
|
|
4937
|
+
};
|
|
4938
|
+
|
|
4939
|
+
/**
|
|
4940
|
+
* Sliding-window rate-limit middleware with pluggable stores and keys,
|
|
4941
|
+
* mirroring `api.middlewares.rate_limit`.
|
|
4942
|
+
*
|
|
4943
|
+
* Two axes are pluggable:
|
|
4944
|
+
*
|
|
4945
|
+
* - **Store** — where the counters live. {@link MemoryRateLimitStore} (default,
|
|
4946
|
+
* in-process) fits a single worker; {@link RedisRateLimitStore} shares state
|
|
4947
|
+
* across replicas via an atomic Lua sliding-window log.
|
|
4948
|
+
* - **Key** — *who* a request counts against. {@link keyByIp} (default),
|
|
4949
|
+
* {@link keyByHeader} (e.g. an API key), {@link keyByJwtClaim} /
|
|
4950
|
+
* {@link keyByJwtSubject} (per authenticated principal), each falling back to
|
|
4951
|
+
* the client IP for anonymous traffic.
|
|
4952
|
+
*/
|
|
4953
|
+
|
|
4954
|
+
/** Outcome of a single rate-limit check. */
|
|
4955
|
+
interface RateLimitResult {
|
|
4956
|
+
/** `true` when the request fits under the limit. */
|
|
4957
|
+
allowed: boolean;
|
|
4958
|
+
/** Requests still allowed in the current window (`0` when rejected). */
|
|
4959
|
+
remaining: number;
|
|
4960
|
+
/** Seconds to wait before retrying (`0` when allowed, `>= 1` on rejection). */
|
|
4961
|
+
retryAfter: number;
|
|
4962
|
+
}
|
|
4963
|
+
/** Backend that counts hits per key inside a sliding window. */
|
|
4964
|
+
interface RateLimitStore {
|
|
4965
|
+
/**
|
|
4966
|
+
* Register one hit for `key` and report whether it is allowed.
|
|
4967
|
+
*
|
|
4968
|
+
* @param key - The rate-limit bucket key.
|
|
4969
|
+
* @param maxRequests - Maximum hits allowed in the window.
|
|
4970
|
+
* @param windowSeconds - Sliding-window length in seconds.
|
|
4971
|
+
* @returns The decision for this hit.
|
|
4972
|
+
*/
|
|
4973
|
+
hit(key: string, maxRequests: number, windowSeconds: number): Promise<RateLimitResult>;
|
|
4974
|
+
}
|
|
4975
|
+
/**
|
|
4976
|
+
* In-process sliding-window store backed by per-key timestamp logs.
|
|
4977
|
+
*
|
|
4978
|
+
* State lives in this worker's memory only — correct for a single process. For
|
|
4979
|
+
* multi-replica deployments use {@link RedisRateLimitStore}.
|
|
4980
|
+
*/
|
|
4981
|
+
declare class MemoryRateLimitStore implements RateLimitStore {
|
|
4982
|
+
private readonly buckets;
|
|
4983
|
+
hit(key: string, maxRequests: number, windowSeconds: number): Promise<RateLimitResult>;
|
|
4984
|
+
}
|
|
4985
|
+
/** Minimal async Redis surface used by {@link RedisRateLimitStore}. */
|
|
4986
|
+
interface RateLimitRedisLike {
|
|
4987
|
+
eval(script: string, options: {
|
|
4988
|
+
keys: string[];
|
|
4989
|
+
arguments: string[];
|
|
4990
|
+
}): Promise<unknown>;
|
|
4991
|
+
}
|
|
4992
|
+
/**
|
|
4993
|
+
* Distributed sliding-window store backed by a Redis sorted set. A single Lua
|
|
4994
|
+
* script prunes expired members, counts survivors and conditionally adds the
|
|
4995
|
+
* new hit, so the check is atomic across replicas. On a backend error the
|
|
4996
|
+
* request is allowed when `failOpen` (the default).
|
|
4997
|
+
*/
|
|
4998
|
+
declare class RedisRateLimitStore implements RateLimitStore {
|
|
4999
|
+
private readonly redis;
|
|
5000
|
+
private readonly namespace;
|
|
5001
|
+
private readonly failOpen;
|
|
5002
|
+
/**
|
|
5003
|
+
* @param redis - Async Redis client exposing `eval({ keys, arguments })`.
|
|
5004
|
+
* @param options - Key namespace and fail-open behavior.
|
|
5005
|
+
*/
|
|
5006
|
+
constructor(redis: RateLimitRedisLike, options?: {
|
|
5007
|
+
namespace?: string;
|
|
5008
|
+
failOpen?: boolean;
|
|
5009
|
+
});
|
|
5010
|
+
hit(key: string, maxRequests: number, windowSeconds: number): Promise<RateLimitResult>;
|
|
5011
|
+
}
|
|
5012
|
+
/** Builds a rate-limit bucket key from a request (sync or async). */
|
|
5013
|
+
type RateLimitKeyFunc = (req: Request) => string | Promise<string>;
|
|
5014
|
+
/** Minimal JWT decoder surface used by the `keyByJwt*` helpers. */
|
|
5015
|
+
interface JwtDecoderLike {
|
|
5016
|
+
decode(token: string): Promise<Record<string, unknown>>;
|
|
5017
|
+
}
|
|
5018
|
+
/** Build a key function that buckets by resolved client IP. */
|
|
5019
|
+
declare function keyByIp(options?: ClientIpOptions): RateLimitKeyFunc;
|
|
5020
|
+
/**
|
|
5021
|
+
* Build a key function that buckets by a request header value (e.g. an API
|
|
5022
|
+
* key), falling back to the client IP for anonymous callers.
|
|
5023
|
+
*/
|
|
5024
|
+
declare function keyByHeader(headerName: string, options?: {
|
|
5025
|
+
scope?: string;
|
|
5026
|
+
fallbackToIp?: boolean;
|
|
5027
|
+
trustedIpHeader?: string;
|
|
5028
|
+
}): RateLimitKeyFunc;
|
|
5029
|
+
/**
|
|
5030
|
+
* Build a key function that buckets by a claim in the bearer token, falling
|
|
5031
|
+
* back to the client IP for anonymous traffic.
|
|
5032
|
+
*/
|
|
5033
|
+
declare function keyByJwtClaim(jwt: JwtDecoderLike, claim: string, options?: {
|
|
5034
|
+
scope?: string;
|
|
5035
|
+
fallbackToIp?: boolean;
|
|
5036
|
+
trustedIpHeader?: string;
|
|
5037
|
+
}): RateLimitKeyFunc;
|
|
5038
|
+
/** Build a key function that buckets by the JWT `sub` claim (per-user). */
|
|
5039
|
+
declare function keyByJwtSubject(jwt: JwtDecoderLike, options?: {
|
|
5040
|
+
fallbackToIp?: boolean;
|
|
5041
|
+
trustedIpHeader?: string;
|
|
5042
|
+
}): RateLimitKeyFunc;
|
|
5043
|
+
/** Options for {@link rateLimitMiddleware}. */
|
|
5044
|
+
interface RateLimitOptions {
|
|
5045
|
+
/** Maximum requests per window. Default `60`. */
|
|
5046
|
+
maxRequests?: number;
|
|
5047
|
+
/** Window length in seconds. Default `60`. */
|
|
5048
|
+
windowSeconds?: number;
|
|
5049
|
+
/** Build a rate-limit key from the request. Overrides `trustedIpHeader`. */
|
|
5050
|
+
keyFunc?: RateLimitKeyFunc;
|
|
5051
|
+
/** Single edge-set header to resolve the client IP from when keying by IP. */
|
|
5052
|
+
trustedIpHeader?: string;
|
|
5053
|
+
/** Counter backend. Defaults to an in-process {@link MemoryRateLimitStore}. */
|
|
5054
|
+
store?: RateLimitStore;
|
|
5055
|
+
/** Exact paths to skip entirely (e.g. health probes). */
|
|
5056
|
+
exemptPaths?: string[];
|
|
5057
|
+
/** Whether to add a `Retry-After` header on 429s. Default `true`. */
|
|
5058
|
+
retryAfterHeader?: boolean;
|
|
5059
|
+
/** Body message of the 429 response. */
|
|
5060
|
+
errorMessage?: string;
|
|
5061
|
+
}
|
|
5062
|
+
/**
|
|
5063
|
+
* Build a sliding-window rate-limit middleware.
|
|
5064
|
+
*
|
|
5065
|
+
* @param options - Limits, key/store strategy and exemptions.
|
|
5066
|
+
* @returns An Express middleware rejecting excess traffic with `429`.
|
|
5067
|
+
* @throws {RangeError} When `maxRequests` < 1 or `windowSeconds` <= 0.
|
|
5068
|
+
*/
|
|
5069
|
+
declare function rateLimitMiddleware(options?: RateLimitOptions): RequestHandler;
|
|
5070
|
+
|
|
5071
|
+
/**
|
|
5072
|
+
* `requestTracingMiddleware` — structured per-request access logging, mirroring
|
|
5073
|
+
* the request-tracing concern of the FastAPI SDK.
|
|
5074
|
+
*
|
|
5075
|
+
* Logs one JSON line per request with method, path, status, duration and the
|
|
5076
|
+
* request id (from the request-id context), so every request is traceable in a
|
|
5077
|
+
* log aggregator. It is the lightweight, dependency-free counterpart to full
|
|
5078
|
+
* OpenTelemetry tracing — the request id correlates logs across services.
|
|
5079
|
+
*/
|
|
5080
|
+
|
|
5081
|
+
/** Options for {@link requestTracingMiddleware}. */
|
|
5082
|
+
interface RequestTracingOptions {
|
|
5083
|
+
/** Logger name. Default `tempest_express_sdk.api.tracing`. */
|
|
5084
|
+
loggerName?: string;
|
|
5085
|
+
/** Log level for completed requests. Default `"info"`. */
|
|
5086
|
+
level?: LogLevel;
|
|
5087
|
+
/** Exact paths to skip (e.g. health probes). */
|
|
5088
|
+
exemptPaths?: string[];
|
|
5089
|
+
}
|
|
5090
|
+
/**
|
|
5091
|
+
* Build an access-logging middleware. Records the request on completion with
|
|
5092
|
+
* its duration in milliseconds.
|
|
5093
|
+
*
|
|
5094
|
+
* @param options - Logger name, level and exempt paths.
|
|
5095
|
+
* @returns An Express middleware.
|
|
5096
|
+
*/
|
|
5097
|
+
declare function requestTracingMiddleware(options?: RequestTracingOptions): RequestHandler;
|
|
5098
|
+
|
|
5099
|
+
/**
|
|
5100
|
+
* OAuth2 / OIDC clients, mirroring `api.oauth`.
|
|
5101
|
+
*
|
|
5102
|
+
* Three clients out of the box: {@link GoogleOAuthClient},
|
|
5103
|
+
* {@link GitHubOAuthClient} and the generic {@link OIDCProvider} (Auth0,
|
|
5104
|
+
* Keycloak, Okta, Entra, Cognito). They cover only the OAuth2 dance — build an
|
|
5105
|
+
* authorize URL, exchange the code for tokens, fetch the user. Storing the user,
|
|
5106
|
+
* minting your own session token and setting cookies are the service's calls.
|
|
5107
|
+
*/
|
|
5108
|
+
|
|
5109
|
+
/** Raised when a provider rejects part of the OAuth dance. */
|
|
5110
|
+
declare class OAuthError extends AppException {
|
|
5111
|
+
static statusCode: number;
|
|
5112
|
+
static code: string;
|
|
5113
|
+
}
|
|
5114
|
+
/** The single normalized identity shape the rest of the app sees. */
|
|
5115
|
+
interface OAuthUser {
|
|
5116
|
+
/** Provider label (`"google"`, `"github"`, `"oidc:auth0"`, …). */
|
|
5117
|
+
provider: string;
|
|
5118
|
+
/** Stable per-provider id; pair with `provider` for a global key. */
|
|
5119
|
+
subject: string;
|
|
5120
|
+
email: string | null;
|
|
5121
|
+
name: string | null;
|
|
5122
|
+
picture: string | null;
|
|
5123
|
+
/** The raw provider payload. */
|
|
5124
|
+
raw: Record<string, unknown>;
|
|
5125
|
+
}
|
|
5126
|
+
/** The token bundle returned by a code exchange. */
|
|
5127
|
+
interface OAuthTokens {
|
|
5128
|
+
accessToken: string;
|
|
5129
|
+
tokenType: string;
|
|
5130
|
+
refreshToken: string | null;
|
|
5131
|
+
/** The OIDC id token (JWT), or `null` on plain OAuth2. */
|
|
5132
|
+
idToken: string | null;
|
|
5133
|
+
expiresIn: number | null;
|
|
5134
|
+
scope: string | null;
|
|
5135
|
+
raw: Record<string, unknown>;
|
|
5136
|
+
}
|
|
5137
|
+
/**
|
|
5138
|
+
* Generate a URL-safe random `state` value. Store it server-side (or a signed
|
|
5139
|
+
* cookie) before redirecting and compare on callback — a mismatch is a forged
|
|
5140
|
+
* redirect.
|
|
5141
|
+
*
|
|
5142
|
+
* @param nBytes - Entropy bytes. Default `32`.
|
|
5143
|
+
* @returns A URL-safe token.
|
|
5144
|
+
*/
|
|
5145
|
+
declare function generateOAuthState(nBytes?: number): string;
|
|
5146
|
+
/** Common constructor options for the OAuth clients. */
|
|
5147
|
+
interface OAuthClientOptions {
|
|
5148
|
+
clientId: string;
|
|
5149
|
+
clientSecret: string;
|
|
5150
|
+
redirectUri: string;
|
|
5151
|
+
scopes?: string[];
|
|
5152
|
+
httpClient?: HTTPClient;
|
|
5153
|
+
}
|
|
5154
|
+
/** Base class implementing the OAuth2 dance; subclasses fill in the endpoints. */
|
|
5155
|
+
declare abstract class BaseOAuthClient {
|
|
5156
|
+
abstract readonly providerName: string;
|
|
5157
|
+
protected readonly clientId: string;
|
|
5158
|
+
protected readonly clientSecret: string;
|
|
5159
|
+
protected readonly redirectUri: string;
|
|
5160
|
+
protected readonly scopes: string[];
|
|
5161
|
+
protected readonly http: HTTPClient;
|
|
5162
|
+
constructor(options: OAuthClientOptions);
|
|
5163
|
+
protected defaultScopes(): string[];
|
|
5164
|
+
/** The provider's authorization endpoint. */
|
|
5165
|
+
protected abstract authorizeUrl(): string;
|
|
5166
|
+
/** The provider's token endpoint. */
|
|
5167
|
+
protected abstract tokenUrl(): string;
|
|
5168
|
+
/** The provider's userinfo endpoint, or `null` when unavailable. */
|
|
5169
|
+
protected userinfoUrl(): string | null;
|
|
5170
|
+
/** Map a raw userinfo payload to {@link OAuthUser}. */
|
|
5171
|
+
protected abstract parseUser(payload: Record<string, unknown>): OAuthUser;
|
|
5172
|
+
/**
|
|
5173
|
+
* Build the fully-formed authorize URL to redirect the user to.
|
|
5174
|
+
*
|
|
5175
|
+
* @param state - A value from {@link generateOAuthState}, saved server-side.
|
|
5176
|
+
* @param extra - Extra query params (e.g. `{ access_type: "offline" }`).
|
|
5177
|
+
* @returns The authorize URL.
|
|
5178
|
+
*/
|
|
5179
|
+
buildAuthorizeUrl(state: string, extra?: Record<string, string>): string;
|
|
5180
|
+
/**
|
|
5181
|
+
* Exchange an authorization code for tokens.
|
|
5182
|
+
*
|
|
5183
|
+
* @param code - The `code` query param from the callback.
|
|
5184
|
+
* @returns The parsed token bundle.
|
|
5185
|
+
* @throws {OAuthError} When the provider rejects the exchange.
|
|
5186
|
+
*/
|
|
5187
|
+
exchangeCode(code: string): Promise<OAuthTokens>;
|
|
5188
|
+
/**
|
|
5189
|
+
* Fetch the normalized user identity for a token bundle.
|
|
5190
|
+
*
|
|
5191
|
+
* @param tokens - The tokens from {@link exchangeCode}.
|
|
5192
|
+
* @returns The normalized user.
|
|
5193
|
+
* @throws {OAuthError} When userinfo is unconfigured or the call fails.
|
|
5194
|
+
*/
|
|
5195
|
+
fetchUser(tokens: OAuthTokens): Promise<OAuthUser>;
|
|
5196
|
+
}
|
|
5197
|
+
/** Google identity (OIDC). Default scopes: `openid email profile`. */
|
|
5198
|
+
declare class GoogleOAuthClient extends BaseOAuthClient {
|
|
5199
|
+
readonly providerName = "google";
|
|
5200
|
+
protected defaultScopes(): string[];
|
|
5201
|
+
protected authorizeUrl(): string;
|
|
5202
|
+
protected tokenUrl(): string;
|
|
5203
|
+
protected userinfoUrl(): string;
|
|
5204
|
+
protected parseUser(payload: Record<string, unknown>): OAuthUser;
|
|
5205
|
+
}
|
|
5206
|
+
/** GitHub OAuth (no id_token; identity from `GET /user`). */
|
|
5207
|
+
declare class GitHubOAuthClient extends BaseOAuthClient {
|
|
5208
|
+
readonly providerName = "github";
|
|
5209
|
+
protected defaultScopes(): string[];
|
|
5210
|
+
protected authorizeUrl(): string;
|
|
5211
|
+
protected tokenUrl(): string;
|
|
5212
|
+
protected userinfoUrl(): string;
|
|
5213
|
+
protected parseUser(payload: Record<string, unknown>): OAuthUser;
|
|
5214
|
+
}
|
|
5215
|
+
/** Options for {@link OIDCProvider}. */
|
|
5216
|
+
interface OIDCProviderOptions extends OAuthClientOptions {
|
|
5217
|
+
authorizeUrl: string;
|
|
5218
|
+
tokenUrl: string;
|
|
5219
|
+
userinfoUrl?: string | null;
|
|
5220
|
+
providerName?: string;
|
|
5221
|
+
}
|
|
5222
|
+
/**
|
|
5223
|
+
* Generic discovery-driven OIDC client. Pass the authorize / token / userinfo
|
|
5224
|
+
* endpoints (fetch them once at boot from `${issuer}/.well-known/openid-configuration`).
|
|
5225
|
+
* Default scopes: `openid email profile`.
|
|
5226
|
+
*/
|
|
5227
|
+
declare class OIDCProvider extends BaseOAuthClient {
|
|
5228
|
+
readonly providerName: string;
|
|
5229
|
+
private readonly _authorizeUrl;
|
|
5230
|
+
private readonly _tokenUrl;
|
|
5231
|
+
private readonly _userinfoUrl;
|
|
5232
|
+
constructor(options: OIDCProviderOptions);
|
|
5233
|
+
protected defaultScopes(): string[];
|
|
5234
|
+
protected authorizeUrl(): string;
|
|
5235
|
+
protected tokenUrl(): string;
|
|
5236
|
+
protected userinfoUrl(): string | null;
|
|
5237
|
+
protected parseUser(payload: Record<string, unknown>): OAuthUser;
|
|
5238
|
+
}
|
|
5239
|
+
|
|
5240
|
+
/**
|
|
5241
|
+
* `WebhookSignatureVerifier` — HMAC signature verification for inbound
|
|
5242
|
+
* webhooks, mirroring `api.webhooks`.
|
|
5243
|
+
*
|
|
5244
|
+
* Providers compute `hmac(secret, body)` and ship the digest in a header (hex or
|
|
5245
|
+
* base64). This verifies it in constant time and exposes an Express middleware
|
|
5246
|
+
* that checks the header against the **raw** request body.
|
|
5247
|
+
*/
|
|
5248
|
+
|
|
5249
|
+
/** Options for {@link WebhookSignatureVerifier}. */
|
|
5250
|
+
interface WebhookSignatureOptions {
|
|
5251
|
+
/** Digest algorithm (e.g. `"sha256"`, `"sha512"`). Default `"sha256"`. */
|
|
5252
|
+
algorithm?: string;
|
|
5253
|
+
/** Header carrying the signature. Default `"X-Signature"`. */
|
|
5254
|
+
headerName?: string;
|
|
5255
|
+
/** Digest encoding. Default `"hex"`. */
|
|
5256
|
+
encoding?: "hex" | "base64";
|
|
5257
|
+
/** Prefix stripped from the header before comparing (e.g. `"sha256="`). */
|
|
5258
|
+
prefix?: string;
|
|
5259
|
+
}
|
|
5260
|
+
/** Verifies an HMAC webhook signature over a raw request body. */
|
|
5261
|
+
declare class WebhookSignatureVerifier {
|
|
5262
|
+
private readonly secret;
|
|
5263
|
+
private readonly algorithm;
|
|
5264
|
+
private readonly headerName;
|
|
5265
|
+
private readonly encoding;
|
|
5266
|
+
private readonly prefix;
|
|
5267
|
+
/**
|
|
5268
|
+
* @param secret - The shared signing secret.
|
|
5269
|
+
* @param options - Algorithm, header name, encoding and optional prefix.
|
|
5270
|
+
*/
|
|
5271
|
+
constructor(secret: string | Buffer, options?: WebhookSignatureOptions);
|
|
5272
|
+
/** The header name this verifier reads. */
|
|
5273
|
+
get header(): string;
|
|
5274
|
+
/**
|
|
5275
|
+
* Compute the expected signature for a raw body.
|
|
5276
|
+
*
|
|
5277
|
+
* @param body - The raw request body.
|
|
5278
|
+
* @returns The signature in the configured encoding.
|
|
5279
|
+
*/
|
|
5280
|
+
expected(body: BinaryLike): string;
|
|
5281
|
+
/**
|
|
5282
|
+
* Verify a signature against a raw body (constant time).
|
|
5283
|
+
*
|
|
5284
|
+
* @param body - The raw request body.
|
|
5285
|
+
* @param signature - The header value (including any configured prefix).
|
|
5286
|
+
* @returns `true` when it matches.
|
|
5287
|
+
*/
|
|
5288
|
+
verify(body: BinaryLike, signature: string): boolean;
|
|
5289
|
+
/**
|
|
5290
|
+
* Build an Express middleware that rejects requests with a bad signature.
|
|
5291
|
+
*
|
|
5292
|
+
* The route **must** receive the raw body as a `Buffer` — mount
|
|
5293
|
+
* `express.raw({ type: "..." })` (matching every content type) before this
|
|
5294
|
+
* middleware so `req.body` is the raw bytes. On success the request proceeds
|
|
5295
|
+
* (parse `req.body` yourself).
|
|
5296
|
+
*
|
|
5297
|
+
* @param options - Custom error message.
|
|
5298
|
+
* @returns An Express middleware.
|
|
5299
|
+
*/
|
|
5300
|
+
middleware(options?: {
|
|
5301
|
+
errorMessage?: string;
|
|
5302
|
+
}): RequestHandler;
|
|
5303
|
+
}
|
|
5304
|
+
|
|
5305
|
+
/**
|
|
5306
|
+
* `makeToolSpecRouter` — a machine-readable capability manifest at the root
|
|
5307
|
+
* prefix, mirroring `api.routers.tool_spec`.
|
|
5308
|
+
*
|
|
5309
|
+
* Services expose a small manifest so callers discover capabilities without
|
|
5310
|
+
* parsing the full OpenAPI document. Pass a static object, a sync provider, or
|
|
5311
|
+
* an async provider (recomputed per request).
|
|
5312
|
+
*/
|
|
5313
|
+
|
|
5314
|
+
/** The manifest, or a (possibly async) provider of it. */
|
|
5315
|
+
type SpecProvider = Record<string, unknown> | (() => Record<string, unknown>) | (() => Promise<Record<string, unknown>>);
|
|
5316
|
+
/** Options for {@link makeToolSpecRouter}. */
|
|
5317
|
+
interface ToolSpecOptions {
|
|
5318
|
+
/** Endpoint path. Default `"/tool-spec"`. */
|
|
5319
|
+
path?: string;
|
|
5320
|
+
}
|
|
5321
|
+
/**
|
|
5322
|
+
* Build a router serving the manifest at a root-prefix `GET` route.
|
|
5323
|
+
*
|
|
5324
|
+
* @param spec - A static object or a sync/async provider.
|
|
5325
|
+
* @param options - The endpoint path.
|
|
5326
|
+
* @returns An Express router with a single `GET` route.
|
|
5327
|
+
*/
|
|
5328
|
+
declare function makeToolSpecRouter(spec: SpecProvider, options?: ToolSpecOptions): Router;
|
|
5329
|
+
|
|
5330
|
+
/**
|
|
5331
|
+
* `makeLogsRouter` — a paginated read endpoint over the file logs, mirroring
|
|
5332
|
+
* `api.routers.logs`.
|
|
5333
|
+
*
|
|
5334
|
+
* Reads the per-level / `500.log` files written by `configureFileLogging`,
|
|
5335
|
+
* parses each JSON line, and serves the newest-first, offset-paginated. Guard it
|
|
5336
|
+
* (this exposes operational data) with any middleware you pass in `guards`.
|
|
5337
|
+
*/
|
|
5338
|
+
|
|
5339
|
+
/** Selector for which log file(s) to read. */
|
|
5340
|
+
type LogSource = "all" | "debug" | "info" | "warning" | "error" | "500";
|
|
5341
|
+
/** Options for {@link makeLogsRouter}. */
|
|
5342
|
+
interface LogsRouterOptions {
|
|
5343
|
+
/** Directory holding the log files (same one passed to `configureFileLogging`). */
|
|
5344
|
+
dir: string;
|
|
5345
|
+
/** Endpoint path. Default `"/logs"`. */
|
|
5346
|
+
path?: string;
|
|
5347
|
+
/** Middlewares run before the handler (e.g. a token guard). */
|
|
5348
|
+
guards?: RequestHandler[];
|
|
5349
|
+
}
|
|
5350
|
+
/**
|
|
5351
|
+
* Build a router serving `GET <path>` with query params `source`, `page` and
|
|
5352
|
+
* `pageSize`. Returns `{ items, total, page, pageSize, pages }`, newest first.
|
|
5353
|
+
*
|
|
5354
|
+
* @param options - Log directory, path and optional guards.
|
|
5355
|
+
* @returns An Express router.
|
|
5356
|
+
*/
|
|
5357
|
+
declare function makeLogsRouter(options: LogsRouterOptions): Router;
|
|
5358
|
+
|
|
5359
|
+
/**
|
|
5360
|
+
* In-memory test-database helpers, mirroring `testing.database`.
|
|
5361
|
+
*
|
|
5362
|
+
* Stand up a fully-wired `tempest-db-js` engine over an in-memory SQLite
|
|
5363
|
+
* database whose schema is created directly from your models — no migration
|
|
5364
|
+
* files, no temp files, no external service. One shared connection backs both
|
|
5365
|
+
* the DDL and every session, so repositories see the tables you declared.
|
|
5366
|
+
*
|
|
5367
|
+
* The helpers are framework-agnostic (no `vitest`/`jest` import), so wrap them
|
|
5368
|
+
* in whatever harness the consuming project uses.
|
|
5369
|
+
*/
|
|
5370
|
+
|
|
5371
|
+
/** A disposable in-memory test database. */
|
|
5372
|
+
interface TestDatabase {
|
|
5373
|
+
/** The wired async engine — hand its sessions to repositories. */
|
|
5374
|
+
readonly engine: AsyncEngine;
|
|
5375
|
+
/** Open a fresh session on the shared in-memory connection. */
|
|
5376
|
+
session(): AsyncSession;
|
|
5377
|
+
/** Dispose the engine and drop the in-memory database. */
|
|
5378
|
+
close(): Promise<void>;
|
|
5379
|
+
}
|
|
5380
|
+
/**
|
|
5381
|
+
* Create an in-memory SQLite test database with tables reflected from `models`.
|
|
5382
|
+
*
|
|
5383
|
+
* @param models - The model classes whose tables should be created.
|
|
5384
|
+
* @returns A {@link TestDatabase} — remember to `await close()` in teardown.
|
|
5385
|
+
*
|
|
5386
|
+
* @example
|
|
5387
|
+
* ```ts
|
|
5388
|
+
* const db = createTestDatabase([UserModel]);
|
|
5389
|
+
* const repo = new UserRepository(db.session());
|
|
5390
|
+
* await repo.create({ name: "Ana", email: "ana@x.com", passwordHash: "..." });
|
|
5391
|
+
* await db.close();
|
|
5392
|
+
* ```
|
|
5393
|
+
*/
|
|
5394
|
+
declare function createTestDatabase(models: readonly ModelClass[]): TestDatabase;
|
|
5395
|
+
/**
|
|
5396
|
+
* Run `fn` against a fresh in-memory test database, disposing it afterwards even
|
|
5397
|
+
* if `fn` throws.
|
|
5398
|
+
*
|
|
5399
|
+
* @param models - The model classes whose tables should be created.
|
|
5400
|
+
* @param fn - Receives the {@link TestDatabase} and returns a promise.
|
|
5401
|
+
* @returns Whatever `fn` resolves to.
|
|
5402
|
+
*
|
|
5403
|
+
* @example
|
|
5404
|
+
* ```ts
|
|
5405
|
+
* await withTestDatabase([UserModel], async (db) => {
|
|
5406
|
+
* const repo = new UserRepository(db.session());
|
|
5407
|
+
* expect(await repo.count()).toBe(0);
|
|
5408
|
+
* });
|
|
5409
|
+
* ```
|
|
5410
|
+
*/
|
|
5411
|
+
declare function withTestDatabase<T>(models: readonly ModelClass[], fn: (db: TestDatabase) => Promise<T>): Promise<T>;
|
|
5412
|
+
|
|
3718
5413
|
/** The installed SDK version. Single source of truth for the barrel + CLI. */
|
|
3719
|
-
declare const VERSION = "0.
|
|
5414
|
+
declare const VERSION = "0.20.0";
|
|
3720
5415
|
|
|
3721
|
-
export { type ActivationInput, ActivationService, type ActivationServiceOptions, type ActivationStore, type AdminField, type AdminListQuery, type AdminListResult, type AdminResource, type AdminRouterOptions, AdminSite, AppException, type AppExceptionHandlerOptions, type AppExceptionOptions, type AttachWebSocketOptions, AttemptThrottle, type AttemptThrottleOptions, type AuthResponse, type AuthRouterOptions, type AuthUser, type BaseAppSettings, BaseController, BaseModel, type BaseResponse, BaseService, type BrokerManager, CEP_PATTERN, CNPJ_PATTERN, CPF_PATTERN, type CPUMetrics, type CacheManager, type CachedOptions, type CatalogData, CircuitOpenError, type ClientIpOptions, CompositeFeatureFlagBackend, ConflictException, type CreateAppOpenApi, type CreateAppOptions, type CursorPaginationFilter, DEFAULT_LOCALE, type EmailMessage, type EmailOptions, EmailProvider, type EmailProviderOptions, EmailUtils, type Enum, type EnumHelpers, type EnumSpec, EnvFeatureFlagBackend, EventStream, type EventStreamOptions, type ExceptionDetails, ExpiredTokenException, type FeatureFlagBackend, FeatureFlags, type FlagContext, ForbiddenException, type GPUMetrics, type GenerateOpenApiOptions, HTTPClient, type HTTPClientOptions, HTTP_500_MARKER, type HandshakeInfo, type HealthCheck, type HealthRouterOptions, type InboundHandler, type InboundMessage, InvalidTokenException, type IssuedSession, JSONLogger, JWTUtils, type JWTUtilsOptions, type JwtAuthOptions, type JwtClaims, LocalUploadStorage, type LocalUploadStorageOptions, type LogExtra, type LogLevel, type LoginInput, type LoginResult, type MediaKind, MemoryBroker, MemoryCacheManager, MemoryFeatureFlagBackend, type MemoryMetrics, MemorySessionStore, MemoryThrottleBackend, MessageCatalog, type MessageHandler, type MessagingProvider, type MetricsRouterOptions, MetricsUtils, type MfaChallenge, type MfaChallengeInput, type MfaCodeInput, type MfaEnrollment, MfaService, type MfaServiceOptions, type MfaStore, NotFoundException, type OpenApiDocument, type OpenApiInfo, type OutboundMedia, type OutboundResult, PHONE_BR_PATTERN, type PaginationFilter, type PasswordResetConfirmInput, type PasswordResetRequestInput, PasswordResetService, type PasswordResetServiceOptions, type PasswordResetStore, PasswordUtils, REQUEST_ID_HEADER, RabbitBroker, type RabbitBrokerOptions, RedisCacheManager, type RedisLike, type RedisPublisherLike, RedisSSEBroker, type RedisSSEBrokerOptions, RedisSessionStore, type RedisSubscriberLike, type RedocOptions, type RefreshInput, Region, type RegionValue, type RegisterExceptionHandlersOptions, type RequestContext, type ResponseMapper, RetryPolicy, type RunServerOptions, SSEBroker, type SaveOptions, type SendOptions, ServerSentEvent, type ServerSentEventInit, type Session, type SessionMiddlewareOptions, type SessionRedisLike, SessionService, type SessionServiceOptions, type SessionStore, type SignupInput, type StateBR, type SwaggerOptions, type SystemMetrics, TOTPHelper, type TOTPOptions, type TaskHandler, TaskManager, type TaskManagerOptions, TelegramProvider, type TelegramProviderOptions, type ThrottleBackend, type ThrottleStatus, type ToDictOptions, type TokenPair, TooManyRequestsException, type TooManyRequestsOptions, TwilioSmsProvider, type TwilioSmsProviderOptions, type TwilioWebhookOptions, UF, type UFValue, UnauthorizedException, type UnhandledExceptionHandlerOptions, type UploadResult, type UploadStorage, UserAuthService, type UserAuthServiceOptions, type UserPublic, type UserStore, VERSION, ValidationException, type WSEnvelope, WebPushDispatcher, type WebPushDispatcherOptions, WebPushError, WebPushGoneError, type WebPushKeys, type WebPushPayload, type WebPushSubscription, type WebSocketConnection, WebSocketHub, type WebSocketHubOptions, type WebSocketLike, WhatsAppProvider, type WhatsAppProviderOptions, type WhatsAppWebhookOptions, activationSchema, attachWebSocketHub, authResponseSchema, baseAppSettingsSchema, baseAppSettingsShape, baseResponseSchema, bearerToken, buildContentDisposition, cached, cepField, citiesByUf, cnpjField, coerceFlag, configureLogging, corsSettingsShape, cpfField, cpfOrCnpjField, createApp, createOpenApiRegistry, createdByColumn, cursorPaginationFilterSchema, cursorPaginationSchema, databaseSettingsShape, decodeCursor, defaultMessageCatalog, defineEnum, deletedAtColumn, encodeCursor, generateOpaqueToken, generateOpenApiDocument, getAuth, getClientIp, getConditions, getPaginationConditions, getRequestId, getState, hashOpaqueToken, inboundMessageSchema, isValidCep, isValidCity, isValidCnpj, isValidCpf, isValidCpfCnpj, isValidPhoneBr, isValidUf, listStates, loadSettings, loginSchema, makeAdminRouter, makeAppExceptionHandler, makeAuthRouter, makeFlagGuard, makeHealthRouter, makeJwtAuthMiddleware, makeMetricsRouter, makeSessionMiddleware, makeTwilioWebhookRouter, makeUnhandledExceptionHandler, makeWhatsAppWebhookRouter, mfaChallengeSchema, mfaCodeSchema, mfaEnrollResponseSchema, modifyDict, mountOpenApiJson, mountRedoc, mountSwaggerUi, normalizeCep, normalizeCnpj, normalizeCpf, normalizeCpfCnpj, normalizePhoneBr, normalizeUf, notFoundHandler, onlyDigits, paginationFilterSchema, paginationSchema, parseAcceptLanguage, parseCookies, passwordResetConfirmSchema, passwordResetRequestSchema, phoneBrField, refreshSchema, registerExceptionHandlers, requestIdMiddleware, requireRoles, runServer, runWithRequestContext, serverSettingsShape, sessionCookie, setRequestId, signupSchema, sseResponse, statesByRegion, tableNameFor, toDict, toUtc, tokenFromUrl, tokenPairSchema, ufField, updatedByColumn, userPublicSchema, utcnow, validateTwilioSignature, verifyOpaqueToken, webPushKeysSchema, webPushPayloadSchema, webPushSubscriptionSchema, wsEnvelopeSchema };
|
|
5416
|
+
export { type ActivationInput, ActivationService, type ActivationServiceOptions, type ActivationStore, type AdminField, type AdminListQuery, type AdminListResult, type AdminResource, type AdminRouterOptions, AdminSite, AppException, type AppExceptionHandlerOptions, type AppExceptionOptions, type AttachWebSocketOptions, AttemptThrottle, type AttemptThrottleOptions, AuditAction, type AuthResponse, type AuthResultPageOptions, type AuthRouterOptions, type AuthUser, type BackupOptions, type BaseAppSettings, BaseAuditLogModel, BaseController, BaseModel, BaseOAuthClient, BaseOutboxModel, type BaseResponse, BaseService, BaseUserModel, BaseUserRefreshTokenModel, BaseUserTokenModel, type BodySizeLimitOptions, type BroadcastOptions, type BroadcastResult, type BrokerManager, CEP_PATTERN, CNPJ_PATTERN, CPF_PATTERN, type CPUMetrics, CSRF_COOKIE_NAME, CSRF_HEADER_NAME, type CacheManager, type CachedOptions, type CachedResponse, type CatalogData, CircuitOpenError, type ClientIpOptions, CompositeFeatureFlagBackend, ConflictException, type CreateAppOpenApi, type CreateAppOptions, type CsrfOptions, type CursorPaginationFilter, DEFAULT_LOCALE, type DownloadOptions, type EmailMessage, type EmailOptions, EmailProvider, type EmailProviderOptions, EmailUtils, type Enum, type EnumHelpers, type EnumSpec, EnvFeatureFlagBackend, EventStream, type EventStreamOptions, type ExceptionDetails, ExpiredTokenException, type FeatureFlagBackend, FeatureFlags, type FieldChange, type FileLoggingHandle, type FileLoggingOptions, type FlagContext, ForbiddenException, type GPUMetrics, type GenerateOpenApiOptions, GitHubOAuthClient, GoogleOAuthClient, GracefulShutdown, type GracefulShutdownOptions, HTTPClient, type HTTPClientOptions, HTTP_500_LOG_FILE, HTTP_500_MARKER, type HandshakeInfo, type HealthCheck, type HealthRouterOptions, HttpMetrics, IDEMPOTENCY_HEADER, type IdempotencyOptions, type IdempotencyRedisLike, type IdempotencyStore, type InboundHandler, type InboundMessage, InvalidTokenException, type IssuedSession, JSONLogger, JWTUtils, type JWTUtilsOptions, type JwtAuthOptions, type JwtClaims, type JwtDecoderLike, LEVEL_LOG_FILES, LocalUploadStorage, type LocalUploadStorageOptions, type LogEntry, type LogExtra, type LogLevel, type LogSink, type LogSource, type LoginInput, type LoginResult, type LogsRouterOptions, type MediaKind, MemoryBroker, MemoryCacheManager, MemoryFeatureFlagBackend, MemoryIdempotencyStore, type MemoryMetrics, MemoryRateLimitStore, MemorySessionStore, MemoryThrottleBackend, MessageCatalog, type MessageHandler, MessagingHub, type MessagingProvider, type MetricsRouterOptions, MetricsUtils, type MfaChallenge, type MfaChallengeInput, type MfaCodeInput, type MfaEnrollment, MfaService, type MfaServiceOptions, type MfaStore, NotFoundException, type OAuthClientOptions, OAuthError, type OAuthTokens, type OAuthUser, OIDCProvider, type OIDCProviderOptions, type OpenApiDocument, type OpenApiInfo, type OutboundMedia, type OutboundResult, type OutboxPublisher, OutboxRelay, type OutboxRelayOptions, OutboxStatus, PHONE_BR_PATTERN, type PaginationFilter, type PaginationLinkOptions, type PasswordResetConfirmInput, type PasswordResetFormOptions, type PasswordResetRequestInput, PasswordResetService, type PasswordResetServiceOptions, type PasswordResetStore, PasswordUtils, REQUEST_ID_HEADER, RabbitBroker, type RabbitBrokerOptions, type RateLimitKeyFunc, type RateLimitOptions, type RateLimitRedisLike, type RateLimitResult, type RateLimitStore, RedisCacheManager, RedisIdempotencyStore, type RedisLike, type RedisPublisherLike, RedisRateLimitStore, RedisSSEBroker, type RedisSSEBrokerOptions, RedisSessionStore, type RedisSubscriberLike, type RedocOptions, type RefreshInput, Region, type RegionValue, type RegisterExceptionHandlersOptions, type RequestContext, type RequestTracingOptions, type ResponseMapper, RetryPolicy, type RunServerOptions, type S3ClientLike, S3UploadStorage, type S3UploadStorageOptions, SSEBroker, type SaveOptions, type SendOptions, ServerSentEvent, type ServerSentEventInit, type Session, type SessionMiddlewareOptions, type SessionRedisLike, SessionService, type SessionServiceOptions, type SessionStore, type SignupInput, type SlowQueryOptions, type SpecProvider, type StateBR, type SwaggerOptions, type SyncFilter, type SystemMetrics, TOTPHelper, type TOTPOptions, type TaskHandler, TaskManager, type TaskManagerOptions, TelegramProvider, type TelegramProviderOptions, TenantScopedRepository, type TestDatabase, type ThrottleBackend, type ThrottleStatus, type ToDictOptions, type TokenPair, TooManyRequestsException, type TooManyRequestsOptions, type ToolSpecOptions, TwilioSmsProvider, type TwilioSmsProviderOptions, type TwilioWebhookOptions, UF, type UFValue, UnauthorizedException, type UnhandledExceptionHandlerOptions, type UploadResult, type UploadStorage, UserAuthService, type UserAuthServiceOptions, type UserPublic, type UserStore, UserTokenPurpose, VERSION, ValidationException, type WSEnvelope, WebPushDispatcher, type WebPushDispatcherOptions, WebPushError, WebPushGoneError, type WebPushKeys, type WebPushPayload, type WebPushSubscription, type WebSocketConnection, WebSocketHub, type WebSocketHubOptions, type WebSocketLike, type WebhookSignatureOptions, WebhookSignatureVerifier, WhatsAppProvider, type WhatsAppProviderOptions, type WhatsAppWebhookOptions, activationSchema, addLogSink, attachWebSocketHub, authResponseSchema, authSettingsShape, backupDatabase, baseAppSettingsSchema, baseAppSettingsShape, baseResponseSchema, bearerToken, bodySizeLimitMiddleware, broadcastText, buildContentDisposition, buildPaginationLinkHeader, cached, centsField, cepField, citiesByUf, cnpjField, coerceFlag, configureFileLogging, configureLogging, corsSettingsShape, cpfField, cpfOrCnpjField, createApp, createOpenApiRegistry, createTestDatabase, createdByColumn, csrfMiddleware, cursorPaginationFilterSchema, cursorPaginationSchema, databaseSettingsShape, decodeCursor, defaultMessageCatalog, defineEnum, deletedAtColumn, diffSnapshots, emailSettingsShape, encodeCursor, envBoolean, envList, generateCsrfToken, generateOAuthState, generateOpaqueToken, generateOpenApiDocument, getAuth, getClientIp, getConditions, getPaginationConditions, getRequestId, getState, hashOpaqueToken, hexColorField, idempotencyMiddleware, inboundMessageSchema, isValidCep, isValidCity, isValidCnpj, isValidCpf, isValidCpfCnpj, isValidPhoneBr, isValidUf, jwtSettingsShape, keyByHeader, keyByIp, keyByJwtClaim, keyByJwtSubject, latitudeField, listStates, loadSettings, logEntrySchema, logSettingsShape, loginSchema, longitudeField, makeAdminRouter, makeAppExceptionHandler, makeAuthRouter, makeFlagGuard, makeHealthRouter, makeJwtAuthMiddleware, makeLogsRouter, makeMetricsRouter, makeSessionMiddleware, makeToolSpecRouter, makeTwilioWebhookRouter, makeUnhandledExceptionHandler, makeWhatsAppWebhookRouter, mfaChallengeSchema, mfaCodeSchema, mfaEnrollResponseSchema, minioSettingsShape, modifyDict, mountOpenApiJson, mountRedoc, mountSwaggerUi, nonEmptyStrField, nonNegativeFloatField, nonNegativeIntField, normalizeCep, normalizeCnpj, normalizeCpf, normalizeCpfCnpj, normalizePhoneBr, normalizeUf, notFoundHandler, onlyDigits, paginationFilterSchema, paginationSchema, parseAcceptLanguage, parseCookies, passwordResetConfirmSchema, passwordResetRequestSchema, percentField, phoneBrField, portField, positiveFloatField, positiveIntField, priceField, prometheusMiddleware, rabbitmqSettingsShape, rateLimitMiddleware, ratingField, ratioField, redisSettingsShape, refreshSchema, registerExceptionHandlers, renderAuthResultPage, renderPasswordResetFormPage, requestIdMiddleware, requestTracingMiddleware, requireRoles, resolveDownloadPath, runServer, runWithRequestContext, sendBytesDownload, sendFileDownload, serverSettingsShape, sessionCookie, sessionSettingsShape, setRequestId, signupSchema, slugField, snapshot, sseResponse, statesByRegion, syncFilterSchema, syncPaginationSchema, tableNameFor, toDict, toUtc, tokenFromUrl, tokenPairSchema, tokenSettingsShape, ufField, updatedByColumn, uploadSettingsShape, userPublicSchema, utcnow, validateTwilioSignature, verifyOpaqueToken, webPushKeysSchema, webPushPayloadSchema, webPushSettingsShape, webPushSubscriptionSchema, webSocketSettingsShape, withTestDatabase, wrapWithSlowQueryLog, wsEnvelopeSchema };
|