paygate-mcp 10.11.0 → 10.12.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/api-versioning.d.ts +122 -0
- package/dist/api-versioning.d.ts.map +1 -0
- package/dist/api-versioning.js +316 -0
- package/dist/api-versioning.js.map +1 -0
- package/dist/billing-cycles.d.ts +122 -0
- package/dist/billing-cycles.d.ts.map +1 -0
- package/dist/billing-cycles.js +249 -0
- package/dist/billing-cycles.js.map +1 -0
- package/dist/credit-reservation.d.ts +110 -0
- package/dist/credit-reservation.d.ts.map +1 -0
- package/dist/credit-reservation.js +229 -0
- package/dist/credit-reservation.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +9 -1
- package/dist/index.js.map +1 -1
- package/dist/slo-monitor.d.ts +125 -0
- package/dist/slo-monitor.d.ts.map +1 -0
- package/dist/slo-monitor.js +227 -0
- package/dist/slo-monitor.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ApiVersionRouter — Route tool calls to versioned backends.
|
|
3
|
+
*
|
|
4
|
+
* Manage multiple versions of tools, route requests to the correct
|
|
5
|
+
* version based on key configuration, and enable safe migrations
|
|
6
|
+
* with deprecation warnings and sunset dates.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```ts
|
|
10
|
+
* const router = new ApiVersionRouter();
|
|
11
|
+
*
|
|
12
|
+
* router.registerVersion({
|
|
13
|
+
* tool: 'search',
|
|
14
|
+
* version: 'v1',
|
|
15
|
+
* status: 'deprecated',
|
|
16
|
+
* sunsetDate: '2026-04-01',
|
|
17
|
+
* });
|
|
18
|
+
*
|
|
19
|
+
* router.registerVersion({
|
|
20
|
+
* tool: 'search',
|
|
21
|
+
* version: 'v2',
|
|
22
|
+
* status: 'current',
|
|
23
|
+
* });
|
|
24
|
+
*
|
|
25
|
+
* router.setKeyVersion('key_abc', 'search', 'v2');
|
|
26
|
+
*
|
|
27
|
+
* const resolved = router.resolve('key_abc', 'search');
|
|
28
|
+
* // { version: 'v2', status: 'current', deprecated: false }
|
|
29
|
+
* ```
|
|
30
|
+
*/
|
|
31
|
+
export type VersionStatus = 'preview' | 'current' | 'deprecated' | 'sunset';
|
|
32
|
+
export interface ToolVersion {
|
|
33
|
+
tool: string;
|
|
34
|
+
version: string;
|
|
35
|
+
status: VersionStatus;
|
|
36
|
+
/** ISO date string when this version will be sunset. */
|
|
37
|
+
sunsetDate?: string;
|
|
38
|
+
/** Description of changes in this version. */
|
|
39
|
+
changelog?: string;
|
|
40
|
+
/** When this version was registered. */
|
|
41
|
+
registeredAt: number;
|
|
42
|
+
}
|
|
43
|
+
export interface VersionRegistration {
|
|
44
|
+
tool: string;
|
|
45
|
+
version: string;
|
|
46
|
+
status?: VersionStatus;
|
|
47
|
+
sunsetDate?: string;
|
|
48
|
+
changelog?: string;
|
|
49
|
+
}
|
|
50
|
+
export interface VersionResolveResult {
|
|
51
|
+
tool: string;
|
|
52
|
+
version: string;
|
|
53
|
+
status: VersionStatus;
|
|
54
|
+
deprecated: boolean;
|
|
55
|
+
sunsetDate?: string;
|
|
56
|
+
warning?: string;
|
|
57
|
+
}
|
|
58
|
+
export interface MigrationPlan {
|
|
59
|
+
tool: string;
|
|
60
|
+
fromVersion: string;
|
|
61
|
+
toVersion: string;
|
|
62
|
+
affectedKeys: string[];
|
|
63
|
+
fromStatus: VersionStatus;
|
|
64
|
+
toStatus: VersionStatus;
|
|
65
|
+
}
|
|
66
|
+
export interface ApiVersionConfig {
|
|
67
|
+
/** Default version to use when no key-specific version is set. */
|
|
68
|
+
defaultVersionStrategy?: 'latest' | 'current';
|
|
69
|
+
/** Auto-sunset versions past their sunset date. */
|
|
70
|
+
autoSunset?: boolean;
|
|
71
|
+
}
|
|
72
|
+
export interface ApiVersionStats {
|
|
73
|
+
totalTools: number;
|
|
74
|
+
totalVersions: number;
|
|
75
|
+
currentVersions: number;
|
|
76
|
+
deprecatedVersions: number;
|
|
77
|
+
sunsetVersions: number;
|
|
78
|
+
previewVersions: number;
|
|
79
|
+
keyOverrides: number;
|
|
80
|
+
totalResolutions: number;
|
|
81
|
+
}
|
|
82
|
+
export declare class ApiVersionRouter {
|
|
83
|
+
private versions;
|
|
84
|
+
private keyVersions;
|
|
85
|
+
private defaultStrategy;
|
|
86
|
+
private autoSunset;
|
|
87
|
+
private totalResolutions;
|
|
88
|
+
constructor(config?: ApiVersionConfig);
|
|
89
|
+
/** Register a tool version. */
|
|
90
|
+
registerVersion(reg: VersionRegistration): ToolVersion;
|
|
91
|
+
/** Remove a tool version. */
|
|
92
|
+
removeVersion(tool: string, version: string): boolean;
|
|
93
|
+
/** Get a specific tool version. */
|
|
94
|
+
getVersion(tool: string, version: string): ToolVersion | null;
|
|
95
|
+
/** List all versions for a tool. */
|
|
96
|
+
getToolVersions(tool: string): ToolVersion[];
|
|
97
|
+
/** List all tools that have versions. */
|
|
98
|
+
getVersionedTools(): string[];
|
|
99
|
+
/** Update the status of a version. */
|
|
100
|
+
setVersionStatus(tool: string, version: string, status: VersionStatus): boolean;
|
|
101
|
+
/** Set a specific version for a key+tool combination. */
|
|
102
|
+
setKeyVersion(key: string, tool: string, version: string): boolean;
|
|
103
|
+
/** Remove key-specific version override. */
|
|
104
|
+
removeKeyVersion(key: string, tool: string): boolean;
|
|
105
|
+
/** Get key-specific version override. */
|
|
106
|
+
getKeyVersion(key: string, tool: string): string | null;
|
|
107
|
+
/** Resolve which version to use for a key+tool request. */
|
|
108
|
+
resolve(key: string, tool: string): VersionResolveResult | null;
|
|
109
|
+
/** Generate a migration plan for moving keys from one version to another. */
|
|
110
|
+
planMigration(tool: string, fromVersion: string, toVersion: string): MigrationPlan | null;
|
|
111
|
+
/** Execute a migration: move all keys from one version to another. */
|
|
112
|
+
executeMigration(tool: string, fromVersion: string, toVersion: string): number;
|
|
113
|
+
/** Get all deprecated versions across all tools. */
|
|
114
|
+
getDeprecatedVersions(): ToolVersion[];
|
|
115
|
+
/** Get versions approaching sunset (within days). */
|
|
116
|
+
getApproachingSunset(withinDays?: number): ToolVersion[];
|
|
117
|
+
getStats(): ApiVersionStats;
|
|
118
|
+
/** Clear all data. */
|
|
119
|
+
destroy(): void;
|
|
120
|
+
private checkSunsets;
|
|
121
|
+
}
|
|
122
|
+
//# sourceMappingURL=api-versioning.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api-versioning.d.ts","sourceRoot":"","sources":["../src/api-versioning.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,316 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* ApiVersionRouter — Route tool calls to versioned backends.
|
|
4
|
+
*
|
|
5
|
+
* Manage multiple versions of tools, route requests to the correct
|
|
6
|
+
* version based on key configuration, and enable safe migrations
|
|
7
|
+
* with deprecation warnings and sunset dates.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```ts
|
|
11
|
+
* const router = new ApiVersionRouter();
|
|
12
|
+
*
|
|
13
|
+
* router.registerVersion({
|
|
14
|
+
* tool: 'search',
|
|
15
|
+
* version: 'v1',
|
|
16
|
+
* status: 'deprecated',
|
|
17
|
+
* sunsetDate: '2026-04-01',
|
|
18
|
+
* });
|
|
19
|
+
*
|
|
20
|
+
* router.registerVersion({
|
|
21
|
+
* tool: 'search',
|
|
22
|
+
* version: 'v2',
|
|
23
|
+
* status: 'current',
|
|
24
|
+
* });
|
|
25
|
+
*
|
|
26
|
+
* router.setKeyVersion('key_abc', 'search', 'v2');
|
|
27
|
+
*
|
|
28
|
+
* const resolved = router.resolve('key_abc', 'search');
|
|
29
|
+
* // { version: 'v2', status: 'current', deprecated: false }
|
|
30
|
+
* ```
|
|
31
|
+
*/
|
|
32
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
33
|
+
exports.ApiVersionRouter = void 0;
|
|
34
|
+
// ── Implementation ───────────────────────────────────────────────────
|
|
35
|
+
class ApiVersionRouter {
|
|
36
|
+
// tool → version → ToolVersion
|
|
37
|
+
versions = new Map();
|
|
38
|
+
// key:tool → version
|
|
39
|
+
keyVersions = new Map();
|
|
40
|
+
defaultStrategy;
|
|
41
|
+
autoSunset;
|
|
42
|
+
// Stats
|
|
43
|
+
totalResolutions = 0;
|
|
44
|
+
constructor(config = {}) {
|
|
45
|
+
this.defaultStrategy = config.defaultVersionStrategy ?? 'current';
|
|
46
|
+
this.autoSunset = config.autoSunset ?? true;
|
|
47
|
+
}
|
|
48
|
+
// ── Version Registration ────────────────────────────────────────────
|
|
49
|
+
/** Register a tool version. */
|
|
50
|
+
registerVersion(reg) {
|
|
51
|
+
if (!this.versions.has(reg.tool)) {
|
|
52
|
+
this.versions.set(reg.tool, new Map());
|
|
53
|
+
}
|
|
54
|
+
const toolVersions = this.versions.get(reg.tool);
|
|
55
|
+
const version = {
|
|
56
|
+
tool: reg.tool,
|
|
57
|
+
version: reg.version,
|
|
58
|
+
status: reg.status ?? 'current',
|
|
59
|
+
sunsetDate: reg.sunsetDate,
|
|
60
|
+
changelog: reg.changelog,
|
|
61
|
+
registeredAt: Date.now(),
|
|
62
|
+
};
|
|
63
|
+
toolVersions.set(reg.version, version);
|
|
64
|
+
return version;
|
|
65
|
+
}
|
|
66
|
+
/** Remove a tool version. */
|
|
67
|
+
removeVersion(tool, version) {
|
|
68
|
+
const toolVersions = this.versions.get(tool);
|
|
69
|
+
if (!toolVersions)
|
|
70
|
+
return false;
|
|
71
|
+
const result = toolVersions.delete(version);
|
|
72
|
+
if (toolVersions.size === 0)
|
|
73
|
+
this.versions.delete(tool);
|
|
74
|
+
// Remove key overrides pointing to this version
|
|
75
|
+
for (const [k, v] of this.keyVersions.entries()) {
|
|
76
|
+
if (k.startsWith(tool + ':') && v === version) {
|
|
77
|
+
// Actually key format is key:tool, so check differently
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
// Clean up key overrides for removed version
|
|
81
|
+
const keysToRemove = [];
|
|
82
|
+
for (const [compositeKey, ver] of this.keyVersions.entries()) {
|
|
83
|
+
const parts = compositeKey.split(':');
|
|
84
|
+
const keyTool = parts.slice(1).join(':');
|
|
85
|
+
if (keyTool === tool && ver === version) {
|
|
86
|
+
keysToRemove.push(compositeKey);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
for (const k of keysToRemove)
|
|
90
|
+
this.keyVersions.delete(k);
|
|
91
|
+
return result;
|
|
92
|
+
}
|
|
93
|
+
/** Get a specific tool version. */
|
|
94
|
+
getVersion(tool, version) {
|
|
95
|
+
return this.versions.get(tool)?.get(version) ?? null;
|
|
96
|
+
}
|
|
97
|
+
/** List all versions for a tool. */
|
|
98
|
+
getToolVersions(tool) {
|
|
99
|
+
const toolVersions = this.versions.get(tool);
|
|
100
|
+
if (!toolVersions)
|
|
101
|
+
return [];
|
|
102
|
+
return [...toolVersions.values()].sort((a, b) => a.version.localeCompare(b.version));
|
|
103
|
+
}
|
|
104
|
+
/** List all tools that have versions. */
|
|
105
|
+
getVersionedTools() {
|
|
106
|
+
return [...this.versions.keys()];
|
|
107
|
+
}
|
|
108
|
+
/** Update the status of a version. */
|
|
109
|
+
setVersionStatus(tool, version, status) {
|
|
110
|
+
const v = this.versions.get(tool)?.get(version);
|
|
111
|
+
if (!v)
|
|
112
|
+
return false;
|
|
113
|
+
v.status = status;
|
|
114
|
+
return true;
|
|
115
|
+
}
|
|
116
|
+
// ── Key Version Overrides ──────────────────────────────────────────
|
|
117
|
+
/** Set a specific version for a key+tool combination. */
|
|
118
|
+
setKeyVersion(key, tool, version) {
|
|
119
|
+
// Verify version exists
|
|
120
|
+
if (!this.versions.get(tool)?.has(version))
|
|
121
|
+
return false;
|
|
122
|
+
this.keyVersions.set(`${key}:${tool}`, version);
|
|
123
|
+
return true;
|
|
124
|
+
}
|
|
125
|
+
/** Remove key-specific version override. */
|
|
126
|
+
removeKeyVersion(key, tool) {
|
|
127
|
+
return this.keyVersions.delete(`${key}:${tool}`);
|
|
128
|
+
}
|
|
129
|
+
/** Get key-specific version override. */
|
|
130
|
+
getKeyVersion(key, tool) {
|
|
131
|
+
return this.keyVersions.get(`${key}:${tool}`) ?? null;
|
|
132
|
+
}
|
|
133
|
+
// ── Resolution ──────────────────────────────────────────────────────
|
|
134
|
+
/** Resolve which version to use for a key+tool request. */
|
|
135
|
+
resolve(key, tool) {
|
|
136
|
+
this.totalResolutions++;
|
|
137
|
+
// Auto-sunset check
|
|
138
|
+
if (this.autoSunset)
|
|
139
|
+
this.checkSunsets(tool);
|
|
140
|
+
const toolVersions = this.versions.get(tool);
|
|
141
|
+
if (!toolVersions || toolVersions.size === 0)
|
|
142
|
+
return null;
|
|
143
|
+
// Check key-specific override first
|
|
144
|
+
let version;
|
|
145
|
+
const keyOverride = this.keyVersions.get(`${key}:${tool}`);
|
|
146
|
+
if (keyOverride && toolVersions.has(keyOverride)) {
|
|
147
|
+
version = keyOverride;
|
|
148
|
+
}
|
|
149
|
+
// Fall back to default strategy
|
|
150
|
+
if (!version) {
|
|
151
|
+
if (this.defaultStrategy === 'current') {
|
|
152
|
+
// Find the version with status 'current'
|
|
153
|
+
for (const v of toolVersions.values()) {
|
|
154
|
+
if (v.status === 'current') {
|
|
155
|
+
version = v.version;
|
|
156
|
+
break;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
// If no 'current', use latest registered (version string as tiebreaker)
|
|
161
|
+
if (!version) {
|
|
162
|
+
const all = [...toolVersions.values()].sort((a, b) => b.registeredAt - a.registeredAt || b.version.localeCompare(a.version));
|
|
163
|
+
// Prefer non-sunset versions
|
|
164
|
+
const active = all.filter(v => v.status !== 'sunset');
|
|
165
|
+
version = (active.length > 0 ? active[0] : all[0]).version;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
const v = toolVersions.get(version);
|
|
169
|
+
const deprecated = v.status === 'deprecated';
|
|
170
|
+
let warning;
|
|
171
|
+
if (deprecated) {
|
|
172
|
+
warning = `Tool "${tool}" version "${version}" is deprecated.`;
|
|
173
|
+
if (v.sunsetDate)
|
|
174
|
+
warning += ` Sunset date: ${v.sunsetDate}.`;
|
|
175
|
+
// Suggest current version
|
|
176
|
+
for (const candidate of toolVersions.values()) {
|
|
177
|
+
if (candidate.status === 'current') {
|
|
178
|
+
warning += ` Please migrate to "${candidate.version}".`;
|
|
179
|
+
break;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
else if (v.status === 'sunset') {
|
|
184
|
+
warning = `Tool "${tool}" version "${version}" is sunset and should no longer be used.`;
|
|
185
|
+
}
|
|
186
|
+
return {
|
|
187
|
+
tool,
|
|
188
|
+
version: v.version,
|
|
189
|
+
status: v.status,
|
|
190
|
+
deprecated,
|
|
191
|
+
sunsetDate: v.sunsetDate,
|
|
192
|
+
warning,
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
// ── Migration Planning ─────────────────────────────────────────────
|
|
196
|
+
/** Generate a migration plan for moving keys from one version to another. */
|
|
197
|
+
planMigration(tool, fromVersion, toVersion) {
|
|
198
|
+
const from = this.getVersion(tool, fromVersion);
|
|
199
|
+
const to = this.getVersion(tool, toVersion);
|
|
200
|
+
if (!from || !to)
|
|
201
|
+
return null;
|
|
202
|
+
// Find keys currently using fromVersion
|
|
203
|
+
const affectedKeys = [];
|
|
204
|
+
for (const [compositeKey, ver] of this.keyVersions.entries()) {
|
|
205
|
+
const parts = compositeKey.split(':');
|
|
206
|
+
const key = parts[0];
|
|
207
|
+
const keyTool = parts.slice(1).join(':');
|
|
208
|
+
if (keyTool === tool && ver === fromVersion) {
|
|
209
|
+
affectedKeys.push(key);
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
return {
|
|
213
|
+
tool,
|
|
214
|
+
fromVersion,
|
|
215
|
+
toVersion,
|
|
216
|
+
affectedKeys,
|
|
217
|
+
fromStatus: from.status,
|
|
218
|
+
toStatus: to.status,
|
|
219
|
+
};
|
|
220
|
+
}
|
|
221
|
+
/** Execute a migration: move all keys from one version to another. */
|
|
222
|
+
executeMigration(tool, fromVersion, toVersion) {
|
|
223
|
+
const plan = this.planMigration(tool, fromVersion, toVersion);
|
|
224
|
+
if (!plan)
|
|
225
|
+
return 0;
|
|
226
|
+
let migrated = 0;
|
|
227
|
+
for (const key of plan.affectedKeys) {
|
|
228
|
+
this.setKeyVersion(key, tool, toVersion);
|
|
229
|
+
migrated++;
|
|
230
|
+
}
|
|
231
|
+
return migrated;
|
|
232
|
+
}
|
|
233
|
+
// ── Deprecation ────────────────────────────────────────────────────
|
|
234
|
+
/** Get all deprecated versions across all tools. */
|
|
235
|
+
getDeprecatedVersions() {
|
|
236
|
+
const result = [];
|
|
237
|
+
for (const toolVersions of this.versions.values()) {
|
|
238
|
+
for (const v of toolVersions.values()) {
|
|
239
|
+
if (v.status === 'deprecated')
|
|
240
|
+
result.push(v);
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
return result;
|
|
244
|
+
}
|
|
245
|
+
/** Get versions approaching sunset (within days). */
|
|
246
|
+
getApproachingSunset(withinDays = 30) {
|
|
247
|
+
const cutoff = Date.now() + withinDays * 24 * 3600_000;
|
|
248
|
+
const result = [];
|
|
249
|
+
for (const toolVersions of this.versions.values()) {
|
|
250
|
+
for (const v of toolVersions.values()) {
|
|
251
|
+
if (v.sunsetDate) {
|
|
252
|
+
const sunsetMs = new Date(v.sunsetDate).getTime();
|
|
253
|
+
if (sunsetMs <= cutoff && v.status !== 'sunset')
|
|
254
|
+
result.push(v);
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
return result;
|
|
259
|
+
}
|
|
260
|
+
// ── Stats ──────────────────────────────────────────────────────────
|
|
261
|
+
getStats() {
|
|
262
|
+
let totalVersions = 0;
|
|
263
|
+
let current = 0, deprecated = 0, sunset = 0, preview = 0;
|
|
264
|
+
for (const toolVersions of this.versions.values()) {
|
|
265
|
+
for (const v of toolVersions.values()) {
|
|
266
|
+
totalVersions++;
|
|
267
|
+
switch (v.status) {
|
|
268
|
+
case 'current':
|
|
269
|
+
current++;
|
|
270
|
+
break;
|
|
271
|
+
case 'deprecated':
|
|
272
|
+
deprecated++;
|
|
273
|
+
break;
|
|
274
|
+
case 'sunset':
|
|
275
|
+
sunset++;
|
|
276
|
+
break;
|
|
277
|
+
case 'preview':
|
|
278
|
+
preview++;
|
|
279
|
+
break;
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
return {
|
|
284
|
+
totalTools: this.versions.size,
|
|
285
|
+
totalVersions,
|
|
286
|
+
currentVersions: current,
|
|
287
|
+
deprecatedVersions: deprecated,
|
|
288
|
+
sunsetVersions: sunset,
|
|
289
|
+
previewVersions: preview,
|
|
290
|
+
keyOverrides: this.keyVersions.size,
|
|
291
|
+
totalResolutions: this.totalResolutions,
|
|
292
|
+
};
|
|
293
|
+
}
|
|
294
|
+
/** Clear all data. */
|
|
295
|
+
destroy() {
|
|
296
|
+
this.versions.clear();
|
|
297
|
+
this.keyVersions.clear();
|
|
298
|
+
this.totalResolutions = 0;
|
|
299
|
+
}
|
|
300
|
+
// ── Private ─────────────────────────────────────────────────────────
|
|
301
|
+
checkSunsets(tool) {
|
|
302
|
+
const toolVersions = this.versions.get(tool);
|
|
303
|
+
if (!toolVersions)
|
|
304
|
+
return;
|
|
305
|
+
const now = Date.now();
|
|
306
|
+
for (const v of toolVersions.values()) {
|
|
307
|
+
if (v.sunsetDate && v.status !== 'sunset') {
|
|
308
|
+
const sunsetMs = new Date(v.sunsetDate).getTime();
|
|
309
|
+
if (sunsetMs <= now)
|
|
310
|
+
v.status = 'sunset';
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
exports.ApiVersionRouter = ApiVersionRouter;
|
|
316
|
+
//# sourceMappingURL=api-versioning.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api-versioning.js","sourceRoot":"","sources":["../src/api-versioning.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* BillingCycleManager — Aggregate usage into billing periods.
|
|
3
|
+
*
|
|
4
|
+
* Creates recurring billing cycles (daily, weekly, monthly) per key,
|
|
5
|
+
* tracks usage within each cycle, and generates invoices.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```ts
|
|
9
|
+
* const billing = new BillingCycleManager();
|
|
10
|
+
*
|
|
11
|
+
* billing.createSubscription({
|
|
12
|
+
* key: 'key_abc',
|
|
13
|
+
* frequency: 'monthly',
|
|
14
|
+
* startDate: '2026-02-01',
|
|
15
|
+
* });
|
|
16
|
+
*
|
|
17
|
+
* billing.recordUsage('key_abc', { tool: 'search', credits: 5 });
|
|
18
|
+
*
|
|
19
|
+
* const invoice = billing.generateInvoice('key_abc');
|
|
20
|
+
* // { totalCredits: 5, lineItems: [...], period: { start, end } }
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
export type BillingFrequency = 'daily' | 'weekly' | 'monthly';
|
|
24
|
+
export type InvoiceStatus = 'draft' | 'finalized' | 'paid' | 'voided';
|
|
25
|
+
export interface BillingSubscription {
|
|
26
|
+
key: string;
|
|
27
|
+
frequency: BillingFrequency;
|
|
28
|
+
startDate: string;
|
|
29
|
+
active: boolean;
|
|
30
|
+
currentCycleStart: number;
|
|
31
|
+
currentCycleEnd: number;
|
|
32
|
+
createdAt: number;
|
|
33
|
+
}
|
|
34
|
+
export interface SubscriptionCreateParams {
|
|
35
|
+
key: string;
|
|
36
|
+
frequency: BillingFrequency;
|
|
37
|
+
startDate?: string;
|
|
38
|
+
}
|
|
39
|
+
export interface UsageRecord {
|
|
40
|
+
tool: string;
|
|
41
|
+
credits: number;
|
|
42
|
+
timestamp: number;
|
|
43
|
+
metadata?: Record<string, string>;
|
|
44
|
+
}
|
|
45
|
+
export interface InvoiceLineItem {
|
|
46
|
+
tool: string;
|
|
47
|
+
callCount: number;
|
|
48
|
+
totalCredits: number;
|
|
49
|
+
}
|
|
50
|
+
export interface Invoice {
|
|
51
|
+
id: string;
|
|
52
|
+
key: string;
|
|
53
|
+
status: InvoiceStatus;
|
|
54
|
+
frequency: BillingFrequency;
|
|
55
|
+
periodStart: number;
|
|
56
|
+
periodEnd: number;
|
|
57
|
+
lineItems: InvoiceLineItem[];
|
|
58
|
+
totalCredits: number;
|
|
59
|
+
totalCalls: number;
|
|
60
|
+
createdAt: number;
|
|
61
|
+
finalizedAt?: number;
|
|
62
|
+
}
|
|
63
|
+
export interface BillingCycleConfig {
|
|
64
|
+
maxUsageRecords?: number;
|
|
65
|
+
maxInvoices?: number;
|
|
66
|
+
}
|
|
67
|
+
export interface BillingCycleStats {
|
|
68
|
+
totalSubscriptions: number;
|
|
69
|
+
activeSubscriptions: number;
|
|
70
|
+
totalInvoices: number;
|
|
71
|
+
totalUsageRecords: number;
|
|
72
|
+
totalCreditsInvoiced: number;
|
|
73
|
+
}
|
|
74
|
+
export declare class BillingCycleManager {
|
|
75
|
+
private subscriptions;
|
|
76
|
+
private usage;
|
|
77
|
+
private invoices;
|
|
78
|
+
private maxUsageRecords;
|
|
79
|
+
private maxInvoices;
|
|
80
|
+
private invoiceIdCounter;
|
|
81
|
+
private totalCreditsInvoiced;
|
|
82
|
+
constructor(config?: BillingCycleConfig);
|
|
83
|
+
/** Create a billing subscription for a key. */
|
|
84
|
+
createSubscription(params: SubscriptionCreateParams): BillingSubscription;
|
|
85
|
+
/** Get subscription for a key. */
|
|
86
|
+
getSubscription(key: string): BillingSubscription | null;
|
|
87
|
+
/** Pause a subscription. */
|
|
88
|
+
pauseSubscription(key: string): boolean;
|
|
89
|
+
/** Resume a subscription. */
|
|
90
|
+
resumeSubscription(key: string): boolean;
|
|
91
|
+
/** Cancel (remove) a subscription. */
|
|
92
|
+
cancelSubscription(key: string): boolean;
|
|
93
|
+
/** List all subscriptions. */
|
|
94
|
+
listSubscriptions(): BillingSubscription[];
|
|
95
|
+
/** Record usage for a key. */
|
|
96
|
+
recordUsage(key: string, record: {
|
|
97
|
+
tool: string;
|
|
98
|
+
credits: number;
|
|
99
|
+
metadata?: Record<string, string>;
|
|
100
|
+
}): void;
|
|
101
|
+
/** Get usage records for a key within a time range. */
|
|
102
|
+
getUsage(key: string, startTime?: number, endTime?: number): UsageRecord[];
|
|
103
|
+
/** Generate an invoice for the current billing cycle. */
|
|
104
|
+
generateInvoice(key: string): Invoice | null;
|
|
105
|
+
/** Finalize an invoice (mark as ready for payment). */
|
|
106
|
+
finalizeInvoice(invoiceId: string): boolean;
|
|
107
|
+
/** Mark an invoice as paid. */
|
|
108
|
+
markPaid(invoiceId: string): boolean;
|
|
109
|
+
/** Void an invoice. */
|
|
110
|
+
voidInvoice(invoiceId: string): boolean;
|
|
111
|
+
/** Get an invoice by ID. */
|
|
112
|
+
getInvoice(id: string): Invoice | null;
|
|
113
|
+
/** Get all invoices for a key. */
|
|
114
|
+
getKeyInvoices(key: string, limit?: number): Invoice[];
|
|
115
|
+
/** Advance current cycle to the next period. */
|
|
116
|
+
advanceCycle(sub: BillingSubscription): boolean;
|
|
117
|
+
getStats(): BillingCycleStats;
|
|
118
|
+
/** Clear all data. */
|
|
119
|
+
destroy(): void;
|
|
120
|
+
private computeCycleEnd;
|
|
121
|
+
}
|
|
122
|
+
//# sourceMappingURL=billing-cycles.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"billing-cycles.d.ts","sourceRoot":"","sources":["../src/billing-cycles.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAIH,MAAM,MAAM,gBAAgB,GAAG,OAAO,GAAG,QAAQ,GAAG,SAAS,CAAC;AAC9D,MAAM,MAAM,aAAa,GAAG,OAAO,GAAG,WAAW,GAAG,MAAM,GAAG,QAAQ,CAAC;AAEtE,MAAM,WAAW,mBAAmB;IAClC,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,EAAE,gBAAgB,CAAC;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,OAAO,CAAC;IAChB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,eAAe,EAAE,MAAM,CAAC;IACxB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,wBAAwB;IACvC,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,EAAE,gBAAgB,CAAC;IAC5B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACnC;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,OAAO;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,aAAa,CAAC;IACtB,SAAS,EAAE,gBAAgB,CAAC;IAC5B,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,eAAe,EAAE,CAAC;IAC7B,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,kBAAkB;IACjC,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,iBAAiB;IAChC,kBAAkB,EAAE,MAAM,CAAC;IAC3B,mBAAmB,EAAE,MAAM,CAAC;IAC5B,aAAa,EAAE,MAAM,CAAC;IACtB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,oBAAoB,EAAE,MAAM,CAAC;CAC9B;AAID,qBAAa,mBAAmB;IAC9B,OAAO,CAAC,aAAa,CAA0C;IAC/D,OAAO,CAAC,KAAK,CAAoC;IACjD,OAAO,CAAC,QAAQ,CAAiB;IACjC,OAAO,CAAC,eAAe,CAAS;IAChC,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,gBAAgB,CAAK;IAG7B,OAAO,CAAC,oBAAoB,CAAK;gBAErB,MAAM,GAAE,kBAAuB;IAO3C,+CAA+C;IAC/C,kBAAkB,CAAC,MAAM,EAAE,wBAAwB,GAAG,mBAAmB;IAqBzE,kCAAkC;IAClC,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,mBAAmB,GAAG,IAAI;IAIxD,4BAA4B;IAC5B,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAOvC,6BAA6B;IAC7B,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAOxC,sCAAsC;IACtC,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAIxC,8BAA8B;IAC9B,iBAAiB,IAAI,mBAAmB,EAAE;IAM1C,8BAA8B;IAC9B,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;KAAE,GAAG,IAAI;IAiB5G,uDAAuD;IACvD,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,WAAW,EAAE;IAU1E,yDAAyD;IACzD,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,GAAG,IAAI;IAqD5C,uDAAuD;IACvD,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO;IAS3C,+BAA+B;IAC/B,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO;IAOpC,uBAAuB;IACvB,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO;IAOvC,4BAA4B;IAC5B,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,GAAG,IAAI;IAItC,kCAAkC;IAClC,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,EAAE;IAOtD,gDAAgD;IAChD,YAAY,CAAC,GAAG,EAAE,mBAAmB,GAAG,OAAO;IAc/C,QAAQ,IAAI,iBAAiB;IAe7B,sBAAsB;IACtB,OAAO,IAAI,IAAI;IAUf,OAAO,CAAC,eAAe;CAexB"}
|