paygate-mcp 10.18.0 → 10.19.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.
@@ -0,0 +1,109 @@
1
+ /**
2
+ * ErrorClassifier — Classify and categorize errors for analytics and routing.
3
+ *
4
+ * Register error patterns, classify incoming errors by matching,
5
+ * and track error frequency for prioritization.
6
+ *
7
+ * @example
8
+ * ```ts
9
+ * const classifier = new ErrorClassifier();
10
+ *
11
+ * classifier.registerPattern({
12
+ * category: 'rate_limit',
13
+ * pattern: /rate limit|too many requests|429/i,
14
+ * severity: 'warning',
15
+ * retryable: true,
16
+ * });
17
+ *
18
+ * const result = classifier.classify(new Error('Rate limit exceeded'));
19
+ * // { category: 'rate_limit', severity: 'warning', retryable: true, ... }
20
+ * ```
21
+ */
22
+ export type ErrorSeverity = 'info' | 'warning' | 'error' | 'critical';
23
+ export interface ErrorPattern {
24
+ id: string;
25
+ category: string;
26
+ pattern: RegExp;
27
+ severity: ErrorSeverity;
28
+ retryable: boolean;
29
+ description: string;
30
+ }
31
+ export interface PatternRegistration {
32
+ category: string;
33
+ pattern: RegExp;
34
+ severity?: ErrorSeverity;
35
+ retryable?: boolean;
36
+ description?: string;
37
+ }
38
+ export interface ClassifyResult {
39
+ classified: boolean;
40
+ category: string;
41
+ severity: ErrorSeverity;
42
+ retryable: boolean;
43
+ patternId: string | null;
44
+ description: string;
45
+ message: string;
46
+ timestamp: number;
47
+ }
48
+ export interface ErrorFrequency {
49
+ category: string;
50
+ count: number;
51
+ lastSeen: number;
52
+ firstSeen: number;
53
+ }
54
+ export interface ErrorClassifierConfig {
55
+ /** Max classification history. Default 10000. */
56
+ maxHistory?: number;
57
+ /** Max registered patterns. Default 500. */
58
+ maxPatterns?: number;
59
+ /** Default severity for unclassified errors. Default 'error'. */
60
+ defaultSeverity?: ErrorSeverity;
61
+ }
62
+ export interface ErrorClassifierStats {
63
+ totalPatterns: number;
64
+ totalClassified: number;
65
+ totalUnclassified: number;
66
+ categories: number;
67
+ topCategories: ErrorFrequency[];
68
+ }
69
+ export declare class ErrorClassifier {
70
+ private patterns;
71
+ private history;
72
+ private frequency;
73
+ private nextId;
74
+ private maxHistory;
75
+ private maxPatterns;
76
+ private defaultSeverity;
77
+ private totalClassified;
78
+ private totalUnclassified;
79
+ constructor(config?: ErrorClassifierConfig);
80
+ /** Register an error pattern. */
81
+ registerPattern(reg: PatternRegistration): ErrorPattern;
82
+ /** Remove a pattern by ID. */
83
+ removePattern(id: string): boolean;
84
+ /** Get a pattern by ID. */
85
+ getPattern(id: string): ErrorPattern | null;
86
+ /** List all patterns. */
87
+ listPatterns(): ErrorPattern[];
88
+ /** Classify an error. */
89
+ classify(error: Error | string): ClassifyResult;
90
+ /** Classify and return just the category name. */
91
+ categorize(error: Error | string): string;
92
+ /** Check if an error is retryable. */
93
+ isRetryable(error: Error | string): boolean;
94
+ /** Get classification history. */
95
+ getHistory(options?: {
96
+ category?: string;
97
+ severity?: ErrorSeverity;
98
+ limit?: number;
99
+ }): ClassifyResult[];
100
+ /** Get error frequency by category. */
101
+ getFrequency(): ErrorFrequency[];
102
+ /** Get frequency for a specific category. */
103
+ getCategoryFrequency(category: string): ErrorFrequency | null;
104
+ getStats(): ErrorClassifierStats;
105
+ /** Clear all data. */
106
+ destroy(): void;
107
+ private recordResult;
108
+ }
109
+ //# sourceMappingURL=error-classifier.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"error-classifier.d.ts","sourceRoot":"","sources":["../src/error-classifier.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAIH,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,SAAS,GAAG,OAAO,GAAG,UAAU,CAAC;AAEtE,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,aAAa,CAAC;IACxB,SAAS,EAAE,OAAO,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,mBAAmB;IAClC,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,aAAa,CAAC;IACzB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,cAAc;IAC7B,UAAU,EAAE,OAAO,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,aAAa,CAAC;IACxB,SAAS,EAAE,OAAO,CAAC;IACnB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,qBAAqB;IACpC,iDAAiD;IACjD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,4CAA4C;IAC5C,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,iEAAiE;IACjE,eAAe,CAAC,EAAE,aAAa,CAAC;CACjC;AAED,MAAM,WAAW,oBAAoB;IACnC,aAAa,EAAE,MAAM,CAAC;IACtB,eAAe,EAAE,MAAM,CAAC;IACxB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,cAAc,EAAE,CAAC;CACjC;AAID,qBAAa,eAAe;IAC1B,OAAO,CAAC,QAAQ,CAAmC;IACnD,OAAO,CAAC,OAAO,CAAwB;IACvC,OAAO,CAAC,SAAS,CAAqC;IACtD,OAAO,CAAC,MAAM,CAAK;IAEnB,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,eAAe,CAAgB;IAGvC,OAAO,CAAC,eAAe,CAAK;IAC5B,OAAO,CAAC,iBAAiB,CAAK;gBAElB,MAAM,GAAE,qBAA0B;IAQ9C,iCAAiC;IACjC,eAAe,CAAC,GAAG,EAAE,mBAAmB,GAAG,YAAY;IAoBvD,8BAA8B;IAC9B,aAAa,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO;IAIlC,2BAA2B;IAC3B,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,YAAY,GAAG,IAAI;IAI3C,yBAAyB;IACzB,YAAY,IAAI,YAAY,EAAE;IAM9B,yBAAyB;IACzB,QAAQ,CAAC,KAAK,EAAE,KAAK,GAAG,MAAM,GAAG,cAAc;IAyC/C,kDAAkD;IAClD,UAAU,CAAC,KAAK,EAAE,KAAK,GAAG,MAAM,GAAG,MAAM;IAIzC,sCAAsC;IACtC,WAAW,CAAC,KAAK,EAAE,KAAK,GAAG,MAAM,GAAG,OAAO;IAM3C,kCAAkC;IAClC,UAAU,CAAC,OAAO,CAAC,EAAE;QAAE,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,aAAa,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,cAAc,EAAE;IAQvG,uCAAuC;IACvC,YAAY,IAAI,cAAc,EAAE;IAIhC,6CAA6C;IAC7C,oBAAoB,CAAC,QAAQ,EAAE,MAAM,GAAG,cAAc,GAAG,IAAI;IAM7D,QAAQ,IAAI,oBAAoB;IAWhC,sBAAsB;IACtB,OAAO,IAAI,IAAI;IAUf,OAAO,CAAC,YAAY;CAmBrB"}
@@ -0,0 +1,181 @@
1
+ "use strict";
2
+ /**
3
+ * ErrorClassifier — Classify and categorize errors for analytics and routing.
4
+ *
5
+ * Register error patterns, classify incoming errors by matching,
6
+ * and track error frequency for prioritization.
7
+ *
8
+ * @example
9
+ * ```ts
10
+ * const classifier = new ErrorClassifier();
11
+ *
12
+ * classifier.registerPattern({
13
+ * category: 'rate_limit',
14
+ * pattern: /rate limit|too many requests|429/i,
15
+ * severity: 'warning',
16
+ * retryable: true,
17
+ * });
18
+ *
19
+ * const result = classifier.classify(new Error('Rate limit exceeded'));
20
+ * // { category: 'rate_limit', severity: 'warning', retryable: true, ... }
21
+ * ```
22
+ */
23
+ Object.defineProperty(exports, "__esModule", { value: true });
24
+ exports.ErrorClassifier = void 0;
25
+ // ── Implementation ───────────────────────────────────────────────────
26
+ class ErrorClassifier {
27
+ patterns = new Map();
28
+ history = [];
29
+ frequency = new Map();
30
+ nextId = 1;
31
+ maxHistory;
32
+ maxPatterns;
33
+ defaultSeverity;
34
+ // Stats
35
+ totalClassified = 0;
36
+ totalUnclassified = 0;
37
+ constructor(config = {}) {
38
+ this.maxHistory = config.maxHistory ?? 10_000;
39
+ this.maxPatterns = config.maxPatterns ?? 500;
40
+ this.defaultSeverity = config.defaultSeverity ?? 'error';
41
+ }
42
+ // ── Pattern Management ────────────────────────────────────────
43
+ /** Register an error pattern. */
44
+ registerPattern(reg) {
45
+ if (!reg.category)
46
+ throw new Error('Category is required');
47
+ if (!reg.pattern)
48
+ throw new Error('Pattern is required');
49
+ if (this.patterns.size >= this.maxPatterns) {
50
+ throw new Error(`Maximum ${this.maxPatterns} patterns reached`);
51
+ }
52
+ const pattern = {
53
+ id: `ep_${this.nextId++}`,
54
+ category: reg.category,
55
+ pattern: reg.pattern,
56
+ severity: reg.severity ?? this.defaultSeverity,
57
+ retryable: reg.retryable ?? false,
58
+ description: reg.description ?? '',
59
+ };
60
+ this.patterns.set(pattern.id, pattern);
61
+ return pattern;
62
+ }
63
+ /** Remove a pattern by ID. */
64
+ removePattern(id) {
65
+ return this.patterns.delete(id);
66
+ }
67
+ /** Get a pattern by ID. */
68
+ getPattern(id) {
69
+ return this.patterns.get(id) ?? null;
70
+ }
71
+ /** List all patterns. */
72
+ listPatterns() {
73
+ return [...this.patterns.values()];
74
+ }
75
+ // ── Classification ─────────────────────────────────────────────
76
+ /** Classify an error. */
77
+ classify(error) {
78
+ const message = typeof error === 'string' ? error : error.message;
79
+ const now = Date.now();
80
+ // Try to match against registered patterns
81
+ for (const pattern of this.patterns.values()) {
82
+ if (pattern.pattern.test(message)) {
83
+ const result = {
84
+ classified: true,
85
+ category: pattern.category,
86
+ severity: pattern.severity,
87
+ retryable: pattern.retryable,
88
+ patternId: pattern.id,
89
+ description: pattern.description,
90
+ message,
91
+ timestamp: now,
92
+ };
93
+ this.recordResult(result);
94
+ this.totalClassified++;
95
+ return result;
96
+ }
97
+ }
98
+ // Unclassified
99
+ const result = {
100
+ classified: false,
101
+ category: 'unknown',
102
+ severity: this.defaultSeverity,
103
+ retryable: false,
104
+ patternId: null,
105
+ description: 'No matching pattern found',
106
+ message,
107
+ timestamp: now,
108
+ };
109
+ this.recordResult(result);
110
+ this.totalUnclassified++;
111
+ return result;
112
+ }
113
+ /** Classify and return just the category name. */
114
+ categorize(error) {
115
+ return this.classify(error).category;
116
+ }
117
+ /** Check if an error is retryable. */
118
+ isRetryable(error) {
119
+ return this.classify(error).retryable;
120
+ }
121
+ // ── Query ──────────────────────────────────────────────────────
122
+ /** Get classification history. */
123
+ getHistory(options) {
124
+ let results = [...this.history];
125
+ if (options?.category)
126
+ results = results.filter(r => r.category === options.category);
127
+ if (options?.severity)
128
+ results = results.filter(r => r.severity === options.severity);
129
+ const limit = options?.limit ?? 50;
130
+ return results.slice(-limit);
131
+ }
132
+ /** Get error frequency by category. */
133
+ getFrequency() {
134
+ return [...this.frequency.values()].sort((a, b) => b.count - a.count);
135
+ }
136
+ /** Get frequency for a specific category. */
137
+ getCategoryFrequency(category) {
138
+ return this.frequency.get(category) ?? null;
139
+ }
140
+ // ── Stats ──────────────────────────────────────────────────────
141
+ getStats() {
142
+ const topCategories = this.getFrequency().slice(0, 5);
143
+ return {
144
+ totalPatterns: this.patterns.size,
145
+ totalClassified: this.totalClassified,
146
+ totalUnclassified: this.totalUnclassified,
147
+ categories: this.frequency.size,
148
+ topCategories,
149
+ };
150
+ }
151
+ /** Clear all data. */
152
+ destroy() {
153
+ this.patterns.clear();
154
+ this.history = [];
155
+ this.frequency.clear();
156
+ this.totalClassified = 0;
157
+ this.totalUnclassified = 0;
158
+ }
159
+ // ── Private ───────────────────────────────────────────────────
160
+ recordResult(result) {
161
+ this.history.push(result);
162
+ if (this.history.length > this.maxHistory) {
163
+ this.history.splice(0, this.history.length - this.maxHistory);
164
+ }
165
+ const existing = this.frequency.get(result.category);
166
+ if (existing) {
167
+ existing.count++;
168
+ existing.lastSeen = result.timestamp;
169
+ }
170
+ else {
171
+ this.frequency.set(result.category, {
172
+ category: result.category,
173
+ count: 1,
174
+ lastSeen: result.timestamp,
175
+ firstSeen: result.timestamp,
176
+ });
177
+ }
178
+ }
179
+ }
180
+ exports.ErrorClassifier = ErrorClassifier;
181
+ //# sourceMappingURL=error-classifier.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"error-classifier.js","sourceRoot":"","sources":["../src/error-classifier.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;;;AA0DH,wEAAwE;AAExE,MAAa,eAAe;IAClB,QAAQ,GAAG,IAAI,GAAG,EAAwB,CAAC;IAC3C,OAAO,GAAqB,EAAE,CAAC;IAC/B,SAAS,GAAG,IAAI,GAAG,EAA0B,CAAC;IAC9C,MAAM,GAAG,CAAC,CAAC;IAEX,UAAU,CAAS;IACnB,WAAW,CAAS;IACpB,eAAe,CAAgB;IAEvC,QAAQ;IACA,eAAe,GAAG,CAAC,CAAC;IACpB,iBAAiB,GAAG,CAAC,CAAC;IAE9B,YAAY,SAAgC,EAAE;QAC5C,IAAI,CAAC,UAAU,GAAG,MAAM,CAAC,UAAU,IAAI,MAAM,CAAC;QAC9C,IAAI,CAAC,WAAW,GAAG,MAAM,CAAC,WAAW,IAAI,GAAG,CAAC;QAC7C,IAAI,CAAC,eAAe,GAAG,MAAM,CAAC,eAAe,IAAI,OAAO,CAAC;IAC3D,CAAC;IAED,iEAAiE;IAEjE,iCAAiC;IACjC,eAAe,CAAC,GAAwB;QACtC,IAAI,CAAC,GAAG,CAAC,QAAQ;YAAE,MAAM,IAAI,KAAK,CAAC,sBAAsB,CAAC,CAAC;QAC3D,IAAI,CAAC,GAAG,CAAC,OAAO;YAAE,MAAM,IAAI,KAAK,CAAC,qBAAqB,CAAC,CAAC;QACzD,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;YAC3C,MAAM,IAAI,KAAK,CAAC,WAAW,IAAI,CAAC,WAAW,mBAAmB,CAAC,CAAC;QAClE,CAAC;QAED,MAAM,OAAO,GAAiB;YAC5B,EAAE,EAAE,MAAM,IAAI,CAAC,MAAM,EAAE,EAAE;YACzB,QAAQ,EAAE,GAAG,CAAC,QAAQ;YACtB,OAAO,EAAE,GAAG,CAAC,OAAO;YACpB,QAAQ,EAAE,GAAG,CAAC,QAAQ,IAAI,IAAI,CAAC,eAAe;YAC9C,SAAS,EAAE,GAAG,CAAC,SAAS,IAAI,KAAK;YACjC,WAAW,EAAE,GAAG,CAAC,WAAW,IAAI,EAAE;SACnC,CAAC;QAEF,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC;QACvC,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,8BAA8B;IAC9B,aAAa,CAAC,EAAU;QACtB,OAAO,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;IAClC,CAAC;IAED,2BAA2B;IAC3B,UAAU,CAAC,EAAU;QACnB,OAAO,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,IAAI,CAAC;IACvC,CAAC;IAED,yBAAyB;IACzB,YAAY;QACV,OAAO,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;IACrC,CAAC;IAED,kEAAkE;IAElE,yBAAyB;IACzB,QAAQ,CAAC,KAAqB;QAC5B,MAAM,OAAO,GAAG,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC;QAClE,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAEvB,2CAA2C;QAC3C,KAAK,MAAM,OAAO,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,EAAE,CAAC;YAC7C,IAAI,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;gBAClC,MAAM,MAAM,GAAmB;oBAC7B,UAAU,EAAE,IAAI;oBAChB,QAAQ,EAAE,OAAO,CAAC,QAAQ;oBAC1B,QAAQ,EAAE,OAAO,CAAC,QAAQ;oBAC1B,SAAS,EAAE,OAAO,CAAC,SAAS;oBAC5B,SAAS,EAAE,OAAO,CAAC,EAAE;oBACrB,WAAW,EAAE,OAAO,CAAC,WAAW;oBAChC,OAAO;oBACP,SAAS,EAAE,GAAG;iBACf,CAAC;gBAEF,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC;gBAC1B,IAAI,CAAC,eAAe,EAAE,CAAC;gBACvB,OAAO,MAAM,CAAC;YAChB,CAAC;QACH,CAAC;QAED,eAAe;QACf,MAAM,MAAM,GAAmB;YAC7B,UAAU,EAAE,KAAK;YACjB,QAAQ,EAAE,SAAS;YACnB,QAAQ,EAAE,IAAI,CAAC,eAAe;YAC9B,SAAS,EAAE,KAAK;YAChB,SAAS,EAAE,IAAI;YACf,WAAW,EAAE,2BAA2B;YACxC,OAAO;YACP,SAAS,EAAE,GAAG;SACf,CAAC;QAEF,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC;QAC1B,IAAI,CAAC,iBAAiB,EAAE,CAAC;QACzB,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,kDAAkD;IAClD,UAAU,CAAC,KAAqB;QAC9B,OAAO,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC;IACvC,CAAC;IAED,sCAAsC;IACtC,WAAW,CAAC,KAAqB;QAC/B,OAAO,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,SAAS,CAAC;IACxC,CAAC;IAED,kEAAkE;IAElE,kCAAkC;IAClC,UAAU,CAAC,OAAyE;QAClF,IAAI,OAAO,GAAG,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC;QAChC,IAAI,OAAO,EAAE,QAAQ;YAAE,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAC;QACtF,IAAI,OAAO,EAAE,QAAQ;YAAE,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAC;QACtF,MAAM,KAAK,GAAG,OAAO,EAAE,KAAK,IAAI,EAAE,CAAC;QACnC,OAAO,OAAO,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC;IAC/B,CAAC;IAED,uCAAuC;IACvC,YAAY;QACV,OAAO,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC;IACxE,CAAC;IAED,6CAA6C;IAC7C,oBAAoB,CAAC,QAAgB;QACnC,OAAO,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC;IAC9C,CAAC;IAED,kEAAkE;IAElE,QAAQ;QACN,MAAM,aAAa,GAAG,IAAI,CAAC,YAAY,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QACtD,OAAO;YACL,aAAa,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI;YACjC,eAAe,EAAE,IAAI,CAAC,eAAe;YACrC,iBAAiB,EAAE,IAAI,CAAC,iBAAiB;YACzC,UAAU,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI;YAC/B,aAAa;SACd,CAAC;IACJ,CAAC;IAED,sBAAsB;IACtB,OAAO;QACL,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC;QACtB,IAAI,CAAC,OAAO,GAAG,EAAE,CAAC;QAClB,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,CAAC;QACvB,IAAI,CAAC,eAAe,GAAG,CAAC,CAAC;QACzB,IAAI,CAAC,iBAAiB,GAAG,CAAC,CAAC;IAC7B,CAAC;IAED,iEAAiE;IAEzD,YAAY,CAAC,MAAsB;QACzC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAC1B,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,UAAU,EAAE,CAAC;YAC1C,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,EAAE,IAAI,CAAC,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,UAAU,CAAC,CAAC;QAChE,CAAC;QAED,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QACrD,IAAI,QAAQ,EAAE,CAAC;YACb,QAAQ,CAAC,KAAK,EAAE,CAAC;YACjB,QAAQ,CAAC,QAAQ,GAAG,MAAM,CAAC,SAAS,CAAC;QACvC,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,MAAM,CAAC,QAAQ,EAAE;gBAClC,QAAQ,EAAE,MAAM,CAAC,QAAQ;gBACzB,KAAK,EAAE,CAAC;gBACR,QAAQ,EAAE,MAAM,CAAC,SAAS;gBAC1B,SAAS,EAAE,MAAM,CAAC,SAAS;aAC5B,CAAC,CAAC;QACL,CAAC;IACH,CAAC;CACF;AAhLD,0CAgLC"}
@@ -0,0 +1,113 @@
1
+ /**
2
+ * GracePeriodManager — Grace periods for key expiry, quota overages, and payment failures.
3
+ *
4
+ * Define grace period policies, apply them to keys, and check
5
+ * whether a key is within its grace period before hard enforcement.
6
+ *
7
+ * @example
8
+ * ```ts
9
+ * const mgr = new GracePeriodManager();
10
+ *
11
+ * mgr.definePolicy({
12
+ * name: 'payment_failure',
13
+ * durationMs: 7 * 24 * 60 * 60 * 1000, // 7 days
14
+ * reason: 'Payment failed',
15
+ * maxExtensions: 1,
16
+ * });
17
+ *
18
+ * mgr.startGracePeriod('key_abc', 'payment_failure');
19
+ *
20
+ * const check = mgr.check('key_abc');
21
+ * // { inGracePeriod: true, expiresAt: ..., remaining: ... }
22
+ * ```
23
+ */
24
+ export interface GracePolicy {
25
+ id: string;
26
+ name: string;
27
+ durationMs: number;
28
+ reason: string;
29
+ maxExtensions: number;
30
+ }
31
+ export interface PolicyDefineParams {
32
+ name: string;
33
+ durationMs: number;
34
+ reason?: string;
35
+ maxExtensions?: number;
36
+ }
37
+ export interface GracePeriod {
38
+ id: string;
39
+ key: string;
40
+ policyId: string;
41
+ policyName: string;
42
+ reason: string;
43
+ startedAt: number;
44
+ expiresAt: number;
45
+ extensions: number;
46
+ maxExtensions: number;
47
+ active: boolean;
48
+ expiredAt: number | null;
49
+ cancelledAt: number | null;
50
+ }
51
+ export interface GraceCheckResult {
52
+ inGracePeriod: boolean;
53
+ gracePeriod: GracePeriod | null;
54
+ remainingMs: number;
55
+ expired: boolean;
56
+ }
57
+ export interface GracePeriodConfig {
58
+ /** Max active grace periods. Default 10000. */
59
+ maxActivePeriods?: number;
60
+ /** Max policies. Default 100. */
61
+ maxPolicies?: number;
62
+ }
63
+ export interface GracePeriodStats {
64
+ totalPolicies: number;
65
+ activePeriods: number;
66
+ expiredPeriods: number;
67
+ cancelledPeriods: number;
68
+ totalStarted: number;
69
+ totalExpired: number;
70
+ totalCancelled: number;
71
+ totalExtended: number;
72
+ }
73
+ export declare class GracePeriodManager {
74
+ private policies;
75
+ private periods;
76
+ private keyPeriods;
77
+ private nextPolicyId;
78
+ private nextPeriodId;
79
+ private maxActivePeriods;
80
+ private maxPolicies;
81
+ private totalStarted;
82
+ private totalExpired;
83
+ private totalCancelled;
84
+ private totalExtended;
85
+ constructor(config?: GracePeriodConfig);
86
+ /** Define a grace period policy. */
87
+ definePolicy(params: PolicyDefineParams): GracePolicy;
88
+ /** Get a policy by ID or name. */
89
+ getPolicy(idOrName: string): GracePolicy | null;
90
+ /** List all policies. */
91
+ listPolicies(): GracePolicy[];
92
+ /** Remove a policy. */
93
+ removePolicy(id: string): boolean;
94
+ /** Start a grace period for a key. */
95
+ startGracePeriod(key: string, policyIdOrName: string): GracePeriod;
96
+ /** Check a key's grace period status. */
97
+ check(key: string): GraceCheckResult;
98
+ /** Extend a key's grace period. */
99
+ extend(key: string, additionalMs?: number): GracePeriod;
100
+ /** Cancel a key's grace period. */
101
+ cancel(key: string): GracePeriod;
102
+ /** Get a grace period by key. */
103
+ getByKey(key: string): GracePeriod | null;
104
+ /** List all active grace periods. */
105
+ listActive(): GracePeriod[];
106
+ /** List expiring grace periods (within given ms). */
107
+ listExpiring(withinMs: number): GracePeriod[];
108
+ getStats(): GracePeriodStats;
109
+ /** Clear all data. */
110
+ destroy(): void;
111
+ private getActivePeriodCount;
112
+ }
113
+ //# sourceMappingURL=grace-period.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"grace-period.d.ts","sourceRoot":"","sources":["../src/grace-period.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,250 @@
1
+ "use strict";
2
+ /**
3
+ * GracePeriodManager — Grace periods for key expiry, quota overages, and payment failures.
4
+ *
5
+ * Define grace period policies, apply them to keys, and check
6
+ * whether a key is within its grace period before hard enforcement.
7
+ *
8
+ * @example
9
+ * ```ts
10
+ * const mgr = new GracePeriodManager();
11
+ *
12
+ * mgr.definePolicy({
13
+ * name: 'payment_failure',
14
+ * durationMs: 7 * 24 * 60 * 60 * 1000, // 7 days
15
+ * reason: 'Payment failed',
16
+ * maxExtensions: 1,
17
+ * });
18
+ *
19
+ * mgr.startGracePeriod('key_abc', 'payment_failure');
20
+ *
21
+ * const check = mgr.check('key_abc');
22
+ * // { inGracePeriod: true, expiresAt: ..., remaining: ... }
23
+ * ```
24
+ */
25
+ Object.defineProperty(exports, "__esModule", { value: true });
26
+ exports.GracePeriodManager = void 0;
27
+ // ── Implementation ───────────────────────────────────────────────────
28
+ class GracePeriodManager {
29
+ policies = new Map();
30
+ periods = new Map();
31
+ keyPeriods = new Map(); // key → periodId
32
+ nextPolicyId = 1;
33
+ nextPeriodId = 1;
34
+ maxActivePeriods;
35
+ maxPolicies;
36
+ // Stats
37
+ totalStarted = 0;
38
+ totalExpired = 0;
39
+ totalCancelled = 0;
40
+ totalExtended = 0;
41
+ constructor(config = {}) {
42
+ this.maxActivePeriods = config.maxActivePeriods ?? 10_000;
43
+ this.maxPolicies = config.maxPolicies ?? 100;
44
+ }
45
+ // ── Policy Management ──────────────────────────────────────────
46
+ /** Define a grace period policy. */
47
+ definePolicy(params) {
48
+ if (!params.name)
49
+ throw new Error('Policy name is required');
50
+ if (params.durationMs <= 0)
51
+ throw new Error('Duration must be positive');
52
+ if (this.policies.size >= this.maxPolicies) {
53
+ throw new Error(`Maximum ${this.maxPolicies} policies reached`);
54
+ }
55
+ // Check for duplicate names
56
+ for (const p of this.policies.values()) {
57
+ if (p.name === params.name)
58
+ throw new Error(`Policy '${params.name}' already exists`);
59
+ }
60
+ const policy = {
61
+ id: `gp_${this.nextPolicyId++}`,
62
+ name: params.name,
63
+ durationMs: params.durationMs,
64
+ reason: params.reason ?? '',
65
+ maxExtensions: params.maxExtensions ?? 0,
66
+ };
67
+ this.policies.set(policy.id, policy);
68
+ return policy;
69
+ }
70
+ /** Get a policy by ID or name. */
71
+ getPolicy(idOrName) {
72
+ const byId = this.policies.get(idOrName);
73
+ if (byId)
74
+ return byId;
75
+ for (const p of this.policies.values()) {
76
+ if (p.name === idOrName)
77
+ return p;
78
+ }
79
+ return null;
80
+ }
81
+ /** List all policies. */
82
+ listPolicies() {
83
+ return [...this.policies.values()];
84
+ }
85
+ /** Remove a policy. */
86
+ removePolicy(id) {
87
+ return this.policies.delete(id);
88
+ }
89
+ // ── Grace Period Lifecycle ─────────────────────────────────────
90
+ /** Start a grace period for a key. */
91
+ startGracePeriod(key, policyIdOrName) {
92
+ if (!key)
93
+ throw new Error('Key is required');
94
+ const policy = this.getPolicy(policyIdOrName);
95
+ if (!policy)
96
+ throw new Error(`Policy '${policyIdOrName}' not found`);
97
+ // Check if key already has an active grace period
98
+ const existingId = this.keyPeriods.get(key);
99
+ if (existingId) {
100
+ const existing = this.periods.get(existingId);
101
+ if (existing && existing.active) {
102
+ throw new Error(`Key '${key}' already has an active grace period`);
103
+ }
104
+ }
105
+ if (this.getActivePeriodCount() >= this.maxActivePeriods) {
106
+ throw new Error(`Maximum ${this.maxActivePeriods} active periods reached`);
107
+ }
108
+ const now = Date.now();
109
+ const period = {
110
+ id: `gpr_${this.nextPeriodId++}`,
111
+ key,
112
+ policyId: policy.id,
113
+ policyName: policy.name,
114
+ reason: policy.reason,
115
+ startedAt: now,
116
+ expiresAt: now + policy.durationMs,
117
+ extensions: 0,
118
+ maxExtensions: policy.maxExtensions,
119
+ active: true,
120
+ expiredAt: null,
121
+ cancelledAt: null,
122
+ };
123
+ this.periods.set(period.id, period);
124
+ this.keyPeriods.set(key, period.id);
125
+ this.totalStarted++;
126
+ return period;
127
+ }
128
+ /** Check a key's grace period status. */
129
+ check(key) {
130
+ const periodId = this.keyPeriods.get(key);
131
+ if (!periodId) {
132
+ return { inGracePeriod: false, gracePeriod: null, remainingMs: 0, expired: false };
133
+ }
134
+ const period = this.periods.get(periodId);
135
+ if (!period || !period.active) {
136
+ return { inGracePeriod: false, gracePeriod: period ?? null, remainingMs: 0, expired: !!period };
137
+ }
138
+ const now = Date.now();
139
+ if (now >= period.expiresAt) {
140
+ // Grace period expired
141
+ period.active = false;
142
+ period.expiredAt = now;
143
+ this.totalExpired++;
144
+ return { inGracePeriod: false, gracePeriod: period, remainingMs: 0, expired: true };
145
+ }
146
+ return {
147
+ inGracePeriod: true,
148
+ gracePeriod: period,
149
+ remainingMs: period.expiresAt - now,
150
+ expired: false,
151
+ };
152
+ }
153
+ /** Extend a key's grace period. */
154
+ extend(key, additionalMs) {
155
+ const periodId = this.keyPeriods.get(key);
156
+ if (!periodId)
157
+ throw new Error(`No grace period for key '${key}'`);
158
+ const period = this.periods.get(periodId);
159
+ if (!period)
160
+ throw new Error(`Grace period not found`);
161
+ if (!period.active)
162
+ throw new Error(`Grace period for key '${key}' is not active`);
163
+ if (period.extensions >= period.maxExtensions) {
164
+ throw new Error(`Maximum extensions (${period.maxExtensions}) reached for key '${key}'`);
165
+ }
166
+ const policy = this.policies.get(period.policyId);
167
+ const extensionMs = additionalMs ?? policy?.durationMs ?? period.expiresAt - period.startedAt;
168
+ period.expiresAt += extensionMs;
169
+ period.extensions++;
170
+ this.totalExtended++;
171
+ return period;
172
+ }
173
+ /** Cancel a key's grace period. */
174
+ cancel(key) {
175
+ const periodId = this.keyPeriods.get(key);
176
+ if (!periodId)
177
+ throw new Error(`No grace period for key '${key}'`);
178
+ const period = this.periods.get(periodId);
179
+ if (!period)
180
+ throw new Error(`Grace period not found`);
181
+ if (!period.active)
182
+ throw new Error(`Grace period for key '${key}' is not active`);
183
+ period.active = false;
184
+ period.cancelledAt = Date.now();
185
+ this.totalCancelled++;
186
+ return period;
187
+ }
188
+ // ── Query ──────────────────────────────────────────────────────
189
+ /** Get a grace period by key. */
190
+ getByKey(key) {
191
+ const id = this.keyPeriods.get(key);
192
+ return id ? (this.periods.get(id) ?? null) : null;
193
+ }
194
+ /** List all active grace periods. */
195
+ listActive() {
196
+ return [...this.periods.values()].filter(p => p.active && Date.now() < p.expiresAt);
197
+ }
198
+ /** List expiring grace periods (within given ms). */
199
+ listExpiring(withinMs) {
200
+ const deadline = Date.now() + withinMs;
201
+ return [...this.periods.values()]
202
+ .filter(p => p.active && p.expiresAt <= deadline && p.expiresAt > Date.now())
203
+ .sort((a, b) => a.expiresAt - b.expiresAt);
204
+ }
205
+ // ── Stats ──────────────────────────────────────────────────────
206
+ getStats() {
207
+ let active = 0, expired = 0, cancelled = 0;
208
+ const now = Date.now();
209
+ for (const p of this.periods.values()) {
210
+ if (p.active && now < p.expiresAt)
211
+ active++;
212
+ else if (p.expiredAt)
213
+ expired++;
214
+ else if (p.cancelledAt)
215
+ cancelled++;
216
+ }
217
+ return {
218
+ totalPolicies: this.policies.size,
219
+ activePeriods: active,
220
+ expiredPeriods: expired,
221
+ cancelledPeriods: cancelled,
222
+ totalStarted: this.totalStarted,
223
+ totalExpired: this.totalExpired,
224
+ totalCancelled: this.totalCancelled,
225
+ totalExtended: this.totalExtended,
226
+ };
227
+ }
228
+ /** Clear all data. */
229
+ destroy() {
230
+ this.policies.clear();
231
+ this.periods.clear();
232
+ this.keyPeriods.clear();
233
+ this.totalStarted = 0;
234
+ this.totalExpired = 0;
235
+ this.totalCancelled = 0;
236
+ this.totalExtended = 0;
237
+ }
238
+ // ── Private ───────────────────────────────────────────────────
239
+ getActivePeriodCount() {
240
+ let count = 0;
241
+ const now = Date.now();
242
+ for (const p of this.periods.values()) {
243
+ if (p.active && now < p.expiresAt)
244
+ count++;
245
+ }
246
+ return count;
247
+ }
248
+ }
249
+ exports.GracePeriodManager = GracePeriodManager;
250
+ //# sourceMappingURL=grace-period.js.map