@leanmcp/core 0.4.5 → 0.4.7
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/chunk-GTCGBX2K.mjs +279 -0
- package/dist/dynamodb-session-store-G7V5ZRR6.mjs +10 -0
- package/dist/index.d.mts +23 -7
- package/dist/index.d.ts +23 -7
- package/dist/index.js +297 -46
- package/dist/index.mjs +285 -44
- package/package.json +5 -2
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
3
|
+
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
4
|
+
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
5
|
+
}) : x)(function(x) {
|
|
6
|
+
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
7
|
+
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
// src/dynamodb-session-store.ts
|
|
11
|
+
import { DynamoDBClient } from "@aws-sdk/client-dynamodb";
|
|
12
|
+
import { DynamoDBDocumentClient, GetCommand, PutCommand, DeleteCommand, UpdateCommand } from "@aws-sdk/lib-dynamodb";
|
|
13
|
+
|
|
14
|
+
// src/logger.ts
|
|
15
|
+
var LogLevel = /* @__PURE__ */ (function(LogLevel2) {
|
|
16
|
+
LogLevel2[LogLevel2["DEBUG"] = 0] = "DEBUG";
|
|
17
|
+
LogLevel2[LogLevel2["INFO"] = 1] = "INFO";
|
|
18
|
+
LogLevel2[LogLevel2["WARN"] = 2] = "WARN";
|
|
19
|
+
LogLevel2[LogLevel2["ERROR"] = 3] = "ERROR";
|
|
20
|
+
LogLevel2[LogLevel2["NONE"] = 4] = "NONE";
|
|
21
|
+
return LogLevel2;
|
|
22
|
+
})({});
|
|
23
|
+
var COLORS = {
|
|
24
|
+
reset: "\x1B[0m",
|
|
25
|
+
gray: "\x1B[38;5;244m",
|
|
26
|
+
blue: "\x1B[1;34m",
|
|
27
|
+
amber: "\x1B[38;5;214m",
|
|
28
|
+
red: "\x1B[1;31m"
|
|
29
|
+
};
|
|
30
|
+
var levelStyles = {
|
|
31
|
+
[0]: {
|
|
32
|
+
label: "DEBUG",
|
|
33
|
+
color: COLORS.gray
|
|
34
|
+
},
|
|
35
|
+
[1]: {
|
|
36
|
+
label: "INFO",
|
|
37
|
+
color: COLORS.blue
|
|
38
|
+
},
|
|
39
|
+
[2]: {
|
|
40
|
+
label: "WARN",
|
|
41
|
+
color: COLORS.amber
|
|
42
|
+
},
|
|
43
|
+
[3]: {
|
|
44
|
+
label: "ERROR",
|
|
45
|
+
color: COLORS.red
|
|
46
|
+
},
|
|
47
|
+
[4]: {
|
|
48
|
+
label: "NONE",
|
|
49
|
+
color: COLORS.gray
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
var Logger = class {
|
|
53
|
+
static {
|
|
54
|
+
__name(this, "Logger");
|
|
55
|
+
}
|
|
56
|
+
level;
|
|
57
|
+
prefix;
|
|
58
|
+
timestamps;
|
|
59
|
+
colorize;
|
|
60
|
+
context;
|
|
61
|
+
handlers;
|
|
62
|
+
constructor(options = {}) {
|
|
63
|
+
this.level = options.level ?? 1;
|
|
64
|
+
this.prefix = options.prefix ?? "";
|
|
65
|
+
this.timestamps = options.timestamps ?? true;
|
|
66
|
+
this.colorize = options.colorize ?? true;
|
|
67
|
+
this.context = options.context;
|
|
68
|
+
this.handlers = options.handlers ?? [];
|
|
69
|
+
}
|
|
70
|
+
format(level, message) {
|
|
71
|
+
const style = levelStyles[level];
|
|
72
|
+
const timestamp = this.timestamps ? `[${(/* @__PURE__ */ new Date()).toISOString()}]` : "";
|
|
73
|
+
const prefix = this.prefix ? `[${this.prefix}]` : "";
|
|
74
|
+
const context = this.context ? `[${this.context}]` : "";
|
|
75
|
+
const label = `[${style.label}]`;
|
|
76
|
+
const parts = `${timestamp}${prefix}${context}${label} ${message}`;
|
|
77
|
+
if (!this.colorize) return parts;
|
|
78
|
+
return `${style.color}${parts}${COLORS.reset}`;
|
|
79
|
+
}
|
|
80
|
+
shouldLog(level) {
|
|
81
|
+
return level >= this.level && this.level !== 4;
|
|
82
|
+
}
|
|
83
|
+
emit(level, message, consoleFn, ...args) {
|
|
84
|
+
if (!this.shouldLog(level)) return;
|
|
85
|
+
const payload = {
|
|
86
|
+
level,
|
|
87
|
+
levelLabel: levelStyles[level].label,
|
|
88
|
+
message,
|
|
89
|
+
args,
|
|
90
|
+
prefix: this.prefix,
|
|
91
|
+
context: this.context,
|
|
92
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
93
|
+
};
|
|
94
|
+
consoleFn(this.format(level, message), ...args);
|
|
95
|
+
this.handlers.forEach((handler) => {
|
|
96
|
+
try {
|
|
97
|
+
handler(payload);
|
|
98
|
+
} catch (err) {
|
|
99
|
+
console.debug("Logger handler error", err);
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
debug(message, ...args) {
|
|
104
|
+
this.emit(0, message, console.debug, ...args);
|
|
105
|
+
}
|
|
106
|
+
info(message, ...args) {
|
|
107
|
+
this.emit(1, message, console.info, ...args);
|
|
108
|
+
}
|
|
109
|
+
warn(message, ...args) {
|
|
110
|
+
this.emit(2, message, console.warn, ...args);
|
|
111
|
+
}
|
|
112
|
+
error(message, ...args) {
|
|
113
|
+
this.emit(3, message, console.error, ...args);
|
|
114
|
+
}
|
|
115
|
+
setLevel(level) {
|
|
116
|
+
this.level = level;
|
|
117
|
+
}
|
|
118
|
+
getLevel() {
|
|
119
|
+
return this.level;
|
|
120
|
+
}
|
|
121
|
+
};
|
|
122
|
+
var defaultLogger = new Logger({
|
|
123
|
+
level: 1,
|
|
124
|
+
prefix: "LeanMCP"
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
// src/dynamodb-session-store.ts
|
|
128
|
+
var DEFAULT_TABLE_NAME = "leanmcp-sessions";
|
|
129
|
+
var DEFAULT_TTL_SECONDS = 86400;
|
|
130
|
+
var DynamoDBSessionStore = class {
|
|
131
|
+
static {
|
|
132
|
+
__name(this, "DynamoDBSessionStore");
|
|
133
|
+
}
|
|
134
|
+
client;
|
|
135
|
+
tableName;
|
|
136
|
+
ttlSeconds;
|
|
137
|
+
logger;
|
|
138
|
+
constructor(options) {
|
|
139
|
+
this.tableName = options?.tableName || process.env.DYNAMODB_TABLE_NAME || DEFAULT_TABLE_NAME;
|
|
140
|
+
this.ttlSeconds = options?.ttlSeconds || DEFAULT_TTL_SECONDS;
|
|
141
|
+
this.logger = new Logger({
|
|
142
|
+
level: options?.logging ? LogLevel.INFO : LogLevel.NONE,
|
|
143
|
+
prefix: "DynamoDBSessionStore"
|
|
144
|
+
});
|
|
145
|
+
const dynamoClient = new DynamoDBClient({
|
|
146
|
+
region: options?.region || process.env.AWS_REGION || "us-east-1"
|
|
147
|
+
});
|
|
148
|
+
this.client = DynamoDBDocumentClient.from(dynamoClient);
|
|
149
|
+
this.logger.info(`Initialized with table: ${this.tableName}, TTL: ${this.ttlSeconds}s`);
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Check if a session exists in DynamoDB
|
|
153
|
+
*/
|
|
154
|
+
async sessionExists(sessionId) {
|
|
155
|
+
try {
|
|
156
|
+
const result = await this.client.send(new GetCommand({
|
|
157
|
+
TableName: this.tableName,
|
|
158
|
+
Key: {
|
|
159
|
+
sessionId
|
|
160
|
+
},
|
|
161
|
+
ProjectionExpression: "sessionId"
|
|
162
|
+
}));
|
|
163
|
+
const exists = !!result.Item;
|
|
164
|
+
this.logger.debug(`Session ${sessionId} exists: ${exists}`);
|
|
165
|
+
return exists;
|
|
166
|
+
} catch (error) {
|
|
167
|
+
this.logger.error(`Error checking session existence: ${error.message}`);
|
|
168
|
+
return false;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Create a new session in DynamoDB
|
|
173
|
+
*/
|
|
174
|
+
async createSession(sessionId, data) {
|
|
175
|
+
try {
|
|
176
|
+
const now = /* @__PURE__ */ new Date();
|
|
177
|
+
const ttl = Math.floor(Date.now() / 1e3) + this.ttlSeconds;
|
|
178
|
+
await this.client.send(new PutCommand({
|
|
179
|
+
TableName: this.tableName,
|
|
180
|
+
Item: {
|
|
181
|
+
sessionId,
|
|
182
|
+
createdAt: now.toISOString(),
|
|
183
|
+
updatedAt: now.toISOString(),
|
|
184
|
+
ttl,
|
|
185
|
+
data: data || {}
|
|
186
|
+
}
|
|
187
|
+
}));
|
|
188
|
+
this.logger.info(`Created session: ${sessionId} (TTL: ${new Date(ttl * 1e3).toISOString()})`);
|
|
189
|
+
} catch (error) {
|
|
190
|
+
this.logger.error(`Error creating session ${sessionId}: ${error.message}`);
|
|
191
|
+
throw new Error(`Failed to create session: ${error.message}`);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Get session data from DynamoDB
|
|
196
|
+
*/
|
|
197
|
+
async getSession(sessionId) {
|
|
198
|
+
try {
|
|
199
|
+
const result = await this.client.send(new GetCommand({
|
|
200
|
+
TableName: this.tableName,
|
|
201
|
+
Key: {
|
|
202
|
+
sessionId
|
|
203
|
+
}
|
|
204
|
+
}));
|
|
205
|
+
if (!result.Item) {
|
|
206
|
+
this.logger.debug(`Session ${sessionId} not found`);
|
|
207
|
+
return null;
|
|
208
|
+
}
|
|
209
|
+
const sessionData = {
|
|
210
|
+
sessionId: result.Item.sessionId,
|
|
211
|
+
createdAt: new Date(result.Item.createdAt),
|
|
212
|
+
updatedAt: new Date(result.Item.updatedAt),
|
|
213
|
+
ttl: result.Item.ttl,
|
|
214
|
+
data: result.Item.data
|
|
215
|
+
};
|
|
216
|
+
this.logger.debug(`Retrieved session: ${sessionId}`);
|
|
217
|
+
return sessionData;
|
|
218
|
+
} catch (error) {
|
|
219
|
+
this.logger.error(`Error getting session ${sessionId}: ${error.message}`);
|
|
220
|
+
return null;
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
/**
|
|
224
|
+
* Update session data in DynamoDB
|
|
225
|
+
* Automatically refreshes TTL on each update
|
|
226
|
+
*/
|
|
227
|
+
async updateSession(sessionId, updates) {
|
|
228
|
+
try {
|
|
229
|
+
const ttl = Math.floor(Date.now() / 1e3) + this.ttlSeconds;
|
|
230
|
+
await this.client.send(new UpdateCommand({
|
|
231
|
+
TableName: this.tableName,
|
|
232
|
+
Key: {
|
|
233
|
+
sessionId
|
|
234
|
+
},
|
|
235
|
+
UpdateExpression: "SET updatedAt = :now, #data = :data, #ttl = :ttl",
|
|
236
|
+
ExpressionAttributeNames: {
|
|
237
|
+
"#data": "data",
|
|
238
|
+
"#ttl": "ttl"
|
|
239
|
+
},
|
|
240
|
+
ExpressionAttributeValues: {
|
|
241
|
+
":now": (/* @__PURE__ */ new Date()).toISOString(),
|
|
242
|
+
":data": updates.data || {},
|
|
243
|
+
":ttl": ttl
|
|
244
|
+
}
|
|
245
|
+
}));
|
|
246
|
+
this.logger.debug(`Updated session: ${sessionId}`);
|
|
247
|
+
} catch (error) {
|
|
248
|
+
this.logger.error(`Error updating session ${sessionId}: ${error.message}`);
|
|
249
|
+
throw new Error(`Failed to update session: ${error.message}`);
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
/**
|
|
253
|
+
* Delete a session from DynamoDB
|
|
254
|
+
*/
|
|
255
|
+
async deleteSession(sessionId) {
|
|
256
|
+
try {
|
|
257
|
+
await this.client.send(new DeleteCommand({
|
|
258
|
+
TableName: this.tableName,
|
|
259
|
+
Key: {
|
|
260
|
+
sessionId
|
|
261
|
+
}
|
|
262
|
+
}));
|
|
263
|
+
this.logger.info(`Deleted session: ${sessionId}`);
|
|
264
|
+
} catch (error) {
|
|
265
|
+
this.logger.error(`Error deleting session ${sessionId}: ${error.message}`);
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
};
|
|
269
|
+
|
|
270
|
+
export {
|
|
271
|
+
__name,
|
|
272
|
+
__require,
|
|
273
|
+
LogLevel,
|
|
274
|
+
Logger,
|
|
275
|
+
defaultLogger,
|
|
276
|
+
DEFAULT_TABLE_NAME,
|
|
277
|
+
DEFAULT_TTL_SECONDS,
|
|
278
|
+
DynamoDBSessionStore
|
|
279
|
+
};
|
package/dist/index.d.mts
CHANGED
|
@@ -382,15 +382,31 @@ declare function SchemaConstraint(constraints: {
|
|
|
382
382
|
enum?: any[];
|
|
383
383
|
description?: string;
|
|
384
384
|
default?: any;
|
|
385
|
-
|
|
386
|
-
type: string;
|
|
387
|
-
description?: string;
|
|
388
|
-
};
|
|
385
|
+
type?: string;
|
|
389
386
|
}): PropertyDecorator;
|
|
390
387
|
/**
|
|
391
|
-
* Enhanced schema generator that includes constraints
|
|
388
|
+
* Enhanced schema generator that includes constraints.
|
|
389
|
+
* Uses pre-computed metadata (from leanmcp build) when available for fast startup.
|
|
390
|
+
* Falls back to ts-morph parsing in dev mode.
|
|
391
|
+
*/
|
|
392
|
+
declare function classToJsonSchemaWithConstraints(classConstructor: new () => any, sourceFilePath?: string): any;
|
|
393
|
+
|
|
394
|
+
/**
|
|
395
|
+
* Register the source file path for an input class.
|
|
396
|
+
* This is called during decorator execution to capture the source location.
|
|
397
|
+
*/
|
|
398
|
+
declare function registerClassSource(className: string, sourceFile: string): void;
|
|
399
|
+
/**
|
|
400
|
+
* Parse a TypeScript class and extract JSON Schema types for each property.
|
|
401
|
+
* Automatically detects array types like `string[]` and adds proper `items`.
|
|
402
|
+
*
|
|
403
|
+
* This is now SYNCHRONOUS for easier integration with existing code.
|
|
404
|
+
*/
|
|
405
|
+
declare function parseClassTypesSync(classConstructor: new () => any, sourceFilePath?: string): Map<string, any>;
|
|
406
|
+
/**
|
|
407
|
+
* Clear the type cache (useful for hot reloading)
|
|
392
408
|
*/
|
|
393
|
-
declare function
|
|
409
|
+
declare function clearTypeCache(): void;
|
|
394
410
|
|
|
395
411
|
/**
|
|
396
412
|
* Input validation utilities for LeanMCP
|
|
@@ -969,4 +985,4 @@ declare class MCPServerRuntime {
|
|
|
969
985
|
*/
|
|
970
986
|
declare function startMCPServer(options: MCPServerOptions): Promise<MCPServerRuntime>;
|
|
971
987
|
|
|
972
|
-
export { Auth, type AuthErrorOptions, type AuthErrorResult, type AuthOptions, DEFAULT_TABLE_NAME, DEFAULT_TTL_SECONDS, Deprecated, DynamoDBSessionStore, type HTTPServerAuthOptions, type HTTPServerInput, type HTTPServerOptions, type ISessionStore, InMemorySessionStore, LeanMCPSessionProvider, type LeanMCPSessionProviderOptions, LogLevel, type LogPayload, Logger, type LoggerHandler, type LoggerOptions, MCPServer, type MCPServerConstructorOptions, type MCPServerFactory, type MCPServerOptions, MCPServerRuntime, Optional, Prompt, type PromptOptions, type ProtectedResourceMetadata, Render, Resource, type ResourceOptions, SchemaConstraint, type SecurityScheme, type SessionData, Tool, type ToolOptions, UI, UserEnvs, classToJsonSchema, classToJsonSchemaWithConstraints, createAuthError, createHTTPServer, createProtectedResourceMetadata, defaultLogger, extractBearerToken, getDecoratedMethods, getMethodMetadata, isAuthError, startMCPServer, validateNonEmpty, validatePath, validatePort, validateServiceName, validateUrl };
|
|
988
|
+
export { Auth, type AuthErrorOptions, type AuthErrorResult, type AuthOptions, DEFAULT_TABLE_NAME, DEFAULT_TTL_SECONDS, Deprecated, DynamoDBSessionStore, type HTTPServerAuthOptions, type HTTPServerInput, type HTTPServerOptions, type ISessionStore, InMemorySessionStore, LeanMCPSessionProvider, type LeanMCPSessionProviderOptions, LogLevel, type LogPayload, Logger, type LoggerHandler, type LoggerOptions, MCPServer, type MCPServerConstructorOptions, type MCPServerFactory, type MCPServerOptions, MCPServerRuntime, Optional, Prompt, type PromptOptions, type ProtectedResourceMetadata, Render, Resource, type ResourceOptions, SchemaConstraint, type SecurityScheme, type SessionData, Tool, type ToolOptions, UI, UserEnvs, classToJsonSchema, classToJsonSchemaWithConstraints, clearTypeCache, createAuthError, createHTTPServer, createProtectedResourceMetadata, defaultLogger, extractBearerToken, getDecoratedMethods, getMethodMetadata, isAuthError, parseClassTypesSync, registerClassSource, startMCPServer, validateNonEmpty, validatePath, validatePort, validateServiceName, validateUrl };
|
package/dist/index.d.ts
CHANGED
|
@@ -382,15 +382,31 @@ declare function SchemaConstraint(constraints: {
|
|
|
382
382
|
enum?: any[];
|
|
383
383
|
description?: string;
|
|
384
384
|
default?: any;
|
|
385
|
-
|
|
386
|
-
type: string;
|
|
387
|
-
description?: string;
|
|
388
|
-
};
|
|
385
|
+
type?: string;
|
|
389
386
|
}): PropertyDecorator;
|
|
390
387
|
/**
|
|
391
|
-
* Enhanced schema generator that includes constraints
|
|
388
|
+
* Enhanced schema generator that includes constraints.
|
|
389
|
+
* Uses pre-computed metadata (from leanmcp build) when available for fast startup.
|
|
390
|
+
* Falls back to ts-morph parsing in dev mode.
|
|
391
|
+
*/
|
|
392
|
+
declare function classToJsonSchemaWithConstraints(classConstructor: new () => any, sourceFilePath?: string): any;
|
|
393
|
+
|
|
394
|
+
/**
|
|
395
|
+
* Register the source file path for an input class.
|
|
396
|
+
* This is called during decorator execution to capture the source location.
|
|
397
|
+
*/
|
|
398
|
+
declare function registerClassSource(className: string, sourceFile: string): void;
|
|
399
|
+
/**
|
|
400
|
+
* Parse a TypeScript class and extract JSON Schema types for each property.
|
|
401
|
+
* Automatically detects array types like `string[]` and adds proper `items`.
|
|
402
|
+
*
|
|
403
|
+
* This is now SYNCHRONOUS for easier integration with existing code.
|
|
404
|
+
*/
|
|
405
|
+
declare function parseClassTypesSync(classConstructor: new () => any, sourceFilePath?: string): Map<string, any>;
|
|
406
|
+
/**
|
|
407
|
+
* Clear the type cache (useful for hot reloading)
|
|
392
408
|
*/
|
|
393
|
-
declare function
|
|
409
|
+
declare function clearTypeCache(): void;
|
|
394
410
|
|
|
395
411
|
/**
|
|
396
412
|
* Input validation utilities for LeanMCP
|
|
@@ -969,4 +985,4 @@ declare class MCPServerRuntime {
|
|
|
969
985
|
*/
|
|
970
986
|
declare function startMCPServer(options: MCPServerOptions): Promise<MCPServerRuntime>;
|
|
971
987
|
|
|
972
|
-
export { Auth, type AuthErrorOptions, type AuthErrorResult, type AuthOptions, DEFAULT_TABLE_NAME, DEFAULT_TTL_SECONDS, Deprecated, DynamoDBSessionStore, type HTTPServerAuthOptions, type HTTPServerInput, type HTTPServerOptions, type ISessionStore, InMemorySessionStore, LeanMCPSessionProvider, type LeanMCPSessionProviderOptions, LogLevel, type LogPayload, Logger, type LoggerHandler, type LoggerOptions, MCPServer, type MCPServerConstructorOptions, type MCPServerFactory, type MCPServerOptions, MCPServerRuntime, Optional, Prompt, type PromptOptions, type ProtectedResourceMetadata, Render, Resource, type ResourceOptions, SchemaConstraint, type SecurityScheme, type SessionData, Tool, type ToolOptions, UI, UserEnvs, classToJsonSchema, classToJsonSchemaWithConstraints, createAuthError, createHTTPServer, createProtectedResourceMetadata, defaultLogger, extractBearerToken, getDecoratedMethods, getMethodMetadata, isAuthError, startMCPServer, validateNonEmpty, validatePath, validatePort, validateServiceName, validateUrl };
|
|
988
|
+
export { Auth, type AuthErrorOptions, type AuthErrorResult, type AuthOptions, DEFAULT_TABLE_NAME, DEFAULT_TTL_SECONDS, Deprecated, DynamoDBSessionStore, type HTTPServerAuthOptions, type HTTPServerInput, type HTTPServerOptions, type ISessionStore, InMemorySessionStore, LeanMCPSessionProvider, type LeanMCPSessionProviderOptions, LogLevel, type LogPayload, Logger, type LoggerHandler, type LoggerOptions, MCPServer, type MCPServerConstructorOptions, type MCPServerFactory, type MCPServerOptions, MCPServerRuntime, Optional, Prompt, type PromptOptions, type ProtectedResourceMetadata, Render, Resource, type ResourceOptions, SchemaConstraint, type SecurityScheme, type SessionData, Tool, type ToolOptions, UI, UserEnvs, classToJsonSchema, classToJsonSchemaWithConstraints, clearTypeCache, createAuthError, createHTTPServer, createProtectedResourceMetadata, defaultLogger, extractBearerToken, getDecoratedMethods, getMethodMetadata, isAuthError, parseClassTypesSync, registerClassSource, startMCPServer, validateNonEmpty, validatePath, validatePort, validateServiceName, validateUrl };
|