@vasperacapital/vaspera-shared 0.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/.turbo/turbo-build.log +34 -0
- package/.turbo/turbo-typecheck.log +4 -0
- package/dist/errors/index.d.mts +288 -0
- package/dist/errors/index.d.ts +288 -0
- package/dist/errors/index.js +341 -0
- package/dist/errors/index.js.map +1 -0
- package/dist/errors/index.mjs +310 -0
- package/dist/errors/index.mjs.map +1 -0
- package/dist/index.d.mts +57 -0
- package/dist/index.d.ts +57 -0
- package/dist/index.js +458 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +421 -0
- package/dist/index.mjs.map +1 -0
- package/dist/types/index.d.mts +122 -0
- package/dist/types/index.d.ts +122 -0
- package/dist/types/index.js +45 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/index.mjs +19 -0
- package/dist/types/index.mjs.map +1 -0
- package/package.json +48 -0
- package/src/__tests__/api-key.test.ts +129 -0
- package/src/__tests__/encryption.test.ts +129 -0
- package/src/__tests__/errors.test.ts +185 -0
- package/src/errors/codes.ts +213 -0
- package/src/errors/factory.ts +164 -0
- package/src/errors/index.ts +10 -0
- package/src/index.ts +8 -0
- package/src/types/index.ts +164 -0
- package/src/utils/api-key.ts +72 -0
- package/src/utils/encryption.ts +79 -0
- package/src/utils/index.ts +15 -0
- package/tsconfig.json +9 -0
- package/tsup.config.ts +10 -0
|
@@ -0,0 +1,341 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/errors/index.ts
|
|
21
|
+
var errors_exports = {};
|
|
22
|
+
__export(errors_exports, {
|
|
23
|
+
ErrorCodes: () => ErrorCodes,
|
|
24
|
+
Errors: () => Errors,
|
|
25
|
+
VasperaApiError: () => VasperaApiError,
|
|
26
|
+
createError: () => createError,
|
|
27
|
+
createErrorResponse: () => createErrorResponse
|
|
28
|
+
});
|
|
29
|
+
module.exports = __toCommonJS(errors_exports);
|
|
30
|
+
|
|
31
|
+
// src/errors/codes.ts
|
|
32
|
+
var ErrorCodes = {
|
|
33
|
+
// Authentication Errors (VPM-AUTH-XXX)
|
|
34
|
+
AUTH: {
|
|
35
|
+
REQUIRED: {
|
|
36
|
+
code: "VPM-AUTH-001",
|
|
37
|
+
message: "Authentication required",
|
|
38
|
+
httpStatus: 401
|
|
39
|
+
},
|
|
40
|
+
INVALID_TOKEN: {
|
|
41
|
+
code: "VPM-AUTH-002",
|
|
42
|
+
message: "Invalid or expired authentication token",
|
|
43
|
+
httpStatus: 401
|
|
44
|
+
},
|
|
45
|
+
INSUFFICIENT_PERMISSIONS: {
|
|
46
|
+
code: "VPM-AUTH-003",
|
|
47
|
+
message: "Insufficient permissions for this action",
|
|
48
|
+
httpStatus: 403
|
|
49
|
+
},
|
|
50
|
+
SESSION_EXPIRED: {
|
|
51
|
+
code: "VPM-AUTH-004",
|
|
52
|
+
message: "Session has expired, please login again",
|
|
53
|
+
httpStatus: 401
|
|
54
|
+
},
|
|
55
|
+
MFA_REQUIRED: {
|
|
56
|
+
code: "VPM-AUTH-005",
|
|
57
|
+
message: "Multi-factor authentication required",
|
|
58
|
+
httpStatus: 403
|
|
59
|
+
}
|
|
60
|
+
},
|
|
61
|
+
// API Key Errors (VPM-API-KEY-XXX)
|
|
62
|
+
API_KEY: {
|
|
63
|
+
REQUIRED: {
|
|
64
|
+
code: "VPM-API-KEY-001",
|
|
65
|
+
message: "API key is required",
|
|
66
|
+
httpStatus: 401
|
|
67
|
+
},
|
|
68
|
+
INVALID: {
|
|
69
|
+
code: "VPM-API-KEY-002",
|
|
70
|
+
message: "Invalid API key",
|
|
71
|
+
httpStatus: 401
|
|
72
|
+
},
|
|
73
|
+
REVOKED: {
|
|
74
|
+
code: "VPM-API-KEY-003",
|
|
75
|
+
message: "API key has been revoked",
|
|
76
|
+
httpStatus: 401
|
|
77
|
+
},
|
|
78
|
+
EXPIRED: {
|
|
79
|
+
code: "VPM-API-KEY-004",
|
|
80
|
+
message: "API key has expired",
|
|
81
|
+
httpStatus: 401
|
|
82
|
+
},
|
|
83
|
+
RATE_LIMITED: {
|
|
84
|
+
code: "VPM-API-KEY-005",
|
|
85
|
+
message: "API key rate limit exceeded",
|
|
86
|
+
httpStatus: 429
|
|
87
|
+
},
|
|
88
|
+
QUOTA_EXCEEDED: {
|
|
89
|
+
code: "VPM-API-KEY-006",
|
|
90
|
+
message: "Monthly usage quota exceeded",
|
|
91
|
+
httpStatus: 429
|
|
92
|
+
}
|
|
93
|
+
},
|
|
94
|
+
// MCP Tool Errors (VPM-MCP-XXX)
|
|
95
|
+
MCP: {
|
|
96
|
+
TOOL_NOT_FOUND: {
|
|
97
|
+
code: "VPM-MCP-001",
|
|
98
|
+
message: "Requested tool not found",
|
|
99
|
+
httpStatus: 404
|
|
100
|
+
},
|
|
101
|
+
INVALID_ARGUMENTS: {
|
|
102
|
+
code: "VPM-MCP-002",
|
|
103
|
+
message: "Invalid tool arguments provided",
|
|
104
|
+
httpStatus: 400
|
|
105
|
+
},
|
|
106
|
+
EXECUTION_FAILED: {
|
|
107
|
+
code: "VPM-MCP-003",
|
|
108
|
+
message: "Tool execution failed",
|
|
109
|
+
httpStatus: 500
|
|
110
|
+
},
|
|
111
|
+
TIMEOUT: {
|
|
112
|
+
code: "VPM-MCP-004",
|
|
113
|
+
message: "Tool execution timed out",
|
|
114
|
+
httpStatus: 504
|
|
115
|
+
},
|
|
116
|
+
LLM_ERROR: {
|
|
117
|
+
code: "VPM-MCP-005",
|
|
118
|
+
message: "AI model returned an error",
|
|
119
|
+
httpStatus: 502
|
|
120
|
+
},
|
|
121
|
+
CONTEXT_TOO_LARGE: {
|
|
122
|
+
code: "VPM-MCP-006",
|
|
123
|
+
message: "Input context exceeds maximum size",
|
|
124
|
+
httpStatus: 413
|
|
125
|
+
}
|
|
126
|
+
},
|
|
127
|
+
// Billing Errors (VPM-BILLING-XXX)
|
|
128
|
+
BILLING: {
|
|
129
|
+
NO_SUBSCRIPTION: {
|
|
130
|
+
code: "VPM-BILLING-001",
|
|
131
|
+
message: "No active subscription found",
|
|
132
|
+
httpStatus: 402
|
|
133
|
+
},
|
|
134
|
+
SUBSCRIPTION_EXPIRED: {
|
|
135
|
+
code: "VPM-BILLING-002",
|
|
136
|
+
message: "Subscription has expired",
|
|
137
|
+
httpStatus: 402
|
|
138
|
+
},
|
|
139
|
+
PAYMENT_FAILED: {
|
|
140
|
+
code: "VPM-BILLING-003",
|
|
141
|
+
message: "Payment processing failed",
|
|
142
|
+
httpStatus: 402
|
|
143
|
+
},
|
|
144
|
+
FEATURE_NOT_INCLUDED: {
|
|
145
|
+
code: "VPM-BILLING-004",
|
|
146
|
+
message: "Feature not included in current plan",
|
|
147
|
+
httpStatus: 403
|
|
148
|
+
},
|
|
149
|
+
UPGRADE_REQUIRED: {
|
|
150
|
+
code: "VPM-BILLING-005",
|
|
151
|
+
message: "Plan upgrade required for this action",
|
|
152
|
+
httpStatus: 403
|
|
153
|
+
}
|
|
154
|
+
},
|
|
155
|
+
// Integration Errors (VPM-INT-XXX)
|
|
156
|
+
INTEGRATION: {
|
|
157
|
+
NOT_CONNECTED: {
|
|
158
|
+
code: "VPM-INT-001",
|
|
159
|
+
message: "Integration not connected",
|
|
160
|
+
httpStatus: 400
|
|
161
|
+
},
|
|
162
|
+
TOKEN_EXPIRED: {
|
|
163
|
+
code: "VPM-INT-002",
|
|
164
|
+
message: "Integration token expired, reconnection required",
|
|
165
|
+
httpStatus: 401
|
|
166
|
+
},
|
|
167
|
+
REFRESH_FAILED: {
|
|
168
|
+
code: "VPM-INT-003",
|
|
169
|
+
message: "Failed to refresh integration token",
|
|
170
|
+
httpStatus: 502
|
|
171
|
+
},
|
|
172
|
+
API_ERROR: {
|
|
173
|
+
code: "VPM-INT-004",
|
|
174
|
+
message: "External integration API error",
|
|
175
|
+
httpStatus: 502
|
|
176
|
+
},
|
|
177
|
+
RATE_LIMITED: {
|
|
178
|
+
code: "VPM-INT-005",
|
|
179
|
+
message: "Integration rate limit exceeded",
|
|
180
|
+
httpStatus: 429
|
|
181
|
+
}
|
|
182
|
+
},
|
|
183
|
+
// Validation Errors (VPM-VAL-XXX)
|
|
184
|
+
VALIDATION: {
|
|
185
|
+
REQUIRED_FIELD: {
|
|
186
|
+
code: "VPM-VAL-001",
|
|
187
|
+
message: "Required field missing",
|
|
188
|
+
httpStatus: 400
|
|
189
|
+
},
|
|
190
|
+
INVALID_FORMAT: {
|
|
191
|
+
code: "VPM-VAL-002",
|
|
192
|
+
message: "Invalid field format",
|
|
193
|
+
httpStatus: 400
|
|
194
|
+
},
|
|
195
|
+
OUT_OF_RANGE: {
|
|
196
|
+
code: "VPM-VAL-003",
|
|
197
|
+
message: "Value out of allowed range",
|
|
198
|
+
httpStatus: 400
|
|
199
|
+
},
|
|
200
|
+
INVALID_JSON: {
|
|
201
|
+
code: "VPM-VAL-004",
|
|
202
|
+
message: "Invalid JSON in request body",
|
|
203
|
+
httpStatus: 400
|
|
204
|
+
}
|
|
205
|
+
},
|
|
206
|
+
// System Errors (VPM-SYS-XXX)
|
|
207
|
+
SYSTEM: {
|
|
208
|
+
INTERNAL_ERROR: {
|
|
209
|
+
code: "VPM-SYS-001",
|
|
210
|
+
message: "Internal server error",
|
|
211
|
+
httpStatus: 500
|
|
212
|
+
},
|
|
213
|
+
DATABASE_ERROR: {
|
|
214
|
+
code: "VPM-SYS-002",
|
|
215
|
+
message: "Database operation failed",
|
|
216
|
+
httpStatus: 500
|
|
217
|
+
},
|
|
218
|
+
SERVICE_UNAVAILABLE: {
|
|
219
|
+
code: "VPM-SYS-003",
|
|
220
|
+
message: "Service temporarily unavailable",
|
|
221
|
+
httpStatus: 503
|
|
222
|
+
},
|
|
223
|
+
MAINTENANCE_MODE: {
|
|
224
|
+
code: "VPM-SYS-004",
|
|
225
|
+
message: "System is under maintenance",
|
|
226
|
+
httpStatus: 503
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
};
|
|
230
|
+
|
|
231
|
+
// src/errors/factory.ts
|
|
232
|
+
function generateRequestId() {
|
|
233
|
+
return `req_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 9)}`;
|
|
234
|
+
}
|
|
235
|
+
function createError(errorDef, details, requestId) {
|
|
236
|
+
return {
|
|
237
|
+
code: errorDef.code,
|
|
238
|
+
message: errorDef.message,
|
|
239
|
+
details,
|
|
240
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
241
|
+
requestId: requestId || generateRequestId(),
|
|
242
|
+
docUrl: `https://docs.vaspera.pm/errors/${errorDef.code}`
|
|
243
|
+
};
|
|
244
|
+
}
|
|
245
|
+
function createErrorResponse(errorDef, details, requestId) {
|
|
246
|
+
return {
|
|
247
|
+
response: {
|
|
248
|
+
success: false,
|
|
249
|
+
error: createError(errorDef, details, requestId)
|
|
250
|
+
},
|
|
251
|
+
status: errorDef.httpStatus
|
|
252
|
+
};
|
|
253
|
+
}
|
|
254
|
+
function getNextResetDate() {
|
|
255
|
+
const now = /* @__PURE__ */ new Date();
|
|
256
|
+
const nextMonth = new Date(now.getFullYear(), now.getMonth() + 1, 1);
|
|
257
|
+
return nextMonth.toISOString();
|
|
258
|
+
}
|
|
259
|
+
var Errors = {
|
|
260
|
+
authRequired: (requestId) => createErrorResponse(ErrorCodes.AUTH.REQUIRED, void 0, requestId),
|
|
261
|
+
invalidApiKey: (requestId) => createErrorResponse(ErrorCodes.API_KEY.INVALID, void 0, requestId),
|
|
262
|
+
apiKeyRevoked: (requestId) => createErrorResponse(ErrorCodes.API_KEY.REVOKED, void 0, requestId),
|
|
263
|
+
apiKeyExpired: (requestId) => createErrorResponse(ErrorCodes.API_KEY.EXPIRED, void 0, requestId),
|
|
264
|
+
rateLimited: (retryAfter, requestId) => createErrorResponse(
|
|
265
|
+
ErrorCodes.API_KEY.RATE_LIMITED,
|
|
266
|
+
{ retryAfterSeconds: retryAfter },
|
|
267
|
+
requestId
|
|
268
|
+
),
|
|
269
|
+
quotaExceeded: (currentUsage, limit, requestId) => createErrorResponse(
|
|
270
|
+
ErrorCodes.API_KEY.QUOTA_EXCEEDED,
|
|
271
|
+
{ currentUsage, limit, resetDate: getNextResetDate() },
|
|
272
|
+
requestId
|
|
273
|
+
),
|
|
274
|
+
toolNotFound: (toolName, requestId) => createErrorResponse(
|
|
275
|
+
ErrorCodes.MCP.TOOL_NOT_FOUND,
|
|
276
|
+
{ tool: toolName },
|
|
277
|
+
requestId
|
|
278
|
+
),
|
|
279
|
+
toolExecutionFailed: (toolName, reason, requestId) => createErrorResponse(
|
|
280
|
+
ErrorCodes.MCP.EXECUTION_FAILED,
|
|
281
|
+
{ tool: toolName, reason },
|
|
282
|
+
requestId
|
|
283
|
+
),
|
|
284
|
+
toolTimeout: (toolName, timeoutMs, requestId) => createErrorResponse(
|
|
285
|
+
ErrorCodes.MCP.TIMEOUT,
|
|
286
|
+
{ tool: toolName, timeoutMs },
|
|
287
|
+
requestId
|
|
288
|
+
),
|
|
289
|
+
validationFailed: (field, reason, requestId) => createErrorResponse(
|
|
290
|
+
ErrorCodes.VALIDATION.REQUIRED_FIELD,
|
|
291
|
+
{ field, reason },
|
|
292
|
+
requestId
|
|
293
|
+
),
|
|
294
|
+
invalidFormat: (field, expected, requestId) => createErrorResponse(
|
|
295
|
+
ErrorCodes.VALIDATION.INVALID_FORMAT,
|
|
296
|
+
{ field, expected },
|
|
297
|
+
requestId
|
|
298
|
+
),
|
|
299
|
+
internalError: (message, requestId) => createErrorResponse(
|
|
300
|
+
ErrorCodes.SYSTEM.INTERNAL_ERROR,
|
|
301
|
+
message ? { message } : void 0,
|
|
302
|
+
requestId
|
|
303
|
+
),
|
|
304
|
+
databaseError: (operation, requestId) => createErrorResponse(
|
|
305
|
+
ErrorCodes.SYSTEM.DATABASE_ERROR,
|
|
306
|
+
{ operation },
|
|
307
|
+
requestId
|
|
308
|
+
),
|
|
309
|
+
integrationNotConnected: (provider, requestId) => createErrorResponse(
|
|
310
|
+
ErrorCodes.INTEGRATION.NOT_CONNECTED,
|
|
311
|
+
{ provider },
|
|
312
|
+
requestId
|
|
313
|
+
),
|
|
314
|
+
subscriptionRequired: (feature, requiredTier, requestId) => createErrorResponse(
|
|
315
|
+
ErrorCodes.BILLING.FEATURE_NOT_INCLUDED,
|
|
316
|
+
{ feature, requiredTier },
|
|
317
|
+
requestId
|
|
318
|
+
)
|
|
319
|
+
};
|
|
320
|
+
var VasperaApiError = class extends Error {
|
|
321
|
+
errorDef;
|
|
322
|
+
details;
|
|
323
|
+
constructor(errorDef, details) {
|
|
324
|
+
super(errorDef.message);
|
|
325
|
+
this.name = "VasperaApiError";
|
|
326
|
+
this.errorDef = errorDef;
|
|
327
|
+
this.details = details;
|
|
328
|
+
}
|
|
329
|
+
toResponse(requestId) {
|
|
330
|
+
return createErrorResponse(this.errorDef, this.details, requestId);
|
|
331
|
+
}
|
|
332
|
+
};
|
|
333
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
334
|
+
0 && (module.exports = {
|
|
335
|
+
ErrorCodes,
|
|
336
|
+
Errors,
|
|
337
|
+
VasperaApiError,
|
|
338
|
+
createError,
|
|
339
|
+
createErrorResponse
|
|
340
|
+
});
|
|
341
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/errors/index.ts","../../src/errors/codes.ts","../../src/errors/factory.ts"],"sourcesContent":["export { ErrorCodes } from './codes.js';\nexport type { ErrorDefinition, ErrorCodeType } from './codes.js';\n\nexport {\n createError,\n createErrorResponse,\n Errors,\n VasperaApiError,\n} from './factory.js';\nexport type { VasperaError, ErrorResponse } from './factory.js';\n","export interface ErrorDefinition {\n code: string;\n message: string;\n httpStatus: number;\n}\n\nexport const ErrorCodes = {\n // Authentication Errors (VPM-AUTH-XXX)\n AUTH: {\n REQUIRED: {\n code: 'VPM-AUTH-001',\n message: 'Authentication required',\n httpStatus: 401,\n },\n INVALID_TOKEN: {\n code: 'VPM-AUTH-002',\n message: 'Invalid or expired authentication token',\n httpStatus: 401,\n },\n INSUFFICIENT_PERMISSIONS: {\n code: 'VPM-AUTH-003',\n message: 'Insufficient permissions for this action',\n httpStatus: 403,\n },\n SESSION_EXPIRED: {\n code: 'VPM-AUTH-004',\n message: 'Session has expired, please login again',\n httpStatus: 401,\n },\n MFA_REQUIRED: {\n code: 'VPM-AUTH-005',\n message: 'Multi-factor authentication required',\n httpStatus: 403,\n },\n },\n\n // API Key Errors (VPM-API-KEY-XXX)\n API_KEY: {\n REQUIRED: {\n code: 'VPM-API-KEY-001',\n message: 'API key is required',\n httpStatus: 401,\n },\n INVALID: {\n code: 'VPM-API-KEY-002',\n message: 'Invalid API key',\n httpStatus: 401,\n },\n REVOKED: {\n code: 'VPM-API-KEY-003',\n message: 'API key has been revoked',\n httpStatus: 401,\n },\n EXPIRED: {\n code: 'VPM-API-KEY-004',\n message: 'API key has expired',\n httpStatus: 401,\n },\n RATE_LIMITED: {\n code: 'VPM-API-KEY-005',\n message: 'API key rate limit exceeded',\n httpStatus: 429,\n },\n QUOTA_EXCEEDED: {\n code: 'VPM-API-KEY-006',\n message: 'Monthly usage quota exceeded',\n httpStatus: 429,\n },\n },\n\n // MCP Tool Errors (VPM-MCP-XXX)\n MCP: {\n TOOL_NOT_FOUND: {\n code: 'VPM-MCP-001',\n message: 'Requested tool not found',\n httpStatus: 404,\n },\n INVALID_ARGUMENTS: {\n code: 'VPM-MCP-002',\n message: 'Invalid tool arguments provided',\n httpStatus: 400,\n },\n EXECUTION_FAILED: {\n code: 'VPM-MCP-003',\n message: 'Tool execution failed',\n httpStatus: 500,\n },\n TIMEOUT: {\n code: 'VPM-MCP-004',\n message: 'Tool execution timed out',\n httpStatus: 504,\n },\n LLM_ERROR: {\n code: 'VPM-MCP-005',\n message: 'AI model returned an error',\n httpStatus: 502,\n },\n CONTEXT_TOO_LARGE: {\n code: 'VPM-MCP-006',\n message: 'Input context exceeds maximum size',\n httpStatus: 413,\n },\n },\n\n // Billing Errors (VPM-BILLING-XXX)\n BILLING: {\n NO_SUBSCRIPTION: {\n code: 'VPM-BILLING-001',\n message: 'No active subscription found',\n httpStatus: 402,\n },\n SUBSCRIPTION_EXPIRED: {\n code: 'VPM-BILLING-002',\n message: 'Subscription has expired',\n httpStatus: 402,\n },\n PAYMENT_FAILED: {\n code: 'VPM-BILLING-003',\n message: 'Payment processing failed',\n httpStatus: 402,\n },\n FEATURE_NOT_INCLUDED: {\n code: 'VPM-BILLING-004',\n message: 'Feature not included in current plan',\n httpStatus: 403,\n },\n UPGRADE_REQUIRED: {\n code: 'VPM-BILLING-005',\n message: 'Plan upgrade required for this action',\n httpStatus: 403,\n },\n },\n\n // Integration Errors (VPM-INT-XXX)\n INTEGRATION: {\n NOT_CONNECTED: {\n code: 'VPM-INT-001',\n message: 'Integration not connected',\n httpStatus: 400,\n },\n TOKEN_EXPIRED: {\n code: 'VPM-INT-002',\n message: 'Integration token expired, reconnection required',\n httpStatus: 401,\n },\n REFRESH_FAILED: {\n code: 'VPM-INT-003',\n message: 'Failed to refresh integration token',\n httpStatus: 502,\n },\n API_ERROR: {\n code: 'VPM-INT-004',\n message: 'External integration API error',\n httpStatus: 502,\n },\n RATE_LIMITED: {\n code: 'VPM-INT-005',\n message: 'Integration rate limit exceeded',\n httpStatus: 429,\n },\n },\n\n // Validation Errors (VPM-VAL-XXX)\n VALIDATION: {\n REQUIRED_FIELD: {\n code: 'VPM-VAL-001',\n message: 'Required field missing',\n httpStatus: 400,\n },\n INVALID_FORMAT: {\n code: 'VPM-VAL-002',\n message: 'Invalid field format',\n httpStatus: 400,\n },\n OUT_OF_RANGE: {\n code: 'VPM-VAL-003',\n message: 'Value out of allowed range',\n httpStatus: 400,\n },\n INVALID_JSON: {\n code: 'VPM-VAL-004',\n message: 'Invalid JSON in request body',\n httpStatus: 400,\n },\n },\n\n // System Errors (VPM-SYS-XXX)\n SYSTEM: {\n INTERNAL_ERROR: {\n code: 'VPM-SYS-001',\n message: 'Internal server error',\n httpStatus: 500,\n },\n DATABASE_ERROR: {\n code: 'VPM-SYS-002',\n message: 'Database operation failed',\n httpStatus: 500,\n },\n SERVICE_UNAVAILABLE: {\n code: 'VPM-SYS-003',\n message: 'Service temporarily unavailable',\n httpStatus: 503,\n },\n MAINTENANCE_MODE: {\n code: 'VPM-SYS-004',\n message: 'System is under maintenance',\n httpStatus: 503,\n },\n },\n} as const;\n\nexport type ErrorCodeType =\n (typeof ErrorCodes)[keyof typeof ErrorCodes][keyof (typeof ErrorCodes)[keyof typeof ErrorCodes]];\n","import type { ErrorDefinition } from './codes.js';\nimport { ErrorCodes } from './codes.js';\n\nexport interface VasperaError {\n code: string;\n message: string;\n details?: Record<string, unknown>;\n timestamp: string;\n requestId: string;\n docUrl?: string;\n}\n\nexport interface ErrorResponse {\n success: false;\n error: VasperaError;\n}\n\nfunction generateRequestId(): string {\n return `req_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 9)}`;\n}\n\nexport function createError(\n errorDef: ErrorDefinition,\n details?: Record<string, unknown>,\n requestId?: string\n): VasperaError {\n return {\n code: errorDef.code,\n message: errorDef.message,\n details,\n timestamp: new Date().toISOString(),\n requestId: requestId || generateRequestId(),\n docUrl: `https://docs.vaspera.pm/errors/${errorDef.code}`,\n };\n}\n\nexport function createErrorResponse(\n errorDef: ErrorDefinition,\n details?: Record<string, unknown>,\n requestId?: string\n): { response: ErrorResponse; status: number } {\n return {\n response: {\n success: false,\n error: createError(errorDef, details, requestId),\n },\n status: errorDef.httpStatus,\n };\n}\n\nfunction getNextResetDate(): string {\n const now = new Date();\n const nextMonth = new Date(now.getFullYear(), now.getMonth() + 1, 1);\n return nextMonth.toISOString();\n}\n\n// Pre-built error creators for common cases\nexport const Errors = {\n authRequired: (requestId?: string) =>\n createErrorResponse(ErrorCodes.AUTH.REQUIRED, undefined, requestId),\n\n invalidApiKey: (requestId?: string) =>\n createErrorResponse(ErrorCodes.API_KEY.INVALID, undefined, requestId),\n\n apiKeyRevoked: (requestId?: string) =>\n createErrorResponse(ErrorCodes.API_KEY.REVOKED, undefined, requestId),\n\n apiKeyExpired: (requestId?: string) =>\n createErrorResponse(ErrorCodes.API_KEY.EXPIRED, undefined, requestId),\n\n rateLimited: (retryAfter: number, requestId?: string) =>\n createErrorResponse(\n ErrorCodes.API_KEY.RATE_LIMITED,\n { retryAfterSeconds: retryAfter },\n requestId\n ),\n\n quotaExceeded: (currentUsage: number, limit: number, requestId?: string) =>\n createErrorResponse(\n ErrorCodes.API_KEY.QUOTA_EXCEEDED,\n { currentUsage, limit, resetDate: getNextResetDate() },\n requestId\n ),\n\n toolNotFound: (toolName: string, requestId?: string) =>\n createErrorResponse(\n ErrorCodes.MCP.TOOL_NOT_FOUND,\n { tool: toolName },\n requestId\n ),\n\n toolExecutionFailed: (toolName: string, reason: string, requestId?: string) =>\n createErrorResponse(\n ErrorCodes.MCP.EXECUTION_FAILED,\n { tool: toolName, reason },\n requestId\n ),\n\n toolTimeout: (toolName: string, timeoutMs: number, requestId?: string) =>\n createErrorResponse(\n ErrorCodes.MCP.TIMEOUT,\n { tool: toolName, timeoutMs },\n requestId\n ),\n\n validationFailed: (field: string, reason: string, requestId?: string) =>\n createErrorResponse(\n ErrorCodes.VALIDATION.REQUIRED_FIELD,\n { field, reason },\n requestId\n ),\n\n invalidFormat: (field: string, expected: string, requestId?: string) =>\n createErrorResponse(\n ErrorCodes.VALIDATION.INVALID_FORMAT,\n { field, expected },\n requestId\n ),\n\n internalError: (message?: string, requestId?: string) =>\n createErrorResponse(\n ErrorCodes.SYSTEM.INTERNAL_ERROR,\n message ? { message } : undefined,\n requestId\n ),\n\n databaseError: (operation: string, requestId?: string) =>\n createErrorResponse(\n ErrorCodes.SYSTEM.DATABASE_ERROR,\n { operation },\n requestId\n ),\n\n integrationNotConnected: (provider: string, requestId?: string) =>\n createErrorResponse(\n ErrorCodes.INTEGRATION.NOT_CONNECTED,\n { provider },\n requestId\n ),\n\n subscriptionRequired: (feature: string, requiredTier: string, requestId?: string) =>\n createErrorResponse(\n ErrorCodes.BILLING.FEATURE_NOT_INCLUDED,\n { feature, requiredTier },\n requestId\n ),\n};\n\n// Custom error class for throwing in API routes\nexport class VasperaApiError extends Error {\n public readonly errorDef: ErrorDefinition;\n public readonly details?: Record<string, unknown>;\n\n constructor(errorDef: ErrorDefinition, details?: Record<string, unknown>) {\n super(errorDef.message);\n this.name = 'VasperaApiError';\n this.errorDef = errorDef;\n this.details = details;\n }\n\n toResponse(requestId?: string): { response: ErrorResponse; status: number } {\n return createErrorResponse(this.errorDef, this.details, requestId);\n }\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,310 @@
|
|
|
1
|
+
// src/errors/codes.ts
|
|
2
|
+
var ErrorCodes = {
|
|
3
|
+
// Authentication Errors (VPM-AUTH-XXX)
|
|
4
|
+
AUTH: {
|
|
5
|
+
REQUIRED: {
|
|
6
|
+
code: "VPM-AUTH-001",
|
|
7
|
+
message: "Authentication required",
|
|
8
|
+
httpStatus: 401
|
|
9
|
+
},
|
|
10
|
+
INVALID_TOKEN: {
|
|
11
|
+
code: "VPM-AUTH-002",
|
|
12
|
+
message: "Invalid or expired authentication token",
|
|
13
|
+
httpStatus: 401
|
|
14
|
+
},
|
|
15
|
+
INSUFFICIENT_PERMISSIONS: {
|
|
16
|
+
code: "VPM-AUTH-003",
|
|
17
|
+
message: "Insufficient permissions for this action",
|
|
18
|
+
httpStatus: 403
|
|
19
|
+
},
|
|
20
|
+
SESSION_EXPIRED: {
|
|
21
|
+
code: "VPM-AUTH-004",
|
|
22
|
+
message: "Session has expired, please login again",
|
|
23
|
+
httpStatus: 401
|
|
24
|
+
},
|
|
25
|
+
MFA_REQUIRED: {
|
|
26
|
+
code: "VPM-AUTH-005",
|
|
27
|
+
message: "Multi-factor authentication required",
|
|
28
|
+
httpStatus: 403
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
// API Key Errors (VPM-API-KEY-XXX)
|
|
32
|
+
API_KEY: {
|
|
33
|
+
REQUIRED: {
|
|
34
|
+
code: "VPM-API-KEY-001",
|
|
35
|
+
message: "API key is required",
|
|
36
|
+
httpStatus: 401
|
|
37
|
+
},
|
|
38
|
+
INVALID: {
|
|
39
|
+
code: "VPM-API-KEY-002",
|
|
40
|
+
message: "Invalid API key",
|
|
41
|
+
httpStatus: 401
|
|
42
|
+
},
|
|
43
|
+
REVOKED: {
|
|
44
|
+
code: "VPM-API-KEY-003",
|
|
45
|
+
message: "API key has been revoked",
|
|
46
|
+
httpStatus: 401
|
|
47
|
+
},
|
|
48
|
+
EXPIRED: {
|
|
49
|
+
code: "VPM-API-KEY-004",
|
|
50
|
+
message: "API key has expired",
|
|
51
|
+
httpStatus: 401
|
|
52
|
+
},
|
|
53
|
+
RATE_LIMITED: {
|
|
54
|
+
code: "VPM-API-KEY-005",
|
|
55
|
+
message: "API key rate limit exceeded",
|
|
56
|
+
httpStatus: 429
|
|
57
|
+
},
|
|
58
|
+
QUOTA_EXCEEDED: {
|
|
59
|
+
code: "VPM-API-KEY-006",
|
|
60
|
+
message: "Monthly usage quota exceeded",
|
|
61
|
+
httpStatus: 429
|
|
62
|
+
}
|
|
63
|
+
},
|
|
64
|
+
// MCP Tool Errors (VPM-MCP-XXX)
|
|
65
|
+
MCP: {
|
|
66
|
+
TOOL_NOT_FOUND: {
|
|
67
|
+
code: "VPM-MCP-001",
|
|
68
|
+
message: "Requested tool not found",
|
|
69
|
+
httpStatus: 404
|
|
70
|
+
},
|
|
71
|
+
INVALID_ARGUMENTS: {
|
|
72
|
+
code: "VPM-MCP-002",
|
|
73
|
+
message: "Invalid tool arguments provided",
|
|
74
|
+
httpStatus: 400
|
|
75
|
+
},
|
|
76
|
+
EXECUTION_FAILED: {
|
|
77
|
+
code: "VPM-MCP-003",
|
|
78
|
+
message: "Tool execution failed",
|
|
79
|
+
httpStatus: 500
|
|
80
|
+
},
|
|
81
|
+
TIMEOUT: {
|
|
82
|
+
code: "VPM-MCP-004",
|
|
83
|
+
message: "Tool execution timed out",
|
|
84
|
+
httpStatus: 504
|
|
85
|
+
},
|
|
86
|
+
LLM_ERROR: {
|
|
87
|
+
code: "VPM-MCP-005",
|
|
88
|
+
message: "AI model returned an error",
|
|
89
|
+
httpStatus: 502
|
|
90
|
+
},
|
|
91
|
+
CONTEXT_TOO_LARGE: {
|
|
92
|
+
code: "VPM-MCP-006",
|
|
93
|
+
message: "Input context exceeds maximum size",
|
|
94
|
+
httpStatus: 413
|
|
95
|
+
}
|
|
96
|
+
},
|
|
97
|
+
// Billing Errors (VPM-BILLING-XXX)
|
|
98
|
+
BILLING: {
|
|
99
|
+
NO_SUBSCRIPTION: {
|
|
100
|
+
code: "VPM-BILLING-001",
|
|
101
|
+
message: "No active subscription found",
|
|
102
|
+
httpStatus: 402
|
|
103
|
+
},
|
|
104
|
+
SUBSCRIPTION_EXPIRED: {
|
|
105
|
+
code: "VPM-BILLING-002",
|
|
106
|
+
message: "Subscription has expired",
|
|
107
|
+
httpStatus: 402
|
|
108
|
+
},
|
|
109
|
+
PAYMENT_FAILED: {
|
|
110
|
+
code: "VPM-BILLING-003",
|
|
111
|
+
message: "Payment processing failed",
|
|
112
|
+
httpStatus: 402
|
|
113
|
+
},
|
|
114
|
+
FEATURE_NOT_INCLUDED: {
|
|
115
|
+
code: "VPM-BILLING-004",
|
|
116
|
+
message: "Feature not included in current plan",
|
|
117
|
+
httpStatus: 403
|
|
118
|
+
},
|
|
119
|
+
UPGRADE_REQUIRED: {
|
|
120
|
+
code: "VPM-BILLING-005",
|
|
121
|
+
message: "Plan upgrade required for this action",
|
|
122
|
+
httpStatus: 403
|
|
123
|
+
}
|
|
124
|
+
},
|
|
125
|
+
// Integration Errors (VPM-INT-XXX)
|
|
126
|
+
INTEGRATION: {
|
|
127
|
+
NOT_CONNECTED: {
|
|
128
|
+
code: "VPM-INT-001",
|
|
129
|
+
message: "Integration not connected",
|
|
130
|
+
httpStatus: 400
|
|
131
|
+
},
|
|
132
|
+
TOKEN_EXPIRED: {
|
|
133
|
+
code: "VPM-INT-002",
|
|
134
|
+
message: "Integration token expired, reconnection required",
|
|
135
|
+
httpStatus: 401
|
|
136
|
+
},
|
|
137
|
+
REFRESH_FAILED: {
|
|
138
|
+
code: "VPM-INT-003",
|
|
139
|
+
message: "Failed to refresh integration token",
|
|
140
|
+
httpStatus: 502
|
|
141
|
+
},
|
|
142
|
+
API_ERROR: {
|
|
143
|
+
code: "VPM-INT-004",
|
|
144
|
+
message: "External integration API error",
|
|
145
|
+
httpStatus: 502
|
|
146
|
+
},
|
|
147
|
+
RATE_LIMITED: {
|
|
148
|
+
code: "VPM-INT-005",
|
|
149
|
+
message: "Integration rate limit exceeded",
|
|
150
|
+
httpStatus: 429
|
|
151
|
+
}
|
|
152
|
+
},
|
|
153
|
+
// Validation Errors (VPM-VAL-XXX)
|
|
154
|
+
VALIDATION: {
|
|
155
|
+
REQUIRED_FIELD: {
|
|
156
|
+
code: "VPM-VAL-001",
|
|
157
|
+
message: "Required field missing",
|
|
158
|
+
httpStatus: 400
|
|
159
|
+
},
|
|
160
|
+
INVALID_FORMAT: {
|
|
161
|
+
code: "VPM-VAL-002",
|
|
162
|
+
message: "Invalid field format",
|
|
163
|
+
httpStatus: 400
|
|
164
|
+
},
|
|
165
|
+
OUT_OF_RANGE: {
|
|
166
|
+
code: "VPM-VAL-003",
|
|
167
|
+
message: "Value out of allowed range",
|
|
168
|
+
httpStatus: 400
|
|
169
|
+
},
|
|
170
|
+
INVALID_JSON: {
|
|
171
|
+
code: "VPM-VAL-004",
|
|
172
|
+
message: "Invalid JSON in request body",
|
|
173
|
+
httpStatus: 400
|
|
174
|
+
}
|
|
175
|
+
},
|
|
176
|
+
// System Errors (VPM-SYS-XXX)
|
|
177
|
+
SYSTEM: {
|
|
178
|
+
INTERNAL_ERROR: {
|
|
179
|
+
code: "VPM-SYS-001",
|
|
180
|
+
message: "Internal server error",
|
|
181
|
+
httpStatus: 500
|
|
182
|
+
},
|
|
183
|
+
DATABASE_ERROR: {
|
|
184
|
+
code: "VPM-SYS-002",
|
|
185
|
+
message: "Database operation failed",
|
|
186
|
+
httpStatus: 500
|
|
187
|
+
},
|
|
188
|
+
SERVICE_UNAVAILABLE: {
|
|
189
|
+
code: "VPM-SYS-003",
|
|
190
|
+
message: "Service temporarily unavailable",
|
|
191
|
+
httpStatus: 503
|
|
192
|
+
},
|
|
193
|
+
MAINTENANCE_MODE: {
|
|
194
|
+
code: "VPM-SYS-004",
|
|
195
|
+
message: "System is under maintenance",
|
|
196
|
+
httpStatus: 503
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
};
|
|
200
|
+
|
|
201
|
+
// src/errors/factory.ts
|
|
202
|
+
function generateRequestId() {
|
|
203
|
+
return `req_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 9)}`;
|
|
204
|
+
}
|
|
205
|
+
function createError(errorDef, details, requestId) {
|
|
206
|
+
return {
|
|
207
|
+
code: errorDef.code,
|
|
208
|
+
message: errorDef.message,
|
|
209
|
+
details,
|
|
210
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
211
|
+
requestId: requestId || generateRequestId(),
|
|
212
|
+
docUrl: `https://docs.vaspera.pm/errors/${errorDef.code}`
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
function createErrorResponse(errorDef, details, requestId) {
|
|
216
|
+
return {
|
|
217
|
+
response: {
|
|
218
|
+
success: false,
|
|
219
|
+
error: createError(errorDef, details, requestId)
|
|
220
|
+
},
|
|
221
|
+
status: errorDef.httpStatus
|
|
222
|
+
};
|
|
223
|
+
}
|
|
224
|
+
function getNextResetDate() {
|
|
225
|
+
const now = /* @__PURE__ */ new Date();
|
|
226
|
+
const nextMonth = new Date(now.getFullYear(), now.getMonth() + 1, 1);
|
|
227
|
+
return nextMonth.toISOString();
|
|
228
|
+
}
|
|
229
|
+
var Errors = {
|
|
230
|
+
authRequired: (requestId) => createErrorResponse(ErrorCodes.AUTH.REQUIRED, void 0, requestId),
|
|
231
|
+
invalidApiKey: (requestId) => createErrorResponse(ErrorCodes.API_KEY.INVALID, void 0, requestId),
|
|
232
|
+
apiKeyRevoked: (requestId) => createErrorResponse(ErrorCodes.API_KEY.REVOKED, void 0, requestId),
|
|
233
|
+
apiKeyExpired: (requestId) => createErrorResponse(ErrorCodes.API_KEY.EXPIRED, void 0, requestId),
|
|
234
|
+
rateLimited: (retryAfter, requestId) => createErrorResponse(
|
|
235
|
+
ErrorCodes.API_KEY.RATE_LIMITED,
|
|
236
|
+
{ retryAfterSeconds: retryAfter },
|
|
237
|
+
requestId
|
|
238
|
+
),
|
|
239
|
+
quotaExceeded: (currentUsage, limit, requestId) => createErrorResponse(
|
|
240
|
+
ErrorCodes.API_KEY.QUOTA_EXCEEDED,
|
|
241
|
+
{ currentUsage, limit, resetDate: getNextResetDate() },
|
|
242
|
+
requestId
|
|
243
|
+
),
|
|
244
|
+
toolNotFound: (toolName, requestId) => createErrorResponse(
|
|
245
|
+
ErrorCodes.MCP.TOOL_NOT_FOUND,
|
|
246
|
+
{ tool: toolName },
|
|
247
|
+
requestId
|
|
248
|
+
),
|
|
249
|
+
toolExecutionFailed: (toolName, reason, requestId) => createErrorResponse(
|
|
250
|
+
ErrorCodes.MCP.EXECUTION_FAILED,
|
|
251
|
+
{ tool: toolName, reason },
|
|
252
|
+
requestId
|
|
253
|
+
),
|
|
254
|
+
toolTimeout: (toolName, timeoutMs, requestId) => createErrorResponse(
|
|
255
|
+
ErrorCodes.MCP.TIMEOUT,
|
|
256
|
+
{ tool: toolName, timeoutMs },
|
|
257
|
+
requestId
|
|
258
|
+
),
|
|
259
|
+
validationFailed: (field, reason, requestId) => createErrorResponse(
|
|
260
|
+
ErrorCodes.VALIDATION.REQUIRED_FIELD,
|
|
261
|
+
{ field, reason },
|
|
262
|
+
requestId
|
|
263
|
+
),
|
|
264
|
+
invalidFormat: (field, expected, requestId) => createErrorResponse(
|
|
265
|
+
ErrorCodes.VALIDATION.INVALID_FORMAT,
|
|
266
|
+
{ field, expected },
|
|
267
|
+
requestId
|
|
268
|
+
),
|
|
269
|
+
internalError: (message, requestId) => createErrorResponse(
|
|
270
|
+
ErrorCodes.SYSTEM.INTERNAL_ERROR,
|
|
271
|
+
message ? { message } : void 0,
|
|
272
|
+
requestId
|
|
273
|
+
),
|
|
274
|
+
databaseError: (operation, requestId) => createErrorResponse(
|
|
275
|
+
ErrorCodes.SYSTEM.DATABASE_ERROR,
|
|
276
|
+
{ operation },
|
|
277
|
+
requestId
|
|
278
|
+
),
|
|
279
|
+
integrationNotConnected: (provider, requestId) => createErrorResponse(
|
|
280
|
+
ErrorCodes.INTEGRATION.NOT_CONNECTED,
|
|
281
|
+
{ provider },
|
|
282
|
+
requestId
|
|
283
|
+
),
|
|
284
|
+
subscriptionRequired: (feature, requiredTier, requestId) => createErrorResponse(
|
|
285
|
+
ErrorCodes.BILLING.FEATURE_NOT_INCLUDED,
|
|
286
|
+
{ feature, requiredTier },
|
|
287
|
+
requestId
|
|
288
|
+
)
|
|
289
|
+
};
|
|
290
|
+
var VasperaApiError = class extends Error {
|
|
291
|
+
errorDef;
|
|
292
|
+
details;
|
|
293
|
+
constructor(errorDef, details) {
|
|
294
|
+
super(errorDef.message);
|
|
295
|
+
this.name = "VasperaApiError";
|
|
296
|
+
this.errorDef = errorDef;
|
|
297
|
+
this.details = details;
|
|
298
|
+
}
|
|
299
|
+
toResponse(requestId) {
|
|
300
|
+
return createErrorResponse(this.errorDef, this.details, requestId);
|
|
301
|
+
}
|
|
302
|
+
};
|
|
303
|
+
export {
|
|
304
|
+
ErrorCodes,
|
|
305
|
+
Errors,
|
|
306
|
+
VasperaApiError,
|
|
307
|
+
createError,
|
|
308
|
+
createErrorResponse
|
|
309
|
+
};
|
|
310
|
+
//# sourceMappingURL=index.mjs.map
|