@t4dhg/mcp-factorial 1.0.0 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +125 -26
- package/dist/api.d.ts +104 -8
- package/dist/api.d.ts.map +1 -1
- package/dist/api.js +261 -98
- package/dist/api.js.map +1 -1
- package/dist/cache.d.ts +88 -0
- package/dist/cache.d.ts.map +1 -0
- package/dist/cache.js +169 -0
- package/dist/cache.js.map +1 -0
- package/dist/config.d.ts +57 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +112 -0
- package/dist/config.js.map +1 -0
- package/dist/errors.d.ts +100 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +186 -0
- package/dist/errors.js.map +1 -0
- package/dist/http-client.d.ts +43 -0
- package/dist/http-client.d.ts.map +1 -0
- package/dist/http-client.js +146 -0
- package/dist/http-client.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1021 -70
- package/dist/index.js.map +1 -1
- package/dist/pagination.d.ts +96 -0
- package/dist/pagination.d.ts.map +1 -0
- package/dist/pagination.js +114 -0
- package/dist/pagination.js.map +1 -0
- package/dist/schemas.d.ts +502 -0
- package/dist/schemas.d.ts.map +1 -0
- package/dist/schemas.js +241 -0
- package/dist/schemas.js.map +1 -0
- package/dist/types.d.ts +61 -48
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +6 -1
- package/dist/types.js.map +1 -1
- package/package.json +42 -5
package/dist/cache.js
ADDED
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Simple in-memory TTL cache for MCP FactorialHR
|
|
3
|
+
*
|
|
4
|
+
* Reduces API calls by caching frequently accessed data.
|
|
5
|
+
*/
|
|
6
|
+
import { debug } from './config.js';
|
|
7
|
+
/**
|
|
8
|
+
* TTL values for different resource types (in milliseconds)
|
|
9
|
+
*/
|
|
10
|
+
export const CACHE_TTL = {
|
|
11
|
+
employees: 5 * 60 * 1000, // 5 minutes
|
|
12
|
+
teams: 10 * 60 * 1000, // 10 minutes
|
|
13
|
+
locations: 15 * 60 * 1000, // 15 minutes
|
|
14
|
+
contracts: 3 * 60 * 1000, // 3 minutes
|
|
15
|
+
leaves: 2 * 60 * 1000, // 2 minutes
|
|
16
|
+
shifts: 1 * 60 * 1000, // 1 minute
|
|
17
|
+
default: 5 * 60 * 1000, // 5 minutes default
|
|
18
|
+
};
|
|
19
|
+
/**
|
|
20
|
+
* Simple TTL-based cache manager
|
|
21
|
+
*/
|
|
22
|
+
export class CacheManager {
|
|
23
|
+
cache = new Map();
|
|
24
|
+
cleanupInterval = null;
|
|
25
|
+
constructor() {
|
|
26
|
+
// Run cleanup every minute
|
|
27
|
+
this.cleanupInterval = setInterval(() => this.cleanup(), 60000);
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Generate a cache key from resource type and parameters
|
|
31
|
+
*/
|
|
32
|
+
static key(resource, params) {
|
|
33
|
+
if (!params || Object.keys(params).length === 0) {
|
|
34
|
+
return resource;
|
|
35
|
+
}
|
|
36
|
+
// Sort params for consistent key generation
|
|
37
|
+
const record = params;
|
|
38
|
+
const sortedParams = Object.keys(record)
|
|
39
|
+
.sort()
|
|
40
|
+
.filter(k => record[k] !== undefined)
|
|
41
|
+
.map(k => `${k}=${JSON.stringify(record[k])}`)
|
|
42
|
+
.join('&');
|
|
43
|
+
return `${resource}:${sortedParams}`;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Get a value from the cache
|
|
47
|
+
* @returns The cached value or undefined if not found/expired
|
|
48
|
+
*/
|
|
49
|
+
get(key) {
|
|
50
|
+
const entry = this.cache.get(key);
|
|
51
|
+
if (!entry) {
|
|
52
|
+
return undefined;
|
|
53
|
+
}
|
|
54
|
+
if (Date.now() > entry.expiresAt) {
|
|
55
|
+
this.cache.delete(key);
|
|
56
|
+
debug(`Cache miss (expired): ${key}`);
|
|
57
|
+
return undefined;
|
|
58
|
+
}
|
|
59
|
+
debug(`Cache hit: ${key}`);
|
|
60
|
+
return entry.data;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Set a value in the cache
|
|
64
|
+
* @param key - Cache key
|
|
65
|
+
* @param data - Data to cache
|
|
66
|
+
* @param ttlMs - Time to live in milliseconds
|
|
67
|
+
*/
|
|
68
|
+
set(key, data, ttlMs = CACHE_TTL.default) {
|
|
69
|
+
this.cache.set(key, {
|
|
70
|
+
data,
|
|
71
|
+
expiresAt: Date.now() + ttlMs,
|
|
72
|
+
});
|
|
73
|
+
debug(`Cache set: ${key} (TTL: ${ttlMs}ms)`);
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Invalidate a specific cache entry
|
|
77
|
+
*/
|
|
78
|
+
invalidate(key) {
|
|
79
|
+
const deleted = this.cache.delete(key);
|
|
80
|
+
if (deleted) {
|
|
81
|
+
debug(`Cache invalidated: ${key}`);
|
|
82
|
+
}
|
|
83
|
+
return deleted;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Invalidate all cache entries matching a prefix
|
|
87
|
+
*/
|
|
88
|
+
invalidatePrefix(prefix) {
|
|
89
|
+
let count = 0;
|
|
90
|
+
for (const key of this.cache.keys()) {
|
|
91
|
+
if (key.startsWith(prefix)) {
|
|
92
|
+
this.cache.delete(key);
|
|
93
|
+
count++;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
if (count > 0) {
|
|
97
|
+
debug(`Cache invalidated ${count} entries with prefix: ${prefix}`);
|
|
98
|
+
}
|
|
99
|
+
return count;
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Clear all cache entries
|
|
103
|
+
*/
|
|
104
|
+
clear() {
|
|
105
|
+
const size = this.cache.size;
|
|
106
|
+
this.cache.clear();
|
|
107
|
+
debug(`Cache cleared (${size} entries)`);
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Get cache statistics
|
|
111
|
+
*/
|
|
112
|
+
stats() {
|
|
113
|
+
return {
|
|
114
|
+
size: this.cache.size,
|
|
115
|
+
keys: Array.from(this.cache.keys()),
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Remove expired entries
|
|
120
|
+
*/
|
|
121
|
+
cleanup() {
|
|
122
|
+
const now = Date.now();
|
|
123
|
+
let removed = 0;
|
|
124
|
+
for (const [key, entry] of this.cache.entries()) {
|
|
125
|
+
if (now > entry.expiresAt) {
|
|
126
|
+
this.cache.delete(key);
|
|
127
|
+
removed++;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
if (removed > 0) {
|
|
131
|
+
debug(`Cache cleanup: removed ${removed} expired entries`);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Stop the cleanup interval (for testing/cleanup)
|
|
136
|
+
*/
|
|
137
|
+
destroy() {
|
|
138
|
+
if (this.cleanupInterval) {
|
|
139
|
+
clearInterval(this.cleanupInterval);
|
|
140
|
+
this.cleanupInterval = null;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Global cache instance
|
|
146
|
+
*/
|
|
147
|
+
export const cache = new CacheManager();
|
|
148
|
+
/**
|
|
149
|
+
* Helper to get cached data or fetch it
|
|
150
|
+
* @param key - Cache key
|
|
151
|
+
* @param fetcher - Function to fetch data if not cached
|
|
152
|
+
* @param ttlMs - Time to live in milliseconds
|
|
153
|
+
*/
|
|
154
|
+
export async function cached(key, fetcher, ttlMs = CACHE_TTL.default) {
|
|
155
|
+
const cachedValue = cache.get(key);
|
|
156
|
+
if (cachedValue !== undefined) {
|
|
157
|
+
return cachedValue;
|
|
158
|
+
}
|
|
159
|
+
const data = await fetcher();
|
|
160
|
+
cache.set(key, data, ttlMs);
|
|
161
|
+
return data;
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Get the TTL for a resource type
|
|
165
|
+
*/
|
|
166
|
+
export function getTTL(resourceType) {
|
|
167
|
+
return CACHE_TTL[resourceType] ?? CACHE_TTL.default;
|
|
168
|
+
}
|
|
169
|
+
//# sourceMappingURL=cache.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cache.js","sourceRoot":"","sources":["../src/cache.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAUpC;;GAEG;AACH,MAAM,CAAC,MAAM,SAAS,GAAG;IACvB,SAAS,EAAE,CAAC,GAAG,EAAE,GAAG,IAAI,EAAE,YAAY;IACtC,KAAK,EAAE,EAAE,GAAG,EAAE,GAAG,IAAI,EAAE,aAAa;IACpC,SAAS,EAAE,EAAE,GAAG,EAAE,GAAG,IAAI,EAAE,aAAa;IACxC,SAAS,EAAE,CAAC,GAAG,EAAE,GAAG,IAAI,EAAE,YAAY;IACtC,MAAM,EAAE,CAAC,GAAG,EAAE,GAAG,IAAI,EAAE,YAAY;IACnC,MAAM,EAAE,CAAC,GAAG,EAAE,GAAG,IAAI,EAAE,WAAW;IAClC,OAAO,EAAE,CAAC,GAAG,EAAE,GAAG,IAAI,EAAE,oBAAoB;CACpC,CAAC;AAOX;;GAEG;AACH,MAAM,OAAO,YAAY;IACf,KAAK,GAAG,IAAI,GAAG,EAA+B,CAAC;IAC/C,eAAe,GAA0C,IAAI,CAAC;IAEtE;QACE,2BAA2B;QAC3B,IAAI,CAAC,eAAe,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,KAAK,CAAC,CAAC;IAClE,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,GAAG,CAAC,QAAgB,EAAE,MAAe;QAC1C,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAChD,OAAO,QAAQ,CAAC;QAClB,CAAC;QACD,4CAA4C;QAC5C,MAAM,MAAM,GAAG,MAAiC,CAAC;QACjD,MAAM,YAAY,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC;aACrC,IAAI,EAAE;aACN,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,SAAS,CAAC;aACpC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;aAC7C,IAAI,CAAC,GAAG,CAAC,CAAC;QACb,OAAO,GAAG,QAAQ,IAAI,YAAY,EAAE,CAAC;IACvC,CAAC;IAED;;;OAGG;IACH,GAAG,CAAI,GAAW;QAChB,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAClC,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,OAAO,SAAS,CAAC;QACnB,CAAC;QAED,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC,SAAS,EAAE,CAAC;YACjC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YACvB,KAAK,CAAC,yBAAyB,GAAG,EAAE,CAAC,CAAC;YACtC,OAAO,SAAS,CAAC;QACnB,CAAC;QAED,KAAK,CAAC,cAAc,GAAG,EAAE,CAAC,CAAC;QAC3B,OAAO,KAAK,CAAC,IAAS,CAAC;IACzB,CAAC;IAED;;;;;OAKG;IACH,GAAG,CAAI,GAAW,EAAE,IAAO,EAAE,QAAgB,SAAS,CAAC,OAAO;QAC5D,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE;YAClB,IAAI;YACJ,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK;SAC9B,CAAC,CAAC;QACH,KAAK,CAAC,cAAc,GAAG,UAAU,KAAK,KAAK,CAAC,CAAC;IAC/C,CAAC;IAED;;OAEG;IACH,UAAU,CAAC,GAAW;QACpB,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACvC,IAAI,OAAO,EAAE,CAAC;YACZ,KAAK,CAAC,sBAAsB,GAAG,EAAE,CAAC,CAAC;QACrC,CAAC;QACD,OAAO,OAAO,CAAC;IACjB,CAAC;IAED;;OAEG;IACH,gBAAgB,CAAC,MAAc;QAC7B,IAAI,KAAK,GAAG,CAAC,CAAC;QACd,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,EAAE,CAAC;YACpC,IAAI,GAAG,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;gBAC3B,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;gBACvB,KAAK,EAAE,CAAC;YACV,CAAC;QACH,CAAC;QACD,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;YACd,KAAK,CAAC,qBAAqB,KAAK,yBAAyB,MAAM,EAAE,CAAC,CAAC;QACrE,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;IAED;;OAEG;IACH,KAAK;QACH,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC;QAC7B,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;QACnB,KAAK,CAAC,kBAAkB,IAAI,WAAW,CAAC,CAAC;IAC3C,CAAC;IAED;;OAEG;IACH,KAAK;QACH,OAAO;YACL,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI;YACrB,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;SACpC,CAAC;IACJ,CAAC;IAED;;OAEG;IACK,OAAO;QACb,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACvB,IAAI,OAAO,GAAG,CAAC,CAAC;QAChB,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,EAAE,CAAC;YAChD,IAAI,GAAG,GAAG,KAAK,CAAC,SAAS,EAAE,CAAC;gBAC1B,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;gBACvB,OAAO,EAAE,CAAC;YACZ,CAAC;QACH,CAAC;QACD,IAAI,OAAO,GAAG,CAAC,EAAE,CAAC;YAChB,KAAK,CAAC,0BAA0B,OAAO,kBAAkB,CAAC,CAAC;QAC7D,CAAC;IACH,CAAC;IAED;;OAEG;IACH,OAAO;QACL,IAAI,IAAI,CAAC,eAAe,EAAE,CAAC;YACzB,aAAa,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;YACpC,IAAI,CAAC,eAAe,GAAG,IAAI,CAAC;QAC9B,CAAC;IACH,CAAC;CACF;AAED;;GAEG;AACH,MAAM,CAAC,MAAM,KAAK,GAAG,IAAI,YAAY,EAAE,CAAC;AAExC;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,MAAM,CAC1B,GAAW,EACX,OAAyB,EACzB,QAAgB,SAAS,CAAC,OAAO;IAEjC,MAAM,WAAW,GAAG,KAAK,CAAC,GAAG,CAAI,GAAG,CAAC,CAAC;IACtC,IAAI,WAAW,KAAK,SAAS,EAAE,CAAC;QAC9B,OAAO,WAAW,CAAC;IACrB,CAAC;IAED,MAAM,IAAI,GAAG,MAAM,OAAO,EAAE,CAAC;IAC7B,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC;IAC5B,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,MAAM,CAAC,YAA0B;IAC/C,OAAO,SAAS,CAAC,YAAY,CAAC,IAAI,SAAS,CAAC,OAAO,CAAC;AACtD,CAAC"}
|
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration management for MCP FactorialHR
|
|
3
|
+
*
|
|
4
|
+
* Centralizes all configuration options and environment variable handling.
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Configuration interface for FactorialHR API client
|
|
8
|
+
*/
|
|
9
|
+
export interface FactorialConfig {
|
|
10
|
+
/** FactorialHR API key (required) */
|
|
11
|
+
apiKey: string;
|
|
12
|
+
/** API version (e.g., '2025-10-01') */
|
|
13
|
+
apiVersion: string;
|
|
14
|
+
/** Base URL for the Factorial API */
|
|
15
|
+
baseUrl: string;
|
|
16
|
+
/** Request timeout in milliseconds */
|
|
17
|
+
timeout: number;
|
|
18
|
+
/** Maximum number of retry attempts */
|
|
19
|
+
maxRetries: number;
|
|
20
|
+
/** Enable debug logging */
|
|
21
|
+
debug: boolean;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Load environment variables from .env file with priority:
|
|
25
|
+
* 1. ENV_FILE_PATH environment variable
|
|
26
|
+
* 2. Current working directory .env
|
|
27
|
+
* 3. Home directory .env
|
|
28
|
+
* 4. Common project locations
|
|
29
|
+
* 5. Default dotenv behavior
|
|
30
|
+
*/
|
|
31
|
+
export declare function loadEnv(): void;
|
|
32
|
+
/**
|
|
33
|
+
* Get the Factorial API key from environment variables
|
|
34
|
+
* @throws Error if API key is not set
|
|
35
|
+
*/
|
|
36
|
+
export declare function getApiKey(): string;
|
|
37
|
+
/**
|
|
38
|
+
* Get the API version from environment or default
|
|
39
|
+
*/
|
|
40
|
+
export declare function getApiVersion(): string;
|
|
41
|
+
/**
|
|
42
|
+
* Get the base URL for the Factorial API
|
|
43
|
+
*/
|
|
44
|
+
export declare function getBaseUrl(): string;
|
|
45
|
+
/**
|
|
46
|
+
* Get the complete configuration object
|
|
47
|
+
*/
|
|
48
|
+
export declare function getConfig(): FactorialConfig;
|
|
49
|
+
/**
|
|
50
|
+
* Check if debug mode is enabled
|
|
51
|
+
*/
|
|
52
|
+
export declare function isDebugEnabled(): boolean;
|
|
53
|
+
/**
|
|
54
|
+
* Debug logger - only logs when DEBUG=true
|
|
55
|
+
*/
|
|
56
|
+
export declare function debug(message: string, data?: unknown): void;
|
|
57
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAMH;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,qCAAqC;IACrC,MAAM,EAAE,MAAM,CAAC;IACf,uCAAuC;IACvC,UAAU,EAAE,MAAM,CAAC;IACnB,qCAAqC;IACrC,OAAO,EAAE,MAAM,CAAC;IAChB,sCAAsC;IACtC,OAAO,EAAE,MAAM,CAAC;IAChB,uCAAuC;IACvC,UAAU,EAAE,MAAM,CAAC;IACnB,2BAA2B;IAC3B,KAAK,EAAE,OAAO,CAAC;CAChB;AAOD;;;;;;;GAOG;AACH,wBAAgB,OAAO,IAAI,IAAI,CAkC9B;AAED;;;GAGG;AACH,wBAAgB,SAAS,IAAI,MAAM,CAUlC;AAED;;GAEG;AACH,wBAAgB,aAAa,IAAI,MAAM,CAEtC;AAED;;GAEG;AACH,wBAAgB,UAAU,IAAI,MAAM,CAKnC;AAED;;GAEG;AACH,wBAAgB,SAAS,IAAI,eAAe,CAS3C;AAED;;GAEG;AACH,wBAAgB,cAAc,IAAI,OAAO,CAExC;AAED;;GAEG;AACH,wBAAgB,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,IAAI,CAS3D"}
|
package/dist/config.js
ADDED
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration management for MCP FactorialHR
|
|
3
|
+
*
|
|
4
|
+
* Centralizes all configuration options and environment variable handling.
|
|
5
|
+
*/
|
|
6
|
+
import { config } from 'dotenv';
|
|
7
|
+
import { existsSync } from 'fs';
|
|
8
|
+
import { join } from 'path';
|
|
9
|
+
// Default configuration values
|
|
10
|
+
const DEFAULT_API_VERSION = '2025-10-01';
|
|
11
|
+
const DEFAULT_TIMEOUT = 30000; // 30 seconds
|
|
12
|
+
const DEFAULT_MAX_RETRIES = 3;
|
|
13
|
+
/**
|
|
14
|
+
* Load environment variables from .env file with priority:
|
|
15
|
+
* 1. ENV_FILE_PATH environment variable
|
|
16
|
+
* 2. Current working directory .env
|
|
17
|
+
* 3. Home directory .env
|
|
18
|
+
* 4. Common project locations
|
|
19
|
+
* 5. Default dotenv behavior
|
|
20
|
+
*/
|
|
21
|
+
export function loadEnv() {
|
|
22
|
+
// 1. Check if explicit path provided
|
|
23
|
+
if (process.env.ENV_FILE_PATH && existsSync(process.env.ENV_FILE_PATH)) {
|
|
24
|
+
config({ path: process.env.ENV_FILE_PATH });
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
// 2. Check current working directory
|
|
28
|
+
const cwdEnv = join(process.cwd(), '.env');
|
|
29
|
+
if (existsSync(cwdEnv)) {
|
|
30
|
+
config({ path: cwdEnv });
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
// 3. Check home directory
|
|
34
|
+
const homeDir = process.env.HOME || process.env.USERPROFILE || '';
|
|
35
|
+
const homeEnv = join(homeDir, '.env');
|
|
36
|
+
if (existsSync(homeEnv)) {
|
|
37
|
+
config({ path: homeEnv });
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
// 4. Check common project locations
|
|
41
|
+
const commonPaths = [join(homeDir, 'turborepo', '.env'), join(homeDir, 'projects', '.env')];
|
|
42
|
+
for (const envPath of commonPaths) {
|
|
43
|
+
if (existsSync(envPath)) {
|
|
44
|
+
config({ path: envPath });
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
// Fall back to default dotenv behavior
|
|
49
|
+
config();
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Get the Factorial API key from environment variables
|
|
53
|
+
* @throws Error if API key is not set
|
|
54
|
+
*/
|
|
55
|
+
export function getApiKey() {
|
|
56
|
+
const apiKey = process.env.FACTORIAL_API_KEY;
|
|
57
|
+
if (!apiKey) {
|
|
58
|
+
throw new Error('FACTORIAL_API_KEY is not set. ' +
|
|
59
|
+
'Please add it to your .env file or pass it via the MCP configuration. ' +
|
|
60
|
+
'See https://github.com/t4dhg/mcp-factorial for setup instructions.');
|
|
61
|
+
}
|
|
62
|
+
return apiKey;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Get the API version from environment or default
|
|
66
|
+
*/
|
|
67
|
+
export function getApiVersion() {
|
|
68
|
+
return process.env.FACTORIAL_API_VERSION || DEFAULT_API_VERSION;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Get the base URL for the Factorial API
|
|
72
|
+
*/
|
|
73
|
+
export function getBaseUrl() {
|
|
74
|
+
if (process.env.FACTORIAL_BASE_URL) {
|
|
75
|
+
return process.env.FACTORIAL_BASE_URL;
|
|
76
|
+
}
|
|
77
|
+
return `https://api.factorialhr.com/api/${getApiVersion()}/resources`;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Get the complete configuration object
|
|
81
|
+
*/
|
|
82
|
+
export function getConfig() {
|
|
83
|
+
return {
|
|
84
|
+
apiKey: getApiKey(),
|
|
85
|
+
apiVersion: getApiVersion(),
|
|
86
|
+
baseUrl: getBaseUrl(),
|
|
87
|
+
timeout: parseInt(process.env.FACTORIAL_TIMEOUT_MS || String(DEFAULT_TIMEOUT), 10),
|
|
88
|
+
maxRetries: parseInt(process.env.FACTORIAL_MAX_RETRIES || String(DEFAULT_MAX_RETRIES), 10),
|
|
89
|
+
debug: process.env.DEBUG === 'true',
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Check if debug mode is enabled
|
|
94
|
+
*/
|
|
95
|
+
export function isDebugEnabled() {
|
|
96
|
+
return process.env.DEBUG === 'true';
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Debug logger - only logs when DEBUG=true
|
|
100
|
+
*/
|
|
101
|
+
export function debug(message, data) {
|
|
102
|
+
if (isDebugEnabled()) {
|
|
103
|
+
const timestamp = new Date().toISOString();
|
|
104
|
+
if (data !== undefined) {
|
|
105
|
+
console.error(`[${timestamp}] [mcp-factorial] ${message}`, JSON.stringify(data, null, 2));
|
|
106
|
+
}
|
|
107
|
+
else {
|
|
108
|
+
console.error(`[${timestamp}] [mcp-factorial] ${message}`);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
|
package/dist/errors.d.ts
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Structured error types for MCP FactorialHR
|
|
3
|
+
*
|
|
4
|
+
* Provides a clear error hierarchy for better error handling and user messages.
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Base error class for all Factorial-related errors
|
|
8
|
+
*/
|
|
9
|
+
export declare class FactorialError extends Error {
|
|
10
|
+
readonly isRetryable: boolean;
|
|
11
|
+
readonly context?: Record<string, unknown>;
|
|
12
|
+
constructor(message: string, options?: {
|
|
13
|
+
isRetryable?: boolean;
|
|
14
|
+
context?: Record<string, unknown>;
|
|
15
|
+
cause?: Error;
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* HTTP-related errors with status code
|
|
20
|
+
*/
|
|
21
|
+
export declare class HttpError extends FactorialError {
|
|
22
|
+
readonly statusCode: number;
|
|
23
|
+
readonly endpoint: string;
|
|
24
|
+
constructor(statusCode: number, endpoint: string, message: string, options?: {
|
|
25
|
+
isRetryable?: boolean;
|
|
26
|
+
context?: Record<string, unknown>;
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Authentication error (401)
|
|
31
|
+
*/
|
|
32
|
+
export declare class AuthenticationError extends HttpError {
|
|
33
|
+
constructor(endpoint: string, context?: Record<string, unknown>);
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Authorization error (403)
|
|
37
|
+
*/
|
|
38
|
+
export declare class AuthorizationError extends HttpError {
|
|
39
|
+
constructor(endpoint: string, context?: Record<string, unknown>);
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Resource not found error (404)
|
|
43
|
+
*/
|
|
44
|
+
export declare class NotFoundError extends HttpError {
|
|
45
|
+
constructor(endpoint: string, context?: Record<string, unknown>);
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Rate limit error (429)
|
|
49
|
+
*/
|
|
50
|
+
export declare class RateLimitError extends HttpError {
|
|
51
|
+
readonly retryAfter?: number;
|
|
52
|
+
constructor(endpoint: string, retryAfter?: number, context?: Record<string, unknown>);
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Validation error (400)
|
|
56
|
+
*/
|
|
57
|
+
export declare class ValidationError extends HttpError {
|
|
58
|
+
constructor(endpoint: string, message: string, context?: Record<string, unknown>);
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Server error (5xx)
|
|
62
|
+
*/
|
|
63
|
+
export declare class ServerError extends HttpError {
|
|
64
|
+
constructor(statusCode: number, endpoint: string, message?: string, context?: Record<string, unknown>);
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Request timeout error
|
|
68
|
+
*/
|
|
69
|
+
export declare class TimeoutError extends FactorialError {
|
|
70
|
+
readonly timeoutMs: number;
|
|
71
|
+
constructor(timeoutMs: number, endpoint?: string);
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Network error (connection issues)
|
|
75
|
+
*/
|
|
76
|
+
export declare class NetworkError extends FactorialError {
|
|
77
|
+
constructor(message: string, cause?: Error);
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Configuration error
|
|
81
|
+
*/
|
|
82
|
+
export declare class ConfigurationError extends FactorialError {
|
|
83
|
+
constructor(message: string);
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Schema validation error (response doesn't match expected format)
|
|
87
|
+
*/
|
|
88
|
+
export declare class SchemaValidationError extends FactorialError {
|
|
89
|
+
readonly schemaName: string;
|
|
90
|
+
constructor(schemaName: string, message: string, context?: Record<string, unknown>);
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Determine if an error is retryable
|
|
94
|
+
*/
|
|
95
|
+
export declare function isRetryableError(error: unknown): boolean;
|
|
96
|
+
/**
|
|
97
|
+
* Get a user-friendly error message from any error
|
|
98
|
+
*/
|
|
99
|
+
export declare function getUserMessage(error: unknown): string;
|
|
100
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;GAEG;AACH,qBAAa,cAAe,SAAQ,KAAK;IACvC,SAAgB,WAAW,EAAE,OAAO,CAAC;IACrC,SAAgB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;gBAGhD,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE;QACR,WAAW,CAAC,EAAE,OAAO,CAAC;QACtB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QAClC,KAAK,CAAC,EAAE,KAAK,CAAC;KACf;CAUJ;AAED;;GAEG;AACH,qBAAa,SAAU,SAAQ,cAAc;IAC3C,SAAgB,UAAU,EAAE,MAAM,CAAC;IACnC,SAAgB,QAAQ,EAAE,MAAM,CAAC;gBAG/B,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE;QACR,WAAW,CAAC,EAAE,OAAO,CAAC;QACtB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;KACnC;CAOJ;AAED;;GAEG;AACH,qBAAa,mBAAoB,SAAQ,SAAS;gBACpC,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;CAOhE;AAED;;GAEG;AACH,qBAAa,kBAAmB,SAAQ,SAAS;gBACnC,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;CAYhE;AAED;;GAEG;AACH,qBAAa,aAAc,SAAQ,SAAS;gBAC9B,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;CAYhE;AAED;;GAEG;AACH,qBAAa,cAAe,SAAQ,SAAS;IAC3C,SAAgB,UAAU,CAAC,EAAE,MAAM,CAAC;gBAExB,QAAQ,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;CAYrF;AAED;;GAEG;AACH,qBAAa,eAAgB,SAAQ,SAAS;gBAChC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;CAOjF;AAED;;GAEG;AACH,qBAAa,WAAY,SAAQ,SAAS;gBAEtC,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;CAapC;AAED;;GAEG;AACH,qBAAa,YAAa,SAAQ,cAAc;IAC9C,SAAgB,SAAS,EAAE,MAAM,CAAC;gBAEtB,SAAS,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM;CAQjD;AAED;;GAEG;AACH,qBAAa,YAAa,SAAQ,cAAc;gBAClC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,KAAK;CAO3C;AAED;;GAEG;AACH,qBAAa,kBAAmB,SAAQ,cAAc;gBACxC,OAAO,EAAE,MAAM;CAI5B;AAED;;GAEG;AACH,qBAAa,qBAAsB,SAAQ,cAAc;IACvD,SAAgB,UAAU,EAAE,MAAM,CAAC;gBAEvB,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;CAQnF;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CASxD;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAQrD"}
|
package/dist/errors.js
ADDED
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Structured error types for MCP FactorialHR
|
|
3
|
+
*
|
|
4
|
+
* Provides a clear error hierarchy for better error handling and user messages.
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Base error class for all Factorial-related errors
|
|
8
|
+
*/
|
|
9
|
+
export class FactorialError extends Error {
|
|
10
|
+
isRetryable;
|
|
11
|
+
context;
|
|
12
|
+
constructor(message, options) {
|
|
13
|
+
super(message);
|
|
14
|
+
this.name = 'FactorialError';
|
|
15
|
+
this.isRetryable = options?.isRetryable ?? false;
|
|
16
|
+
this.context = options?.context;
|
|
17
|
+
if (options?.cause) {
|
|
18
|
+
this.cause = options.cause;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* HTTP-related errors with status code
|
|
24
|
+
*/
|
|
25
|
+
export class HttpError extends FactorialError {
|
|
26
|
+
statusCode;
|
|
27
|
+
endpoint;
|
|
28
|
+
constructor(statusCode, endpoint, message, options) {
|
|
29
|
+
super(message, options);
|
|
30
|
+
this.name = 'HttpError';
|
|
31
|
+
this.statusCode = statusCode;
|
|
32
|
+
this.endpoint = endpoint;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Authentication error (401)
|
|
37
|
+
*/
|
|
38
|
+
export class AuthenticationError extends HttpError {
|
|
39
|
+
constructor(endpoint, context) {
|
|
40
|
+
super(401, endpoint, 'Invalid API key. Please check your FACTORIAL_API_KEY.', {
|
|
41
|
+
isRetryable: false,
|
|
42
|
+
context,
|
|
43
|
+
});
|
|
44
|
+
this.name = 'AuthenticationError';
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Authorization error (403)
|
|
49
|
+
*/
|
|
50
|
+
export class AuthorizationError extends HttpError {
|
|
51
|
+
constructor(endpoint, context) {
|
|
52
|
+
super(403, endpoint, 'Access denied. Your API key may not have permission for this operation.', {
|
|
53
|
+
isRetryable: false,
|
|
54
|
+
context,
|
|
55
|
+
});
|
|
56
|
+
this.name = 'AuthorizationError';
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Resource not found error (404)
|
|
61
|
+
*/
|
|
62
|
+
export class NotFoundError extends HttpError {
|
|
63
|
+
constructor(endpoint, context) {
|
|
64
|
+
super(404, endpoint, 'Resource not found. The requested employee, team, or location may not exist.', {
|
|
65
|
+
isRetryable: false,
|
|
66
|
+
context,
|
|
67
|
+
});
|
|
68
|
+
this.name = 'NotFoundError';
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Rate limit error (429)
|
|
73
|
+
*/
|
|
74
|
+
export class RateLimitError extends HttpError {
|
|
75
|
+
retryAfter;
|
|
76
|
+
constructor(endpoint, retryAfter, context) {
|
|
77
|
+
const message = retryAfter
|
|
78
|
+
? `Rate limit exceeded. Please wait ${retryAfter} seconds before trying again.`
|
|
79
|
+
: 'Rate limit exceeded. Please wait a moment before trying again.';
|
|
80
|
+
super(429, endpoint, message, {
|
|
81
|
+
isRetryable: true,
|
|
82
|
+
context,
|
|
83
|
+
});
|
|
84
|
+
this.name = 'RateLimitError';
|
|
85
|
+
this.retryAfter = retryAfter;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Validation error (400)
|
|
90
|
+
*/
|
|
91
|
+
export class ValidationError extends HttpError {
|
|
92
|
+
constructor(endpoint, message, context) {
|
|
93
|
+
super(400, endpoint, message, {
|
|
94
|
+
isRetryable: false,
|
|
95
|
+
context,
|
|
96
|
+
});
|
|
97
|
+
this.name = 'ValidationError';
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Server error (5xx)
|
|
102
|
+
*/
|
|
103
|
+
export class ServerError extends HttpError {
|
|
104
|
+
constructor(statusCode, endpoint, message, context) {
|
|
105
|
+
super(statusCode, endpoint, message || `Server error (${statusCode}). Please try again later.`, {
|
|
106
|
+
isRetryable: true,
|
|
107
|
+
context,
|
|
108
|
+
});
|
|
109
|
+
this.name = 'ServerError';
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Request timeout error
|
|
114
|
+
*/
|
|
115
|
+
export class TimeoutError extends FactorialError {
|
|
116
|
+
timeoutMs;
|
|
117
|
+
constructor(timeoutMs, endpoint) {
|
|
118
|
+
super(`Request timed out after ${timeoutMs / 1000} seconds. Please try again.`, {
|
|
119
|
+
isRetryable: true,
|
|
120
|
+
context: { endpoint, timeoutMs },
|
|
121
|
+
});
|
|
122
|
+
this.name = 'TimeoutError';
|
|
123
|
+
this.timeoutMs = timeoutMs;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Network error (connection issues)
|
|
128
|
+
*/
|
|
129
|
+
export class NetworkError extends FactorialError {
|
|
130
|
+
constructor(message, cause) {
|
|
131
|
+
super(message, {
|
|
132
|
+
isRetryable: true,
|
|
133
|
+
cause,
|
|
134
|
+
});
|
|
135
|
+
this.name = 'NetworkError';
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Configuration error
|
|
140
|
+
*/
|
|
141
|
+
export class ConfigurationError extends FactorialError {
|
|
142
|
+
constructor(message) {
|
|
143
|
+
super(message, { isRetryable: false });
|
|
144
|
+
this.name = 'ConfigurationError';
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Schema validation error (response doesn't match expected format)
|
|
149
|
+
*/
|
|
150
|
+
export class SchemaValidationError extends FactorialError {
|
|
151
|
+
schemaName;
|
|
152
|
+
constructor(schemaName, message, context) {
|
|
153
|
+
super(`API response validation failed for ${schemaName}: ${message}`, {
|
|
154
|
+
isRetryable: false,
|
|
155
|
+
context,
|
|
156
|
+
});
|
|
157
|
+
this.name = 'SchemaValidationError';
|
|
158
|
+
this.schemaName = schemaName;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Determine if an error is retryable
|
|
163
|
+
*/
|
|
164
|
+
export function isRetryableError(error) {
|
|
165
|
+
if (error instanceof FactorialError) {
|
|
166
|
+
return error.isRetryable;
|
|
167
|
+
}
|
|
168
|
+
// Network errors are generally retryable
|
|
169
|
+
if (error instanceof Error && error.name === 'AbortError') {
|
|
170
|
+
return true;
|
|
171
|
+
}
|
|
172
|
+
return false;
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Get a user-friendly error message from any error
|
|
176
|
+
*/
|
|
177
|
+
export function getUserMessage(error) {
|
|
178
|
+
if (error instanceof FactorialError) {
|
|
179
|
+
return error.message;
|
|
180
|
+
}
|
|
181
|
+
if (error instanceof Error) {
|
|
182
|
+
return error.message;
|
|
183
|
+
}
|
|
184
|
+
return 'An unexpected error occurred';
|
|
185
|
+
}
|
|
186
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"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"}
|