@getstrata/core 0.2.0 → 0.3.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.
Files changed (129) hide show
  1. package/README.md +6 -0
  2. package/dist/bootstrap/applicationRegistry.d.ts +16 -0
  3. package/dist/bootstrap/config.d.ts +19 -0
  4. package/dist/bootstrap/contracts.d.ts +63 -0
  5. package/dist/bootstrap/httpKernel.d.ts +26 -0
  6. package/dist/config/app.d.ts +10 -0
  7. package/dist/config/contentSecurityPolicy.d.ts +5 -0
  8. package/dist/config/cors.d.ts +9 -0
  9. package/dist/config/database.d.ts +10 -0
  10. package/dist/config/features.d.ts +18 -0
  11. package/dist/config/frontend.d.ts +6 -0
  12. package/dist/config/rateLimit.d.ts +9 -0
  13. package/dist/config/uploads.d.ts +5 -0
  14. package/dist/core/auth/accessControl.d.ts +8 -0
  15. package/dist/core/auth/authContext.d.ts +12 -0
  16. package/dist/core/auth/guard.d.ts +36 -0
  17. package/dist/core/auth/membershipContext.d.ts +16 -0
  18. package/dist/core/auth/membershipContextMiddleware.d.ts +3 -0
  19. package/dist/core/auth/membershipMiddleware.d.ts +2 -0
  20. package/dist/core/auth/oauth/oidcProvider.d.ts +18 -0
  21. package/dist/core/auth/oauth/providers.d.ts +22 -0
  22. package/dist/core/auth/oauth/samlProvider.d.ts +9 -0
  23. package/dist/core/auth/oauth/types.d.ts +11 -0
  24. package/dist/core/auth/password.d.ts +3 -0
  25. package/dist/core/auth/policy.d.ts +15 -0
  26. package/dist/core/auth/tokenHash.d.ts +3 -0
  27. package/dist/core/cache/repository.d.ts +17 -0
  28. package/dist/core/cache/store.d.ts +12 -0
  29. package/dist/core/cache/taggedCache.d.ts +9 -0
  30. package/dist/core/cache/tags.d.ts +11 -0
  31. package/dist/core/crypto/fieldEncryption.d.ts +13 -0
  32. package/dist/core/crypto/mfaSecret.d.ts +3 -0
  33. package/dist/core/database/baseRepository.d.ts +44 -0
  34. package/dist/core/database/connection.d.ts +7 -0
  35. package/dist/core/database/connectionContext.d.ts +7 -0
  36. package/dist/core/database/errors.d.ts +12 -0
  37. package/dist/core/database/index.d.ts +11 -0
  38. package/dist/core/database/query.d.ts +51 -0
  39. package/dist/core/database/relationships.d.ts +26 -0
  40. package/dist/core/database/table.d.ts +13 -0
  41. package/dist/core/database/transaction.d.ts +3 -0
  42. package/dist/core/database/types.d.ts +29 -0
  43. package/dist/core/errors/http.d.ts +33 -0
  44. package/dist/core/events/eventBus.d.ts +10 -0
  45. package/dist/core/events/index.d.ts +4 -0
  46. package/dist/core/facades/index.d.ts +10 -0
  47. package/dist/core/http/authMiddleware.d.ts +5 -0
  48. package/dist/core/http/authorizeMiddleware.d.ts +5 -0
  49. package/dist/core/http/bodySizeLimitMiddleware.d.ts +4 -0
  50. package/dist/core/http/conditionalResponse.d.ts +2 -0
  51. package/dist/core/http/contentNegotiation.d.ts +2 -0
  52. package/dist/core/http/corsMiddleware.d.ts +3 -0
  53. package/dist/core/http/csrfMiddleware.d.ts +3 -0
  54. package/dist/core/http/csrfToken.d.ts +14 -0
  55. package/dist/core/http/etag.d.ts +18 -0
  56. package/dist/core/http/flashMiddleware.d.ts +3 -0
  57. package/dist/core/http/flashSession.d.ts +12 -0
  58. package/dist/core/http/formRequest.d.ts +10 -0
  59. package/dist/core/http/index.d.ts +27 -0
  60. package/dist/core/http/loginThrottleMiddleware.d.ts +11 -0
  61. package/dist/core/http/memoryThrottleMiddleware.d.ts +9 -0
  62. package/dist/core/http/metricsMiddleware.d.ts +4 -0
  63. package/dist/core/http/middleware.d.ts +8 -0
  64. package/dist/core/http/pagination.d.ts +11 -0
  65. package/dist/core/http/parseFormBody.d.ts +6 -0
  66. package/dist/core/http/parseMultipartUpload.d.ts +10 -0
  67. package/dist/core/http/requestMetaContext.d.ts +16 -0
  68. package/dist/core/http/requireAbilityMiddleware.d.ts +4 -0
  69. package/dist/core/http/requireAuthMiddleware.d.ts +4 -0
  70. package/dist/core/http/requireGlobalAdminMiddleware.d.ts +3 -0
  71. package/dist/core/http/requireWebAuthMiddleware.d.ts +4 -0
  72. package/dist/core/http/resources.d.ts +7 -0
  73. package/dist/core/http/route.d.ts +6 -0
  74. package/dist/core/http/routeMiddleware.d.ts +3 -0
  75. package/dist/core/http/routeModelBinding.d.ts +3 -0
  76. package/dist/core/http/securedRouteModelBinding.d.ts +10 -0
  77. package/dist/core/http/securityHeadersMiddleware.d.ts +3 -0
  78. package/dist/core/http/throttleMiddleware.d.ts +11 -0
  79. package/dist/core/http/validation.d.ts +23 -0
  80. package/dist/core/http/webErrorResponse.d.ts +5 -0
  81. package/dist/core/http/webFormRequest.d.ts +6 -0
  82. package/dist/core/logging/logger.d.ts +17 -0
  83. package/dist/core/logging/requestLoggingMiddleware.d.ts +3 -0
  84. package/dist/core/mail/mailer.d.ts +36 -0
  85. package/dist/core/metrics/prometheus.d.ts +26 -0
  86. package/dist/core/pagination/index.d.ts +17 -0
  87. package/dist/core/queue/index.d.ts +19 -0
  88. package/dist/core/security/publicReads.d.ts +3 -0
  89. package/dist/core/security/securityEvents.d.ts +6 -0
  90. package/dist/core/security/tokenExpiry.d.ts +2 -0
  91. package/dist/core/security/totp.d.ts +3 -0
  92. package/dist/core/storage/storage.d.ts +41 -0
  93. package/dist/core/tenant/databaseTenantContext.d.ts +2 -0
  94. package/dist/core/tenant/resolveTenant.d.ts +3 -0
  95. package/dist/core/tenant/tenantContext.d.ts +14 -0
  96. package/dist/core/tenant/tenantDatabaseScope.d.ts +7 -0
  97. package/dist/core/tenant/tenantMiddleware.d.ts +6 -0
  98. package/dist/core/tracing/otel.d.ts +26 -0
  99. package/dist/core/tracing/traceContext.d.ts +10 -0
  100. package/dist/core/tracing/tracingMiddleware.d.ts +3 -0
  101. package/dist/core/view/etaViewEngine.d.ts +15 -0
  102. package/dist/core/view/htmlResponse.d.ts +6 -0
  103. package/dist/core/view/index.d.ts +5 -0
  104. package/dist/core/view/viewEngine.d.ts +6 -0
  105. package/dist/core/view/webLayoutData.d.ts +17 -0
  106. package/dist/db/connection/createConnection.d.ts +6 -0
  107. package/dist/db/connection/index.d.ts +11 -0
  108. package/dist/domain/abilities.d.ts +5 -0
  109. package/dist/domain/auth.d.ts +4 -0
  110. package/dist/framework/public-api.d.ts +30 -0
  111. package/dist/index.js +17 -2
  112. package/dist/modules/organization/memberRepository.d.ts +14 -0
  113. package/dist/modules/organization/memberTypes.d.ts +9 -0
  114. package/dist/modules/user/apiTokenRepository.d.ts +8 -0
  115. package/dist/modules/user/apiTokenTable.d.ts +3 -0
  116. package/dist/modules/user/authService.d.ts +23 -0
  117. package/dist/modules/user/notificationRepository.d.ts +6 -0
  118. package/dist/modules/user/notificationService.d.ts +25 -0
  119. package/dist/modules/user/notificationTable.d.ts +3 -0
  120. package/dist/modules/user/notificationTypes.d.ts +12 -0
  121. package/dist/modules/user/oauthIdentityRepository.d.ts +9 -0
  122. package/dist/modules/user/provider.d.ts +11 -0
  123. package/dist/modules/user/repository.d.ts +12 -0
  124. package/dist/modules/user/table.d.ts +3 -0
  125. package/dist/modules/user/tokenService.d.ts +29 -0
  126. package/dist/modules/user/types.d.ts +46 -0
  127. package/dist/types/services.d.ts +16 -0
  128. package/package.json +7 -6
  129. package/index.ts +0 -1
@@ -0,0 +1,26 @@
1
+ interface HasManyRelation<TParent, TChild, LocalKey extends keyof TParent & string = keyof TParent & string, ForeignKey extends keyof TChild & string = keyof TChild & string> {
2
+ type: "hasMany";
3
+ name: string;
4
+ localKey: LocalKey;
5
+ foreignKey: ForeignKey;
6
+ }
7
+ interface BelongsToRelation<TChild, TParent, ForeignKey extends keyof TChild & string = keyof TChild & string, OwnerKey extends keyof TParent & string = keyof TParent & string> {
8
+ type: "belongsTo";
9
+ name: string;
10
+ foreignKey: ForeignKey;
11
+ ownerKey: OwnerKey;
12
+ }
13
+ declare function hasMany<TParent, TChild, LocalKey extends keyof TParent & string = keyof TParent & string, ForeignKey extends keyof TChild & string = keyof TChild & string>(definition: {
14
+ name: string;
15
+ localKey: LocalKey;
16
+ foreignKey: ForeignKey;
17
+ }): HasManyRelation<TParent, TChild, LocalKey, ForeignKey>;
18
+ declare function belongsTo<TChild, TParent, ForeignKey extends keyof TChild & string = keyof TChild & string, OwnerKey extends keyof TParent & string = keyof TParent & string>(definition: {
19
+ name: string;
20
+ foreignKey: ForeignKey;
21
+ ownerKey: OwnerKey;
22
+ }): BelongsToRelation<TChild, TParent, ForeignKey, OwnerKey>;
23
+ declare function indexHasManyRelation<TParent, TChild, LocalKey extends keyof TParent & string, ForeignKey extends keyof TChild & string>(parents: readonly TParent[], children: readonly TChild[], relation: HasManyRelation<TParent, TChild, LocalKey, ForeignKey>): Map<TParent[LocalKey], TChild[]>;
24
+ declare function indexBelongsToRelation<TChild, TParent, ForeignKey extends keyof TChild & string, OwnerKey extends keyof TParent & string>(children: readonly TChild[], parents: readonly TParent[], relation: BelongsToRelation<TChild, TParent, ForeignKey, OwnerKey>): Map<TChild[ForeignKey], TParent>;
25
+ export type { BelongsToRelation, HasManyRelation };
26
+ export { belongsTo, hasMany, indexBelongsToRelation, indexHasManyRelation };
@@ -0,0 +1,13 @@
1
+ import type { QueryOrder } from "./types.ts";
2
+ interface TableDefinition<TEntity, PrimaryKey extends keyof TEntity & string = keyof TEntity & string> {
3
+ name: string;
4
+ primaryKey: PrimaryKey;
5
+ columns: readonly (keyof TEntity & string)[];
6
+ defaultOrderBy?: QueryOrder<TEntity> | QueryOrder<TEntity>[];
7
+ softDeletes?: boolean | {
8
+ column?: keyof TEntity & string;
9
+ };
10
+ }
11
+ declare function defineTable<TEntity, PrimaryKey extends keyof TEntity & string = keyof TEntity & string>(definition: TableDefinition<TEntity, PrimaryKey>): TableDefinition<TEntity, PrimaryKey>;
12
+ export type { TableDefinition };
13
+ export { defineTable };
@@ -0,0 +1,3 @@
1
+ import type { DatabaseConnection } from "./baseRepository.ts";
2
+ declare function runInTransaction<TValue>(operation: (connection: DatabaseConnection) => Promise<TValue>): Promise<TValue>;
3
+ export { runInTransaction };
@@ -0,0 +1,29 @@
1
+ type DatabaseComparable = string | number | Date;
2
+ type DatabaseScalar = DatabaseComparable | boolean | null;
3
+ type QueryOperator = {
4
+ eq?: DatabaseScalar;
5
+ in?: readonly DatabaseScalar[];
6
+ gt?: DatabaseComparable;
7
+ gte?: DatabaseComparable;
8
+ lt?: DatabaseComparable;
9
+ lte?: DatabaseComparable;
10
+ isNull?: boolean;
11
+ };
12
+ type QueryFilterValue = DatabaseScalar | readonly DatabaseScalar[] | QueryOperator;
13
+ type QueryWhere<TEntity> = Partial<Record<keyof TEntity & string, QueryFilterValue>>;
14
+ type QueryOrder<TEntity> = {
15
+ column: keyof TEntity & string;
16
+ direction?: "ASC" | "DESC" | "asc" | "desc";
17
+ };
18
+ type QueryOrderShorthand<TEntity> = Partial<Record<keyof TEntity & string, "ASC" | "DESC" | "asc" | "desc">>;
19
+ interface QueryOptions<TEntity> {
20
+ where?: QueryWhere<TEntity>;
21
+ orderBy?: QueryOrder<TEntity> | QueryOrder<TEntity>[] | QueryOrderShorthand<TEntity>;
22
+ limit?: number;
23
+ offset?: number;
24
+ withTrashed?: boolean;
25
+ onlyTrashed?: boolean;
26
+ }
27
+ type MutationValues<TEntity> = Partial<TEntity>;
28
+ type UpdateValues<TEntity, PrimaryKey extends keyof TEntity & string = keyof TEntity & string> = Partial<Omit<TEntity, PrimaryKey>>;
29
+ export type { DatabaseComparable, DatabaseScalar, MutationValues, QueryFilterValue, QueryOperator, QueryOptions, QueryOrder, QueryWhere, UpdateValues, };
@@ -0,0 +1,33 @@
1
+ declare class HttpError extends Error {
2
+ readonly status: number;
3
+ readonly details?: unknown;
4
+ constructor(status: number, message: string, details?: unknown);
5
+ }
6
+ declare class BadRequestError extends HttpError {
7
+ constructor(message?: string, details?: unknown);
8
+ }
9
+ declare class NotFoundError extends HttpError {
10
+ constructor(message?: string, details?: unknown);
11
+ }
12
+ declare class ConflictError extends HttpError {
13
+ constructor(message?: string, details?: unknown);
14
+ }
15
+ declare class UnprocessableEntityError extends HttpError {
16
+ constructor(message?: string, details?: unknown);
17
+ }
18
+ declare class ValidationError extends HttpError {
19
+ constructor(message?: string, details?: unknown);
20
+ }
21
+ declare class ForbiddenError extends HttpError {
22
+ constructor(message?: string, details?: unknown);
23
+ }
24
+ declare class UnauthorizedError extends HttpError {
25
+ constructor(message?: string, details?: unknown);
26
+ }
27
+ declare class PayloadTooLargeError extends HttpError {
28
+ constructor(message?: string, details?: unknown);
29
+ }
30
+ declare class PreconditionFailedError extends HttpError {
31
+ constructor(message?: string, details?: unknown);
32
+ }
33
+ export { BadRequestError, ConflictError, ForbiddenError, HttpError, NotFoundError, PayloadTooLargeError, PreconditionFailedError, UnauthorizedError, UnprocessableEntityError, ValidationError, };
@@ -0,0 +1,10 @@
1
+ type EventListener = (payload: unknown) => void | Promise<void>;
2
+ declare class EventBus {
3
+ constructor();
4
+ private readonly listeners;
5
+ listen(event: string, listener: EventListener): () => void;
6
+ dispatch(event: string, payload: unknown): Promise<void>;
7
+ }
8
+ declare const eventBus: EventBus;
9
+ export type { EventListener };
10
+ export { EventBus, eventBus };
@@ -0,0 +1,4 @@
1
+ export type { EventListener } from "./eventBus";
2
+ export { EventBus, eventBus } from "./eventBus";
3
+ declare function modelEventName(tableName: string, action: string): string;
4
+ export { modelEventName };
@@ -0,0 +1,10 @@
1
+ declare function cache(): import("../../types/services").CacheLike;
2
+ declare function auth(): import("../auth/guard").AuthManager;
3
+ declare function policyGate(): import("../auth/policy").PolicyGate;
4
+ declare function queue(): import("../queue").Queue;
5
+ declare function events(): import("../events").EventBus;
6
+ declare function config<T>(key: string): T | undefined;
7
+ declare function log(): import("../logging/logger").Logger;
8
+ declare function mail(): import("../mail/mailer").Mailer;
9
+ declare function storageFacade(): import("../storage/storage").StorageManager;
10
+ export { auth, cache, config, events, log, mail, policyGate, queue, storageFacade as storage };
@@ -0,0 +1,5 @@
1
+ import { type AuthUser, authContext } from "../auth/authContext";
2
+ import type { AuthManager } from "../auth/guard";
3
+ declare function createAuthMiddleware(auth: AuthManager): (request: Request, next: () => Promise<Response>) => Promise<Response>;
4
+ export type { AuthUser };
5
+ export { authContext, createAuthMiddleware };
@@ -0,0 +1,5 @@
1
+ import type { AuthManager } from "../auth/guard";
2
+ import type { Policy, PolicyGate } from "../auth/policy";
3
+ import type { Middleware } from "./middleware";
4
+ declare function createAuthorizeMiddleware(gate: PolicyGate, auth: AuthManager, resource: string, action: keyof Policy): Middleware;
5
+ export { createAuthorizeMiddleware };
@@ -0,0 +1,4 @@
1
+ import type { Middleware } from "./middleware";
2
+ declare function resolveMaxBodyBytes(): number;
3
+ declare function createBodySizeLimitMiddleware(maxBytes?: number): Middleware;
4
+ export { createBodySizeLimitMiddleware, resolveMaxBodyBytes };
@@ -0,0 +1,2 @@
1
+ declare function conditionalJsonResponse(request: Request | undefined, data: unknown, init?: ResponseInit): Response;
2
+ export { conditionalJsonResponse };
@@ -0,0 +1,2 @@
1
+ declare function requestPrefersJson(request?: Request): boolean;
2
+ export { requestPrefersJson };
@@ -0,0 +1,3 @@
1
+ import type { Middleware } from "./middleware";
2
+ declare function createCorsMiddleware(): Middleware;
3
+ export { createCorsMiddleware };
@@ -0,0 +1,3 @@
1
+ import type { Middleware } from "./middleware";
2
+ declare function createCsrfMiddleware(): Middleware;
3
+ export { createCsrfMiddleware };
@@ -0,0 +1,14 @@
1
+ declare const CSRF_COOKIE = "workhub_csrf";
2
+ declare function createCsrfTokenCookie(): {
3
+ token: string;
4
+ cookie: string;
5
+ };
6
+ declare function resolveCsrfToken(request: Request): {
7
+ token: string;
8
+ cookie?: string;
9
+ };
10
+ declare function readSubmittedCsrfToken(request: Request): string | null;
11
+ declare function readSubmittedCsrfTokenFromBody(request: Request): Promise<string | null>;
12
+ declare function verifyCsrfToken(request: Request, submittedToken: string | null): boolean;
13
+ declare function resolveCsrfTokenForRequest(request: Request): string;
14
+ export { CSRF_COOKIE, createCsrfTokenCookie, readSubmittedCsrfToken, readSubmittedCsrfTokenFromBody, resolveCsrfToken, resolveCsrfTokenForRequest, verifyCsrfToken, };
@@ -0,0 +1,18 @@
1
+ interface EtagVersioned {
2
+ id?: number | string;
3
+ updated_at?: Date | string | null;
4
+ created_at?: Date | string | null;
5
+ }
6
+ declare function isEtagEnabled(): boolean;
7
+ declare function computeEtagFromJson(data: unknown): string;
8
+ declare function etagFromResource(resource: EtagVersioned): string;
9
+ declare function etagValuesMatch(left: string, right: string): boolean;
10
+ declare function ifNoneMatchSatisfied(request: Request, etag: string): boolean;
11
+ declare function ifMatchSatisfied(request: Request, etag: string): boolean;
12
+ declare function assertIfMatch(request: Request, etag: string, options?: {
13
+ required?: boolean;
14
+ }): void;
15
+ declare function notModifiedResponse(etag: string): Response;
16
+ declare function applyConditionalGet(request: Request, response: Response, etag: string): Response;
17
+ export type { EtagVersioned };
18
+ export { applyConditionalGet, assertIfMatch, computeEtagFromJson, etagFromResource, etagValuesMatch, ifMatchSatisfied, ifNoneMatchSatisfied, isEtagEnabled, notModifiedResponse, };
@@ -0,0 +1,3 @@
1
+ import type { Middleware } from "./middleware";
2
+ declare function createFlashMiddleware(): Middleware;
3
+ export { createFlashMiddleware };
@@ -0,0 +1,12 @@
1
+ type FlashLevel = "success" | "error" | "info";
2
+ interface FlashMessage {
3
+ level: FlashLevel;
4
+ message: string;
5
+ }
6
+ declare function createFlashCookie(message: FlashMessage): string;
7
+ declare function clearFlashCookie(): string;
8
+ declare function pullFlash(request: Request): FlashMessage | null;
9
+ declare function flashResponse(response: Response, message: FlashMessage): Response;
10
+ declare function withFlashClear(response: Response): Response;
11
+ export type { FlashLevel, FlashMessage };
12
+ export { clearFlashCookie, createFlashCookie, flashResponse, pullFlash, withFlashClear };
@@ -0,0 +1,10 @@
1
+ declare abstract class FormRequest<TOutput> {
2
+ authorize(_request: Request): boolean | Promise<boolean>;
3
+ protected abstract parse(payload: unknown): TOutput;
4
+ validate(request: Request): Promise<TOutput>;
5
+ }
6
+ declare abstract class QueryFormRequest<TOutput> {
7
+ validate(request?: Request): TOutput;
8
+ protected abstract parseQuery(request?: Request): TOutput;
9
+ }
10
+ export { FormRequest, QueryFormRequest };
@@ -0,0 +1,27 @@
1
+ export { BadRequestError, ConflictError, ForbiddenError, HttpError, NotFoundError, PayloadTooLargeError, PreconditionFailedError, UnauthorizedError, UnprocessableEntityError, ValidationError, } from "../errors/http";
2
+ export type { PaginatedResult, PaginationMeta } from "../pagination";
3
+ export { createAuthMiddleware } from "./authMiddleware";
4
+ export { createAuthorizeMiddleware } from "./authorizeMiddleware";
5
+ export { conditionalJsonResponse } from "./conditionalResponse";
6
+ export type { EtagVersioned } from "./etag";
7
+ export { applyConditionalGet, assertIfMatch, computeEtagFromJson, etagFromResource, etagValuesMatch, ifMatchSatisfied, ifNoneMatchSatisfied, isEtagEnabled, notModifiedResponse, } from "./etag";
8
+ export { FormRequest, QueryFormRequest } from "./formRequest";
9
+ export type { Middleware, RouteHandler } from "./middleware";
10
+ export { applyMiddlewareToRoutes, composeMiddleware, requestIdMiddleware, wrapRouteHandler, } from "./middleware";
11
+ export { buildPaginationMeta, DEFAULT_PER_PAGE, MAX_PER_PAGE, paginatedResponse, parsePaginationQuery, } from "./pagination";
12
+ export { createRequireAuthMiddleware } from "./requireAuthMiddleware";
13
+ export { serializeDate, toPaginatedResourceCollection, toResourceCollection } from "./resources";
14
+ export { withMiddleware } from "./routeMiddleware";
15
+ export { bindRouteModel } from "./routeModelBinding";
16
+ export { securedBindRouteModel } from "./securedRouteModelBinding";
17
+ export { buildRequestCacheKey, expectObject, getQueryParams, parseJsonBody, parseOptionalBooleanQueryParam, parseOptionalEnumQueryParam, parseOptionalPositiveIntQueryParam, parsePositiveIntParam, readOptionalEnum, readOptionalPositiveInt, readOptionalString, readRequiredEnum, readRequiredPositiveInt, readRequiredString, } from "./validation";
18
+ declare function jsonResponse(data: unknown, init?: ResponseInit): Response;
19
+ declare function createdResponse(data: unknown, init?: ResponseInit): Response;
20
+ declare function noContentResponse(): Response;
21
+ declare function errorResponse(error: unknown): Response;
22
+ declare function withErrorHandling<TArgs extends unknown[]>(handler: (...args: TArgs) => Response | Promise<Response>): (...args: TArgs) => Promise<Response>;
23
+ export type { ParsedUpload } from "./parseMultipartUpload";
24
+ export { parseMultipartUpload, sanitizeUploadFileName } from "./parseMultipartUpload";
25
+ export type { RouteRequest } from "./route";
26
+ export { getRouteParams } from "./route";
27
+ export { createdResponse, errorResponse, jsonResponse, noContentResponse, withErrorHandling };
@@ -0,0 +1,11 @@
1
+ import type { Middleware } from "./middleware";
2
+ interface LoginThrottleOptions {
3
+ redisUrl: string;
4
+ maxAttempts: number;
5
+ decaySeconds: number;
6
+ keyPrefix?: string;
7
+ }
8
+ declare function resolveLoginIdentity(request: Request): string;
9
+ declare function createLoginThrottleMiddleware(options: LoginThrottleOptions): Middleware;
10
+ export type { LoginThrottleOptions };
11
+ export { createLoginThrottleMiddleware, resolveLoginIdentity };
@@ -0,0 +1,9 @@
1
+ import type { Middleware } from "./middleware";
2
+ interface MemoryThrottleOptions {
3
+ maxAttempts: number;
4
+ decaySeconds: number;
5
+ keyPrefix?: string;
6
+ }
7
+ declare function createMemoryThrottleMiddleware(options: MemoryThrottleOptions): Middleware;
8
+ export type { MemoryThrottleOptions };
9
+ export { createMemoryThrottleMiddleware };
@@ -0,0 +1,4 @@
1
+ import type { Middleware } from "./middleware";
2
+ declare function normalizeMetricPath(pathname: string): string;
3
+ declare function createMetricsMiddleware(): Middleware;
4
+ export { createMetricsMiddleware, normalizeMetricPath };
@@ -0,0 +1,8 @@
1
+ type Middleware = (request: Request, next: () => Promise<Response>) => Promise<Response>;
2
+ type RouteHandler = (request: Request) => Response | Promise<Response>;
3
+ declare function composeMiddleware(...middleware: Middleware[]): (handler: RouteHandler) => RouteHandler;
4
+ declare function requestIdMiddleware(request: Request, next: () => Promise<Response>): Promise<Response>;
5
+ declare function wrapRouteHandler<T>(handler: T, middleware: Middleware[]): T;
6
+ declare function applyMiddlewareToRoutes<T extends Record<string, unknown>>(routes: T, middleware: Middleware[]): T;
7
+ export type { Middleware, RouteHandler };
8
+ export { applyMiddlewareToRoutes, composeMiddleware, requestIdMiddleware, wrapRouteHandler };
@@ -0,0 +1,11 @@
1
+ import { buildPaginationMeta, type PaginatedResult, type PaginationMeta } from "../pagination";
2
+ declare const DEFAULT_PER_PAGE = 15;
3
+ declare const MAX_PER_PAGE = 100;
4
+ interface PaginationQuery {
5
+ page: number;
6
+ perPage: number;
7
+ }
8
+ declare function parsePaginationQuery(request?: Request): PaginationQuery;
9
+ declare function paginatedResponse<T>(data: T[], meta: PaginationMeta, init?: ResponseInit): Response;
10
+ export type { PaginatedResult, PaginationMeta, PaginationQuery };
11
+ export { buildPaginationMeta, DEFAULT_PER_PAGE, MAX_PER_PAGE, paginatedResponse, parsePaginationQuery, };
@@ -0,0 +1,6 @@
1
+ interface FormDataLike {
2
+ entries(): Iterable<[string, unknown]>;
3
+ }
4
+ declare function parseFormBody(request: Request): Promise<Record<string, string>>;
5
+ declare function formDataToRecord(formData: FormDataLike): Record<string, string>;
6
+ export { formDataToRecord, parseFormBody };
@@ -0,0 +1,10 @@
1
+ interface ParsedUpload {
2
+ fileName: string;
3
+ mimeType: string;
4
+ size: number;
5
+ contents: Uint8Array;
6
+ }
7
+ declare function sanitizeUploadFileName(name: string): string;
8
+ declare function parseMultipartUpload(request: Request, fieldName?: string): Promise<ParsedUpload>;
9
+ export type { ParsedUpload };
10
+ export { parseMultipartUpload, sanitizeUploadFileName };
@@ -0,0 +1,16 @@
1
+ import { AsyncLocalStorage } from "node:async_hooks";
2
+ type RequestMeta = {
3
+ ipAddress: string | null;
4
+ userAgent: string | null;
5
+ request?: Request;
6
+ flash?: {
7
+ level: string;
8
+ message: string;
9
+ } | null;
10
+ csrfToken?: string;
11
+ };
12
+ declare const requestMetaContext: AsyncLocalStorage<RequestMeta>;
13
+ declare function runWithRequestMeta<T>(meta: RequestMeta, callback: () => T | Promise<T>): T | Promise<T>;
14
+ declare function currentRequestMeta(): RequestMeta;
15
+ export type { RequestMeta };
16
+ export { currentRequestMeta, requestMetaContext, runWithRequestMeta };
@@ -0,0 +1,4 @@
1
+ import type TokenService from "../../modules/user/tokenService";
2
+ import type { Middleware } from "./middleware";
3
+ declare function createRequireAbilityMiddleware(tokenService: TokenService): (ability: string) => Middleware;
4
+ export { createRequireAbilityMiddleware };
@@ -0,0 +1,4 @@
1
+ import type { AuthManager } from "../auth/guard";
2
+ import type { Middleware } from "./middleware";
3
+ declare function createRequireAuthMiddleware(auth: AuthManager): Middleware;
4
+ export { createRequireAuthMiddleware };
@@ -0,0 +1,3 @@
1
+ import type { Middleware } from "./middleware";
2
+ declare function createRequireGlobalAdminMiddleware(): Middleware;
3
+ export { createRequireGlobalAdminMiddleware };
@@ -0,0 +1,4 @@
1
+ import type { AuthManager } from "../auth/guard";
2
+ import type { Middleware } from "./middleware";
3
+ declare function createRequireWebAuthMiddleware(auth: AuthManager): Middleware;
4
+ export { createRequireWebAuthMiddleware };
@@ -0,0 +1,7 @@
1
+ declare function serializeDate(value: Date | string): string;
2
+ declare function toResourceCollection<TInput, TOutput>(items: readonly TInput[], transformer: (item: TInput) => TOutput): TOutput[];
3
+ declare function toPaginatedResourceCollection<TInput, TOutput, TMeta extends object>(items: readonly TInput[], meta: TMeta, transformer: (item: TInput) => TOutput): {
4
+ data: TOutput[];
5
+ meta: TMeta;
6
+ };
7
+ export { serializeDate, toPaginatedResourceCollection, toResourceCollection };
@@ -0,0 +1,6 @@
1
+ type RouteRequest<TParams extends Record<string, string>> = Request & {
2
+ params: TParams;
3
+ };
4
+ declare function getRouteParams<TParams extends Record<string, string>>(request: RouteRequest<TParams>): TParams;
5
+ export type { RouteRequest };
6
+ export { getRouteParams };
@@ -0,0 +1,3 @@
1
+ import { type Middleware, type RouteHandler } from "./middleware";
2
+ declare function withMiddleware(...middleware: Middleware[]): (handler: RouteHandler) => RouteHandler;
3
+ export { withMiddleware };
@@ -0,0 +1,3 @@
1
+ import type { RouteRequest } from "./route";
2
+ declare function bindRouteModel<TParams extends Record<string, string>, TModel, TParam extends keyof TParams & string>(param: TParam, resolver: (id: number, request: RouteRequest<TParams>) => Promise<TModel>, handler: (request: RouteRequest<TParams>, model: TModel) => Response | Promise<Response>): (request: RouteRequest<TParams>) => Promise<Response>;
3
+ export { bindRouteModel };
@@ -0,0 +1,10 @@
1
+ import type { Policy } from "../auth/policy";
2
+ import type { RouteRequest } from "./route";
3
+ interface RouteModelAuthorization {
4
+ resource: string;
5
+ action: keyof Policy;
6
+ requireIfMatch?: boolean;
7
+ }
8
+ declare function securedBindRouteModel<TParams extends Record<string, string>, TModel, TParam extends keyof TParams & string>(param: TParam, resolver: (id: number, request: RouteRequest<TParams>) => Promise<TModel>, authorization: RouteModelAuthorization, handler: (request: RouteRequest<TParams>, model: TModel) => Response | Promise<Response>): (request: RouteRequest<TParams>) => Promise<Response>;
9
+ export type { RouteModelAuthorization };
10
+ export { securedBindRouteModel };
@@ -0,0 +1,3 @@
1
+ import type { Middleware } from "./middleware";
2
+ declare function createSecurityHeadersMiddleware(): Middleware;
3
+ export { createSecurityHeadersMiddleware };
@@ -0,0 +1,11 @@
1
+ import type { Middleware } from "./middleware";
2
+ interface ThrottleOptions {
3
+ redisUrl: string;
4
+ maxAttempts: number;
5
+ decaySeconds: number;
6
+ keyPrefix?: string;
7
+ }
8
+ declare function resolveThrottleIdentity(request: Request): string;
9
+ declare function createThrottleMiddleware(options: ThrottleOptions): Middleware;
10
+ export type { ThrottleOptions };
11
+ export { createThrottleMiddleware, resolveThrottleIdentity };
@@ -0,0 +1,23 @@
1
+ declare function buildRequestCacheKey(fallbackPath: string, request?: Request): string;
2
+ declare function getQueryParams(request?: Request): URLSearchParams;
3
+ declare function parseOptionalPositiveIntQueryParam(params: URLSearchParams, name: string): number | undefined;
4
+ declare function parseOptionalBooleanQueryParam(params: URLSearchParams, name: string): boolean | undefined;
5
+ declare function parseOptionalEnumQueryParam<TValue extends string>(params: URLSearchParams, name: string, allowedValues: readonly TValue[]): TValue | undefined;
6
+ declare function expectObject(value: unknown, label?: string): Record<string, unknown>;
7
+ declare function parseJsonBody<TValue>(request: Request, validator: (payload: unknown) => TValue): Promise<TValue>;
8
+ declare function readRequiredString(payload: Record<string, unknown>, field: string, options?: {
9
+ minLength?: number;
10
+ maxLength?: number;
11
+ pattern?: RegExp;
12
+ }): string;
13
+ declare function readOptionalString(payload: Record<string, unknown>, field: string, options?: {
14
+ minLength?: number;
15
+ maxLength?: number;
16
+ pattern?: RegExp;
17
+ }): string | undefined;
18
+ declare function readRequiredEnum<TValue extends string>(payload: Record<string, unknown>, field: string, allowedValues: readonly TValue[]): TValue;
19
+ declare function readOptionalEnum<TValue extends string>(payload: Record<string, unknown>, field: string, allowedValues: readonly TValue[]): TValue | undefined;
20
+ declare function readRequiredPositiveInt(payload: Record<string, unknown>, field: string): number;
21
+ declare function readOptionalPositiveInt(payload: Record<string, unknown>, field: string): number | undefined;
22
+ declare function parsePositiveIntParam(value: string, name?: string): number;
23
+ export { buildRequestCacheKey, expectObject, getQueryParams, parseJsonBody, parseOptionalBooleanQueryParam, parseOptionalEnumQueryParam, parseOptionalPositiveIntQueryParam, parsePositiveIntParam, readOptionalEnum, readOptionalPositiveInt, readOptionalString, readRequiredEnum, readRequiredPositiveInt, readRequiredString, };
@@ -0,0 +1,5 @@
1
+ type FieldErrors = Record<string, string[]>;
2
+ declare function normalizeFieldErrors(details: unknown): FieldErrors;
3
+ declare function webErrorResponse(error: unknown, request?: Request): Response | null;
4
+ export type { FieldErrors };
5
+ export { normalizeFieldErrors, webErrorResponse };
@@ -0,0 +1,6 @@
1
+ declare abstract class WebFormRequest<TOutput> {
2
+ authorize(_request: Request): boolean | Promise<boolean>;
3
+ protected abstract parse(payload: unknown): TOutput;
4
+ validate(request: Request): Promise<TOutput>;
5
+ }
6
+ export { WebFormRequest };
@@ -0,0 +1,17 @@
1
+ type LogLevel = "debug" | "info" | "warn" | "error";
2
+ interface LogContext {
3
+ requestId?: string;
4
+ [key: string]: unknown;
5
+ }
6
+ declare class Logger {
7
+ private readonly channel;
8
+ constructor(channel?: string);
9
+ private write;
10
+ debug(message: string, context?: LogContext): void;
11
+ info(message: string, context?: LogContext): void;
12
+ warn(message: string, context?: LogContext): void;
13
+ error(message: string, context?: LogContext): void;
14
+ }
15
+ declare const appLogger: Logger;
16
+ export type { LogContext, LogLevel };
17
+ export { appLogger, Logger };
@@ -0,0 +1,3 @@
1
+ import type { Middleware } from "../http/middleware";
2
+ declare function createRequestLoggingMiddleware(): Middleware;
3
+ export { createRequestLoggingMiddleware };
@@ -0,0 +1,36 @@
1
+ interface MailMessage {
2
+ to: string;
3
+ subject: string;
4
+ body: string;
5
+ }
6
+ interface MailDriver {
7
+ send(message: MailMessage): Promise<void>;
8
+ }
9
+ interface SmtpConfig {
10
+ host: string;
11
+ port: number;
12
+ username?: string;
13
+ password?: string;
14
+ from: string;
15
+ secure: boolean;
16
+ }
17
+ type SmtpTransport = (config: SmtpConfig, message: MailMessage) => Promise<void>;
18
+ declare function resolveSmtpConfig(): SmtpConfig;
19
+ declare class LogMailDriver implements MailDriver {
20
+ send(message: MailMessage): Promise<void>;
21
+ }
22
+ declare class SmtpMailDriver implements MailDriver {
23
+ private readonly config;
24
+ private readonly transport;
25
+ constructor(config: SmtpConfig, transport?: SmtpTransport);
26
+ send(message: MailMessage): Promise<void>;
27
+ }
28
+ declare class Mailer {
29
+ private readonly driver;
30
+ constructor(driver: MailDriver);
31
+ send(message: MailMessage): Promise<void>;
32
+ }
33
+ declare function createMailDriver(): MailDriver;
34
+ declare function mailer(): Mailer;
35
+ export type { MailDriver, MailMessage, SmtpConfig, SmtpTransport };
36
+ export { createMailDriver, LogMailDriver, Mailer, mailer, resolveSmtpConfig, SmtpMailDriver };
@@ -0,0 +1,26 @@
1
+ interface MetricLabels {
2
+ method: string;
3
+ path: string;
4
+ status: string;
5
+ }
6
+ declare class PrometheusRegistry {
7
+ private readonly httpRequestsTotal;
8
+ private readonly httpRequestDurationMs;
9
+ incrementHttpRequest(labels: MetricLabels): void;
10
+ observeHttpDuration(labels: MetricLabels, durationMs: number): void;
11
+ renderMetrics(): string;
12
+ resetForTests(): void;
13
+ getHttpRequestSummary(): {
14
+ totalRequests: number;
15
+ byStatus: Record<string, number>;
16
+ topPaths: Array<{
17
+ method: string;
18
+ path: string;
19
+ count: number;
20
+ }>;
21
+ };
22
+ private metricKey;
23
+ }
24
+ declare const prometheusRegistry: PrometheusRegistry;
25
+ export type { MetricLabels };
26
+ export { PrometheusRegistry, prometheusRegistry };
@@ -0,0 +1,17 @@
1
+ interface PaginationMeta {
2
+ page: number;
3
+ per_page: number;
4
+ total: number;
5
+ last_page: number;
6
+ }
7
+ interface PaginatedResult<T> {
8
+ data: T[];
9
+ meta: PaginationMeta;
10
+ }
11
+ declare function buildPaginationMeta(input: {
12
+ page: number;
13
+ perPage: number;
14
+ total: number;
15
+ }): PaginationMeta;
16
+ export type { PaginatedResult, PaginationMeta };
17
+ export { buildPaginationMeta };
@@ -0,0 +1,19 @@
1
+ type QueuePriority = "high" | "default" | "low";
2
+ declare abstract class Job<TPayload extends object = object> {
3
+ readonly maxAttempts?: number;
4
+ readonly backoffMs?: number;
5
+ readonly priority?: QueuePriority;
6
+ abstract handle(payload: TPayload): Promise<void>;
7
+ }
8
+ interface Queue {
9
+ dispatch<TPayload extends object>(job: Job<TPayload>, payload: TPayload): Promise<void>;
10
+ }
11
+ declare class SyncQueue implements Queue {
12
+ dispatch<TPayload extends object>(job: Job<TPayload>, payload: TPayload): Promise<void>;
13
+ }
14
+ declare class AsyncQueue implements Queue {
15
+ dispatch<TPayload extends object>(job: Job<TPayload>, payload: TPayload): Promise<void>;
16
+ }
17
+ declare function createQueue(driver: "sync" | "async"): Queue;
18
+ export type { Queue, QueuePriority };
19
+ export { AsyncQueue, createQueue, Job, SyncQueue };
@@ -0,0 +1,3 @@
1
+ declare function isPublicReadsEnabled(): boolean;
2
+ declare function guestCanViewResource(): boolean;
3
+ export { guestCanViewResource, isPublicReadsEnabled };
@@ -0,0 +1,6 @@
1
+ interface SecurityEventDetails {
2
+ [key: string]: unknown;
3
+ }
4
+ declare function logSecurityEvent(event: string, details?: SecurityEventDetails): void;
5
+ export type { SecurityEventDetails };
6
+ export { logSecurityEvent };