@heavybit/shared-lib 1.3.1 → 2.1.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/README.md +100 -0
- package/dist/cjs/common/errors.js +44 -5
- package/dist/cjs/common/errors.js.map +1 -1
- package/dist/cjs/common/phone.js +43 -10
- package/dist/cjs/common/phone.js.map +1 -1
- package/dist/cjs/common/response.js +78 -5
- package/dist/cjs/common/response.js.map +1 -1
- package/dist/cjs/config/index.js +1 -1
- package/dist/cjs/config/index.js.map +1 -1
- package/dist/cjs/context/index.js +49 -0
- package/dist/cjs/context/index.js.map +1 -0
- package/dist/cjs/contracts/index.js +0 -2
- package/dist/cjs/contracts/index.js.map +1 -1
- package/dist/cjs/contracts/notification-dispatch.js +87 -63
- package/dist/cjs/contracts/notification-dispatch.js.map +1 -1
- package/dist/cjs/express/auth.js +44 -11
- package/dist/cjs/express/auth.js.map +1 -1
- package/dist/cjs/express/index.js +1 -0
- package/dist/cjs/express/index.js.map +1 -1
- package/dist/cjs/express/middleware.js +154 -34
- package/dist/cjs/express/middleware.js.map +1 -1
- package/dist/cjs/express/respond.js +47 -0
- package/dist/cjs/express/respond.js.map +1 -0
- package/dist/cjs/index.js +1 -0
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/logging/index.js +76 -40
- package/dist/cjs/logging/index.js.map +1 -1
- package/dist/cjs/logging/redact.js +117 -0
- package/dist/cjs/logging/redact.js.map +1 -0
- package/dist/cjs/messaging/index.js +1 -0
- package/dist/cjs/messaging/index.js.map +1 -1
- package/dist/cjs/messaging/staff-notifier.js +36 -44
- package/dist/cjs/messaging/staff-notifier.js.map +1 -1
- package/dist/cjs/messaging/staff-recipients.js +57 -0
- package/dist/cjs/messaging/staff-recipients.js.map +1 -0
- package/dist/cjs/validation/index.js +27 -3
- package/dist/cjs/validation/index.js.map +1 -1
- package/dist/esm/common/errors.js +42 -4
- package/dist/esm/common/errors.js.map +1 -1
- package/dist/esm/common/phone.js +43 -10
- package/dist/esm/common/phone.js.map +1 -1
- package/dist/esm/common/response.js +75 -5
- package/dist/esm/common/response.js.map +1 -1
- package/dist/esm/config/index.js +1 -1
- package/dist/esm/config/index.js.map +1 -1
- package/dist/esm/context/index.js +44 -0
- package/dist/esm/context/index.js.map +1 -0
- package/dist/esm/contracts/index.js +0 -2
- package/dist/esm/contracts/index.js.map +1 -1
- package/dist/esm/contracts/notification-dispatch.js +85 -62
- package/dist/esm/contracts/notification-dispatch.js.map +1 -1
- package/dist/esm/express/auth.js +45 -12
- package/dist/esm/express/auth.js.map +1 -1
- package/dist/esm/express/index.js +1 -0
- package/dist/esm/express/index.js.map +1 -1
- package/dist/esm/express/middleware.js +146 -27
- package/dist/esm/express/middleware.js.map +1 -1
- package/dist/esm/express/respond.js +42 -0
- package/dist/esm/express/respond.js.map +1 -0
- package/dist/esm/index.js +1 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/logging/index.js +68 -39
- package/dist/esm/logging/index.js.map +1 -1
- package/dist/esm/logging/redact.js +110 -0
- package/dist/esm/logging/redact.js.map +1 -0
- package/dist/esm/messaging/index.js +1 -0
- package/dist/esm/messaging/index.js.map +1 -1
- package/dist/esm/messaging/staff-notifier.js +36 -43
- package/dist/esm/messaging/staff-notifier.js.map +1 -1
- package/dist/esm/messaging/staff-recipients.js +53 -0
- package/dist/esm/messaging/staff-recipients.js.map +1 -0
- package/dist/esm/validation/index.js +27 -2
- package/dist/esm/validation/index.js.map +1 -1
- package/dist/types/alerting/index.d.ts +1 -1
- package/dist/types/alerting/index.d.ts.map +1 -1
- package/dist/types/cache/index.d.ts +1 -1
- package/dist/types/cache/index.d.ts.map +1 -1
- package/dist/types/common/errors.d.ts +48 -7
- package/dist/types/common/errors.d.ts.map +1 -1
- package/dist/types/common/phone.d.ts +35 -6
- package/dist/types/common/phone.d.ts.map +1 -1
- package/dist/types/common/response.d.ts +66 -5
- package/dist/types/common/response.d.ts.map +1 -1
- package/dist/types/config/index.d.ts +1 -1
- package/dist/types/config/index.d.ts.map +1 -1
- package/dist/types/context/index.d.ts +39 -0
- package/dist/types/context/index.d.ts.map +1 -0
- package/dist/types/contracts/index.d.ts +0 -2
- package/dist/types/contracts/index.d.ts.map +1 -1
- package/dist/types/contracts/notification-dispatch.d.ts +208 -90
- package/dist/types/contracts/notification-dispatch.d.ts.map +1 -1
- package/dist/types/express/auth.d.ts +42 -6
- package/dist/types/express/auth.d.ts.map +1 -1
- package/dist/types/express/index.d.ts +1 -0
- package/dist/types/express/index.d.ts.map +1 -1
- package/dist/types/express/middleware.d.ts +86 -7
- package/dist/types/express/middleware.d.ts.map +1 -1
- package/dist/types/express/respond.d.ts +41 -0
- package/dist/types/express/respond.d.ts.map +1 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/logging/index.d.ts +30 -4
- package/dist/types/logging/index.d.ts.map +1 -1
- package/dist/types/logging/redact.d.ts +54 -0
- package/dist/types/logging/redact.d.ts.map +1 -0
- package/dist/types/messaging/index.d.ts +1 -0
- package/dist/types/messaging/index.d.ts.map +1 -1
- package/dist/types/messaging/staff-notifier.d.ts +67 -36
- package/dist/types/messaging/staff-notifier.d.ts.map +1 -1
- package/dist/types/messaging/staff-recipients.d.ts +50 -0
- package/dist/types/messaging/staff-recipients.d.ts.map +1 -0
- package/dist/types/types/index.d.ts +36 -1
- package/dist/types/types/index.d.ts.map +1 -1
- package/dist/types/validation/index.d.ts +33 -2
- package/dist/types/validation/index.d.ts.map +1 -1
- package/package.json +2 -2
- package/dist/cjs/contracts/editorial-draft.js +0 -120
- package/dist/cjs/contracts/editorial-draft.js.map +0 -1
- package/dist/cjs/contracts/upload-import.js +0 -54
- package/dist/cjs/contracts/upload-import.js.map +0 -1
- package/dist/esm/contracts/editorial-draft.js +0 -117
- package/dist/esm/contracts/editorial-draft.js.map +0 -1
- package/dist/esm/contracts/upload-import.js +0 -51
- package/dist/esm/contracts/upload-import.js.map +0 -1
- package/dist/types/contracts/editorial-draft.d.ts +0 -610
- package/dist/types/contracts/editorial-draft.d.ts.map +0 -1
- package/dist/types/contracts/upload-import.d.ts +0 -96
- package/dist/types/contracts/upload-import.d.ts.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/cache/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,KAAK,YAAY,EAAE,MAAM,SAAS,CAAC;AAEnD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAEhD,MAAM,WAAW,eAAe;IAC9B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,wFAAwF;IACxF,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;CACjB;AAED,MAAM,WAAW,KAAK;IACpB,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC;IAC5C,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,EAAE,OAAO,CAAC,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACxE,GAAG,CAAC,GAAG,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACtC,+GAA+G;IAC/G,IAAI,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,CAAC,EAAE,eAAe,GAAG;QAAE,SAAS,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;IAChH,cAAc,CAAC,GAAG,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAClD;AAED,MAAM,WAAW,YAAY;IAC3B,oDAAoD;IACpD,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IACpB,gGAAgG;IAChG,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,sDAAsD;IACtD,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AA+BD;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,YAAY,GAAG,KAAK,CA+FxD;AAED,MAAM,WAAW,kBAAkB;IACjC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/cache/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,KAAK,YAAY,EAAE,MAAM,SAAS,CAAC;AAEnD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAEhD,MAAM,WAAW,eAAe;IAC9B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,wFAAwF;IACxF,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;CACjB;AAED,MAAM,WAAW,KAAK;IACpB,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC;IAC5C,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,EAAE,OAAO,CAAC,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACxE,GAAG,CAAC,GAAG,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACtC,+GAA+G;IAC/G,IAAI,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,CAAC,EAAE,eAAe,GAAG;QAAE,SAAS,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;IAChH,cAAc,CAAC,GAAG,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAClD;AAED,MAAM,WAAW,YAAY;IAC3B,oDAAoD;IACpD,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IACpB,gGAAgG;IAChG,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,sDAAsD;IACtD,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AA+BD;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,YAAY,GAAG,KAAK,CA+FxD;AAED,MAAM,WAAW,kBAAkB;IACjC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,6DAA6D;IAC7D,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,YAAY,CAAC;CACxB;AAED,8FAA8F;AAC9F,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,kBAAkB,GAAG,KAAK,CAmBjE;AAED,YAAY,EAAE,KAAK,EAAE,CAAC"}
|
|
@@ -3,6 +3,12 @@ export type ErrorDetails = Record<string, string[]>;
|
|
|
3
3
|
* Base class for errors that map to an HTTP status. Throw these from services; the shared
|
|
4
4
|
* error middleware turns them into the standard envelope. Anything that is not an AppError is
|
|
5
5
|
* reported as a 500 with a generic message so internals never leak.
|
|
6
|
+
*
|
|
7
|
+
* @param statusCode HTTP status. 4xx messages reach the caller; 5xx messages never do.
|
|
8
|
+
* @param message Caller-facing message (4xx) or log message (5xx).
|
|
9
|
+
* @param options `code` (defaults from the status), field `errors`, `retryable` (consumers),
|
|
10
|
+
* `retryAfterSeconds` (sent as `Retry-After`) and `cause`.
|
|
11
|
+
* @example throw new AppError(402, 'Payment is required first', { code: 'PAYMENT_REQUIRED' });
|
|
6
12
|
*/
|
|
7
13
|
export declare class AppError extends Error {
|
|
8
14
|
readonly statusCode: number;
|
|
@@ -10,48 +16,73 @@ export declare class AppError extends Error {
|
|
|
10
16
|
readonly errors?: ErrorDetails;
|
|
11
17
|
/** Consumers dead-letter immediately instead of retrying when this is false. */
|
|
12
18
|
readonly retryable: boolean;
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
+
/** Seconds the caller should wait before retrying; the error middleware sends it as `Retry-After`. */
|
|
20
|
+
readonly retryAfterSeconds?: number;
|
|
21
|
+
constructor(statusCode: number, message: string, options?: AppErrorOptions);
|
|
22
|
+
}
|
|
23
|
+
/** Options for {@link AppError}. `code` should be UPPER_SNAKE_CASE; it defaults from the status. */
|
|
24
|
+
export interface AppErrorOptions {
|
|
25
|
+
code?: string;
|
|
26
|
+
errors?: ErrorDetails;
|
|
27
|
+
retryable?: boolean;
|
|
28
|
+
retryAfterSeconds?: number;
|
|
29
|
+
cause?: unknown;
|
|
19
30
|
}
|
|
31
|
+
/**
|
|
32
|
+
* Shorthand for an error with an explicit status and code.
|
|
33
|
+
*
|
|
34
|
+
* @param statusCode HTTP status (4xx messages reach the caller; 5xx are replaced with a generic message).
|
|
35
|
+
* @param code UPPER_SNAKE_CASE machine-readable code, e.g. `SLUG_TAKEN`.
|
|
36
|
+
* @param message Human-readable message for 4xx responses.
|
|
37
|
+
* @param errors Optional field errors (`{ 'items.0.qty': ['Must be positive'] }`).
|
|
38
|
+
* @returns An {@link AppError} to `throw`.
|
|
39
|
+
* @example throw httpError(409, 'SLUG_TAKEN', 'That address is already in use');
|
|
40
|
+
*/
|
|
41
|
+
export declare function httpError(statusCode: number, code: string, message: string, errors?: ErrorDetails): AppError;
|
|
42
|
+
/** 400 BAD_REQUEST: the request is malformed or breaks a business rule. */
|
|
20
43
|
export declare class BadRequestError extends AppError {
|
|
21
44
|
constructor(message?: string, options?: {
|
|
22
45
|
code?: string;
|
|
23
46
|
errors?: ErrorDetails;
|
|
24
47
|
});
|
|
25
48
|
}
|
|
49
|
+
/** 401 UNAUTHENTICATED: no valid identity. */
|
|
26
50
|
export declare class UnauthorizedError extends AppError {
|
|
27
51
|
constructor(message?: string, options?: {
|
|
28
52
|
code?: string;
|
|
29
53
|
});
|
|
30
54
|
}
|
|
55
|
+
/** 403 FORBIDDEN: authenticated, but not allowed. */
|
|
31
56
|
export declare class ForbiddenError extends AppError {
|
|
32
57
|
constructor(message?: string, options?: {
|
|
33
58
|
code?: string;
|
|
34
59
|
});
|
|
35
60
|
}
|
|
61
|
+
/** 404 NOT_FOUND. Also use it for out-of-scope resources so their existence is not revealed. */
|
|
36
62
|
export declare class NotFoundError extends AppError {
|
|
37
63
|
constructor(message?: string, options?: {
|
|
38
64
|
code?: string;
|
|
39
65
|
});
|
|
40
66
|
}
|
|
67
|
+
/** 409 CONFLICT: duplicate or state conflict. */
|
|
41
68
|
export declare class ConflictError extends AppError {
|
|
42
69
|
constructor(message?: string, options?: {
|
|
43
70
|
code?: string;
|
|
44
71
|
errors?: ErrorDetails;
|
|
45
72
|
});
|
|
46
73
|
}
|
|
74
|
+
/** 422 VALIDATION_FAILED with field errors (`{ 'items.0.qty': ['…'] }`). */
|
|
47
75
|
export declare class ValidationError extends AppError {
|
|
48
76
|
constructor(errors: ErrorDetails, message?: string);
|
|
49
77
|
}
|
|
78
|
+
/** 429. Pass `retryAfterSeconds` so the error middleware sets the `Retry-After` header. */
|
|
50
79
|
export declare class TooManyRequestsError extends AppError {
|
|
51
80
|
constructor(message?: string, options?: {
|
|
52
81
|
code?: string;
|
|
82
|
+
retryAfterSeconds?: number;
|
|
53
83
|
});
|
|
54
84
|
}
|
|
85
|
+
/** 503 SERVICE_UNAVAILABLE: a dependency is down. The message is logged, never sent (callers see the generic one). */
|
|
55
86
|
export declare class ServiceUnavailableError extends AppError {
|
|
56
87
|
constructor(message?: string, options?: {
|
|
57
88
|
code?: string;
|
|
@@ -65,7 +96,17 @@ export declare class NonRetryableError extends AppError {
|
|
|
65
96
|
cause?: unknown;
|
|
66
97
|
});
|
|
67
98
|
}
|
|
99
|
+
/** Type guard for {@link AppError} (and its subclasses). */
|
|
68
100
|
export declare function isAppError(error: unknown): error is AppError;
|
|
69
|
-
/**
|
|
101
|
+
/** The message every 5xx response carries. */
|
|
102
|
+
export declare const GENERIC_ERROR_MESSAGE = "Internal server error";
|
|
103
|
+
/**
|
|
104
|
+
* Message safe to show a caller. Only 4xx AppErrors keep their own message; every 5xx (including
|
|
105
|
+
* 503s, whose messages often name upstreams or RPC methods) and every non-AppError get the generic one.
|
|
106
|
+
*
|
|
107
|
+
* @param error Anything thrown.
|
|
108
|
+
* @returns The message to put in the response body.
|
|
109
|
+
* @example publicMessage(new NotFoundError('Order not found')) // 'Order not found'
|
|
110
|
+
*/
|
|
70
111
|
export declare function publicMessage(error: unknown): string;
|
|
71
112
|
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../../src/common/errors.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,YAAY,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;AAEpD
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../../src/common/errors.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,10 +1,39 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Normalises a phone number to E.164
|
|
3
|
-
*
|
|
2
|
+
* Normalises a phone number to E.164. The region is required (no app default): local formats such as
|
|
3
|
+
* `0712345678` only make sense against a country, and that country is app configuration.
|
|
4
|
+
*
|
|
5
|
+
* @param phone Number as typed (local or international format).
|
|
6
|
+
* @param region ISO 3166-1 alpha-2 region used for local formats (e.g. `KE`, `GB`).
|
|
7
|
+
* @returns E.164 (`+254712345678`), or null when not a valid number for that region.
|
|
8
|
+
* @example toE164('0712345678', 'KE') // '+254712345678'
|
|
9
|
+
*/
|
|
10
|
+
export declare function toE164(phone: string, region: string): string | null;
|
|
11
|
+
/**
|
|
12
|
+
* E.164 without the plus sign, as most SMS gateways expect.
|
|
13
|
+
*
|
|
14
|
+
* @param phone Number as typed.
|
|
15
|
+
* @param region ISO region for local formats.
|
|
16
|
+
* @returns Digits only, or null when invalid.
|
|
17
|
+
* @example toMsisdn('0712345678', 'KE') // '254712345678'
|
|
18
|
+
*/
|
|
19
|
+
export declare function toMsisdn(phone: string, region: string): string | null;
|
|
20
|
+
/**
|
|
21
|
+
* The region a number belongs to.
|
|
22
|
+
*
|
|
23
|
+
* @param phone Number as typed.
|
|
24
|
+
* @param region ISO region used to interpret local formats.
|
|
25
|
+
* @returns ISO region code, or null when it cannot be determined.
|
|
26
|
+
* @example phoneRegion('+447400123456', 'KE') // 'GB'
|
|
27
|
+
*/
|
|
28
|
+
export declare function phoneRegion(phone: string, region: string): string | null;
|
|
29
|
+
/**
|
|
30
|
+
* Masks a phone number for logs and UI, so a full number never lands in a log line or screen.
|
|
31
|
+
* Never reveals more than about a third of the input: numbers of 10+ characters keep the first 4 and
|
|
32
|
+
* last 2; shorter inputs keep only the last 2; 4 characters or fewer are fully masked.
|
|
33
|
+
*
|
|
34
|
+
* @param phone Any phone string (normalised or not).
|
|
35
|
+
* @returns The masked value.
|
|
36
|
+
* @example maskPhone('254712345678') // '2547****78'
|
|
4
37
|
*/
|
|
5
|
-
export declare function toE164(phone: string, defaultRegion?: string): string | null;
|
|
6
|
-
/** E.164 without the plus sign, as most SMS gateways expect (`254712345678`). */
|
|
7
|
-
export declare function toMsisdn(phone: string, defaultRegion?: string): string | null;
|
|
8
|
-
export declare function phoneRegion(phone: string, defaultRegion?: string): string | null;
|
|
9
38
|
export declare function maskPhone(phone: string): string;
|
|
10
39
|
//# sourceMappingURL=phone.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"phone.d.ts","sourceRoot":"","sources":["../../../src/common/phone.ts"],"names":[],"mappings":"AAKA
|
|
1
|
+
{"version":3,"file":"phone.d.ts","sourceRoot":"","sources":["../../../src/common/phone.ts"],"names":[],"mappings":"AAKA;;;;;;;;GAQG;AACH,wBAAgB,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAOnE;AAED;;;;;;;GAOG;AACH,wBAAgB,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAGrE;AAED;;;;;;;GAOG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAMxE;AAED;;;;;;;;GAQG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAI/C"}
|
|
@@ -1,12 +1,73 @@
|
|
|
1
|
-
import type { ApiResponse, PaginationMeta, PaginatedResult } from '../types/index.js';
|
|
2
|
-
/**
|
|
1
|
+
import type { ApiResponse, CursorPage, CursorPageMeta, ErrorBody, PaginationMeta, PaginatedResult } from '../types/index.js';
|
|
2
|
+
/**
|
|
3
|
+
* Standard success envelope: `{ success, message, data }`.
|
|
4
|
+
*
|
|
5
|
+
* @param data Payload placed under `data`.
|
|
6
|
+
* @param message Human-readable message (default `Success`).
|
|
7
|
+
* @returns The envelope, ready for `res.json`.
|
|
8
|
+
* @example res.json(successResponse(order, 'Order placed'));
|
|
9
|
+
*/
|
|
3
10
|
export declare function successResponse<T>(data: T, message?: string): ApiResponse<T>;
|
|
4
|
-
/**
|
|
5
|
-
|
|
11
|
+
/**
|
|
12
|
+
* Standard error envelope: `{ success: false, message, code?, errors?, requestId? }`.
|
|
13
|
+
* Prefer throwing an AppError and letting the error middleware answer; use this only where a
|
|
14
|
+
* middleware must answer directly. For a body with a guaranteed `code`, use {@link errorBody}.
|
|
15
|
+
*
|
|
16
|
+
* @param message Message for the caller (never an internal error message).
|
|
17
|
+
* @param errors Optional field errors.
|
|
18
|
+
* @param code Optional UPPER_SNAKE_CASE code.
|
|
19
|
+
* @param requestId Optional correlation id of the request.
|
|
20
|
+
* @returns An envelope with `success: false`.
|
|
21
|
+
*/
|
|
22
|
+
export declare function errorResponse(message: string, errors?: Record<string, string[]>, code?: string, requestId?: string): ApiResponse<never>;
|
|
23
|
+
/**
|
|
24
|
+
* The error body with a required `code`, as the error middleware sends it.
|
|
25
|
+
*
|
|
26
|
+
* @param code UPPER_SNAKE_CASE machine-readable code.
|
|
27
|
+
* @param message Message for the caller (generic for 5xx).
|
|
28
|
+
* @param options `errors` (field errors) and `requestId` (correlation id), both omitted when absent.
|
|
29
|
+
* @returns `{ success: false, code, message, errors?, requestId? }`.
|
|
30
|
+
*
|
|
31
|
+
* @example res.status(404).json(errorBody('NOT_FOUND', 'Resource not found', { requestId }));
|
|
32
|
+
*/
|
|
33
|
+
export declare function errorBody(code: string, message: string, options?: {
|
|
34
|
+
errors?: Record<string, string[]>;
|
|
35
|
+
requestId?: string;
|
|
36
|
+
}): ErrorBody;
|
|
37
|
+
/**
|
|
38
|
+
* Offset pagination meta. `totalPages` is at least 1 so an empty list still reads as "page 1 of 1".
|
|
39
|
+
*
|
|
40
|
+
* @param total Total matching rows.
|
|
41
|
+
* @param page 1-based page that was returned.
|
|
42
|
+
* @param limit Page size.
|
|
43
|
+
* @returns `{ page, limit, total, totalPages, hasNext, hasPrev }`.
|
|
44
|
+
* @example buildPaginationMeta(45, 2, 20) // { page: 2, totalPages: 3, hasNext: true, hasPrev: true, … }
|
|
45
|
+
*/
|
|
6
46
|
export declare function buildPaginationMeta(total: number, page: number, limit: number): PaginationMeta;
|
|
7
|
-
/**
|
|
47
|
+
/**
|
|
48
|
+
* Offset-paginated envelope: `{ success, message, data: T[], meta }`.
|
|
49
|
+
*
|
|
50
|
+
* @returns The envelope with meta from {@link buildPaginationMeta}.
|
|
51
|
+
* @example res.json(paginatedResponse(rows, total, page, limit));
|
|
52
|
+
*/
|
|
8
53
|
export declare function paginatedResponse<T>(data: T[], total: number, page: number, limit: number, message?: string): ApiResponse<T[]>;
|
|
54
|
+
/**
|
|
55
|
+
* Offset page as a service returns it (data + meta, no envelope).
|
|
56
|
+
*
|
|
57
|
+
* @returns `{ data, meta }`.
|
|
58
|
+
* @example return buildPaginatedResult(rows, total, page, limit);
|
|
59
|
+
*/
|
|
9
60
|
export declare function buildPaginatedResult<T>(data: T[], total: number, page: number, limit: number): PaginatedResult<T>;
|
|
10
61
|
/** SQL offset for 1-based pages. */
|
|
11
62
|
export declare function pageOffset(page: number, limit: number): number;
|
|
63
|
+
/**
|
|
64
|
+
* Cursor pagination meta. `hasMore` is derived from `nextCursor`, so the two can never disagree.
|
|
65
|
+
*
|
|
66
|
+
* @param limit The page size that was applied.
|
|
67
|
+
* @param nextCursor Opaque cursor for the next page, or null on the last page.
|
|
68
|
+
* @example buildCursorPageMeta(20, rows.length > 20 ? encodeCursor(rows[19]) : null)
|
|
69
|
+
*/
|
|
70
|
+
export declare function buildCursorPageMeta(limit: number, nextCursor: string | null): CursorPageMeta;
|
|
71
|
+
/** Cursor-paginated envelope: `{ success, message, data: T[], meta: { limit, nextCursor, hasMore } }`. */
|
|
72
|
+
export declare function cursorPaginatedResponse<T>(page: CursorPage<T>, message?: string): ApiResponse<T[]>;
|
|
12
73
|
//# sourceMappingURL=response.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"response.d.ts","sourceRoot":"","sources":["../../../src/common/response.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"response.d.ts","sourceRoot":"","sources":["../../../src/common/response.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,UAAU,EAAE,cAAc,EAAE,SAAS,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAE7H;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,OAAO,SAAY,GAAG,WAAW,CAAC,CAAC,CAAC,CAE/E;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,EAAE,IAAI,CAAC,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,WAAW,CAAC,KAAK,CAAC,CAEvI;AAED;;;;;;;;;GASG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,GAAE;IAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAO,GAAG,SAAS,CAQ3I;AAED;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,cAAc,CAG9F;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,SAAY,GAAG,WAAW,CAAC,CAAC,EAAE,CAAC,CAEjI;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,eAAe,CAAC,CAAC,CAAC,CAEjH;AAED,oCAAoC;AACpC,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAE9D;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI,GAAG,cAAc,CAE5F;AAED,0GAA0G;AAC1G,wBAAgB,uBAAuB,CAAC,CAAC,EAAE,IAAI,EAAE,UAAU,CAAC,CAAC,CAAC,EAAE,OAAO,SAAY,GAAG,WAAW,CAAC,CAAC,EAAE,CAAC,CAErG"}
|
|
@@ -8,7 +8,7 @@ export declare const serviceEnv: z.ZodObject<{
|
|
|
8
8
|
NODE_ENV: z.ZodDefault<z.ZodEnum<["development", "test", "staging", "production"]>>;
|
|
9
9
|
PORT: z.ZodNumber;
|
|
10
10
|
SERVICE_NAME: z.ZodString;
|
|
11
|
-
/** Short app identifier used in exchange names and key prefixes (e.g. `
|
|
11
|
+
/** Short app identifier used in exchange names and key prefixes (e.g. `myapp`). */
|
|
12
12
|
APP_NAME: z.ZodDefault<z.ZodString>;
|
|
13
13
|
LOG_LEVEL: z.ZodOptional<z.ZodEnum<["error", "warn", "info", "http", "debug"]>>;
|
|
14
14
|
CORS_ORIGINS: z.ZodDefault<z.ZodString>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/config/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB;;;;GAIG;AACH,eAAO,MAAM,UAAU;;;;IAIrB,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/config/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB;;;;GAIG;AACH,eAAO,MAAM,UAAU;;;;IAIrB,mFAAmF;;;;IAInF,gDAAgD;;IAEhD,4DAA4D;;;;;;;;;;;;;;;;;;;;EAE5D,CAAC;AAEH,eAAO,MAAM,WAAW;;;;;;;;;;;;;;;;;;;;;EAOtB,CAAC;AAEH,eAAO,MAAM,YAAY;;;;;;;IAOvB,kFAAkF;;;;;;;;;;;;;;;;;;;;;EAGlF,CAAC;AAEH,eAAO,MAAM,QAAQ;;;IAGnB,kFAAkF;;;;;;;;;;EAElF,CAAC;AAEH,oFAAoF;AACpF,wBAAgB,cAAc,CAAC,GAAG,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,YAAY,CAAC,GAAG,MAAM,CAIxE;AAED,iGAAiG;AACjG,wBAAgB,UAAU,CAAC,IAAI,SAAiC,GAAG,IAAI,CAYtE;AAED,qBAAa,WAAY,SAAQ,KAAK;CAAG;AAEzC,qGAAqG;AACrG,wBAAgB,OAAO,CAAC,CAAC,SAAS,CAAC,CAAC,UAAU,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAE,MAAM,CAAC,UAAwB,EAAE,OAAO,GAAE;IAAE,MAAM,CAAC,EAAE,OAAO,CAAA;CAAO,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAQlJ;AAED,2DAA2D;AAC3D,eAAO,MAAM,WAAW,GAAI,OAAO,MAAM,GAAG,SAAS,KAAG,MAAM,EAAmE,CAAC"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Per-request values that follow the request through every `await`, timer and callback, so loggers,
|
|
3
|
+
* error handlers and outbound clients can read them without threading `req` through every call.
|
|
4
|
+
* `scopes` is a generic map of the scope ids the caller acts within (for example `{ tenant: '01J…' }`);
|
|
5
|
+
* the app decides the key names.
|
|
6
|
+
*/
|
|
7
|
+
export interface RequestContext {
|
|
8
|
+
correlationId: string;
|
|
9
|
+
service?: string;
|
|
10
|
+
userId?: string;
|
|
11
|
+
scopes?: Record<string, string>;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Runs `fn` (and all async work it starts) inside `context`. Use it at every entry point that is not an
|
|
15
|
+
* HTTP request: queue consumers, jobs and scripts.
|
|
16
|
+
*
|
|
17
|
+
* @param context Values for the duration of `fn`; the object is copied, so later edits don't leak back.
|
|
18
|
+
* @param fn Work to run inside the context.
|
|
19
|
+
* @returns Whatever `fn` returns.
|
|
20
|
+
* @example await runWithContext({ correlationId: msg.correlationId, service: 'worker' }, () => handle(msg));
|
|
21
|
+
*/
|
|
22
|
+
export declare function runWithContext<T>(context: RequestContext, fn: () => T): T;
|
|
23
|
+
/**
|
|
24
|
+
* The current request context.
|
|
25
|
+
*
|
|
26
|
+
* @returns The context, or undefined outside {@link runWithContext} / `correlationMiddleware`.
|
|
27
|
+
* @example const id = getRequestContext()?.correlationId;
|
|
28
|
+
*/
|
|
29
|
+
export declare function getRequestContext(): Readonly<RequestContext> | undefined;
|
|
30
|
+
/**
|
|
31
|
+
* Adds values to the current context, for example the user id and scopes once auth has run. A no-op
|
|
32
|
+
* outside a context. The correlation id can't be changed once set.
|
|
33
|
+
*
|
|
34
|
+
* @param patch Values to add or replace; `scopes` are merged key by key.
|
|
35
|
+
* @returns True when a context was active and updated.
|
|
36
|
+
* @example updateRequestContext({ userId: user.id, scopes: user.scopes });
|
|
37
|
+
*/
|
|
38
|
+
export declare function updateRequestContext(patch: Partial<Omit<RequestContext, 'correlationId'>>): boolean;
|
|
39
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/context/index.ts"],"names":[],"mappings":"AAEA;;;;;GAKG;AACH,MAAM,WAAW,cAAc;IAC7B,aAAa,EAAE,MAAM,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACjC;AAID;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAAC,CAAC,EAAE,OAAO,EAAE,cAAc,EAAE,EAAE,EAAE,MAAM,CAAC,GAAG,CAAC,CAEzE;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,IAAI,QAAQ,CAAC,cAAc,CAAC,GAAG,SAAS,CAExE;AAED;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,OAAO,CAAC,IAAI,CAAC,cAAc,EAAE,eAAe,CAAC,CAAC,GAAG,OAAO,CAOnG"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/contracts/index.ts"],"names":[],"mappings":"AAAA,cAAc,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/contracts/index.ts"],"names":[],"mappings":"AAAA,cAAc,4BAA4B,CAAC"}
|