@kuckit/domain 1.0.2 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cache-BCBllCiT.d.ts +37 -0
- package/dist/clock-B_Gmbgwt.d.ts +14 -0
- package/dist/clock-CS5-oXPW.js +10 -0
- package/dist/clock-CS5-oXPW.js.map +1 -0
- package/dist/entities/index.d.ts +3 -0
- package/dist/entities/index.js +3 -0
- package/dist/entities/user.d.ts +2 -0
- package/dist/entities/user.js +1 -0
- package/dist/entities-CSLBfyVE.js +1 -0
- package/dist/errors/index.d.ts +2 -0
- package/dist/errors/index.js +3 -0
- package/dist/errors-CIxiXSCn.js +94 -0
- package/dist/errors-CIxiXSCn.js.map +1 -0
- package/dist/event-bus-6ldeQa_H.d.ts +51 -0
- package/dist/event-publisher-BBAp1zM3.d.ts +27 -0
- package/dist/events/event-bus.d.ts +3 -0
- package/dist/events/event-bus.js +1 -0
- package/dist/events/index.d.ts +4 -0
- package/dist/events/index.js +3 -0
- package/dist/events/types.d.ts +2 -0
- package/dist/events/types.js +1 -0
- package/dist/events-CBFE7GCV.js +1 -0
- package/dist/index-BoGG5KAY.d.ts +1 -0
- package/dist/index-C2geSgue.d.ts +1 -0
- package/dist/index-D25YYUbd.d.ts +1 -0
- package/dist/index-mPubFfG4.d.ts +64 -0
- package/dist/index.d.ts +13 -312
- package/dist/index.js +5 -99
- package/dist/logger-QZhxEopI.d.ts +23 -0
- package/dist/ports/cache.d.ts +2 -0
- package/dist/ports/cache.js +1 -0
- package/dist/ports/clock.d.ts +2 -0
- package/dist/ports/clock.js +3 -0
- package/dist/ports/event-publisher.d.ts +2 -0
- package/dist/ports/event-publisher.js +1 -0
- package/dist/ports/index.d.ts +9 -0
- package/dist/ports/index.js +4 -0
- package/dist/ports/logger.d.ts +2 -0
- package/dist/ports/logger.js +1 -0
- package/dist/ports/rate-limiter.d.ts +2 -0
- package/dist/ports/rate-limiter.js +1 -0
- package/dist/ports/user-repository.d.ts +3 -0
- package/dist/ports/user-repository.js +1 -0
- package/dist/ports-6MZqRxhO.js +1 -0
- package/dist/rate-limiter--mNNkSfP.d.ts +31 -0
- package/dist/types-BMU8Ezie.d.ts +58 -0
- package/dist/user-BZDhbOim.d.ts +17 -0
- package/dist/user-repository-C4N9DoGU.d.ts +16 -0
- package/package.json +1 -1
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
//#region src/ports/cache.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Cache store port interface
|
|
4
|
+
* Defines contract for caching implementations
|
|
5
|
+
*/
|
|
6
|
+
interface CacheStore {
|
|
7
|
+
/**
|
|
8
|
+
* Get a value from cache
|
|
9
|
+
* @param key Cache key
|
|
10
|
+
* @returns Cached value or undefined if not found or expired
|
|
11
|
+
*/
|
|
12
|
+
get<T>(key: string): Promise<T | undefined>;
|
|
13
|
+
/**
|
|
14
|
+
* Set a value in cache
|
|
15
|
+
* @param key Cache key
|
|
16
|
+
* @param value Value to cache
|
|
17
|
+
* @param ttlMs Time to live in milliseconds (undefined = no expiration)
|
|
18
|
+
*/
|
|
19
|
+
set<T>(key: string, value: T, ttlMs?: number): Promise<void>;
|
|
20
|
+
/**
|
|
21
|
+
* Delete a value from cache
|
|
22
|
+
* @param key Cache key
|
|
23
|
+
*/
|
|
24
|
+
del(key: string): Promise<void>;
|
|
25
|
+
/**
|
|
26
|
+
* Clear all values from cache
|
|
27
|
+
*/
|
|
28
|
+
clear(): Promise<void>;
|
|
29
|
+
/**
|
|
30
|
+
* Check if a key exists in cache
|
|
31
|
+
* @param key Cache key
|
|
32
|
+
*/
|
|
33
|
+
has(key: string): Promise<boolean>;
|
|
34
|
+
}
|
|
35
|
+
//#endregion
|
|
36
|
+
export { CacheStore as t };
|
|
37
|
+
//# sourceMappingURL=cache-BCBllCiT.d.ts.map
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
//#region src/ports/clock.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Clock port for time-related operations
|
|
4
|
+
* Enables testing with fixed time
|
|
5
|
+
*/
|
|
6
|
+
interface Clock {
|
|
7
|
+
now(): Date;
|
|
8
|
+
}
|
|
9
|
+
declare class SystemClock implements Clock {
|
|
10
|
+
now(): Date;
|
|
11
|
+
}
|
|
12
|
+
//#endregion
|
|
13
|
+
export { SystemClock as n, Clock as t };
|
|
14
|
+
//# sourceMappingURL=clock-B_Gmbgwt.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"clock-CS5-oXPW.js","names":[],"sources":["../src/ports/clock.ts"],"sourcesContent":["/**\n * Clock port for time-related operations\n * Enables testing with fixed time\n */\nexport interface Clock {\n\tnow(): Date\n}\n\nexport class SystemClock implements Clock {\n\tnow(): Date {\n\t\treturn new Date()\n\t}\n}\n"],"mappings":";AAQA,IAAa,cAAb,MAA0C;CACzC,MAAY;AACX,yBAAO,IAAI,MAAM"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { };
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import { a as forbidden, c as unauthorized, i as conflict, l as validationError, n as ErrorCode, o as internalError, r as ErrorSeverity, s as notFound, t as AppError } from "../index-mPubFfG4.js";
|
|
2
|
+
export { AppError, ErrorCode, ErrorSeverity, conflict, forbidden, internalError, notFound, unauthorized, validationError };
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import { a as forbidden, c as unauthorized, i as conflict, l as validationError, n as ErrorCode, o as internalError, r as ErrorSeverity, s as notFound, t as AppError } from "../errors-CIxiXSCn.js";
|
|
2
|
+
|
|
3
|
+
export { AppError, ErrorCode, ErrorSeverity, conflict, forbidden, internalError, notFound, unauthorized, validationError };
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
//#region src/errors/index.ts
|
|
2
|
+
/**
|
|
3
|
+
* Application error codes (domain-level)
|
|
4
|
+
*/
|
|
5
|
+
let ErrorCode = /* @__PURE__ */ function(ErrorCode$1) {
|
|
6
|
+
ErrorCode$1["USER_NOT_FOUND"] = "USER_NOT_FOUND";
|
|
7
|
+
ErrorCode$1["USER_ALREADY_EXISTS"] = "USER_ALREADY_EXISTS";
|
|
8
|
+
ErrorCode$1["INVALID_EMAIL"] = "INVALID_EMAIL";
|
|
9
|
+
ErrorCode$1["UNAUTHORIZED"] = "UNAUTHORIZED";
|
|
10
|
+
ErrorCode$1["FORBIDDEN"] = "FORBIDDEN";
|
|
11
|
+
ErrorCode$1["SESSION_EXPIRED"] = "SESSION_EXPIRED";
|
|
12
|
+
ErrorCode$1["INVALID_INPUT"] = "INVALID_INPUT";
|
|
13
|
+
ErrorCode$1["VALIDATION_ERROR"] = "VALIDATION_ERROR";
|
|
14
|
+
ErrorCode$1["RATE_LIMITED"] = "RATE_LIMITED";
|
|
15
|
+
ErrorCode$1["NOT_FOUND"] = "NOT_FOUND";
|
|
16
|
+
ErrorCode$1["CONFLICT"] = "CONFLICT";
|
|
17
|
+
ErrorCode$1["INTERNAL_SERVER_ERROR"] = "INTERNAL_SERVER_ERROR";
|
|
18
|
+
return ErrorCode$1;
|
|
19
|
+
}({});
|
|
20
|
+
/**
|
|
21
|
+
* Severity levels for error classification
|
|
22
|
+
*/
|
|
23
|
+
let ErrorSeverity = /* @__PURE__ */ function(ErrorSeverity$1) {
|
|
24
|
+
ErrorSeverity$1["LOW"] = "LOW";
|
|
25
|
+
ErrorSeverity$1["MEDIUM"] = "MEDIUM";
|
|
26
|
+
ErrorSeverity$1["HIGH"] = "HIGH";
|
|
27
|
+
ErrorSeverity$1["CRITICAL"] = "CRITICAL";
|
|
28
|
+
return ErrorSeverity$1;
|
|
29
|
+
}({});
|
|
30
|
+
/**
|
|
31
|
+
* Application error base class
|
|
32
|
+
*/
|
|
33
|
+
var AppError = class AppError extends Error {
|
|
34
|
+
code;
|
|
35
|
+
severity;
|
|
36
|
+
statusCode;
|
|
37
|
+
meta;
|
|
38
|
+
constructor(code, message, options = {}) {
|
|
39
|
+
super(message);
|
|
40
|
+
this.name = "AppError";
|
|
41
|
+
this.code = code;
|
|
42
|
+
this.severity = options.severity || ErrorSeverity.MEDIUM;
|
|
43
|
+
this.statusCode = options.statusCode || 500;
|
|
44
|
+
this.meta = options.meta || {};
|
|
45
|
+
Object.setPrototypeOf(this, AppError.prototype);
|
|
46
|
+
}
|
|
47
|
+
toJSON() {
|
|
48
|
+
return {
|
|
49
|
+
name: this.name,
|
|
50
|
+
code: this.code,
|
|
51
|
+
message: this.message,
|
|
52
|
+
severity: this.severity,
|
|
53
|
+
statusCode: this.statusCode,
|
|
54
|
+
meta: this.meta
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
/**
|
|
59
|
+
* Helper functions to create specific errors
|
|
60
|
+
*/
|
|
61
|
+
const notFound = (resource, meta) => new AppError(ErrorCode.NOT_FOUND, `${resource} not found`, {
|
|
62
|
+
statusCode: 404,
|
|
63
|
+
severity: ErrorSeverity.LOW,
|
|
64
|
+
meta
|
|
65
|
+
});
|
|
66
|
+
const unauthorized = (reason, meta) => new AppError(ErrorCode.UNAUTHORIZED, reason, {
|
|
67
|
+
statusCode: 401,
|
|
68
|
+
severity: ErrorSeverity.LOW,
|
|
69
|
+
meta
|
|
70
|
+
});
|
|
71
|
+
const forbidden = (reason, meta) => new AppError(ErrorCode.FORBIDDEN, reason, {
|
|
72
|
+
statusCode: 403,
|
|
73
|
+
severity: ErrorSeverity.LOW,
|
|
74
|
+
meta
|
|
75
|
+
});
|
|
76
|
+
const validationError = (message, meta) => new AppError(ErrorCode.VALIDATION_ERROR, message, {
|
|
77
|
+
statusCode: 400,
|
|
78
|
+
severity: ErrorSeverity.LOW,
|
|
79
|
+
meta
|
|
80
|
+
});
|
|
81
|
+
const conflict = (message, meta) => new AppError(ErrorCode.CONFLICT, message, {
|
|
82
|
+
statusCode: 409,
|
|
83
|
+
severity: ErrorSeverity.LOW,
|
|
84
|
+
meta
|
|
85
|
+
});
|
|
86
|
+
const internalError = (message, meta) => new AppError(ErrorCode.INTERNAL_SERVER_ERROR, message, {
|
|
87
|
+
statusCode: 500,
|
|
88
|
+
severity: ErrorSeverity.HIGH,
|
|
89
|
+
meta
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
//#endregion
|
|
93
|
+
export { forbidden as a, unauthorized as c, conflict as i, validationError as l, ErrorCode as n, internalError as o, ErrorSeverity as r, notFound as s, AppError as t };
|
|
94
|
+
//# sourceMappingURL=errors-CIxiXSCn.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors-CIxiXSCn.js","names":[],"sources":["../src/errors/index.ts"],"sourcesContent":["/**\n * Application error codes (domain-level)\n */\nexport enum ErrorCode {\n\t// User errors\n\tUSER_NOT_FOUND = 'USER_NOT_FOUND',\n\tUSER_ALREADY_EXISTS = 'USER_ALREADY_EXISTS',\n\tINVALID_EMAIL = 'INVALID_EMAIL',\n\n\t// Auth errors\n\tUNAUTHORIZED = 'UNAUTHORIZED',\n\tFORBIDDEN = 'FORBIDDEN',\n\tSESSION_EXPIRED = 'SESSION_EXPIRED',\n\n\t// Validation errors\n\tINVALID_INPUT = 'INVALID_INPUT',\n\tVALIDATION_ERROR = 'VALIDATION_ERROR',\n\n\t// Rate limiting\n\tRATE_LIMITED = 'RATE_LIMITED',\n\n\t// Generic errors\n\tNOT_FOUND = 'NOT_FOUND',\n\tCONFLICT = 'CONFLICT',\n\tINTERNAL_SERVER_ERROR = 'INTERNAL_SERVER_ERROR',\n}\n\n/**\n * Severity levels for error classification\n */\nexport enum ErrorSeverity {\n\tLOW = 'LOW', // Client error, expected\n\tMEDIUM = 'MEDIUM', // Unexpected but recoverable\n\tHIGH = 'HIGH', // System error, requires attention\n\tCRITICAL = 'CRITICAL', // Complete system failure\n}\n\n/**\n * Application error base class\n */\nexport class AppError extends Error {\n\tpublic readonly code: ErrorCode\n\tpublic readonly severity: ErrorSeverity\n\tpublic readonly statusCode: number\n\tpublic readonly meta: Record<string, any>\n\n\tconstructor(\n\t\tcode: ErrorCode,\n\t\tmessage: string,\n\t\toptions: {\n\t\t\tstatusCode?: number\n\t\t\tseverity?: ErrorSeverity\n\t\t\tmeta?: Record<string, any>\n\t\t} = {}\n\t) {\n\t\tsuper(message)\n\t\tthis.name = 'AppError'\n\t\tthis.code = code\n\t\tthis.severity = options.severity || ErrorSeverity.MEDIUM\n\t\tthis.statusCode = options.statusCode || 500\n\t\tthis.meta = options.meta || {}\n\n\t\tObject.setPrototypeOf(this, AppError.prototype)\n\t}\n\n\ttoJSON() {\n\t\treturn {\n\t\t\tname: this.name,\n\t\t\tcode: this.code,\n\t\t\tmessage: this.message,\n\t\t\tseverity: this.severity,\n\t\t\tstatusCode: this.statusCode,\n\t\t\tmeta: this.meta,\n\t\t}\n\t}\n}\n\n/**\n * Helper functions to create specific errors\n */\n\nexport const notFound = (resource: string, meta?: Record<string, any>) =>\n\tnew AppError(ErrorCode.NOT_FOUND, `${resource} not found`, {\n\t\tstatusCode: 404,\n\t\tseverity: ErrorSeverity.LOW,\n\t\tmeta,\n\t})\n\nexport const unauthorized = (reason: string, meta?: Record<string, any>) =>\n\tnew AppError(ErrorCode.UNAUTHORIZED, reason, {\n\t\tstatusCode: 401,\n\t\tseverity: ErrorSeverity.LOW,\n\t\tmeta,\n\t})\n\nexport const forbidden = (reason: string, meta?: Record<string, any>) =>\n\tnew AppError(ErrorCode.FORBIDDEN, reason, {\n\t\tstatusCode: 403,\n\t\tseverity: ErrorSeverity.LOW,\n\t\tmeta,\n\t})\n\nexport const validationError = (message: string, meta?: Record<string, any>) =>\n\tnew AppError(ErrorCode.VALIDATION_ERROR, message, {\n\t\tstatusCode: 400,\n\t\tseverity: ErrorSeverity.LOW,\n\t\tmeta,\n\t})\n\nexport const conflict = (message: string, meta?: Record<string, any>) =>\n\tnew AppError(ErrorCode.CONFLICT, message, {\n\t\tstatusCode: 409,\n\t\tseverity: ErrorSeverity.LOW,\n\t\tmeta,\n\t})\n\nexport const internalError = (message: string, meta?: Record<string, any>) =>\n\tnew AppError(ErrorCode.INTERNAL_SERVER_ERROR, message, {\n\t\tstatusCode: 500,\n\t\tseverity: ErrorSeverity.HIGH,\n\t\tmeta,\n\t})\n"],"mappings":";;;;AAGA,IAAY,kDAAL;AAEN;AACA;AACA;AAGA;AACA;AACA;AAGA;AACA;AAGA;AAGA;AACA;AACA;;;;;;AAMD,IAAY,0DAAL;AACN;AACA;AACA;AACA;;;;;;AAMD,IAAa,WAAb,MAAa,iBAAiB,MAAM;CACnC,AAAgB;CAChB,AAAgB;CAChB,AAAgB;CAChB,AAAgB;CAEhB,YACC,MACA,SACA,UAII,EAAE,EACL;AACD,QAAM,QAAQ;AACd,OAAK,OAAO;AACZ,OAAK,OAAO;AACZ,OAAK,WAAW,QAAQ,YAAY,cAAc;AAClD,OAAK,aAAa,QAAQ,cAAc;AACxC,OAAK,OAAO,QAAQ,QAAQ,EAAE;AAE9B,SAAO,eAAe,MAAM,SAAS,UAAU;;CAGhD,SAAS;AACR,SAAO;GACN,MAAM,KAAK;GACX,MAAM,KAAK;GACX,SAAS,KAAK;GACd,UAAU,KAAK;GACf,YAAY,KAAK;GACjB,MAAM,KAAK;GACX;;;;;;AAQH,MAAa,YAAY,UAAkB,SAC1C,IAAI,SAAS,UAAU,WAAW,GAAG,SAAS,aAAa;CAC1D,YAAY;CACZ,UAAU,cAAc;CACxB;CACA,CAAC;AAEH,MAAa,gBAAgB,QAAgB,SAC5C,IAAI,SAAS,UAAU,cAAc,QAAQ;CAC5C,YAAY;CACZ,UAAU,cAAc;CACxB;CACA,CAAC;AAEH,MAAa,aAAa,QAAgB,SACzC,IAAI,SAAS,UAAU,WAAW,QAAQ;CACzC,YAAY;CACZ,UAAU,cAAc;CACxB;CACA,CAAC;AAEH,MAAa,mBAAmB,SAAiB,SAChD,IAAI,SAAS,UAAU,kBAAkB,SAAS;CACjD,YAAY;CACZ,UAAU,cAAc;CACxB;CACA,CAAC;AAEH,MAAa,YAAY,SAAiB,SACzC,IAAI,SAAS,UAAU,UAAU,SAAS;CACzC,YAAY;CACZ,UAAU,cAAc;CACxB;CACA,CAAC;AAEH,MAAa,iBAAiB,SAAiB,SAC9C,IAAI,SAAS,UAAU,uBAAuB,SAAS;CACtD,YAAY;CACZ,UAAU,cAAc;CACxB;CACA,CAAC"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { a as TypedDomainEvent, i as EventName } from "./types-BMU8Ezie.js";
|
|
2
|
+
|
|
3
|
+
//#region src/events/event-bus.d.ts
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Event handler function
|
|
7
|
+
* Handles a specific event type
|
|
8
|
+
* Should not throw; errors are caught and logged
|
|
9
|
+
*/
|
|
10
|
+
type EventHandler<TName extends EventName = EventName> = (event: TypedDomainEvent<TName>) => void | Promise<void>;
|
|
11
|
+
/**
|
|
12
|
+
* Event bus interface
|
|
13
|
+
* Handles publishing domain events and managing subscriptions
|
|
14
|
+
*/
|
|
15
|
+
interface EventBus {
|
|
16
|
+
/**
|
|
17
|
+
* Publish event synchronously
|
|
18
|
+
* Awaits all handlers to complete before returning
|
|
19
|
+
* Errors in handlers are caught and logged, don't block others
|
|
20
|
+
*
|
|
21
|
+
* @param event The domain event to publish
|
|
22
|
+
*/
|
|
23
|
+
publish<TName extends EventName>(event: TypedDomainEvent<TName>): Promise<void>;
|
|
24
|
+
/**
|
|
25
|
+
* Publish event asynchronously
|
|
26
|
+
* Uses queueMicrotask to defer execution, returns immediately
|
|
27
|
+
* Errors in handlers are caught and logged
|
|
28
|
+
*
|
|
29
|
+
* @param event The domain event to publish
|
|
30
|
+
*/
|
|
31
|
+
publishAsync<TName extends EventName>(event: TypedDomainEvent<TName>): void;
|
|
32
|
+
/**
|
|
33
|
+
* Subscribe to specific event type
|
|
34
|
+
* Returns unsubscribe function to remove handler
|
|
35
|
+
*
|
|
36
|
+
* @param eventName Event name to subscribe to (e.g., 'user.created')
|
|
37
|
+
* @param handler Event handler function
|
|
38
|
+
* @returns Unsubscribe function
|
|
39
|
+
*/
|
|
40
|
+
subscribe<TName extends EventName>(eventName: TName, handler: EventHandler<TName>): () => void;
|
|
41
|
+
/**
|
|
42
|
+
* Subscribe to all events
|
|
43
|
+
*
|
|
44
|
+
* @param handler Event handler function
|
|
45
|
+
* @returns Unsubscribe function
|
|
46
|
+
*/
|
|
47
|
+
subscribeAll(handler: EventHandler): () => void;
|
|
48
|
+
}
|
|
49
|
+
//#endregion
|
|
50
|
+
export { EventHandler as n, EventBus as t };
|
|
51
|
+
//# sourceMappingURL=event-bus-6ldeQa_H.d.ts.map
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
//#region src/ports/event-publisher.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Event publisher port
|
|
4
|
+
* Used by use cases to publish domain events
|
|
5
|
+
*
|
|
6
|
+
* Note: This is a simplified interface for use case dependencies.
|
|
7
|
+
* The actual EventBus in infrastructure is more feature-rich.
|
|
8
|
+
*/
|
|
9
|
+
interface EventPublisher {
|
|
10
|
+
/**
|
|
11
|
+
* Publish a domain event
|
|
12
|
+
* @param eventName Event name (e.g., 'user.created')
|
|
13
|
+
* @param payload Event payload data
|
|
14
|
+
* @param aggregateId The aggregate ID (e.g., userId)
|
|
15
|
+
*/
|
|
16
|
+
publish(eventName: string, payload: Record<string, any>, aggregateId: string): Promise<void>;
|
|
17
|
+
/**
|
|
18
|
+
* Subscribe to events (for event handlers in infrastructure)
|
|
19
|
+
* @param eventName The event name to listen for
|
|
20
|
+
* @param handler The handler function
|
|
21
|
+
* @returns Unsubscribe function
|
|
22
|
+
*/
|
|
23
|
+
subscribe(eventName: string, handler: (payload: Record<string, any>) => Promise<void> | void): () => void;
|
|
24
|
+
}
|
|
25
|
+
//#endregion
|
|
26
|
+
export { EventPublisher as t };
|
|
27
|
+
//# sourceMappingURL=event-publisher-BBAp1zM3.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { };
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { a as TypedDomainEvent, i as EventName, n as EventMap, r as EventMeta, t as DomainEvent } from "../types-BMU8Ezie.js";
|
|
2
|
+
import { n as EventHandler, t as EventBus } from "../event-bus-6ldeQa_H.js";
|
|
3
|
+
import "../index-BoGG5KAY.js";
|
|
4
|
+
export { DomainEvent, EventBus, EventHandler, EventMap, EventMeta, EventName, TypedDomainEvent };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { };
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
//#region src/errors/index.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Application error codes (domain-level)
|
|
4
|
+
*/
|
|
5
|
+
declare enum ErrorCode {
|
|
6
|
+
USER_NOT_FOUND = "USER_NOT_FOUND",
|
|
7
|
+
USER_ALREADY_EXISTS = "USER_ALREADY_EXISTS",
|
|
8
|
+
INVALID_EMAIL = "INVALID_EMAIL",
|
|
9
|
+
UNAUTHORIZED = "UNAUTHORIZED",
|
|
10
|
+
FORBIDDEN = "FORBIDDEN",
|
|
11
|
+
SESSION_EXPIRED = "SESSION_EXPIRED",
|
|
12
|
+
INVALID_INPUT = "INVALID_INPUT",
|
|
13
|
+
VALIDATION_ERROR = "VALIDATION_ERROR",
|
|
14
|
+
RATE_LIMITED = "RATE_LIMITED",
|
|
15
|
+
NOT_FOUND = "NOT_FOUND",
|
|
16
|
+
CONFLICT = "CONFLICT",
|
|
17
|
+
INTERNAL_SERVER_ERROR = "INTERNAL_SERVER_ERROR",
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Severity levels for error classification
|
|
21
|
+
*/
|
|
22
|
+
declare enum ErrorSeverity {
|
|
23
|
+
LOW = "LOW",
|
|
24
|
+
// Client error, expected
|
|
25
|
+
MEDIUM = "MEDIUM",
|
|
26
|
+
// Unexpected but recoverable
|
|
27
|
+
HIGH = "HIGH",
|
|
28
|
+
// System error, requires attention
|
|
29
|
+
CRITICAL = "CRITICAL",
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Application error base class
|
|
33
|
+
*/
|
|
34
|
+
declare class AppError extends Error {
|
|
35
|
+
readonly code: ErrorCode;
|
|
36
|
+
readonly severity: ErrorSeverity;
|
|
37
|
+
readonly statusCode: number;
|
|
38
|
+
readonly meta: Record<string, any>;
|
|
39
|
+
constructor(code: ErrorCode, message: string, options?: {
|
|
40
|
+
statusCode?: number;
|
|
41
|
+
severity?: ErrorSeverity;
|
|
42
|
+
meta?: Record<string, any>;
|
|
43
|
+
});
|
|
44
|
+
toJSON(): {
|
|
45
|
+
name: string;
|
|
46
|
+
code: ErrorCode;
|
|
47
|
+
message: string;
|
|
48
|
+
severity: ErrorSeverity;
|
|
49
|
+
statusCode: number;
|
|
50
|
+
meta: Record<string, any>;
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Helper functions to create specific errors
|
|
55
|
+
*/
|
|
56
|
+
declare const notFound: (resource: string, meta?: Record<string, any>) => AppError;
|
|
57
|
+
declare const unauthorized: (reason: string, meta?: Record<string, any>) => AppError;
|
|
58
|
+
declare const forbidden: (reason: string, meta?: Record<string, any>) => AppError;
|
|
59
|
+
declare const validationError: (message: string, meta?: Record<string, any>) => AppError;
|
|
60
|
+
declare const conflict: (message: string, meta?: Record<string, any>) => AppError;
|
|
61
|
+
declare const internalError: (message: string, meta?: Record<string, any>) => AppError;
|
|
62
|
+
//#endregion
|
|
63
|
+
export { forbidden as a, unauthorized as c, conflict as i, validationError as l, ErrorCode as n, internalError as o, ErrorSeverity as r, notFound as s, AppError as t };
|
|
64
|
+
//# sourceMappingURL=index-mPubFfG4.d.ts.map
|
package/dist/index.d.ts
CHANGED
|
@@ -1,313 +1,14 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
}
|
|
15
|
-
//#endregion
|
|
16
|
-
//#region src/ports/user-repository.d.ts
|
|
17
|
-
/**
|
|
18
|
-
* Repository port (interface) for user persistence
|
|
19
|
-
* Infrastructure layer will implement this
|
|
20
|
-
*/
|
|
21
|
-
interface UserRepository {
|
|
22
|
-
findById(id: string): Promise<User | null>;
|
|
23
|
-
findByEmail(email: string): Promise<User | null>;
|
|
24
|
-
save(user: User): Promise<void>;
|
|
25
|
-
}
|
|
26
|
-
//#endregion
|
|
27
|
-
//#region src/ports/clock.d.ts
|
|
28
|
-
/**
|
|
29
|
-
* Clock port for time-related operations
|
|
30
|
-
* Enables testing with fixed time
|
|
31
|
-
*/
|
|
32
|
-
interface Clock {
|
|
33
|
-
now(): Date;
|
|
34
|
-
}
|
|
35
|
-
declare class SystemClock implements Clock {
|
|
36
|
-
now(): Date;
|
|
37
|
-
}
|
|
38
|
-
//#endregion
|
|
39
|
-
//#region src/ports/logger.d.ts
|
|
40
|
-
/**
|
|
41
|
-
* Logger port - structured logging for Loki/Prometheus
|
|
42
|
-
* Loki-compatible: labels and structured fields in meta
|
|
43
|
-
*/
|
|
44
|
-
interface Logger {
|
|
45
|
-
debug: (message: string, meta?: LogContext) => void;
|
|
46
|
-
info: (message: string, meta?: LogContext) => void;
|
|
47
|
-
warn: (message: string, meta?: LogContext) => void;
|
|
48
|
-
error: (message: string, meta?: LogContext | Error) => void;
|
|
49
|
-
}
|
|
50
|
-
/**
|
|
51
|
-
* Structured log context (Loki labels)
|
|
52
|
-
*/
|
|
53
|
-
interface LogContext {
|
|
54
|
-
requestId?: string;
|
|
55
|
-
userId?: string;
|
|
56
|
-
feature?: string;
|
|
57
|
-
[key: string]: any;
|
|
58
|
-
}
|
|
59
|
-
//#endregion
|
|
60
|
-
//#region src/ports/event-publisher.d.ts
|
|
61
|
-
/**
|
|
62
|
-
* Event publisher port
|
|
63
|
-
* Used by use cases to publish domain events
|
|
64
|
-
*
|
|
65
|
-
* Note: This is a simplified interface for use case dependencies.
|
|
66
|
-
* The actual EventBus in infrastructure is more feature-rich.
|
|
67
|
-
*/
|
|
68
|
-
interface EventPublisher {
|
|
69
|
-
/**
|
|
70
|
-
* Publish a domain event
|
|
71
|
-
* @param eventName Event name (e.g., 'user.created')
|
|
72
|
-
* @param payload Event payload data
|
|
73
|
-
* @param aggregateId The aggregate ID (e.g., userId)
|
|
74
|
-
*/
|
|
75
|
-
publish(eventName: string, payload: Record<string, any>, aggregateId: string): Promise<void>;
|
|
76
|
-
/**
|
|
77
|
-
* Subscribe to events (for event handlers in infrastructure)
|
|
78
|
-
* @param eventName The event name to listen for
|
|
79
|
-
* @param handler The handler function
|
|
80
|
-
* @returns Unsubscribe function
|
|
81
|
-
*/
|
|
82
|
-
subscribe(eventName: string, handler: (payload: Record<string, any>) => Promise<void> | void): () => void;
|
|
83
|
-
}
|
|
84
|
-
//#endregion
|
|
85
|
-
//#region src/ports/cache.d.ts
|
|
86
|
-
/**
|
|
87
|
-
* Cache store port interface
|
|
88
|
-
* Defines contract for caching implementations
|
|
89
|
-
*/
|
|
90
|
-
interface CacheStore {
|
|
91
|
-
/**
|
|
92
|
-
* Get a value from cache
|
|
93
|
-
* @param key Cache key
|
|
94
|
-
* @returns Cached value or undefined if not found or expired
|
|
95
|
-
*/
|
|
96
|
-
get<T>(key: string): Promise<T | undefined>;
|
|
97
|
-
/**
|
|
98
|
-
* Set a value in cache
|
|
99
|
-
* @param key Cache key
|
|
100
|
-
* @param value Value to cache
|
|
101
|
-
* @param ttlMs Time to live in milliseconds (undefined = no expiration)
|
|
102
|
-
*/
|
|
103
|
-
set<T>(key: string, value: T, ttlMs?: number): Promise<void>;
|
|
104
|
-
/**
|
|
105
|
-
* Delete a value from cache
|
|
106
|
-
* @param key Cache key
|
|
107
|
-
*/
|
|
108
|
-
del(key: string): Promise<void>;
|
|
109
|
-
/**
|
|
110
|
-
* Clear all values from cache
|
|
111
|
-
*/
|
|
112
|
-
clear(): Promise<void>;
|
|
113
|
-
/**
|
|
114
|
-
* Check if a key exists in cache
|
|
115
|
-
* @param key Cache key
|
|
116
|
-
*/
|
|
117
|
-
has(key: string): Promise<boolean>;
|
|
118
|
-
}
|
|
119
|
-
//#endregion
|
|
120
|
-
//#region src/ports/rate-limiter.d.ts
|
|
121
|
-
/**
|
|
122
|
-
* Rate limiter store port interface
|
|
123
|
-
* Uses token bucket algorithm for rate limiting
|
|
124
|
-
*/
|
|
125
|
-
interface RateLimiterStore {
|
|
126
|
-
/**
|
|
127
|
-
* Check if a request should be allowed
|
|
128
|
-
* @param key Rate limit key (per-user, per-IP, etc)
|
|
129
|
-
* @param capacity Bucket capacity (max tokens)
|
|
130
|
-
* @param refillPerSecond Number of tokens to refill per second
|
|
131
|
-
* @returns Object with allowed flag and reset time if rate limited
|
|
132
|
-
*/
|
|
133
|
-
checkLimit(key: string, capacity: number, refillPerSecond: number): Promise<{
|
|
134
|
-
allowed: boolean;
|
|
135
|
-
tokensRemaining: number;
|
|
136
|
-
resetAt: Date;
|
|
137
|
-
}>;
|
|
138
|
-
/**
|
|
139
|
-
* Reset rate limit for a key
|
|
140
|
-
* @param key Rate limit key
|
|
141
|
-
*/
|
|
142
|
-
reset(key: string): Promise<void>;
|
|
143
|
-
/**
|
|
144
|
-
* Clear all rate limit data
|
|
145
|
-
*/
|
|
146
|
-
clear(): Promise<void>;
|
|
147
|
-
}
|
|
148
|
-
//#endregion
|
|
149
|
-
//#region src/errors/index.d.ts
|
|
150
|
-
/**
|
|
151
|
-
* Application error codes (domain-level)
|
|
152
|
-
*/
|
|
153
|
-
declare enum ErrorCode {
|
|
154
|
-
USER_NOT_FOUND = "USER_NOT_FOUND",
|
|
155
|
-
USER_ALREADY_EXISTS = "USER_ALREADY_EXISTS",
|
|
156
|
-
INVALID_EMAIL = "INVALID_EMAIL",
|
|
157
|
-
UNAUTHORIZED = "UNAUTHORIZED",
|
|
158
|
-
FORBIDDEN = "FORBIDDEN",
|
|
159
|
-
SESSION_EXPIRED = "SESSION_EXPIRED",
|
|
160
|
-
INVALID_INPUT = "INVALID_INPUT",
|
|
161
|
-
VALIDATION_ERROR = "VALIDATION_ERROR",
|
|
162
|
-
RATE_LIMITED = "RATE_LIMITED",
|
|
163
|
-
NOT_FOUND = "NOT_FOUND",
|
|
164
|
-
CONFLICT = "CONFLICT",
|
|
165
|
-
INTERNAL_SERVER_ERROR = "INTERNAL_SERVER_ERROR",
|
|
166
|
-
}
|
|
167
|
-
/**
|
|
168
|
-
* Severity levels for error classification
|
|
169
|
-
*/
|
|
170
|
-
declare enum ErrorSeverity {
|
|
171
|
-
LOW = "LOW",
|
|
172
|
-
// Client error, expected
|
|
173
|
-
MEDIUM = "MEDIUM",
|
|
174
|
-
// Unexpected but recoverable
|
|
175
|
-
HIGH = "HIGH",
|
|
176
|
-
// System error, requires attention
|
|
177
|
-
CRITICAL = "CRITICAL",
|
|
178
|
-
}
|
|
179
|
-
/**
|
|
180
|
-
* Application error base class
|
|
181
|
-
*/
|
|
182
|
-
declare class AppError extends Error {
|
|
183
|
-
readonly code: ErrorCode;
|
|
184
|
-
readonly severity: ErrorSeverity;
|
|
185
|
-
readonly statusCode: number;
|
|
186
|
-
readonly meta: Record<string, any>;
|
|
187
|
-
constructor(code: ErrorCode, message: string, options?: {
|
|
188
|
-
statusCode?: number;
|
|
189
|
-
severity?: ErrorSeverity;
|
|
190
|
-
meta?: Record<string, any>;
|
|
191
|
-
});
|
|
192
|
-
toJSON(): {
|
|
193
|
-
name: string;
|
|
194
|
-
code: ErrorCode;
|
|
195
|
-
message: string;
|
|
196
|
-
severity: ErrorSeverity;
|
|
197
|
-
statusCode: number;
|
|
198
|
-
meta: Record<string, any>;
|
|
199
|
-
};
|
|
200
|
-
}
|
|
201
|
-
/**
|
|
202
|
-
* Helper functions to create specific errors
|
|
203
|
-
*/
|
|
204
|
-
declare const notFound: (resource: string, meta?: Record<string, any>) => AppError;
|
|
205
|
-
declare const unauthorized: (reason: string, meta?: Record<string, any>) => AppError;
|
|
206
|
-
declare const forbidden: (reason: string, meta?: Record<string, any>) => AppError;
|
|
207
|
-
declare const validationError: (message: string, meta?: Record<string, any>) => AppError;
|
|
208
|
-
declare const conflict: (message: string, meta?: Record<string, any>) => AppError;
|
|
209
|
-
declare const internalError: (message: string, meta?: Record<string, any>) => AppError;
|
|
210
|
-
//#endregion
|
|
211
|
-
//#region src/events/types.d.ts
|
|
212
|
-
/**
|
|
213
|
-
* Event-driven architecture types
|
|
214
|
-
*
|
|
215
|
-
* Event names follow 'module.action' pattern: 'user.created', 'user.updated'
|
|
216
|
-
* All events are strongly typed through EventMap
|
|
217
|
-
*/
|
|
218
|
-
/**
|
|
219
|
-
* Event metadata included with every domain event
|
|
220
|
-
*/
|
|
221
|
-
interface EventMeta {
|
|
222
|
-
/** Unique identifier for this event */
|
|
223
|
-
readonly eventId: string;
|
|
224
|
-
/** Timestamp when event occurred */
|
|
225
|
-
readonly occurredAt: Date;
|
|
226
|
-
/** Event schema version for migrations */
|
|
227
|
-
readonly version: number;
|
|
228
|
-
/** Aggregate ID (e.g., userId for user events) */
|
|
229
|
-
readonly aggregateId: string;
|
|
230
|
-
/** Correlation ID for tracing across services */
|
|
231
|
-
readonly correlationId: string;
|
|
232
|
-
}
|
|
233
|
-
/**
|
|
234
|
-
* Base domain event type
|
|
235
|
-
* All domain events extend this interface
|
|
236
|
-
*/
|
|
237
|
-
interface DomainEvent<TName extends string = string, TPayload extends Record<string, any> = Record<string, any>> {
|
|
238
|
-
/** Event name in 'module.action' format */
|
|
239
|
-
readonly name: TName;
|
|
240
|
-
/** Event payload (action-specific data) */
|
|
241
|
-
readonly payload: TPayload;
|
|
242
|
-
/** Event metadata (standard for all events) */
|
|
243
|
-
readonly meta: EventMeta;
|
|
244
|
-
}
|
|
245
|
-
/**
|
|
246
|
-
* Event map definition - extend this to add typed events
|
|
247
|
-
* Maps event names to their payload types
|
|
248
|
-
*
|
|
249
|
-
* Example:
|
|
250
|
-
* interface EventMap {
|
|
251
|
-
* 'user.created': { userId: string; email: string }
|
|
252
|
-
* 'user.updated': { userId: string; name: string }
|
|
253
|
-
* }
|
|
254
|
-
*/
|
|
255
|
-
interface EventMap {
|
|
256
|
-
[key: string]: Record<string, any>;
|
|
257
|
-
}
|
|
258
|
-
/**
|
|
259
|
-
* Valid event names derived from EventMap
|
|
260
|
-
*/
|
|
261
|
-
type EventName = keyof EventMap & string;
|
|
262
|
-
/**
|
|
263
|
-
* Typed domain event for a specific event name
|
|
264
|
-
*/
|
|
265
|
-
type TypedDomainEvent<TName extends EventName = EventName> = DomainEvent<TName, EventMap[TName]>;
|
|
266
|
-
//#endregion
|
|
267
|
-
//#region src/events/event-bus.d.ts
|
|
268
|
-
/**
|
|
269
|
-
* Event handler function
|
|
270
|
-
* Handles a specific event type
|
|
271
|
-
* Should not throw; errors are caught and logged
|
|
272
|
-
*/
|
|
273
|
-
type EventHandler<TName extends EventName = EventName> = (event: TypedDomainEvent<TName>) => void | Promise<void>;
|
|
274
|
-
/**
|
|
275
|
-
* Event bus interface
|
|
276
|
-
* Handles publishing domain events and managing subscriptions
|
|
277
|
-
*/
|
|
278
|
-
interface EventBus {
|
|
279
|
-
/**
|
|
280
|
-
* Publish event synchronously
|
|
281
|
-
* Awaits all handlers to complete before returning
|
|
282
|
-
* Errors in handlers are caught and logged, don't block others
|
|
283
|
-
*
|
|
284
|
-
* @param event The domain event to publish
|
|
285
|
-
*/
|
|
286
|
-
publish<TName extends EventName>(event: TypedDomainEvent<TName>): Promise<void>;
|
|
287
|
-
/**
|
|
288
|
-
* Publish event asynchronously
|
|
289
|
-
* Uses queueMicrotask to defer execution, returns immediately
|
|
290
|
-
* Errors in handlers are caught and logged
|
|
291
|
-
*
|
|
292
|
-
* @param event The domain event to publish
|
|
293
|
-
*/
|
|
294
|
-
publishAsync<TName extends EventName>(event: TypedDomainEvent<TName>): void;
|
|
295
|
-
/**
|
|
296
|
-
* Subscribe to specific event type
|
|
297
|
-
* Returns unsubscribe function to remove handler
|
|
298
|
-
*
|
|
299
|
-
* @param eventName Event name to subscribe to (e.g., 'user.created')
|
|
300
|
-
* @param handler Event handler function
|
|
301
|
-
* @returns Unsubscribe function
|
|
302
|
-
*/
|
|
303
|
-
subscribe<TName extends EventName>(eventName: TName, handler: EventHandler<TName>): () => void;
|
|
304
|
-
/**
|
|
305
|
-
* Subscribe to all events
|
|
306
|
-
*
|
|
307
|
-
* @param handler Event handler function
|
|
308
|
-
* @returns Unsubscribe function
|
|
309
|
-
*/
|
|
310
|
-
subscribeAll(handler: EventHandler): () => void;
|
|
311
|
-
}
|
|
312
|
-
//#endregion
|
|
1
|
+
import { t as User } from "./user-BZDhbOim.js";
|
|
2
|
+
import "./index-D25YYUbd.js";
|
|
3
|
+
import { a as forbidden, c as unauthorized, i as conflict, l as validationError, n as ErrorCode, o as internalError, r as ErrorSeverity, s as notFound, t as AppError } from "./index-mPubFfG4.js";
|
|
4
|
+
import { a as TypedDomainEvent, i as EventName, n as EventMap, r as EventMeta, t as DomainEvent } from "./types-BMU8Ezie.js";
|
|
5
|
+
import { n as EventHandler, t as EventBus } from "./event-bus-6ldeQa_H.js";
|
|
6
|
+
import "./index-BoGG5KAY.js";
|
|
7
|
+
import { t as UserRepository } from "./user-repository-C4N9DoGU.js";
|
|
8
|
+
import { n as SystemClock, t as Clock } from "./clock-B_Gmbgwt.js";
|
|
9
|
+
import { n as Logger, t as LogContext } from "./logger-QZhxEopI.js";
|
|
10
|
+
import { t as EventPublisher } from "./event-publisher-BBAp1zM3.js";
|
|
11
|
+
import { t as CacheStore } from "./cache-BCBllCiT.js";
|
|
12
|
+
import { t as RateLimiterStore } from "./rate-limiter--mNNkSfP.js";
|
|
13
|
+
import "./index-C2geSgue.js";
|
|
313
14
|
export { AppError, CacheStore, Clock, DomainEvent, ErrorCode, ErrorSeverity, EventBus, EventHandler, EventMap, EventMeta, EventName, EventPublisher, LogContext, Logger, RateLimiterStore, SystemClock, TypedDomainEvent, User, UserRepository, conflict, forbidden, internalError, notFound, unauthorized, validationError };
|
package/dist/index.js
CHANGED
|
@@ -1,101 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
};
|
|
1
|
+
import "./entities-CSLBfyVE.js";
|
|
2
|
+
import { t as SystemClock } from "./clock-CS5-oXPW.js";
|
|
3
|
+
import "./ports-6MZqRxhO.js";
|
|
4
|
+
import { a as forbidden, c as unauthorized, i as conflict, l as validationError, n as ErrorCode, o as internalError, r as ErrorSeverity, s as notFound, t as AppError } from "./errors-CIxiXSCn.js";
|
|
5
|
+
import "./events-CBFE7GCV.js";
|
|
7
6
|
|
|
8
|
-
//#endregion
|
|
9
|
-
//#region src/errors/index.ts
|
|
10
|
-
/**
|
|
11
|
-
* Application error codes (domain-level)
|
|
12
|
-
*/
|
|
13
|
-
let ErrorCode = /* @__PURE__ */ function(ErrorCode$1) {
|
|
14
|
-
ErrorCode$1["USER_NOT_FOUND"] = "USER_NOT_FOUND";
|
|
15
|
-
ErrorCode$1["USER_ALREADY_EXISTS"] = "USER_ALREADY_EXISTS";
|
|
16
|
-
ErrorCode$1["INVALID_EMAIL"] = "INVALID_EMAIL";
|
|
17
|
-
ErrorCode$1["UNAUTHORIZED"] = "UNAUTHORIZED";
|
|
18
|
-
ErrorCode$1["FORBIDDEN"] = "FORBIDDEN";
|
|
19
|
-
ErrorCode$1["SESSION_EXPIRED"] = "SESSION_EXPIRED";
|
|
20
|
-
ErrorCode$1["INVALID_INPUT"] = "INVALID_INPUT";
|
|
21
|
-
ErrorCode$1["VALIDATION_ERROR"] = "VALIDATION_ERROR";
|
|
22
|
-
ErrorCode$1["RATE_LIMITED"] = "RATE_LIMITED";
|
|
23
|
-
ErrorCode$1["NOT_FOUND"] = "NOT_FOUND";
|
|
24
|
-
ErrorCode$1["CONFLICT"] = "CONFLICT";
|
|
25
|
-
ErrorCode$1["INTERNAL_SERVER_ERROR"] = "INTERNAL_SERVER_ERROR";
|
|
26
|
-
return ErrorCode$1;
|
|
27
|
-
}({});
|
|
28
|
-
/**
|
|
29
|
-
* Severity levels for error classification
|
|
30
|
-
*/
|
|
31
|
-
let ErrorSeverity = /* @__PURE__ */ function(ErrorSeverity$1) {
|
|
32
|
-
ErrorSeverity$1["LOW"] = "LOW";
|
|
33
|
-
ErrorSeverity$1["MEDIUM"] = "MEDIUM";
|
|
34
|
-
ErrorSeverity$1["HIGH"] = "HIGH";
|
|
35
|
-
ErrorSeverity$1["CRITICAL"] = "CRITICAL";
|
|
36
|
-
return ErrorSeverity$1;
|
|
37
|
-
}({});
|
|
38
|
-
/**
|
|
39
|
-
* Application error base class
|
|
40
|
-
*/
|
|
41
|
-
var AppError = class AppError extends Error {
|
|
42
|
-
code;
|
|
43
|
-
severity;
|
|
44
|
-
statusCode;
|
|
45
|
-
meta;
|
|
46
|
-
constructor(code, message, options = {}) {
|
|
47
|
-
super(message);
|
|
48
|
-
this.name = "AppError";
|
|
49
|
-
this.code = code;
|
|
50
|
-
this.severity = options.severity || ErrorSeverity.MEDIUM;
|
|
51
|
-
this.statusCode = options.statusCode || 500;
|
|
52
|
-
this.meta = options.meta || {};
|
|
53
|
-
Object.setPrototypeOf(this, AppError.prototype);
|
|
54
|
-
}
|
|
55
|
-
toJSON() {
|
|
56
|
-
return {
|
|
57
|
-
name: this.name,
|
|
58
|
-
code: this.code,
|
|
59
|
-
message: this.message,
|
|
60
|
-
severity: this.severity,
|
|
61
|
-
statusCode: this.statusCode,
|
|
62
|
-
meta: this.meta
|
|
63
|
-
};
|
|
64
|
-
}
|
|
65
|
-
};
|
|
66
|
-
/**
|
|
67
|
-
* Helper functions to create specific errors
|
|
68
|
-
*/
|
|
69
|
-
const notFound = (resource, meta) => new AppError(ErrorCode.NOT_FOUND, `${resource} not found`, {
|
|
70
|
-
statusCode: 404,
|
|
71
|
-
severity: ErrorSeverity.LOW,
|
|
72
|
-
meta
|
|
73
|
-
});
|
|
74
|
-
const unauthorized = (reason, meta) => new AppError(ErrorCode.UNAUTHORIZED, reason, {
|
|
75
|
-
statusCode: 401,
|
|
76
|
-
severity: ErrorSeverity.LOW,
|
|
77
|
-
meta
|
|
78
|
-
});
|
|
79
|
-
const forbidden = (reason, meta) => new AppError(ErrorCode.FORBIDDEN, reason, {
|
|
80
|
-
statusCode: 403,
|
|
81
|
-
severity: ErrorSeverity.LOW,
|
|
82
|
-
meta
|
|
83
|
-
});
|
|
84
|
-
const validationError = (message, meta) => new AppError(ErrorCode.VALIDATION_ERROR, message, {
|
|
85
|
-
statusCode: 400,
|
|
86
|
-
severity: ErrorSeverity.LOW,
|
|
87
|
-
meta
|
|
88
|
-
});
|
|
89
|
-
const conflict = (message, meta) => new AppError(ErrorCode.CONFLICT, message, {
|
|
90
|
-
statusCode: 409,
|
|
91
|
-
severity: ErrorSeverity.LOW,
|
|
92
|
-
meta
|
|
93
|
-
});
|
|
94
|
-
const internalError = (message, meta) => new AppError(ErrorCode.INTERNAL_SERVER_ERROR, message, {
|
|
95
|
-
statusCode: 500,
|
|
96
|
-
severity: ErrorSeverity.HIGH,
|
|
97
|
-
meta
|
|
98
|
-
});
|
|
99
|
-
|
|
100
|
-
//#endregion
|
|
101
7
|
export { AppError, ErrorCode, ErrorSeverity, SystemClock, conflict, forbidden, internalError, notFound, unauthorized, validationError };
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
//#region src/ports/logger.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Logger port - structured logging for Loki/Prometheus
|
|
4
|
+
* Loki-compatible: labels and structured fields in meta
|
|
5
|
+
*/
|
|
6
|
+
interface Logger {
|
|
7
|
+
debug: (message: string, meta?: LogContext) => void;
|
|
8
|
+
info: (message: string, meta?: LogContext) => void;
|
|
9
|
+
warn: (message: string, meta?: LogContext) => void;
|
|
10
|
+
error: (message: string, meta?: LogContext | Error) => void;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Structured log context (Loki labels)
|
|
14
|
+
*/
|
|
15
|
+
interface LogContext {
|
|
16
|
+
requestId?: string;
|
|
17
|
+
userId?: string;
|
|
18
|
+
feature?: string;
|
|
19
|
+
[key: string]: any;
|
|
20
|
+
}
|
|
21
|
+
//#endregion
|
|
22
|
+
export { Logger as n, LogContext as t };
|
|
23
|
+
//# sourceMappingURL=logger-QZhxEopI.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { };
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import "../user-BZDhbOim.js";
|
|
2
|
+
import { t as UserRepository } from "../user-repository-C4N9DoGU.js";
|
|
3
|
+
import { n as SystemClock, t as Clock } from "../clock-B_Gmbgwt.js";
|
|
4
|
+
import { n as Logger, t as LogContext } from "../logger-QZhxEopI.js";
|
|
5
|
+
import { t as EventPublisher } from "../event-publisher-BBAp1zM3.js";
|
|
6
|
+
import { t as CacheStore } from "../cache-BCBllCiT.js";
|
|
7
|
+
import { t as RateLimiterStore } from "../rate-limiter--mNNkSfP.js";
|
|
8
|
+
import "../index-C2geSgue.js";
|
|
9
|
+
export { CacheStore, Clock, EventPublisher, LogContext, Logger, RateLimiterStore, SystemClock, UserRepository };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { };
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
//#region src/ports/rate-limiter.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Rate limiter store port interface
|
|
4
|
+
* Uses token bucket algorithm for rate limiting
|
|
5
|
+
*/
|
|
6
|
+
interface RateLimiterStore {
|
|
7
|
+
/**
|
|
8
|
+
* Check if a request should be allowed
|
|
9
|
+
* @param key Rate limit key (per-user, per-IP, etc)
|
|
10
|
+
* @param capacity Bucket capacity (max tokens)
|
|
11
|
+
* @param refillPerSecond Number of tokens to refill per second
|
|
12
|
+
* @returns Object with allowed flag and reset time if rate limited
|
|
13
|
+
*/
|
|
14
|
+
checkLimit(key: string, capacity: number, refillPerSecond: number): Promise<{
|
|
15
|
+
allowed: boolean;
|
|
16
|
+
tokensRemaining: number;
|
|
17
|
+
resetAt: Date;
|
|
18
|
+
}>;
|
|
19
|
+
/**
|
|
20
|
+
* Reset rate limit for a key
|
|
21
|
+
* @param key Rate limit key
|
|
22
|
+
*/
|
|
23
|
+
reset(key: string): Promise<void>;
|
|
24
|
+
/**
|
|
25
|
+
* Clear all rate limit data
|
|
26
|
+
*/
|
|
27
|
+
clear(): Promise<void>;
|
|
28
|
+
}
|
|
29
|
+
//#endregion
|
|
30
|
+
export { RateLimiterStore as t };
|
|
31
|
+
//# sourceMappingURL=rate-limiter--mNNkSfP.d.ts.map
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
//#region src/events/types.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Event-driven architecture types
|
|
4
|
+
*
|
|
5
|
+
* Event names follow 'module.action' pattern: 'user.created', 'user.updated'
|
|
6
|
+
* All events are strongly typed through EventMap
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Event metadata included with every domain event
|
|
10
|
+
*/
|
|
11
|
+
interface EventMeta {
|
|
12
|
+
/** Unique identifier for this event */
|
|
13
|
+
readonly eventId: string;
|
|
14
|
+
/** Timestamp when event occurred */
|
|
15
|
+
readonly occurredAt: Date;
|
|
16
|
+
/** Event schema version for migrations */
|
|
17
|
+
readonly version: number;
|
|
18
|
+
/** Aggregate ID (e.g., userId for user events) */
|
|
19
|
+
readonly aggregateId: string;
|
|
20
|
+
/** Correlation ID for tracing across services */
|
|
21
|
+
readonly correlationId: string;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Base domain event type
|
|
25
|
+
* All domain events extend this interface
|
|
26
|
+
*/
|
|
27
|
+
interface DomainEvent<TName extends string = string, TPayload extends Record<string, any> = Record<string, any>> {
|
|
28
|
+
/** Event name in 'module.action' format */
|
|
29
|
+
readonly name: TName;
|
|
30
|
+
/** Event payload (action-specific data) */
|
|
31
|
+
readonly payload: TPayload;
|
|
32
|
+
/** Event metadata (standard for all events) */
|
|
33
|
+
readonly meta: EventMeta;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Event map definition - extend this to add typed events
|
|
37
|
+
* Maps event names to their payload types
|
|
38
|
+
*
|
|
39
|
+
* Example:
|
|
40
|
+
* interface EventMap {
|
|
41
|
+
* 'user.created': { userId: string; email: string }
|
|
42
|
+
* 'user.updated': { userId: string; name: string }
|
|
43
|
+
* }
|
|
44
|
+
*/
|
|
45
|
+
interface EventMap {
|
|
46
|
+
[key: string]: Record<string, any>;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Valid event names derived from EventMap
|
|
50
|
+
*/
|
|
51
|
+
type EventName = keyof EventMap & string;
|
|
52
|
+
/**
|
|
53
|
+
* Typed domain event for a specific event name
|
|
54
|
+
*/
|
|
55
|
+
type TypedDomainEvent<TName extends EventName = EventName> = DomainEvent<TName, EventMap[TName]>;
|
|
56
|
+
//#endregion
|
|
57
|
+
export { TypedDomainEvent as a, EventName as i, EventMap as n, EventMeta as r, DomainEvent as t };
|
|
58
|
+
//# sourceMappingURL=types-BMU8Ezie.d.ts.map
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
//#region src/entities/user.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* User domain entity
|
|
4
|
+
* Pure TypeScript type with no dependencies
|
|
5
|
+
*/
|
|
6
|
+
interface User {
|
|
7
|
+
readonly id: string;
|
|
8
|
+
readonly name: string;
|
|
9
|
+
readonly email: string;
|
|
10
|
+
readonly emailVerified: boolean;
|
|
11
|
+
readonly permissions: readonly string[];
|
|
12
|
+
readonly createdAt: Date;
|
|
13
|
+
readonly updatedAt: Date;
|
|
14
|
+
}
|
|
15
|
+
//#endregion
|
|
16
|
+
export { User as t };
|
|
17
|
+
//# sourceMappingURL=user-BZDhbOim.d.ts.map
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { t as User } from "./user-BZDhbOim.js";
|
|
2
|
+
|
|
3
|
+
//#region src/ports/user-repository.d.ts
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Repository port (interface) for user persistence
|
|
7
|
+
* Infrastructure layer will implement this
|
|
8
|
+
*/
|
|
9
|
+
interface UserRepository {
|
|
10
|
+
findById(id: string): Promise<User | null>;
|
|
11
|
+
findByEmail(email: string): Promise<User | null>;
|
|
12
|
+
save(user: User): Promise<void>;
|
|
13
|
+
}
|
|
14
|
+
//#endregion
|
|
15
|
+
export { UserRepository as t };
|
|
16
|
+
//# sourceMappingURL=user-repository-C4N9DoGU.d.ts.map
|