webspresso 0.0.99 → 0.0.100
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/AGENTS.md +2 -2
- package/.agents/AUTH.md +246 -0
- package/.agents/CLI.md +47 -0
- package/.agents/ERRORS.md +59 -0
- package/.agents/ORM.md +90 -0
- package/.agents/PLUGINS.md +44 -7
- package/.agents/QUEUE.md +18 -10
- package/.agents/ROUTING.md +33 -0
- package/.agents/STREAMING.md +35 -0
- package/AGENTS.md +1 -0
- package/README.md +145 -93
- package/bin/commands/add-docker.js +467 -0
- package/bin/commands/deploy-check.js +339 -0
- package/bin/webspresso.js +4 -0
- package/core/auth/index.js +63 -1
- package/core/auth/magic-link.js +170 -0
- package/core/auth/manager.js +343 -3
- package/core/auth/middleware.js +30 -5
- package/core/auth/session-manager.js +255 -0
- package/core/auth/sessions.js +351 -0
- package/core/auth/tokens.js +1 -0
- package/core/auth/totp.js +4 -1
- package/core/auth/user-agent.js +161 -0
- package/core/orm/index.js +2 -1
- package/core/orm/model.js +51 -1
- package/core/orm/repository.js +283 -13
- package/core/orm/scopes.js +3 -2
- package/core/orm/types.js +6 -1
- package/core/queue/cron.js +252 -39
- package/core/queue/manager.js +20 -2
- package/core/queue/scheduler.js +115 -59
- package/core/ssr/stream.js +62 -2
- package/index.d.ts +274 -14
- package/index.js +4 -0
- package/package.json +7 -5
- package/plugins/admin-panel/modules/admin-users.js +1 -1
- package/plugins/audit-log/admin-component.js +54 -54
- package/plugins/audit-log/index.js +2 -2
- package/plugins/content/client/inline-edit.js +2 -46
- package/plugins/cors.js +13 -2
- package/plugins/email/auth-bridge.js +66 -0
- package/plugins/email/bundled-templates.js +15 -0
- package/plugins/email/templates/auth-magic-link.mjml +13 -0
- package/plugins/file-manager/admin-component.js +49 -49
- package/plugins/file-manager/index.js +4 -4
- package/plugins/index.js +2 -0
- package/plugins/webhooks/admin-component.js +608 -0
- package/plugins/webhooks/api-handlers.js +237 -0
- package/plugins/webhooks/crypto.js +144 -0
- package/plugins/webhooks/dispatcher.js +708 -0
- package/plugins/webhooks/index.js +263 -0
- package/plugins/webhooks/matcher.js +113 -0
- package/plugins/webhooks/migration-template.js +75 -0
- package/plugins/webhooks/models.js +98 -0
- package/plugins/webhooks/sender.js +176 -0
- package/src/bundle/index.js +2 -1
- package/src/file-router.js +173 -4
- package/src/helpers.js +7 -1
- package/src/njk-frontmatter.js +3 -0
- package/src/routing/cascading.js +112 -0
package/index.d.ts
CHANGED
|
@@ -547,6 +547,19 @@ export interface CascadingLayoutInfo {
|
|
|
547
547
|
configPath: string | null;
|
|
548
548
|
}
|
|
549
549
|
|
|
550
|
+
export interface CascadingErrorBoundaryInfo {
|
|
551
|
+
dirSegment: string;
|
|
552
|
+
errorRelPath: string;
|
|
553
|
+
fullPath: string;
|
|
554
|
+
configPath: string | null;
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
export interface CascadingLoadingInfo {
|
|
558
|
+
dirSegment: string;
|
|
559
|
+
loadingRelPath: string;
|
|
560
|
+
fullPath: string;
|
|
561
|
+
}
|
|
562
|
+
|
|
550
563
|
export namespace cascading {
|
|
551
564
|
export function getDirectoryChain(relativeFilePath: string): string[];
|
|
552
565
|
export function templateHasExtends(templateBody?: string | null, fullPath?: string): boolean;
|
|
@@ -568,6 +581,16 @@ export namespace cascading {
|
|
|
568
581
|
renderContext: Record<string, unknown>,
|
|
569
582
|
isDev?: boolean
|
|
570
583
|
): string;
|
|
584
|
+
export function findNearestErrorBoundary(
|
|
585
|
+
baseDir: string,
|
|
586
|
+
relativeFilePath: string,
|
|
587
|
+
isDev?: boolean
|
|
588
|
+
): CascadingErrorBoundaryInfo | null;
|
|
589
|
+
export function findNearestLoadingTemplate(
|
|
590
|
+
baseDir: string,
|
|
591
|
+
relativeFilePath: string,
|
|
592
|
+
isDev?: boolean
|
|
593
|
+
): CascadingLoadingInfo | null;
|
|
571
594
|
export function clearCascadingCaches(): void;
|
|
572
595
|
}
|
|
573
596
|
|
|
@@ -745,11 +768,20 @@ export interface ScopeContext {
|
|
|
745
768
|
|
|
746
769
|
export type RelationType = 'belongsTo' | 'hasMany' | 'hasOne';
|
|
747
770
|
|
|
771
|
+
export type RelationCascadeOption =
|
|
772
|
+
| boolean
|
|
773
|
+
| 'delete'
|
|
774
|
+
| 'restore'
|
|
775
|
+
| 'all'
|
|
776
|
+
| ('delete' | 'restore' | 'all')[]
|
|
777
|
+
| { delete?: boolean; restore?: boolean };
|
|
778
|
+
|
|
748
779
|
export interface RelationDefinition {
|
|
749
780
|
type: RelationType;
|
|
750
|
-
model: () => ModelDefinition;
|
|
781
|
+
model: string | (() => ModelDefinition<any> | string);
|
|
751
782
|
foreignKey: string;
|
|
752
783
|
localKey?: string;
|
|
784
|
+
cascade?: RelationCascadeOption;
|
|
753
785
|
}
|
|
754
786
|
|
|
755
787
|
export interface AdminPermissions {
|
|
@@ -955,6 +987,8 @@ export function hasModel(name: string): boolean;
|
|
|
955
987
|
|
|
956
988
|
export function clearRegistry(): void;
|
|
957
989
|
|
|
990
|
+
export function isCascadeEnabled(relation: RelationDefinition, operation: 'delete' | 'restore'): boolean;
|
|
991
|
+
|
|
958
992
|
// --- ORM: schema & columns ---
|
|
959
993
|
|
|
960
994
|
/** zdb column helpers (id, string, timestamp, …) + `schema()` */
|
|
@@ -1040,9 +1074,9 @@ export interface Repository<T = Record<string, any>> {
|
|
|
1040
1074
|
createMany(data: (Partial<T> | Record<string, unknown>)[]): Promise<T[]>;
|
|
1041
1075
|
update(id: string | number, data: Partial<T> | Record<string, unknown>): Promise<T | null>;
|
|
1042
1076
|
updateWhere(conditions: Partial<T> | Record<string, unknown>, data: Partial<T> | Record<string, unknown>): Promise<number>;
|
|
1043
|
-
delete(id: string | number): Promise<boolean>;
|
|
1044
|
-
forceDelete(id: string | number): Promise<boolean>;
|
|
1045
|
-
restore(id: string | number): Promise<T | null>;
|
|
1077
|
+
delete(id: string | number, options?: { cascade?: boolean; deletedAt?: Date }): Promise<boolean>;
|
|
1078
|
+
forceDelete(id: string | number, options?: { cascade?: boolean }): Promise<boolean>;
|
|
1079
|
+
restore(id: string | number, options?: { cascade?: boolean; allChildren?: boolean }): Promise<T | null>;
|
|
1046
1080
|
query(): QueryBuilder<T>;
|
|
1047
1081
|
raw(sql: string, bindings?: unknown[]): Promise<unknown>;
|
|
1048
1082
|
count(conditions?: Partial<T> | Record<string, unknown>): Promise<number>;
|
|
@@ -1795,6 +1829,82 @@ export interface ApiKeyRouteOptions {
|
|
|
1795
1829
|
export function apiKeyPlugin(options?: ApiKeyPluginOptions): WebspressoPlugin;
|
|
1796
1830
|
export function createApiKeyMiddleware(options?: ApiKeyPluginOptions & ApiKeyRouteOptions): RequestHandler;
|
|
1797
1831
|
|
|
1832
|
+
export interface WebhookEndpoint {
|
|
1833
|
+
id?: number | string;
|
|
1834
|
+
name: string;
|
|
1835
|
+
url: string;
|
|
1836
|
+
secret?: string;
|
|
1837
|
+
events?: string[] | string;
|
|
1838
|
+
is_active?: boolean;
|
|
1839
|
+
description?: string | null;
|
|
1840
|
+
headers?: Record<string, string> | string | null;
|
|
1841
|
+
metadata?: Record<string, any> | string | null;
|
|
1842
|
+
created_at?: Date | string;
|
|
1843
|
+
updated_at?: Date | string;
|
|
1844
|
+
[key: string]: any;
|
|
1845
|
+
}
|
|
1846
|
+
|
|
1847
|
+
export interface WebhookDelivery {
|
|
1848
|
+
id?: number | string;
|
|
1849
|
+
endpoint_id: number | string;
|
|
1850
|
+
event: string;
|
|
1851
|
+
payload: string;
|
|
1852
|
+
status_code?: number | null;
|
|
1853
|
+
success: boolean;
|
|
1854
|
+
duration_ms?: number | null;
|
|
1855
|
+
error?: string | null;
|
|
1856
|
+
response_body?: string | null;
|
|
1857
|
+
attempt?: number;
|
|
1858
|
+
max_attempts?: number;
|
|
1859
|
+
next_retry_at?: Date | string | null;
|
|
1860
|
+
created_at?: Date | string;
|
|
1861
|
+
updated_at?: Date | string;
|
|
1862
|
+
[key: string]: any;
|
|
1863
|
+
}
|
|
1864
|
+
|
|
1865
|
+
export interface WebhooksPluginOptions {
|
|
1866
|
+
db?: any;
|
|
1867
|
+
knex?: any;
|
|
1868
|
+
endpointsTable?: string;
|
|
1869
|
+
deliveriesTable?: string;
|
|
1870
|
+
maxAttempts?: number;
|
|
1871
|
+
backoffBaseMs?: number;
|
|
1872
|
+
timeoutMs?: number;
|
|
1873
|
+
wrapPayload?: boolean;
|
|
1874
|
+
queue?: any;
|
|
1875
|
+
endpoints?: WebhookEndpoint[];
|
|
1876
|
+
apiPrefix?: string;
|
|
1877
|
+
includeDefaultPage?: boolean;
|
|
1878
|
+
pageTitle?: string;
|
|
1879
|
+
menuOrder?: number;
|
|
1880
|
+
}
|
|
1881
|
+
|
|
1882
|
+
export interface WebhookDispatchResult {
|
|
1883
|
+
dispatched: number;
|
|
1884
|
+
deliveries: WebhookDelivery[];
|
|
1885
|
+
results?: Array<{ success?: boolean; statusCode?: number; error?: string; [key: string]: any }>;
|
|
1886
|
+
}
|
|
1887
|
+
|
|
1888
|
+
export interface WebhookDispatcherInstance {
|
|
1889
|
+
dispatch(event: string, payload: any, options?: { wait?: boolean; endpointId?: number | string }): Promise<WebhookDispatchResult>;
|
|
1890
|
+
pingEndpoint(endpointId: number | string): Promise<any>;
|
|
1891
|
+
retryDelivery(deliveryId: number | string): Promise<any>;
|
|
1892
|
+
createEndpoint(data: Partial<WebhookEndpoint>): Promise<WebhookEndpoint>;
|
|
1893
|
+
getEndpoint(id: number | string): Promise<WebhookEndpoint | null>;
|
|
1894
|
+
updateEndpoint(id: number | string, data: Partial<WebhookEndpoint>): Promise<WebhookEndpoint | null>;
|
|
1895
|
+
deleteEndpoint(id: number | string): Promise<boolean>;
|
|
1896
|
+
listEndpoints(filters?: { active?: boolean; search?: string; limit?: number; offset?: number }): Promise<WebhookEndpoint[]>;
|
|
1897
|
+
listDeliveries(filters?: { endpointId?: number | string; event?: string; success?: boolean | string; page?: number; limit?: number }): Promise<{ items: WebhookDelivery[]; total: number; page: number; limit: number; pages: number }>;
|
|
1898
|
+
getDelivery(id: number | string): Promise<WebhookDelivery | null>;
|
|
1899
|
+
purgeDeliveries(options?: { days?: number }): Promise<number>;
|
|
1900
|
+
dispose(): void;
|
|
1901
|
+
on(event: string, listener: (...args: any[]) => void): this;
|
|
1902
|
+
}
|
|
1903
|
+
|
|
1904
|
+
export function webhooksPlugin(options?: WebhooksPluginOptions): WebspressoPlugin & {
|
|
1905
|
+
dispatcher: WebhookDispatcherInstance;
|
|
1906
|
+
};
|
|
1907
|
+
|
|
1798
1908
|
export interface ContentPluginOptions {
|
|
1799
1909
|
db: import('./index').Database;
|
|
1800
1910
|
adminPath?: string;
|
|
@@ -2283,8 +2393,11 @@ export interface QueueRetentionConfig {
|
|
|
2283
2393
|
export interface ScheduleOptions {
|
|
2284
2394
|
id?: string;
|
|
2285
2395
|
overlap?: boolean;
|
|
2396
|
+
preventOverlap?: boolean;
|
|
2286
2397
|
maxRuns?: number;
|
|
2287
2398
|
utc?: boolean;
|
|
2399
|
+
timezone?: string;
|
|
2400
|
+
tz?: string;
|
|
2288
2401
|
runImmediately?: boolean;
|
|
2289
2402
|
delay?: number | Date;
|
|
2290
2403
|
attempts?: number;
|
|
@@ -2306,6 +2419,7 @@ export interface ScheduleInfo {
|
|
|
2306
2419
|
nextRunAt: Date | null;
|
|
2307
2420
|
isRunning: boolean;
|
|
2308
2421
|
activeJobId: string | number | null;
|
|
2422
|
+
activeJobIds?: (string | number)[];
|
|
2309
2423
|
registeredAt: Date;
|
|
2310
2424
|
}
|
|
2311
2425
|
|
|
@@ -2313,21 +2427,22 @@ export class CronExpression {
|
|
|
2313
2427
|
rawExpression: string;
|
|
2314
2428
|
resolvedExpression: string;
|
|
2315
2429
|
utc: boolean;
|
|
2430
|
+
timezone: string | null;
|
|
2316
2431
|
minutes: Set<number>;
|
|
2317
2432
|
hours: Set<number>;
|
|
2318
2433
|
doms: Set<number>;
|
|
2319
2434
|
months: Set<number>;
|
|
2320
2435
|
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;
|
|
2436
|
+
constructor(expression: string, options?: { utc?: boolean; timezone?: string; tz?: string });
|
|
2437
|
+
match(date?: Date | string | number): boolean;
|
|
2438
|
+
getNextDate(fromDate?: Date | string | number): Date | null;
|
|
2439
|
+
getNextDates(count?: number, fromDate?: Date | string | number): Date[];
|
|
2440
|
+
static isValid(expression: string, options?: { utc?: boolean; timezone?: string; tz?: string }): boolean;
|
|
2441
|
+
static parse(expression: string, options?: { utc?: boolean; timezone?: string; tz?: string }): CronExpression;
|
|
2327
2442
|
}
|
|
2328
2443
|
|
|
2329
|
-
export function parseCron(expression: string, options?: { utc?: boolean }): CronExpression;
|
|
2330
|
-
export function isValidCron(expression: string): boolean;
|
|
2444
|
+
export function parseCron(expression: string, options?: { utc?: boolean; timezone?: string; tz?: string }): CronExpression;
|
|
2445
|
+
export function isValidCron(expression: string, options?: { utc?: boolean; timezone?: string; tz?: string }): boolean;
|
|
2331
2446
|
export function resolveCronAlias(str: string): string;
|
|
2332
2447
|
export const CRON_ALIASES: Record<string, string>;
|
|
2333
2448
|
|
|
@@ -2345,6 +2460,8 @@ export class TaskScheduler {
|
|
|
2345
2460
|
trigger(idOrJobName: string): Promise<Job | null>;
|
|
2346
2461
|
start(): this;
|
|
2347
2462
|
stop(): this;
|
|
2463
|
+
pause(): this;
|
|
2464
|
+
resume(): this;
|
|
2348
2465
|
clear(): void;
|
|
2349
2466
|
destroy(): void;
|
|
2350
2467
|
}
|
|
@@ -2379,6 +2496,8 @@ export class QueueManager extends EventEmitter {
|
|
|
2379
2496
|
unschedule(idOrJobName: string): boolean;
|
|
2380
2497
|
getSchedules(): ScheduleInfo[];
|
|
2381
2498
|
getSchedule(idOrJobName: string): ScheduleInfo | null;
|
|
2499
|
+
triggerSchedule(idOrJobName: string): Promise<Job | null>;
|
|
2500
|
+
triggerCron(idOrJobName: string): Promise<Job | null>;
|
|
2382
2501
|
start(): this;
|
|
2383
2502
|
pause(): this;
|
|
2384
2503
|
resume(): this;
|
|
@@ -2453,14 +2572,20 @@ export interface HtmlStreamOptions {
|
|
|
2453
2572
|
env: import('nunjucks').Environment;
|
|
2454
2573
|
templatePath: string;
|
|
2455
2574
|
context?: Record<string, unknown>;
|
|
2456
|
-
defer?: Record<string, Promise<unknown> | { promise: Promise<unknown>; template?: string }>;
|
|
2575
|
+
defer?: Record<string, Promise<unknown> | { promise: Promise<unknown>; template?: string; loadingTemplate?: string }>;
|
|
2576
|
+
nonce?: string;
|
|
2577
|
+
loadingTemplate?: string | null;
|
|
2578
|
+
layouts?: CascadingLayoutInfo[];
|
|
2457
2579
|
}
|
|
2458
2580
|
|
|
2459
2581
|
export interface RenderStreamOptions {
|
|
2460
2582
|
env?: import('nunjucks').Environment;
|
|
2461
|
-
defer?: Record<string, Promise<unknown> | { promise: Promise<unknown>; template?: string }>;
|
|
2583
|
+
defer?: Record<string, Promise<unknown> | { promise: Promise<unknown>; template?: string; loadingTemplate?: string }>;
|
|
2462
2584
|
status?: number;
|
|
2463
2585
|
flushImmediately?: boolean;
|
|
2586
|
+
nonce?: string;
|
|
2587
|
+
loadingTemplate?: string | null;
|
|
2588
|
+
layouts?: CascadingLayoutInfo[];
|
|
2464
2589
|
}
|
|
2465
2590
|
|
|
2466
2591
|
export function createHtmlStream(options: HtmlStreamOptions): import('stream').Readable;
|
|
@@ -3155,10 +3280,145 @@ export namespace totp {
|
|
|
3155
3280
|
};
|
|
3156
3281
|
}
|
|
3157
3282
|
|
|
3283
|
+
// --- Magic Link / Passwordless Authentication ---
|
|
3284
|
+
|
|
3285
|
+
export interface BuildMagicLinkUrlOptions {
|
|
3286
|
+
baseUrl?: string;
|
|
3287
|
+
path?: string;
|
|
3288
|
+
token: string;
|
|
3289
|
+
}
|
|
3290
|
+
|
|
3291
|
+
export interface FormatMagicLinkHtmlOptions {
|
|
3292
|
+
name?: string;
|
|
3293
|
+
magicLinkUrl: string;
|
|
3294
|
+
expiresMinutes?: number;
|
|
3295
|
+
}
|
|
3296
|
+
|
|
3297
|
+
export interface MagicLinkVerifyMiddlewareOptions {
|
|
3298
|
+
tokenParam?: string;
|
|
3299
|
+
redirectTo?: string;
|
|
3300
|
+
failureRedirect?: string;
|
|
3301
|
+
markEmailVerified?: boolean;
|
|
3302
|
+
jwt?: boolean;
|
|
3303
|
+
}
|
|
3158
3304
|
|
|
3305
|
+
export interface MagicLinkRequestOptions {
|
|
3306
|
+
baseUrl?: string;
|
|
3307
|
+
path?: string;
|
|
3308
|
+
tokenTtlMs?: number;
|
|
3309
|
+
hideUserNotFound?: boolean;
|
|
3310
|
+
buildMagicLinkUrl?: (token: string) => string;
|
|
3311
|
+
}
|
|
3159
3312
|
|
|
3313
|
+
export interface MagicLinkRequestResult {
|
|
3314
|
+
sent: boolean;
|
|
3315
|
+
userFound: boolean;
|
|
3316
|
+
expiresAt?: Date;
|
|
3317
|
+
token?: string;
|
|
3318
|
+
magicLinkUrl?: string;
|
|
3319
|
+
}
|
|
3160
3320
|
|
|
3321
|
+
export interface MagicLinkVerifyResult {
|
|
3322
|
+
ok: true;
|
|
3323
|
+
user: any;
|
|
3324
|
+
userId: string | number;
|
|
3325
|
+
accessToken?: string;
|
|
3326
|
+
refreshToken?: string;
|
|
3327
|
+
}
|
|
3161
3328
|
|
|
3329
|
+
export function buildMagicLinkUrl(options: BuildMagicLinkUrlOptions): string;
|
|
3330
|
+
export function formatMagicLinkHtml(options: FormatMagicLinkHtmlOptions): string;
|
|
3331
|
+
export function createMagicLinkVerifyMiddleware(authManager: any, options?: MagicLinkVerifyMiddlewareOptions): (req: any, res: any, next: any) => Promise<any>;
|
|
3332
|
+
export function createMagicLinkRequestHandler(authManager: any, options?: MagicLinkRequestOptions): (req: any, res: any) => Promise<any>;
|
|
3162
3333
|
|
|
3334
|
+
export namespace magicLink {
|
|
3335
|
+
export {
|
|
3336
|
+
buildMagicLinkUrl,
|
|
3337
|
+
formatMagicLinkHtml,
|
|
3338
|
+
createMagicLinkVerifyMiddleware,
|
|
3339
|
+
createMagicLinkRequestHandler,
|
|
3340
|
+
};
|
|
3341
|
+
}
|
|
3342
|
+
|
|
3343
|
+
// Active Devices & Session Management
|
|
3344
|
+
export interface DeviceInfo {
|
|
3345
|
+
browser: string;
|
|
3346
|
+
os: string;
|
|
3347
|
+
device: 'desktop' | 'mobile' | 'tablet' | 'bot' | 'unknown';
|
|
3348
|
+
isMobile: boolean;
|
|
3349
|
+
isTablet: boolean;
|
|
3350
|
+
isDesktop: boolean;
|
|
3351
|
+
isBot: boolean;
|
|
3352
|
+
}
|
|
3163
3353
|
|
|
3354
|
+
export interface UserSession {
|
|
3355
|
+
id?: number | string;
|
|
3356
|
+
session_id: string;
|
|
3357
|
+
user_id: number | string;
|
|
3358
|
+
ip_address?: string | null;
|
|
3359
|
+
user_agent?: string | null;
|
|
3360
|
+
browser?: string | null;
|
|
3361
|
+
os?: string | null;
|
|
3362
|
+
device?: string | null;
|
|
3363
|
+
last_active_at: Date;
|
|
3364
|
+
created_at?: Date;
|
|
3365
|
+
is_current?: boolean;
|
|
3366
|
+
}
|
|
3367
|
+
|
|
3368
|
+
export interface SessionTracker {
|
|
3369
|
+
track(sessionId: string, userId: string | number, metadata?: { ip?: string; userAgent?: string; browser?: string; os?: string; device?: string }): Promise<UserSession | null>;
|
|
3370
|
+
touch(sessionId: string): Promise<boolean>;
|
|
3371
|
+
get(sessionId: string): Promise<UserSession | null>;
|
|
3372
|
+
list(userId: string | number, currentSessionId?: string | null): Promise<UserSession[]>;
|
|
3373
|
+
isSessionValid(sessionId: string, userId?: string | number | null): Promise<boolean>;
|
|
3374
|
+
revoke(sessionId: string): Promise<boolean>;
|
|
3375
|
+
revokeOthers(userId: string | number, currentSessionId?: string | null): Promise<number>;
|
|
3376
|
+
revokeAll(userId: string | number): Promise<number>;
|
|
3377
|
+
purgeExpired(maxAgeMs: number): Promise<number>;
|
|
3378
|
+
}
|
|
3379
|
+
|
|
3380
|
+
export interface SessionManagerOptions {
|
|
3381
|
+
tracker?: SessionTracker;
|
|
3382
|
+
sessionStore?: any;
|
|
3383
|
+
touchThrottleMs?: number;
|
|
3384
|
+
emitter?: any;
|
|
3385
|
+
}
|
|
3386
|
+
|
|
3387
|
+
export class SessionManager {
|
|
3388
|
+
constructor(options?: SessionManagerOptions);
|
|
3389
|
+
tracker: SessionTracker;
|
|
3390
|
+
sessionStore?: any;
|
|
3391
|
+
touchThrottleMs: number;
|
|
3392
|
+
emitter?: any;
|
|
3393
|
+
track(sessionId: string, userId: string | number, req?: any): Promise<UserSession | null>;
|
|
3394
|
+
touch(sessionId: string): Promise<boolean>;
|
|
3395
|
+
isSessionValid(sessionId: string, userId?: string | number | null): Promise<boolean>;
|
|
3396
|
+
listSessions(userId: string | number, currentSessionId?: string | null): Promise<UserSession[]>;
|
|
3397
|
+
revokeSession(sessionId: string, options?: { userId?: string | number; revokedBy?: string }): Promise<boolean>;
|
|
3398
|
+
revokeOtherSessions(userId: string | number, currentSessionId: string): Promise<number>;
|
|
3399
|
+
revokeAllSessions(userId: string | number): Promise<number>;
|
|
3400
|
+
}
|
|
3401
|
+
|
|
3402
|
+
export function parseUserAgent(userAgent?: string): DeviceInfo;
|
|
3403
|
+
export function getClientIp(req?: any): string;
|
|
3404
|
+
export function createUserSessionsTable(knex: any): Promise<void>;
|
|
3405
|
+
export function dropUserSessionsTable(knex: any): Promise<void>;
|
|
3406
|
+
export function createKnexSessionTracker(db: any, options?: { tableName?: string }): SessionTracker;
|
|
3407
|
+
export function createMemorySessionTracker(): SessionTracker;
|
|
3408
|
+
export function createListSessionsHandler(authManager: any): (req: any, res: any) => Promise<any>;
|
|
3409
|
+
export function createRevokeSessionHandler(authManager: any): (req: any, res: any) => Promise<any>;
|
|
3410
|
+
|
|
3411
|
+
export namespace sessions {
|
|
3412
|
+
export {
|
|
3413
|
+
SessionManager,
|
|
3414
|
+
createUserSessionsTable,
|
|
3415
|
+
dropUserSessionsTable,
|
|
3416
|
+
createKnexSessionTracker,
|
|
3417
|
+
createMemorySessionTracker,
|
|
3418
|
+
getClientIp,
|
|
3419
|
+
parseUserAgent,
|
|
3420
|
+
createListSessionsHandler,
|
|
3421
|
+
createRevokeSessionHandler,
|
|
3422
|
+
};
|
|
3423
|
+
}
|
|
3164
3424
|
|
package/index.js
CHANGED
|
@@ -272,5 +272,9 @@ Object.defineProperties(module.exports, {
|
|
|
272
272
|
createDevProfilerMiddleware: { get: () => require('./src/dev').createDevProfilerMiddleware, enumerable: true, configurable: true },
|
|
273
273
|
generateTypes: { get: () => require('./src/dev/typegen').generateTypes, enumerable: true, configurable: true },
|
|
274
274
|
typegen: { get: () => require('./src/dev/typegen'), enumerable: true, configurable: true },
|
|
275
|
+
|
|
276
|
+
// Webhooks plugin
|
|
277
|
+
webhooks: { get: () => require('./plugins/webhooks'), enumerable: true, configurable: true },
|
|
278
|
+
webhooksPlugin: { get: () => require('./plugins/webhooks').webhooksPlugin, enumerable: true, configurable: true },
|
|
275
279
|
});
|
|
276
280
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "webspresso",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.100",
|
|
4
4
|
"description": "Minimal, production-ready SSR framework for Node.js with file-based routing, Nunjucks templating, built-in i18n, and CLI tooling",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"types": "index.d.ts",
|
|
@@ -126,7 +126,7 @@
|
|
|
126
126
|
"nodemailer": "^10.0.10",
|
|
127
127
|
"nunjucks": "^3.2.4",
|
|
128
128
|
"sanitize-html": "^2.17.7",
|
|
129
|
-
"sharp": "^0.35.
|
|
129
|
+
"sharp": "^0.35.5",
|
|
130
130
|
"swup": "^4.8.3",
|
|
131
131
|
"yaml": "^2.8.3",
|
|
132
132
|
"zod": "^3.23.0",
|
|
@@ -167,7 +167,7 @@
|
|
|
167
167
|
"@types/node": "^20.14.0",
|
|
168
168
|
"@vitest/coverage-v8": "^4.1.11",
|
|
169
169
|
"better-sqlite3": "^11.10.0",
|
|
170
|
-
"chokidar": "^
|
|
170
|
+
"chokidar": "^4.0.3",
|
|
171
171
|
"docboot": "^0.3.0",
|
|
172
172
|
"dotenv": "^16.3.1",
|
|
173
173
|
"express-rate-limit": "^8.4.1",
|
|
@@ -181,9 +181,11 @@
|
|
|
181
181
|
"node": ">=20.0.0"
|
|
182
182
|
},
|
|
183
183
|
"overrides": {
|
|
184
|
-
"basic-ftp": "^
|
|
184
|
+
"basic-ftp": "^6.2.1",
|
|
185
|
+
"chokidar": "^4.0.3",
|
|
186
|
+
"katex": "^0.18.2",
|
|
185
187
|
"tar": "^7.5.11",
|
|
186
|
-
"undici": "^6.
|
|
188
|
+
"undici": "^6.28.1",
|
|
187
189
|
"uuid": "^11.1.1",
|
|
188
190
|
"js-yaml": "^5.4.2",
|
|
189
191
|
"qs": "^6.16.0"
|
|
@@ -692,7 +692,7 @@ const AdminUsersPage = {
|
|
|
692
692
|
m('input.w-full.px-3.py-2.border.border-gray-300.dark:border-slate-600.rounded-lg.bg-white.dark:bg-slate-900.text-gray-900.dark:text-slate-100.focus:ring-2.focus:ring-blue-500', {
|
|
693
693
|
type: 'text',
|
|
694
694
|
required: true,
|
|
695
|
-
placeholder: 'e.g.
|
|
695
|
+
placeholder: 'e.g. Jane Doe',
|
|
696
696
|
value: s.formName,
|
|
697
697
|
oninput: (e) => { s.formName = e.target.value; },
|
|
698
698
|
}),
|