@getstrata/bootstrap 0.2.1 → 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bootstrap/public-api.d.ts +1 -1
- package/dist/config/uploads.d.ts +5 -0
- package/dist/core/auth/membershipMiddleware.d.ts +1 -1
- package/dist/core/cache/tags.d.ts +11 -0
- package/dist/core/database/bindConnection.d.ts +3 -0
- package/dist/core/database/migrations/advisoryLock.d.ts +6 -0
- package/dist/core/database/migrations/runner.d.ts +25 -0
- package/dist/core/database/seeders/runner.d.ts +6 -0
- package/dist/core/database/seeders/types.d.ts +8 -0
- package/dist/core/facades/index.d.ts +10 -0
- package/dist/core/http/conditionalResponse.d.ts +2 -0
- package/dist/core/http/etag.d.ts +18 -0
- package/dist/core/http/formRequest.d.ts +10 -0
- package/dist/core/http/index.d.ts +27 -0
- package/dist/core/http/pagination.d.ts +11 -0
- package/dist/core/http/parseFormBody.d.ts +6 -0
- package/dist/core/http/parseMultipartUpload.d.ts +10 -0
- package/dist/core/http/resources.d.ts +7 -0
- package/dist/core/http/route.d.ts +6 -0
- package/dist/core/http/routeModelBinding.d.ts +3 -0
- package/dist/core/http/securedRouteModelBinding.d.ts +11 -0
- package/dist/core/http/validation.d.ts +23 -0
- package/dist/core/http/webErrorResponse.d.ts +5 -0
- package/dist/core/http/webFormRequest.d.ts +7 -0
- package/dist/core/lifecycle/gracefulShutdown.d.ts +6 -0
- package/dist/core/mail/mailer.d.ts +36 -0
- package/dist/core/storage/storage.d.ts +41 -0
- package/dist/core/validation/rules.d.ts +17 -0
- package/dist/framework/public-api.d.ts +70 -0
- package/dist/index.js +22 -19
- package/package.json +2 -2
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @getstrata/bootstrap — application shell for Strata sibling apps.
|
|
3
3
|
*/
|
|
4
|
+
export { resolveApplicationQueue, setActiveApplicationContext } from "@getstrata/core";
|
|
4
5
|
export { scheduleRunCommand } from "../cli/commands/scheduleRun.ts";
|
|
5
6
|
export type { ScheduledTask } from "../core/scheduler/schedule.ts";
|
|
6
7
|
export { appSchedule, runDueScheduledTasks, Schedule } from "../core/scheduler/schedule.ts";
|
|
7
|
-
export { resolveApplicationQueue, setActiveApplicationContext } from "./applicationRegistry.ts";
|
|
8
8
|
export { APP_PORT_CONFIG_KEY, CORE_AUTH_TOKEN, CORE_CACHE_TOKEN, CORE_CONFIG_TOKEN, CORE_POLICY_GATE_TOKEN, CORE_QUEUE_TOKEN, CORE_TOKEN_SERVICE_TOKEN, DATABASE_URL_CONFIG_KEY, DEFAULT_APP_PORT, REDIS_URL_CONFIG_KEY, } from "./config.ts";
|
|
9
9
|
export { collectProviders, createAppContext, runProviderPhase } from "./context.ts";
|
|
10
10
|
export type { AppContext, AppDependencies, AppModule, AppRouteMap, CachedJson, ConfigStore, ModuleRouteContext, MutableAppDependencies, ProviderContext, ServiceFactory, ServiceProvider, } from "./contracts.ts";
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
declare const DEFAULT_MAX_UPLOAD_BYTES: number;
|
|
2
|
+
declare const ALLOWED_UPLOAD_MIME_TYPES: Set<string>;
|
|
3
|
+
declare function resolveMaxUploadBytes(): number;
|
|
4
|
+
declare function isAllowedMimeType(mimeType: string): boolean;
|
|
5
|
+
export { ALLOWED_UPLOAD_MIME_TYPES, DEFAULT_MAX_UPLOAD_BYTES, isAllowedMimeType, resolveMaxUploadBytes, };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
declare function createMembershipMiddleware(): import("../http
|
|
1
|
+
declare function createMembershipMiddleware(): import("../http").Middleware;
|
|
2
2
|
export { createMembershipMiddleware };
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
declare const CACHE_TAGS: {
|
|
2
|
+
readonly organizations: "organizations";
|
|
3
|
+
readonly projects: "projects";
|
|
4
|
+
readonly tasks: "tasks";
|
|
5
|
+
readonly comments: "comments";
|
|
6
|
+
readonly attachments: "attachments";
|
|
7
|
+
readonly reports: "reports";
|
|
8
|
+
};
|
|
9
|
+
type CacheTag = (typeof CACHE_TAGS)[keyof typeof CACHE_TAGS];
|
|
10
|
+
export type { CacheTag };
|
|
11
|
+
export { CACHE_TAGS };
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
declare const MIGRATION_LOCK_KEY = 42424242;
|
|
2
|
+
type LockableDatabase = {
|
|
3
|
+
unsafe<T>(query: string, params?: readonly unknown[]): Promise<T[]>;
|
|
4
|
+
};
|
|
5
|
+
declare function withMigrationLock<T>(db: LockableDatabase, callback: () => Promise<T>, lockKey?: number): Promise<T>;
|
|
6
|
+
export { MIGRATION_LOCK_KEY, withMigrationLock };
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { Migration, MigrationDatabase, MigrationStatus } from "./types.ts";
|
|
2
|
+
type AppliedMigrationRow = {
|
|
3
|
+
name: string;
|
|
4
|
+
batch: number | string;
|
|
5
|
+
};
|
|
6
|
+
declare function ensureMigrationsTable(db: MigrationDatabase): Promise<void>;
|
|
7
|
+
declare function getAppliedMigrations(db: MigrationDatabase): Promise<AppliedMigrationRow[]>;
|
|
8
|
+
declare function loadMigrationsFromDirectory(directory: string): Promise<Migration[]>;
|
|
9
|
+
declare function getMigrationStatus(db: MigrationDatabase, migrations: Migration[]): Promise<MigrationStatus[]>;
|
|
10
|
+
declare function runPendingMigrations(db: MigrationDatabase, migrations: Migration[], options?: {
|
|
11
|
+
onMigration?: (name: string) => void;
|
|
12
|
+
}): Promise<number>;
|
|
13
|
+
declare function migrateDatabase(db: MigrationDatabase, migrations: Migration[], options?: {
|
|
14
|
+
advisoryLock?: boolean;
|
|
15
|
+
onMigration?: (name: string) => void;
|
|
16
|
+
}): Promise<number>;
|
|
17
|
+
declare function rollbackDatabase(db: MigrationDatabase, migrations: Migration[], options?: {
|
|
18
|
+
onMigration?: (name: string) => void;
|
|
19
|
+
}): Promise<number>;
|
|
20
|
+
declare function freshDatabase(db: MigrationDatabase, migrations: Migration[], options?: {
|
|
21
|
+
advisoryLock?: boolean;
|
|
22
|
+
onMigration?: (name: string) => void;
|
|
23
|
+
}): Promise<void>;
|
|
24
|
+
export { withMigrationLock } from "./advisoryLock.ts";
|
|
25
|
+
export { ensureMigrationsTable, freshDatabase, getAppliedMigrations, getMigrationStatus, loadMigrationsFromDirectory, migrateDatabase, rollbackDatabase, runPendingMigrations, };
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { Seeder, SeederDatabase } from "./types.ts";
|
|
2
|
+
declare function loadSeedersFromDirectory(directory: string): Promise<Seeder[]>;
|
|
3
|
+
declare function runSeedersFromDirectory(directory: string, db: SeederDatabase, options?: {
|
|
4
|
+
onSeeder?: (name: string) => void;
|
|
5
|
+
}): Promise<number>;
|
|
6
|
+
export { loadSeedersFromDirectory, runSeedersFromDirectory };
|
|
@@ -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,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,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, securedBindRouteModelByKey, } 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 { 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,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 { 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,11 @@
|
|
|
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
|
+
declare function securedBindRouteModelByKey<TParams extends Record<string, string>, TModel, TParam extends keyof TParams & string>(param: TParam, resolver: (key: string, request: RouteRequest<TParams>) => Promise<TModel>, authorization: RouteModelAuthorization, handler: (request: RouteRequest<TParams>, model: TModel) => Response | Promise<Response>): (request: RouteRequest<TParams>) => Promise<Response>;
|
|
10
|
+
export type { RouteModelAuthorization };
|
|
11
|
+
export { securedBindRouteModel, securedBindRouteModelByKey };
|
|
@@ -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,7 @@
|
|
|
1
|
+
declare abstract class WebFormRequest<TOutput> {
|
|
2
|
+
authorize(_request: Request): boolean | Promise<boolean>;
|
|
3
|
+
protected abstract parse(payload: unknown): TOutput;
|
|
4
|
+
validatePayload(payload: unknown): TOutput;
|
|
5
|
+
validate(request: Request): Promise<TOutput>;
|
|
6
|
+
}
|
|
7
|
+
export { WebFormRequest };
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
type ShutdownHandler = () => void | Promise<void>;
|
|
2
|
+
declare function registerShutdownHandler(name: string, handler: ShutdownHandler): () => void;
|
|
3
|
+
declare function runGracefulShutdown(signal: string): Promise<void>;
|
|
4
|
+
declare function installGracefulShutdownSignals(signals?: NodeJS.Signals[]): void;
|
|
5
|
+
declare function resetGracefulShutdownForTests(): void;
|
|
6
|
+
export { installGracefulShutdownSignals, registerShutdownHandler, resetGracefulShutdownForTests, runGracefulShutdown, };
|
|
@@ -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,41 @@
|
|
|
1
|
+
import { S3Client } from "bun";
|
|
2
|
+
interface StorageDriver {
|
|
3
|
+
put(path: string, contents: string | Uint8Array): Promise<string>;
|
|
4
|
+
get(path: string): Promise<Uint8Array | null>;
|
|
5
|
+
delete(path: string): Promise<boolean>;
|
|
6
|
+
}
|
|
7
|
+
interface S3StorageConfig {
|
|
8
|
+
accessKeyId: string;
|
|
9
|
+
secretAccessKey: string;
|
|
10
|
+
bucket: string;
|
|
11
|
+
region?: string;
|
|
12
|
+
endpoint?: string;
|
|
13
|
+
}
|
|
14
|
+
declare class LocalStorageDriver implements StorageDriver {
|
|
15
|
+
private readonly rootDirectory;
|
|
16
|
+
constructor(rootDirectory: string);
|
|
17
|
+
private resolvePath;
|
|
18
|
+
put(path: string, contents: string | Uint8Array): Promise<string>;
|
|
19
|
+
get(path: string): Promise<Uint8Array | null>;
|
|
20
|
+
delete(path: string): Promise<boolean>;
|
|
21
|
+
}
|
|
22
|
+
declare class S3StorageDriver implements StorageDriver {
|
|
23
|
+
private readonly client;
|
|
24
|
+
constructor(client: S3Client);
|
|
25
|
+
put(path: string, contents: string | Uint8Array): Promise<string>;
|
|
26
|
+
get(path: string): Promise<Uint8Array | null>;
|
|
27
|
+
delete(path: string): Promise<boolean>;
|
|
28
|
+
}
|
|
29
|
+
declare class StorageManager {
|
|
30
|
+
private readonly driver;
|
|
31
|
+
constructor(driver: StorageDriver);
|
|
32
|
+
put(path: string, contents: string | Uint8Array): Promise<string>;
|
|
33
|
+
get(path: string): Promise<Uint8Array | null>;
|
|
34
|
+
delete(path: string): Promise<boolean>;
|
|
35
|
+
}
|
|
36
|
+
declare function resolveS3Config(): S3StorageConfig;
|
|
37
|
+
declare function createS3Client(config?: S3StorageConfig): S3Client;
|
|
38
|
+
declare function createStorageDriver(): StorageDriver;
|
|
39
|
+
declare function storage(): StorageManager;
|
|
40
|
+
export type { S3StorageConfig, StorageDriver };
|
|
41
|
+
export { createS3Client, createStorageDriver, LocalStorageDriver, resolveS3Config, S3StorageDriver, StorageManager, storage, };
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
type ValidationRule = (field: string, value: unknown, payload: Record<string, unknown>) => string | undefined;
|
|
2
|
+
type ValidationSchema = Record<string, ValidationRule[]>;
|
|
3
|
+
declare function required(): ValidationRule;
|
|
4
|
+
declare function stringRule(): ValidationRule;
|
|
5
|
+
declare function minLength(minimum: number): ValidationRule;
|
|
6
|
+
declare function maxLength(maximum: number): ValidationRule;
|
|
7
|
+
declare function pattern(expression: RegExp): ValidationRule;
|
|
8
|
+
declare function enumRule<TValue extends string>(allowedValues: readonly TValue[]): ValidationRule;
|
|
9
|
+
declare function optional(): ValidationRule;
|
|
10
|
+
declare function integerRule(): ValidationRule;
|
|
11
|
+
declare function emailRule(): ValidationRule;
|
|
12
|
+
declare function confirmed(fieldName: string): ValidationRule;
|
|
13
|
+
declare function positiveIntegerRule(): ValidationRule;
|
|
14
|
+
declare function integerRange(minimum: number, maximum: number): ValidationRule;
|
|
15
|
+
declare function validateObject(payload: unknown, schema: ValidationSchema): Record<string, unknown>;
|
|
16
|
+
export type { ValidationRule, ValidationSchema };
|
|
17
|
+
export { confirmed, emailRule, enumRule, integerRange, integerRule, maxLength, minLength, optional, pattern, positiveIntegerRule, required, stringRule, validateObject, };
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Stable framework surface for application modules and future package extraction.
|
|
3
|
+
* Import from `@getstrata/core` (workspace) or `src/framework/public-api`.
|
|
4
|
+
*/
|
|
5
|
+
export { resolveApplicationAuth, resolveApplicationCache, resolveApplicationConfig, resolveApplicationDependencies, resolveApplicationLogger, resolveApplicationPolicyGate, resolveApplicationQueue, setActiveApplicationContext, } from "../bootstrap/applicationRegistry.ts";
|
|
6
|
+
export type { ServiceProvider } from "../bootstrap/contracts.ts";
|
|
7
|
+
export { ConfigStore, resolveService, ServiceContainer, } from "../bootstrap/contracts.ts";
|
|
8
|
+
export type { AbilityChecker } from "../core/auth/abilityChecker.ts";
|
|
9
|
+
export type { AuthUser } from "../core/auth/authContext.ts";
|
|
10
|
+
export { currentAuthUser, runWithAuthUser } from "../core/auth/authContext.ts";
|
|
11
|
+
export { Policy, PolicyGate } from "../core/auth/policy.ts";
|
|
12
|
+
export { default as CacheRepository } from "../core/cache/repository.ts";
|
|
13
|
+
export { CACHE_TAGS } from "../core/cache/tags.ts";
|
|
14
|
+
export type { DatabaseConnection } from "../core/database/baseRepository.ts";
|
|
15
|
+
export { default as BaseRepository } from "../core/database/baseRepository.ts";
|
|
16
|
+
export { bindDatabaseConnection } from "../core/database/bindConnection.ts";
|
|
17
|
+
export { getActiveDatabaseConnection, runWithDatabaseConnection, } from "../core/database/connectionContext.ts";
|
|
18
|
+
export { withMigrationLock } from "../core/database/migrations/advisoryLock.ts";
|
|
19
|
+
export { freshDatabase, getMigrationStatus, loadMigrationsFromDirectory, migrateDatabase, rollbackDatabase, } from "../core/database/migrations/runner.ts";
|
|
20
|
+
export type { Migration, MigrationDatabase, MigrationStatus, } from "../core/database/migrations/types.ts";
|
|
21
|
+
export type { CastType, GlobalScopeFn, ModelConstructor } from "../core/database/model.ts";
|
|
22
|
+
export { applyCasts, dehydrateValue, filterMassAssignable, hydrateValue, Model, registerModelRepository, } from "../core/database/model.ts";
|
|
23
|
+
export type { BelongsToManyRelation, BelongsToRelation, HasManyRelation, HasOneRelation, } from "../core/database/relationships.ts";
|
|
24
|
+
export { belongsTo, belongsToMany, hasMany, hasOne, indexBelongsToManyRelation, indexBelongsToRelation, indexHasManyRelation, indexHasOneRelation, } from "../core/database/relationships.ts";
|
|
25
|
+
export { RepositoryQuery } from "../core/database/repositoryQuery.ts";
|
|
26
|
+
export type { BlueprintAction, BlueprintCallback, ColumnKind, DatabaseDriver, ForeignKeyOptions, Grammar, IndexDefinition, IndexKind, ResolveDatabaseDriverOptions, SchemaBuilder, } from "../core/database/schema/index.ts";
|
|
27
|
+
export { Blueprint, ColumnDefinition, compileBlueprint, createSchemaBuilder, ForeignIdColumnDefinition, grammarForDriver, inferReferencedTable, MySqlGrammar, PostgresGrammar, resolveDatabaseDriver, Schema, SqliteGrammar, UnsupportedSchemaFeatureError, } from "../core/database/schema/index.ts";
|
|
28
|
+
export { loadSeedersFromDirectory, runSeedersFromDirectory, } from "../core/database/seeders/runner.ts";
|
|
29
|
+
export type { Seeder, SeederDatabase } from "../core/database/seeders/types.ts";
|
|
30
|
+
export { defineTable } from "../core/database/table.ts";
|
|
31
|
+
export { runInTransaction } from "../core/database/transaction.ts";
|
|
32
|
+
export type { QueryJoin, QueryJoinOn, QueryOptions, QueryOrder, QuerySelectItem, QueryWhere, } from "../core/database/types.ts";
|
|
33
|
+
export type { WhereNode } from "../core/database/whereBuilder.ts";
|
|
34
|
+
export { WhereBuilder } from "../core/database/whereBuilder.ts";
|
|
35
|
+
export { BadRequestError, ConflictError, ForbiddenError, NotFoundError, PreconditionFailedError, UnauthorizedError, UnprocessableEntityError, ValidationError, } from "../core/errors/http.ts";
|
|
36
|
+
export { EventBus } from "../core/events/eventBus.ts";
|
|
37
|
+
export { auth, cache, config, events, log, mail, policyGate, queue, storage, } from "../core/facades/index.ts";
|
|
38
|
+
export { createBodySizeLimitMiddleware } from "../core/http/bodySizeLimitMiddleware.ts";
|
|
39
|
+
export { createCsrfMiddleware } from "../core/http/csrfMiddleware.ts";
|
|
40
|
+
export { assertIfMatch, etagFromResource, isEtagEnabled, } from "../core/http/etag.ts";
|
|
41
|
+
export { FormRequest } from "../core/http/formRequest.ts";
|
|
42
|
+
export { applyMiddlewareToRoutes, composeMiddleware, createAuthMiddleware, createAuthorizeMiddleware, createdResponse, createRequireAuthMiddleware, jsonResponse, noContentResponse, paginatedResponse, parsePaginationQuery, securedBindRouteModel, securedBindRouteModelByKey, withErrorHandling, withMiddleware, } from "../core/http/index.ts";
|
|
43
|
+
export { createLoginThrottleMiddleware } from "../core/http/loginThrottleMiddleware.ts";
|
|
44
|
+
export { createMemoryThrottleMiddleware } from "../core/http/memoryThrottleMiddleware.ts";
|
|
45
|
+
export { createMetricsMiddleware, normalizeMetricPath } from "../core/http/metricsMiddleware.ts";
|
|
46
|
+
export type { Middleware, RouteHandler } from "../core/http/middleware.ts";
|
|
47
|
+
export { createRequireWebAuthMiddleware } from "../core/http/requireWebAuthMiddleware.ts";
|
|
48
|
+
export { serializeDate, toPaginatedResourceCollection, toResourceCollection, } from "../core/http/resources.ts";
|
|
49
|
+
export type { RouteRequest } from "../core/http/route.ts";
|
|
50
|
+
export { createSecurityHeadersMiddleware } from "../core/http/securityHeadersMiddleware.ts";
|
|
51
|
+
export { createThrottleMiddleware } from "../core/http/throttleMiddleware.ts";
|
|
52
|
+
export { WebFormRequest } from "../core/http/webFormRequest.ts";
|
|
53
|
+
export { installGracefulShutdownSignals, registerShutdownHandler, runGracefulShutdown, } from "../core/lifecycle/gracefulShutdown.ts";
|
|
54
|
+
export type { MailDriver, MailMessage } from "../core/mail/mailer.ts";
|
|
55
|
+
export { LogMailDriver, Mailer, mailer } from "../core/mail/mailer.ts";
|
|
56
|
+
export type { MetricLabels } from "../core/metrics/prometheus.ts";
|
|
57
|
+
export { PrometheusRegistry, prometheusRegistry } from "../core/metrics/prometheus.ts";
|
|
58
|
+
export type { CursorPaginatedResult, PaginatedResult, PaginationMeta, } from "../core/pagination/index.ts";
|
|
59
|
+
export type { Queue, QueuePriority } from "../core/queue/index.ts";
|
|
60
|
+
export { AsyncQueue, createQueue, Job, SyncQueue } from "../core/queue/index.ts";
|
|
61
|
+
export { createFailedJobService, createProductionQueue, createQueueWorker, createTrackedJob, FailedJobRepository, FailedJobService, jobRegistry, QueueWorker, RedisQueue, ResilientQueue, } from "../core/queue/publicQueue.ts";
|
|
62
|
+
export type { ScheduledTask } from "../core/scheduler/schedule.ts";
|
|
63
|
+
export { appSchedule, runDueScheduledTasks, Schedule } from "../core/scheduler/schedule.ts";
|
|
64
|
+
export type { StorageDriver } from "../core/storage/storage.ts";
|
|
65
|
+
export { LocalStorageDriver, StorageManager } from "../core/storage/storage.ts";
|
|
66
|
+
export type { ValidationRule, ValidationSchema } from "../core/validation/rules.ts";
|
|
67
|
+
export { emailRule, maxLength, minLength, required, stringRule, validateObject, } from "../core/validation/rules.ts";
|
|
68
|
+
export { DEFAULT_VIEWS_DIRECTORY, EtaViewEngine, htmlResponse, isHtmxRequest, resolveWebLayoutData, } from "../core/view/index.ts";
|
|
69
|
+
export type { ViewEngine } from "../core/view/viewEngine.ts";
|
|
70
|
+
export type { WebLayoutAuthUser, WebLayoutData } from "../core/view/webLayoutData.ts";
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
// @bun
|
|
2
|
+
// ../../src/bootstrap/public-api.ts
|
|
3
|
+
import { resolveApplicationQueue as resolveApplicationQueue2, setActiveApplicationContext as setActiveApplicationContext2 } from "@getstrata/core";
|
|
4
|
+
|
|
2
5
|
// ../../src/core/scheduler/schedule.ts
|
|
3
6
|
class Schedule {
|
|
4
7
|
tasks = [];
|
|
@@ -487,6 +490,8 @@ var DEFAULT_CACHE_MAX_ENTRIES = 100;
|
|
|
487
490
|
var DEFAULT_CACHE_DRIVER = "array";
|
|
488
491
|
var DEFAULT_API_TOKEN = "";
|
|
489
492
|
var DEFAULT_QUEUE_DRIVER = "sync";
|
|
493
|
+
// ../../src/bootstrap/context.ts
|
|
494
|
+
import { setActiveApplicationContext } from "@getstrata/core";
|
|
490
495
|
|
|
491
496
|
// ../../src/bootstrap/contracts.ts
|
|
492
497
|
class ServiceContainer {
|
|
@@ -572,23 +577,6 @@ function resolveService(dependencies, token) {
|
|
|
572
577
|
return dependencies.container.resolve(token);
|
|
573
578
|
}
|
|
574
579
|
|
|
575
|
-
// ../../src/bootstrap/applicationRegistry.ts
|
|
576
|
-
var activeContext;
|
|
577
|
-
function setActiveApplicationContext(context) {
|
|
578
|
-
activeContext = context;
|
|
579
|
-
}
|
|
580
|
-
function requireActiveApplicationContext() {
|
|
581
|
-
if (!activeContext) {
|
|
582
|
-
throw new Error("The application context has not been bootstrapped.");
|
|
583
|
-
}
|
|
584
|
-
return activeContext;
|
|
585
|
-
}
|
|
586
|
-
function resolveApplicationCache() {
|
|
587
|
-
return getRequiredDependency(requireActiveApplicationContext().dependencies, "cache");
|
|
588
|
-
}
|
|
589
|
-
function resolveApplicationQueue() {
|
|
590
|
-
return requireActiveApplicationContext().container.resolve(CORE_QUEUE_TOKEN);
|
|
591
|
-
}
|
|
592
580
|
// ../../src/bootstrap/discoverModules.ts
|
|
593
581
|
import { readdirSync } from "fs";
|
|
594
582
|
import { join } from "path";
|
|
@@ -1747,6 +1735,21 @@ class InvalidateCacheTagsJob extends Job {
|
|
|
1747
1735
|
}
|
|
1748
1736
|
var invalidateCacheTagsJob_default = InvalidateCacheTagsJob;
|
|
1749
1737
|
|
|
1738
|
+
// ../../src/bootstrap/applicationRegistry.ts
|
|
1739
|
+
var activeContext;
|
|
1740
|
+
function requireActiveApplicationContext() {
|
|
1741
|
+
if (!activeContext) {
|
|
1742
|
+
throw new Error("The application context has not been bootstrapped.");
|
|
1743
|
+
}
|
|
1744
|
+
return activeContext;
|
|
1745
|
+
}
|
|
1746
|
+
function resolveApplicationCache() {
|
|
1747
|
+
return getRequiredDependency(requireActiveApplicationContext().dependencies, "cache");
|
|
1748
|
+
}
|
|
1749
|
+
function resolveApplicationQueue() {
|
|
1750
|
+
return requireActiveApplicationContext().container.resolve(CORE_QUEUE_TOKEN);
|
|
1751
|
+
}
|
|
1752
|
+
|
|
1750
1753
|
// ../../src/core/jobs/dispatchWebhookJob.ts
|
|
1751
1754
|
import { createHmac as createHmac2 } from "crypto";
|
|
1752
1755
|
class DispatchWebhookJob extends Job {
|
|
@@ -5449,12 +5452,12 @@ function slugify(value) {
|
|
|
5449
5452
|
}
|
|
5450
5453
|
export {
|
|
5451
5454
|
slugify,
|
|
5452
|
-
setActiveApplicationContext,
|
|
5455
|
+
setActiveApplicationContext2 as setActiveApplicationContext,
|
|
5453
5456
|
scheduleRunCommand,
|
|
5454
5457
|
runProviderPhase,
|
|
5455
5458
|
runDueScheduledTasks,
|
|
5456
5459
|
resolveService,
|
|
5457
|
-
resolveApplicationQueue,
|
|
5460
|
+
resolveApplicationQueue2 as resolveApplicationQueue,
|
|
5458
5461
|
prefixRouteMap,
|
|
5459
5462
|
parseFormBody,
|
|
5460
5463
|
mergeWebRoutes,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@getstrata/bootstrap",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.2",
|
|
4
4
|
"description": "Strata application bootstrap — HttpKernel, DI, web session helpers",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -73,7 +73,7 @@
|
|
|
73
73
|
"access": "public"
|
|
74
74
|
},
|
|
75
75
|
"peerDependencies": {
|
|
76
|
-
"@getstrata/core": "^0.5.
|
|
76
|
+
"@getstrata/core": "^0.5.5",
|
|
77
77
|
"typescript": "^5.9.0"
|
|
78
78
|
}
|
|
79
79
|
}
|