webspresso 0.0.98 → 0.0.99
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/.agents/ADMIN.md +11 -1
- package/.agents/AGENTS.md +1 -1
- package/.agents/AUTH.md +169 -0
- package/.agents/ORM.md +88 -4
- package/.agents/PLUGINS.md +73 -5
- package/.agents/QUEUE.md +84 -0
- package/.agents/ROUTING.md +127 -7
- package/AGENTS.md +1 -0
- package/core/auth/index.js +60 -0
- package/core/auth/manager.js +134 -0
- package/core/auth/middleware.js +88 -0
- package/core/auth/oauth.js +517 -0
- package/core/auth/qrcode.js +499 -0
- package/core/auth/totp.js +504 -0
- package/core/orm/eager-loader.js +144 -10
- package/core/orm/index.js +8 -0
- package/core/orm/model.js +4 -0
- package/core/orm/query-builder.js +90 -4
- package/core/orm/repository.js +44 -3
- package/core/orm/search.js +213 -0
- package/core/queue/cron.js +331 -0
- package/core/queue/index.js +8 -1
- package/core/queue/manager.js +82 -1
- package/core/queue/scheduler.js +359 -0
- package/core/sse/index.js +19 -0
- package/core/sse/stream.js +430 -0
- package/index.d.ts +528 -0
- package/index.js +44 -0
- package/package.json +1 -1
- package/plugins/admin-panel/client/parts/05-rich-text-file-helpers.js +323 -31
- package/plugins/admin-panel/client/parts/08-record-list.js +5 -0
- package/plugins/admin-panel/client/verify-spa-parts.js +2 -0
- package/plugins/admin-panel/field-renderers/file-upload.js +187 -104
- package/plugins/admin-panel/field-renderers/index.js +2 -0
- package/plugins/api-key/crypto.js +101 -0
- package/plugins/api-key/index.js +288 -0
- package/plugins/api-key/middleware.js +461 -0
- package/plugins/api-key/migration-template.js +48 -0
- package/plugins/api-key/model.js +50 -0
- package/plugins/api-key/scopes.js +125 -0
- package/plugins/audit-log/admin-component.js +487 -70
- package/plugins/audit-log/api-handlers.js +114 -0
- package/plugins/audit-log/index.js +24 -0
- package/plugins/file-manager/admin-component.js +20 -4
- package/plugins/file-manager/index.js +21 -4
- package/plugins/index.js +6 -0
- package/plugins/oauth/index.js +338 -0
- package/plugins/queue/index.js +4 -0
- package/src/api/api-loader.js +1 -0
- package/src/discovery/file-route-parser.js +44 -1
- package/src/discovery/scan-routes.js +2 -2
- package/src/file-router.js +137 -100
- package/src/helpers.js +9 -0
- package/src/routing/cascading.js +378 -0
- package/src/routing/middleware-resolver.js +92 -0
- package/src/server.js +6 -0
package/index.d.ts
CHANGED
|
@@ -541,8 +541,47 @@ export function mountPages(
|
|
|
541
541
|
registerDynamicFileRoutes: () => void;
|
|
542
542
|
};
|
|
543
543
|
|
|
544
|
+
export interface CascadingLayoutInfo {
|
|
545
|
+
layoutRelPath: string;
|
|
546
|
+
fullPath: string;
|
|
547
|
+
configPath: string | null;
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
export namespace cascading {
|
|
551
|
+
export function getDirectoryChain(relativeFilePath: string): string[];
|
|
552
|
+
export function templateHasExtends(templateBody?: string | null, fullPath?: string): boolean;
|
|
553
|
+
export function findCascadingMiddlewareFiles(baseDir: string, relativeFilePath: string, isDev?: boolean): string[];
|
|
554
|
+
export function loadCascadingMiddlewares(
|
|
555
|
+
baseDir: string,
|
|
556
|
+
relativeFilePath: string,
|
|
557
|
+
middlewareRegistry?: Record<string, unknown>,
|
|
558
|
+
isDev?: boolean
|
|
559
|
+
): Array<(req: any, res: any, next: (err?: any) => void) => void>;
|
|
560
|
+
export function runMiddleware(mw: Function, req: any, res: any): Promise<void>;
|
|
561
|
+
export function runMiddlewareChain(chain: Function[], req: any, res: any): Promise<void>;
|
|
562
|
+
export function findCascadingLayouts(baseDir: string, relativeFilePath: string, isDev?: boolean): CascadingLayoutInfo[];
|
|
563
|
+
export function executeCascadingLayoutLoads(layouts: CascadingLayoutInfo[], req: any, ctx: any, isDev?: boolean): Promise<void>;
|
|
564
|
+
export function applyCascadingLayouts(
|
|
565
|
+
nunjucksEnv: any,
|
|
566
|
+
layouts: CascadingLayoutInfo[],
|
|
567
|
+
pageHtml: string,
|
|
568
|
+
renderContext: Record<string, unknown>,
|
|
569
|
+
isDev?: boolean
|
|
570
|
+
): string;
|
|
571
|
+
export function clearCascadingCaches(): void;
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
export function resolveMiddlewares(
|
|
575
|
+
middlewareConfig: unknown[] | null | undefined,
|
|
576
|
+
middlewareRegistry?: Record<string, unknown>
|
|
577
|
+
): Array<(req: any, res: any, next: (err?: any) => void) => void>;
|
|
578
|
+
|
|
544
579
|
export function filePathToRoute(filePath: string, pagesDir: string): string;
|
|
545
580
|
|
|
581
|
+
export function isRouteGroupSegment(segment: string): boolean;
|
|
582
|
+
|
|
583
|
+
export function stripRouteGroups(route: string): string;
|
|
584
|
+
|
|
546
585
|
export function extractMethodFromFilename(filename: string): {
|
|
547
586
|
method: string;
|
|
548
587
|
baseName: string;
|
|
@@ -864,6 +903,7 @@ export interface ModelOptions<TSchema extends ZodObject<any> = ZodObject<Record<
|
|
|
864
903
|
maxIncludes?: number;
|
|
865
904
|
maxFilterConditions?: number;
|
|
866
905
|
};
|
|
906
|
+
searchable?: string[];
|
|
867
907
|
cache?: boolean | 'auto' | 'smart' | { strategy: 'auto' | 'smart' };
|
|
868
908
|
}
|
|
869
909
|
|
|
@@ -898,6 +938,7 @@ export interface ModelDefinition<TModel = Record<string, any>> {
|
|
|
898
938
|
maxIncludes?: number;
|
|
899
939
|
maxFilterConditions?: number;
|
|
900
940
|
};
|
|
941
|
+
searchable?: string[];
|
|
901
942
|
hooks: Record<string, unknown>;
|
|
902
943
|
cache?: boolean | 'auto' | 'smart' | { strategy: 'auto' | 'smart' };
|
|
903
944
|
}
|
|
@@ -934,7 +975,10 @@ export function getColumnMeta(schema: ZodTypeAny): unknown;
|
|
|
934
975
|
|
|
935
976
|
export interface FindOptions {
|
|
936
977
|
with?: string[];
|
|
978
|
+
include?: string[];
|
|
937
979
|
select?: string[];
|
|
980
|
+
limit?: number;
|
|
981
|
+
offset?: number;
|
|
938
982
|
}
|
|
939
983
|
|
|
940
984
|
export interface PaginatedResult<T = Record<string, any>> {
|
|
@@ -945,6 +989,16 @@ export interface PaginatedResult<T = Record<string, any>> {
|
|
|
945
989
|
totalPages: number;
|
|
946
990
|
}
|
|
947
991
|
|
|
992
|
+
export interface SearchOptions {
|
|
993
|
+
mode?: 'auto' | 'fts' | 'like';
|
|
994
|
+
language?: string;
|
|
995
|
+
matchAllWords?: boolean;
|
|
996
|
+
exact?: boolean;
|
|
997
|
+
rank?: boolean;
|
|
998
|
+
ftsTable?: string;
|
|
999
|
+
boolean?: 'and' | 'or';
|
|
1000
|
+
}
|
|
1001
|
+
|
|
948
1002
|
export interface QueryBuilder<T = Record<string, any>> {
|
|
949
1003
|
where(column: keyof T | string, value: unknown): this;
|
|
950
1004
|
where(column: keyof T | string, operator: string, value: unknown): this;
|
|
@@ -954,14 +1008,19 @@ export interface QueryBuilder<T = Record<string, any>> {
|
|
|
954
1008
|
whereBetween(column: keyof T | string, range: [unknown, unknown]): this;
|
|
955
1009
|
select(...columns: (keyof T | string)[]): this;
|
|
956
1010
|
orderBy(column: keyof T | string, direction?: 'asc' | 'desc'): this;
|
|
1011
|
+
orderByRaw(sql: string, bindings?: unknown[]): this;
|
|
1012
|
+
search(term: string, columns?: string | string[], options?: SearchOptions): this;
|
|
1013
|
+
orSearch(term: string, columns?: string | string[], options?: SearchOptions): this;
|
|
957
1014
|
limit(n: number): this;
|
|
958
1015
|
offset(n: number): this;
|
|
959
1016
|
with(...relations: string[]): this;
|
|
1017
|
+
include(...relations: string[]): this;
|
|
960
1018
|
withTrashed(): this;
|
|
961
1019
|
onlyTrashed(): this;
|
|
962
1020
|
first(): Promise<T | null>;
|
|
963
1021
|
list(): Promise<T[]>;
|
|
964
1022
|
get(): Promise<T[]>;
|
|
1023
|
+
find(): Promise<T[]>;
|
|
965
1024
|
count(): Promise<number>;
|
|
966
1025
|
paginate(page?: number, perPage?: number): Promise<PaginatedResult<T>>;
|
|
967
1026
|
exists(): Promise<boolean>;
|
|
@@ -976,6 +1035,7 @@ export interface Repository<T = Record<string, any>> {
|
|
|
976
1035
|
findById(id: string | number, options?: FindOptions): Promise<T | null>;
|
|
977
1036
|
findOne(conditions: Partial<T> | Record<string, unknown>, options?: FindOptions): Promise<T | null>;
|
|
978
1037
|
findAll(options?: FindOptions): Promise<T[]>;
|
|
1038
|
+
find(conditions?: Partial<T> | Record<string, unknown>, options?: FindOptions): Promise<T[]>;
|
|
979
1039
|
create(data: Partial<T> | Record<string, unknown>): Promise<T>;
|
|
980
1040
|
createMany(data: (Partial<T> | Record<string, unknown>)[]): Promise<T[]>;
|
|
981
1041
|
update(id: string | number, data: Partial<T> | Record<string, unknown>): Promise<T | null>;
|
|
@@ -988,6 +1048,8 @@ export interface Repository<T = Record<string, any>> {
|
|
|
988
1048
|
count(conditions?: Partial<T> | Record<string, unknown>): Promise<number>;
|
|
989
1049
|
exists(conditions: Partial<T> | Record<string, unknown>): Promise<boolean>;
|
|
990
1050
|
with(...relations: string[]): QueryBuilder<T>;
|
|
1051
|
+
include(...relations: string[]): QueryBuilder<T>;
|
|
1052
|
+
search(term: string, columns?: string | string[], options?: SearchOptions): QueryBuilder<T>;
|
|
991
1053
|
model: ModelDefinition<T>;
|
|
992
1054
|
}
|
|
993
1055
|
|
|
@@ -1208,6 +1270,24 @@ export function validateQueryComplexity(
|
|
|
1208
1270
|
includes: string[];
|
|
1209
1271
|
};
|
|
1210
1272
|
|
|
1273
|
+
export function buildSearchClause(params: {
|
|
1274
|
+
knex: any;
|
|
1275
|
+
model: any;
|
|
1276
|
+
term: string;
|
|
1277
|
+
columns?: string | string[];
|
|
1278
|
+
options?: SearchOptions;
|
|
1279
|
+
}): {
|
|
1280
|
+
raw: true;
|
|
1281
|
+
sql: string;
|
|
1282
|
+
bindings: any[];
|
|
1283
|
+
boolean: 'and' | 'or';
|
|
1284
|
+
rankClause: { sql: string; bindings: any[] } | null;
|
|
1285
|
+
} | null;
|
|
1286
|
+
|
|
1287
|
+
export function tokenizeSearchTerm(term: string): string[];
|
|
1288
|
+
|
|
1289
|
+
export function detectDialect(knex: any): 'sqlite' | 'postgres' | 'mysql' | 'generic';
|
|
1290
|
+
|
|
1211
1291
|
export interface SchemaExplorerPluginOptions {
|
|
1212
1292
|
/** Raw JSON API endpoint path (default: '/_schema') */
|
|
1213
1293
|
path?: string;
|
|
@@ -1374,6 +1454,7 @@ export interface AuditLogPluginOptions {
|
|
|
1374
1454
|
tableName?: string;
|
|
1375
1455
|
includeDefaultPage?: boolean;
|
|
1376
1456
|
apiPrefix?: string;
|
|
1457
|
+
registerRecordAction?: boolean;
|
|
1377
1458
|
retentionDays?: number;
|
|
1378
1459
|
cleanupIntervalMs?: number;
|
|
1379
1460
|
autoCleanup?: boolean;
|
|
@@ -1391,6 +1472,8 @@ export function auditLogPlugin(options?: AuditLogPluginOptions): WebspressoPlugi
|
|
|
1391
1472
|
stopCleanup(): void;
|
|
1392
1473
|
getRetentionConfig(): AuditLogRetentionConfig;
|
|
1393
1474
|
queryLogs(filters?: Record<string, unknown>): Promise<any[]>;
|
|
1475
|
+
queryTimeline(model: string, recordId: string | number): Promise<any[]>;
|
|
1476
|
+
getRecordTimeline(model: string, recordId: string | number): Promise<any[]>;
|
|
1394
1477
|
getMigrationTemplate(tableName?: string): string;
|
|
1395
1478
|
};
|
|
1396
1479
|
dispose?(): void;
|
|
@@ -1632,6 +1715,86 @@ export interface BasicAuthPluginOptions {
|
|
|
1632
1715
|
|
|
1633
1716
|
export function basicAuthPlugin(options?: BasicAuthPluginOptions): WebspressoPlugin;
|
|
1634
1717
|
|
|
1718
|
+
export interface ApiKeyRecord {
|
|
1719
|
+
id?: number | string;
|
|
1720
|
+
name: string;
|
|
1721
|
+
key_hash: string;
|
|
1722
|
+
key_hint: string;
|
|
1723
|
+
prefix?: string;
|
|
1724
|
+
user_id?: number | string | null;
|
|
1725
|
+
scopes?: string[] | string | null;
|
|
1726
|
+
rate_limit?: number | null;
|
|
1727
|
+
metadata?: any;
|
|
1728
|
+
expires_at?: Date | string | null;
|
|
1729
|
+
last_used_at?: Date | string | null;
|
|
1730
|
+
revoked_at?: Date | string | null;
|
|
1731
|
+
created_at?: Date | string;
|
|
1732
|
+
updated_at?: Date | string;
|
|
1733
|
+
user?: any;
|
|
1734
|
+
[key: string]: any;
|
|
1735
|
+
}
|
|
1736
|
+
|
|
1737
|
+
export interface ApiKeyPluginOptions {
|
|
1738
|
+
/** Database instance or Knex instance. */
|
|
1739
|
+
db?: any;
|
|
1740
|
+
/** Knex instance. */
|
|
1741
|
+
knex?: any;
|
|
1742
|
+
/** Table name for API keys. Default 'api_keys'. */
|
|
1743
|
+
tableName?: string;
|
|
1744
|
+
/** Default key prefix. Default 'wsp_live_'. */
|
|
1745
|
+
prefix?: string;
|
|
1746
|
+
/** Random byte length for key generation. Default 24. */
|
|
1747
|
+
byteLength?: number;
|
|
1748
|
+
/** Protect all matching routes globally. Default false. */
|
|
1749
|
+
global?: boolean;
|
|
1750
|
+
/** Route prefixes to protect when global: true. Default true (all routes). */
|
|
1751
|
+
routes?: string | string[] | boolean;
|
|
1752
|
+
/** Path prefixes to bypass authentication. */
|
|
1753
|
+
skipPaths?: string[];
|
|
1754
|
+
/** Custom predicate function to skip authentication. */
|
|
1755
|
+
skip?: (req: Request) => boolean;
|
|
1756
|
+
/** Static in-memory keys for testing, serverless, or microservices. */
|
|
1757
|
+
keys?: Array<{ key?: string; key_hash?: string; name?: string; scopes?: string[] | string; [key: string]: any }> | Record<string, any>;
|
|
1758
|
+
/** Automatically update last_used_at timestamp. Default true. */
|
|
1759
|
+
trackUsage?: boolean;
|
|
1760
|
+
/** Throttle interval in milliseconds for last_used_at updates. Default 60000. */
|
|
1761
|
+
updateLastUsedThrottleMs?: number;
|
|
1762
|
+
/** Allow query parameter extraction (?apiKey=...). Default false. */
|
|
1763
|
+
allowQueryParam?: boolean;
|
|
1764
|
+
/** Query parameter name. Default 'apiKey'. */
|
|
1765
|
+
queryParamName?: string;
|
|
1766
|
+
/** Custom key extraction function. */
|
|
1767
|
+
extractKey?: (req: Request) => string | null;
|
|
1768
|
+
/** Custom key lookup by SHA-256 hash. */
|
|
1769
|
+
findKeyByHash?: (hash: string, req?: Request) => Promise<ApiKeyRecord | null> | ApiKeyRecord | null;
|
|
1770
|
+
/** Custom verification hook. */
|
|
1771
|
+
verify?: (rawKey: string, req?: Request) => Promise<ApiKeyRecord | null> | ApiKeyRecord | null;
|
|
1772
|
+
/** Custom user loader for key. */
|
|
1773
|
+
getUser?: (record: ApiKeyRecord, req?: Request) => Promise<any> | any;
|
|
1774
|
+
/** Callback hook on successful authentication. */
|
|
1775
|
+
onAuthenticated?: (req: Request, record: ApiKeyRecord) => void | Promise<void>;
|
|
1776
|
+
/** Custom 401 Unauthorized response handler, string, or object. */
|
|
1777
|
+
unauthorizedResponse?: ((req: Request, res: Response, info?: any) => unknown) | string | Record<string, unknown>;
|
|
1778
|
+
/** Custom 403 Forbidden response handler, string, or object. */
|
|
1779
|
+
forbiddenResponse?: ((req: Request, res: Response, info?: any) => unknown) | string | Record<string, unknown>;
|
|
1780
|
+
}
|
|
1781
|
+
|
|
1782
|
+
export interface ApiKeyRouteOptions {
|
|
1783
|
+
/** Required scope(s) for this route. Supports wildcards ('*', 'reports:*'). */
|
|
1784
|
+
scopes?: string | string[];
|
|
1785
|
+
/** Whether all required scopes must be present (true) or any scope (false). Default true. */
|
|
1786
|
+
requireAllScopes?: boolean;
|
|
1787
|
+
/** If true, allows requests without API key to pass through without error. Default false. */
|
|
1788
|
+
optional?: boolean;
|
|
1789
|
+
/** Custom 401 Unauthorized response. */
|
|
1790
|
+
unauthorizedResponse?: ((req: Request, res: Response, info?: any) => unknown) | string | Record<string, unknown>;
|
|
1791
|
+
/** Custom 403 Forbidden response. */
|
|
1792
|
+
forbiddenResponse?: ((req: Request, res: Response, info?: any) => unknown) | string | Record<string, unknown>;
|
|
1793
|
+
}
|
|
1794
|
+
|
|
1795
|
+
export function apiKeyPlugin(options?: ApiKeyPluginOptions): WebspressoPlugin;
|
|
1796
|
+
export function createApiKeyMiddleware(options?: ApiKeyPluginOptions & ApiKeyRouteOptions): RequestHandler;
|
|
1797
|
+
|
|
1635
1798
|
export interface ContentPluginOptions {
|
|
1636
1799
|
db: import('./index').Database;
|
|
1637
1800
|
adminPath?: string;
|
|
@@ -2117,6 +2280,75 @@ export interface QueueRetentionConfig {
|
|
|
2117
2280
|
runOnStart?: boolean;
|
|
2118
2281
|
}
|
|
2119
2282
|
|
|
2283
|
+
export interface ScheduleOptions {
|
|
2284
|
+
id?: string;
|
|
2285
|
+
overlap?: boolean;
|
|
2286
|
+
maxRuns?: number;
|
|
2287
|
+
utc?: boolean;
|
|
2288
|
+
runImmediately?: boolean;
|
|
2289
|
+
delay?: number | Date;
|
|
2290
|
+
attempts?: number;
|
|
2291
|
+
priority?: number;
|
|
2292
|
+
timeout?: number;
|
|
2293
|
+
backoff?: number | { type?: 'exponential' | 'fixed'; delay?: number };
|
|
2294
|
+
[key: string]: unknown;
|
|
2295
|
+
}
|
|
2296
|
+
|
|
2297
|
+
export interface ScheduleInfo {
|
|
2298
|
+
id: string;
|
|
2299
|
+
name: string;
|
|
2300
|
+
cronExpression: string;
|
|
2301
|
+
cron?: CronExpression;
|
|
2302
|
+
data: unknown;
|
|
2303
|
+
options: ScheduleOptions;
|
|
2304
|
+
runsCount: number;
|
|
2305
|
+
lastRunAt: Date | null;
|
|
2306
|
+
nextRunAt: Date | null;
|
|
2307
|
+
isRunning: boolean;
|
|
2308
|
+
activeJobId: string | number | null;
|
|
2309
|
+
registeredAt: Date;
|
|
2310
|
+
}
|
|
2311
|
+
|
|
2312
|
+
export class CronExpression {
|
|
2313
|
+
rawExpression: string;
|
|
2314
|
+
resolvedExpression: string;
|
|
2315
|
+
utc: boolean;
|
|
2316
|
+
minutes: Set<number>;
|
|
2317
|
+
hours: Set<number>;
|
|
2318
|
+
doms: Set<number>;
|
|
2319
|
+
months: Set<number>;
|
|
2320
|
+
dows: Set<number>;
|
|
2321
|
+
constructor(expression: string, options?: { utc?: boolean });
|
|
2322
|
+
match(date?: Date): boolean;
|
|
2323
|
+
getNextDate(fromDate?: Date): Date | null;
|
|
2324
|
+
getNextDates(count?: number, fromDate?: Date): Date[];
|
|
2325
|
+
static isValid(expression: string): boolean;
|
|
2326
|
+
static parse(expression: string, options?: { utc?: boolean }): CronExpression;
|
|
2327
|
+
}
|
|
2328
|
+
|
|
2329
|
+
export function parseCron(expression: string, options?: { utc?: boolean }): CronExpression;
|
|
2330
|
+
export function isValidCron(expression: string): boolean;
|
|
2331
|
+
export function resolveCronAlias(str: string): string;
|
|
2332
|
+
export const CRON_ALIASES: Record<string, string>;
|
|
2333
|
+
|
|
2334
|
+
export class TaskScheduler {
|
|
2335
|
+
queue: QueueManager;
|
|
2336
|
+
maxIntervalMs: number;
|
|
2337
|
+
isRunning: boolean;
|
|
2338
|
+
schedules: Map<string, any>;
|
|
2339
|
+
constructor(queue: QueueManager, options?: { autoStart?: boolean; maxIntervalMs?: number });
|
|
2340
|
+
schedule(cronExpression: string | CronExpression, jobName: string, data?: unknown, options?: ScheduleOptions): ScheduleInfo;
|
|
2341
|
+
cron(cronExpression: string | CronExpression, jobName: string, data?: unknown, options?: ScheduleOptions): ScheduleInfo;
|
|
2342
|
+
unschedule(idOrJobName: string): boolean;
|
|
2343
|
+
getSchedules(): ScheduleInfo[];
|
|
2344
|
+
getSchedule(idOrJobName: string): ScheduleInfo | null;
|
|
2345
|
+
trigger(idOrJobName: string): Promise<Job | null>;
|
|
2346
|
+
start(): this;
|
|
2347
|
+
stop(): this;
|
|
2348
|
+
clear(): void;
|
|
2349
|
+
destroy(): void;
|
|
2350
|
+
}
|
|
2351
|
+
|
|
2120
2352
|
export class QueueManager extends EventEmitter {
|
|
2121
2353
|
adapter: QueueAdapter;
|
|
2122
2354
|
concurrency: number;
|
|
@@ -2125,6 +2357,7 @@ export class QueueManager extends EventEmitter {
|
|
|
2125
2357
|
isPaused: boolean;
|
|
2126
2358
|
isDraining: boolean;
|
|
2127
2359
|
retentionConfig: QueueRetentionConfig;
|
|
2360
|
+
scheduler: TaskScheduler;
|
|
2128
2361
|
constructor(options?: {
|
|
2129
2362
|
adapter?: QueueAdapter;
|
|
2130
2363
|
concurrency?: number;
|
|
@@ -2141,6 +2374,11 @@ export class QueueManager extends EventEmitter {
|
|
|
2141
2374
|
define(name: string, handler: (job: Job, ctx: { queue: QueueManager }) => Promise<any> | any, options?: DispatchOptions): this;
|
|
2142
2375
|
has(name: string): boolean;
|
|
2143
2376
|
dispatch(name: string, data?: unknown, options?: DispatchOptions): Promise<Job>;
|
|
2377
|
+
schedule(cronExpression: string | CronExpression, name: string, data?: unknown, options?: ScheduleOptions): ScheduleInfo;
|
|
2378
|
+
cron(cronExpression: string | CronExpression, name: string, data?: unknown, options?: ScheduleOptions): ScheduleInfo;
|
|
2379
|
+
unschedule(idOrJobName: string): boolean;
|
|
2380
|
+
getSchedules(): ScheduleInfo[];
|
|
2381
|
+
getSchedule(idOrJobName: string): ScheduleInfo | null;
|
|
2144
2382
|
start(): this;
|
|
2145
2383
|
pause(): this;
|
|
2146
2384
|
resume(): this;
|
|
@@ -2202,6 +2440,10 @@ export function queuePlugin(options?: {
|
|
|
2202
2440
|
olderThan?: Date | string | number;
|
|
2203
2441
|
limit?: number;
|
|
2204
2442
|
}): Promise<number>;
|
|
2443
|
+
schedule(cronExpression: string | CronExpression, name: string, data?: unknown, options?: ScheduleOptions): ScheduleInfo | undefined;
|
|
2444
|
+
cron(cronExpression: string | CronExpression, name: string, data?: unknown, options?: ScheduleOptions): ScheduleInfo | undefined;
|
|
2445
|
+
unschedule(idOrJobName: string): boolean | undefined;
|
|
2446
|
+
getSchedules(): ScheduleInfo[];
|
|
2205
2447
|
};
|
|
2206
2448
|
};
|
|
2207
2449
|
|
|
@@ -2234,6 +2476,54 @@ export const ssr: {
|
|
|
2234
2476
|
renderStream: typeof renderStream;
|
|
2235
2477
|
};
|
|
2236
2478
|
|
|
2479
|
+
// --- Server-Sent Events (SSE) Streaming ---
|
|
2480
|
+
|
|
2481
|
+
export interface SseOptions {
|
|
2482
|
+
status?: number;
|
|
2483
|
+
headers?: Record<string, string>;
|
|
2484
|
+
heartbeat?: number | boolean;
|
|
2485
|
+
heartbeatComment?: string;
|
|
2486
|
+
retry?: number;
|
|
2487
|
+
map?: (chunk: any) => any;
|
|
2488
|
+
}
|
|
2489
|
+
|
|
2490
|
+
export interface SseEventObject {
|
|
2491
|
+
data?: any;
|
|
2492
|
+
event?: string;
|
|
2493
|
+
id?: string | number;
|
|
2494
|
+
retry?: number;
|
|
2495
|
+
}
|
|
2496
|
+
|
|
2497
|
+
export class ServerSentEventsStream extends EventEmitter {
|
|
2498
|
+
req: import('http').IncomingMessage;
|
|
2499
|
+
res: import('http').ServerResponse;
|
|
2500
|
+
options: SseOptions;
|
|
2501
|
+
isOpen: boolean;
|
|
2502
|
+
isClosed: boolean;
|
|
2503
|
+
|
|
2504
|
+
constructor(req: import('http').IncomingMessage, res: import('http').ServerResponse, options?: SseOptions);
|
|
2505
|
+
send(payloadOrData: any | SseEventObject, event?: string, id?: string | number): Promise<boolean>;
|
|
2506
|
+
comment(text: string): boolean;
|
|
2507
|
+
heartbeat(comment?: string): boolean;
|
|
2508
|
+
retry(ms: number): boolean;
|
|
2509
|
+
pipe(source: AsyncIterable<any> | Iterable<any> | import('stream').Readable, mapFn?: (chunk: any) => any): Promise<void>;
|
|
2510
|
+
stream(generatorFn: (stream: ServerSentEventsStream) => any): Promise<void>;
|
|
2511
|
+
close(): void;
|
|
2512
|
+
}
|
|
2513
|
+
|
|
2514
|
+
export function createSseStream(
|
|
2515
|
+
req: import('http').IncomingMessage,
|
|
2516
|
+
res: import('http').ServerResponse,
|
|
2517
|
+
sourceOrOptions?: SseOptions | AsyncIterable<any> | Iterable<any> | import('stream').Readable | ((stream: ServerSentEventsStream) => any),
|
|
2518
|
+
maybeOptions?: SseOptions
|
|
2519
|
+
): ServerSentEventsStream | Promise<void>;
|
|
2520
|
+
|
|
2521
|
+
export const sseStream: {
|
|
2522
|
+
ServerSentEventsStream: typeof ServerSentEventsStream;
|
|
2523
|
+
createSseStream: typeof createSseStream;
|
|
2524
|
+
formatSseFrame: (data?: any, event?: string, id?: string | number, retry?: number) => string;
|
|
2525
|
+
};
|
|
2526
|
+
|
|
2237
2527
|
// --- Model Context Protocol (MCP) Plugin ---
|
|
2238
2528
|
|
|
2239
2529
|
export interface McpPluginOptions {
|
|
@@ -2629,6 +2919,244 @@ export interface GenerateTypesResult {
|
|
|
2629
2919
|
|
|
2630
2920
|
export function generateTypes(options?: GenerateTypesOptions): GenerateTypesResult;
|
|
2631
2921
|
|
|
2922
|
+
// --- OAuth 2.0 & Social Login Plugin ---
|
|
2923
|
+
|
|
2924
|
+
export class OAuthError extends Error {
|
|
2925
|
+
code: string;
|
|
2926
|
+
details?: any;
|
|
2927
|
+
constructor(message: string, code?: string, details?: any);
|
|
2928
|
+
}
|
|
2929
|
+
|
|
2930
|
+
export interface OAuthUserProfile {
|
|
2931
|
+
provider: string;
|
|
2932
|
+
id: string;
|
|
2933
|
+
email?: string | null;
|
|
2934
|
+
emailVerified?: boolean;
|
|
2935
|
+
name?: string | null;
|
|
2936
|
+
firstName?: string | null;
|
|
2937
|
+
lastName?: string | null;
|
|
2938
|
+
username?: string | null;
|
|
2939
|
+
avatarUrl?: string | null;
|
|
2940
|
+
bio?: string | null;
|
|
2941
|
+
location?: string | null;
|
|
2942
|
+
locale?: string | null;
|
|
2943
|
+
raw: Record<string, any>;
|
|
2944
|
+
[key: string]: any;
|
|
2945
|
+
}
|
|
2946
|
+
|
|
2947
|
+
export interface OAuthProviderConfig {
|
|
2948
|
+
name?: string;
|
|
2949
|
+
clientId: string;
|
|
2950
|
+
clientSecret: string;
|
|
2951
|
+
redirectUri?: string;
|
|
2952
|
+
authorizationUrl?: string;
|
|
2953
|
+
tokenUrl?: string;
|
|
2954
|
+
userInfoUrl?: string;
|
|
2955
|
+
scopes?: string[] | string;
|
|
2956
|
+
defaultScopes?: string[];
|
|
2957
|
+
params?: Record<string, any>;
|
|
2958
|
+
normalizeProfile?: (raw: any, extra?: any) => OAuthUserProfile;
|
|
2959
|
+
fetchExtra?: (tokens: any) => Promise<any>;
|
|
2960
|
+
}
|
|
2961
|
+
|
|
2962
|
+
export interface OAuthClientConfig {
|
|
2963
|
+
secret?: string;
|
|
2964
|
+
stateTtlMs?: number;
|
|
2965
|
+
providers?: Record<string, OAuthProviderConfig>;
|
|
2966
|
+
}
|
|
2967
|
+
|
|
2968
|
+
export class OAuthClient {
|
|
2969
|
+
secret: string;
|
|
2970
|
+
stateTtlMs: number;
|
|
2971
|
+
providers: Record<string, OAuthProviderConfig>;
|
|
2972
|
+
constructor(config?: OAuthClientConfig);
|
|
2973
|
+
registerProvider(name: string, options?: OAuthProviderConfig): this;
|
|
2974
|
+
getProvider(name: string): OAuthProviderConfig;
|
|
2975
|
+
getProviderNames(): string[];
|
|
2976
|
+
getAuthorizationUrl(providerName: string, options?: {
|
|
2977
|
+
redirectUri?: string;
|
|
2978
|
+
scopes?: string[] | string;
|
|
2979
|
+
stateData?: Record<string, any>;
|
|
2980
|
+
pkce?: boolean;
|
|
2981
|
+
extraParams?: Record<string, any>;
|
|
2982
|
+
}): { url: string; state: string; codeVerifier?: string };
|
|
2983
|
+
exchangeCode(providerName: string, params: {
|
|
2984
|
+
code: string;
|
|
2985
|
+
redirectUri?: string;
|
|
2986
|
+
codeVerifier?: string;
|
|
2987
|
+
}): Promise<Record<string, any>>;
|
|
2988
|
+
fetchUserProfile(providerName: string, tokens: Record<string, any>): Promise<OAuthUserProfile>;
|
|
2989
|
+
handleCallback(providerName: string, params: {
|
|
2990
|
+
code: string;
|
|
2991
|
+
state: string;
|
|
2992
|
+
redirectUri?: string;
|
|
2993
|
+
}): Promise<{ provider: string; user: OAuthUserProfile; tokens: Record<string, any>; stateData: Record<string, any> }>;
|
|
2994
|
+
}
|
|
2995
|
+
|
|
2996
|
+
export function createOAuthClient(config?: OAuthClientConfig): OAuthClient;
|
|
2997
|
+
export function generatePKCE(): { codeVerifier: string; codeChallenge: string; codeChallengeMethod: 'S256' };
|
|
2998
|
+
export function createSignedState(payload: Record<string, any>, secret: string): string;
|
|
2999
|
+
export function verifySignedState(stateString: string, secret: string, maxAgeMs?: number): Record<string, any>;
|
|
3000
|
+
|
|
3001
|
+
export interface OAuthPluginOptions {
|
|
3002
|
+
client?: OAuthClient;
|
|
3003
|
+
providers?: Record<string, OAuthProviderConfig>;
|
|
3004
|
+
secret?: string;
|
|
3005
|
+
pathPrefix?: string;
|
|
3006
|
+
routes?: boolean;
|
|
3007
|
+
pkce?: boolean;
|
|
3008
|
+
stateTtlMs?: number;
|
|
3009
|
+
defaultReturnTo?: string;
|
|
3010
|
+
failureRedirect?: string;
|
|
3011
|
+
findOrCreateUser?: (params: {
|
|
3012
|
+
provider: string;
|
|
3013
|
+
profile: OAuthUserProfile;
|
|
3014
|
+
tokens: Record<string, any>;
|
|
3015
|
+
stateData: Record<string, any>;
|
|
3016
|
+
req: any;
|
|
3017
|
+
res: any;
|
|
3018
|
+
db?: any;
|
|
3019
|
+
}) => Promise<any>;
|
|
3020
|
+
onSuccess?: (params: {
|
|
3021
|
+
provider: string;
|
|
3022
|
+
user: any;
|
|
3023
|
+
profile: OAuthUserProfile;
|
|
3024
|
+
tokens: Record<string, any>;
|
|
3025
|
+
stateData: Record<string, any>;
|
|
3026
|
+
req: any;
|
|
3027
|
+
res: any;
|
|
3028
|
+
client: OAuthClient;
|
|
3029
|
+
}) => Promise<void | any>;
|
|
3030
|
+
onError?: (params: {
|
|
3031
|
+
error: Error | OAuthError;
|
|
3032
|
+
provider: string;
|
|
3033
|
+
req: any;
|
|
3034
|
+
res: any;
|
|
3035
|
+
client: OAuthClient;
|
|
3036
|
+
}) => Promise<void | any>;
|
|
3037
|
+
db?: any;
|
|
3038
|
+
}
|
|
3039
|
+
|
|
3040
|
+
export function oauthPlugin(options?: OAuthPluginOptions): WebspressoPlugin;
|
|
3041
|
+
|
|
3042
|
+
// ==========================================
|
|
3043
|
+
// 2FA / TOTP (RFC 6238, RFC 4226, RFC 4648)
|
|
3044
|
+
// ==========================================
|
|
3045
|
+
|
|
3046
|
+
export interface Base32EncodeOptions {
|
|
3047
|
+
padding?: boolean;
|
|
3048
|
+
}
|
|
3049
|
+
|
|
3050
|
+
export interface TotpSecretOptions extends Base32EncodeOptions {
|
|
3051
|
+
length?: number;
|
|
3052
|
+
}
|
|
3053
|
+
|
|
3054
|
+
export interface HotpOptions {
|
|
3055
|
+
digits?: number;
|
|
3056
|
+
algorithm?: 'sha1' | 'sha256' | 'sha512' | string;
|
|
3057
|
+
encoding?: 'base32' | 'ascii' | 'utf8' | 'hex';
|
|
3058
|
+
}
|
|
3059
|
+
|
|
3060
|
+
export interface TotpOptions extends HotpOptions {
|
|
3061
|
+
time?: number | Date;
|
|
3062
|
+
step?: number;
|
|
3063
|
+
epoch?: number;
|
|
3064
|
+
}
|
|
3065
|
+
|
|
3066
|
+
export interface TotpVerifyOptions extends TotpOptions {
|
|
3067
|
+
window?: number;
|
|
3068
|
+
detailed?: boolean;
|
|
3069
|
+
}
|
|
3070
|
+
|
|
3071
|
+
export interface TotpUriOptions {
|
|
3072
|
+
secret: string;
|
|
3073
|
+
account?: string;
|
|
3074
|
+
issuer?: string;
|
|
3075
|
+
label?: string;
|
|
3076
|
+
algorithm?: string;
|
|
3077
|
+
digits?: number;
|
|
3078
|
+
period?: number;
|
|
3079
|
+
}
|
|
3080
|
+
|
|
3081
|
+
export interface QrSvgOptions {
|
|
3082
|
+
size?: number;
|
|
3083
|
+
margin?: number;
|
|
3084
|
+
darkColor?: string;
|
|
3085
|
+
lightColor?: string;
|
|
3086
|
+
version?: number;
|
|
3087
|
+
ecc?: 'L' | 'M' | 'Q' | 'H';
|
|
3088
|
+
mask?: number;
|
|
3089
|
+
}
|
|
3090
|
+
|
|
3091
|
+
export interface RecoveryCodeOptions {
|
|
3092
|
+
count?: number;
|
|
3093
|
+
length?: number;
|
|
3094
|
+
hyphen?: boolean;
|
|
3095
|
+
}
|
|
3096
|
+
|
|
3097
|
+
export interface TotpSetupOptions extends TotpSecretOptions {
|
|
3098
|
+
user?: any;
|
|
3099
|
+
account?: string;
|
|
3100
|
+
issuer?: string;
|
|
3101
|
+
recoveryCodeCount?: number;
|
|
3102
|
+
qrOptions?: QrSvgOptions;
|
|
3103
|
+
algorithm?: string;
|
|
3104
|
+
digits?: number;
|
|
3105
|
+
period?: number;
|
|
3106
|
+
}
|
|
3107
|
+
|
|
3108
|
+
export interface TotpSetupResult {
|
|
3109
|
+
secret: string;
|
|
3110
|
+
uri: string;
|
|
3111
|
+
qrSvg: string;
|
|
3112
|
+
qrDataUri: string;
|
|
3113
|
+
recoveryCodes: string[];
|
|
3114
|
+
recoveryCodesHashed: string[];
|
|
3115
|
+
}
|
|
3116
|
+
|
|
3117
|
+
export function base32Encode(buffer: Buffer | string, options?: Base32EncodeOptions): string;
|
|
3118
|
+
export function base32Decode(input: string): Buffer;
|
|
3119
|
+
export function generateTotpSecret(options?: TotpSecretOptions): string;
|
|
3120
|
+
export function generateHotp(secret: string | Buffer, counter: number | bigint, options?: HotpOptions): string;
|
|
3121
|
+
export function verifyHotp(token: string, secret: string | Buffer, counter: number | bigint, options?: HotpOptions): boolean;
|
|
3122
|
+
export function generateTotp(secret: string | Buffer, options?: TotpOptions): string;
|
|
3123
|
+
export function verifyTotp(token: string, secret: string | Buffer, options?: TotpVerifyOptions): boolean | { valid: boolean; delta: number | null };
|
|
3124
|
+
export function generateTotpUri(options: TotpUriOptions): string;
|
|
3125
|
+
export function generateTotpQrSvg(uriOrOptions: string | TotpUriOptions, svgOptions?: QrSvgOptions): string;
|
|
3126
|
+
export function generateTotpQrDataUri(uriOrOptions: string | TotpUriOptions, svgOptions?: QrSvgOptions): string;
|
|
3127
|
+
export function generateRecoveryCodes(options?: RecoveryCodeOptions): string[];
|
|
3128
|
+
export function hashRecoveryCode(code: string): string;
|
|
3129
|
+
export function verifyRecoveryCode(code: string, hashedCodes: string[]): { valid: boolean; matchedIndex: number; remainingHashedCodes: string[] };
|
|
3130
|
+
export function createTotpSetup(options?: TotpSetupOptions): TotpSetupResult;
|
|
3131
|
+
|
|
3132
|
+
export function createQrMatrix(text: string, options?: QrSvgOptions): { matrix: boolean[][]; size: number; version: number };
|
|
3133
|
+
export function generateQrSvg(text: string, options?: QrSvgOptions): string;
|
|
3134
|
+
export function generateQrDataUri(text: string, options?: QrSvgOptions): string;
|
|
3135
|
+
|
|
3136
|
+
export namespace totp {
|
|
3137
|
+
export {
|
|
3138
|
+
base32Encode,
|
|
3139
|
+
base32Decode,
|
|
3140
|
+
generateTotpSecret,
|
|
3141
|
+
generateHotp,
|
|
3142
|
+
verifyHotp,
|
|
3143
|
+
generateTotp,
|
|
3144
|
+
verifyTotp,
|
|
3145
|
+
generateTotpUri,
|
|
3146
|
+
generateTotpQrSvg,
|
|
3147
|
+
generateTotpQrDataUri,
|
|
3148
|
+
generateRecoveryCodes,
|
|
3149
|
+
hashRecoveryCode,
|
|
3150
|
+
verifyRecoveryCode,
|
|
3151
|
+
createTotpSetup,
|
|
3152
|
+
createQrMatrix,
|
|
3153
|
+
generateQrSvg,
|
|
3154
|
+
generateQrDataUri,
|
|
3155
|
+
};
|
|
3156
|
+
}
|
|
3157
|
+
|
|
3158
|
+
|
|
3159
|
+
|
|
2632
3160
|
|
|
2633
3161
|
|
|
2634
3162
|
|