alepha 0.13.8 → 0.14.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.
Files changed (112) hide show
  1. package/dist/api/audits/index.d.ts +2 -1
  2. package/dist/api/audits/index.d.ts.map +1 -0
  3. package/dist/api/files/index.d.ts +2 -1
  4. package/dist/api/files/index.d.ts.map +1 -0
  5. package/dist/api/jobs/index.d.ts +158 -157
  6. package/dist/api/jobs/index.d.ts.map +1 -0
  7. package/dist/api/notifications/index.d.ts.map +1 -0
  8. package/dist/api/parameters/index.d.ts +4 -4
  9. package/dist/api/parameters/index.d.ts.map +1 -0
  10. package/dist/api/users/index.d.ts +132 -131
  11. package/dist/api/users/index.d.ts.map +1 -0
  12. package/dist/api/verifications/index.d.ts.map +1 -0
  13. package/dist/batch/index.d.ts.map +1 -0
  14. package/dist/bucket/index.d.ts.map +1 -0
  15. package/dist/cache/core/index.d.ts.map +1 -0
  16. package/dist/cache/redis/index.d.ts.map +1 -0
  17. package/dist/cli/index.d.ts +44 -32
  18. package/dist/cli/index.d.ts.map +1 -0
  19. package/dist/cli/index.js +380 -109
  20. package/dist/cli/index.js.map +1 -1
  21. package/dist/command/index.d.ts +11 -1
  22. package/dist/command/index.d.ts.map +1 -0
  23. package/dist/command/index.js +45 -6
  24. package/dist/command/index.js.map +1 -1
  25. package/dist/core/index.browser.js +1334 -1318
  26. package/dist/core/index.browser.js.map +1 -1
  27. package/dist/core/index.d.ts +75 -71
  28. package/dist/core/index.d.ts.map +1 -0
  29. package/dist/core/index.js +1337 -1321
  30. package/dist/core/index.js.map +1 -1
  31. package/dist/core/index.native.js +1337 -1321
  32. package/dist/core/index.native.js.map +1 -1
  33. package/dist/datetime/index.d.ts.map +1 -0
  34. package/dist/email/index.d.ts.map +1 -0
  35. package/dist/fake/index.d.ts.map +1 -0
  36. package/dist/file/index.d.ts.map +1 -0
  37. package/dist/lock/core/index.d.ts.map +1 -0
  38. package/dist/lock/redis/index.d.ts.map +1 -0
  39. package/dist/logger/index.d.ts +1 -0
  40. package/dist/logger/index.d.ts.map +1 -0
  41. package/dist/mcp/index.d.ts +820 -0
  42. package/dist/mcp/index.d.ts.map +1 -0
  43. package/dist/mcp/index.js +978 -0
  44. package/dist/mcp/index.js.map +1 -0
  45. package/dist/orm/index.d.ts +180 -107
  46. package/dist/orm/index.d.ts.map +1 -0
  47. package/dist/orm/index.js +260 -174
  48. package/dist/orm/index.js.map +1 -1
  49. package/dist/queue/core/index.d.ts +4 -4
  50. package/dist/queue/core/index.d.ts.map +1 -0
  51. package/dist/queue/redis/index.d.ts.map +1 -0
  52. package/dist/redis/index.d.ts.map +1 -0
  53. package/dist/retry/index.d.ts.map +1 -0
  54. package/dist/router/index.d.ts.map +1 -0
  55. package/dist/scheduler/index.d.ts.map +1 -0
  56. package/dist/security/index.d.ts.map +1 -0
  57. package/dist/server/auth/index.d.ts +155 -155
  58. package/dist/server/auth/index.d.ts.map +1 -0
  59. package/dist/server/cache/index.d.ts.map +1 -0
  60. package/dist/server/compress/index.d.ts.map +1 -0
  61. package/dist/server/cookies/index.d.ts.map +1 -0
  62. package/dist/server/core/index.d.ts.map +1 -0
  63. package/dist/server/cors/index.d.ts.map +1 -0
  64. package/dist/server/health/index.d.ts.map +1 -0
  65. package/dist/server/helmet/index.d.ts.map +1 -0
  66. package/dist/server/links/index.d.ts +33 -33
  67. package/dist/server/links/index.d.ts.map +1 -0
  68. package/dist/server/metrics/index.d.ts.map +1 -0
  69. package/dist/server/multipart/index.d.ts.map +1 -0
  70. package/dist/server/proxy/index.d.ts.map +1 -0
  71. package/dist/server/rate-limit/index.d.ts.map +1 -0
  72. package/dist/server/security/index.d.ts +9 -9
  73. package/dist/server/security/index.d.ts.map +1 -0
  74. package/dist/server/static/index.d.ts.map +1 -0
  75. package/dist/server/swagger/index.d.ts.map +1 -0
  76. package/dist/sms/index.d.ts.map +1 -0
  77. package/dist/thread/index.d.ts.map +1 -0
  78. package/dist/topic/core/index.d.ts.map +1 -0
  79. package/dist/topic/redis/index.d.ts.map +1 -0
  80. package/dist/vite/index.d.ts +10 -2
  81. package/dist/vite/index.d.ts.map +1 -0
  82. package/dist/vite/index.js +36 -14
  83. package/dist/vite/index.js.map +1 -1
  84. package/dist/websocket/index.d.ts.map +1 -0
  85. package/package.json +9 -4
  86. package/src/cli/apps/AlephaCli.ts +2 -0
  87. package/src/cli/apps/AlephaPackageBuilderCli.ts +12 -8
  88. package/src/cli/assets/mainTs.ts +9 -10
  89. package/src/cli/commands/ChangelogCommands.ts +389 -0
  90. package/src/cli/commands/DrizzleCommands.ts +204 -4
  91. package/src/cli/commands/ViteCommands.ts +26 -16
  92. package/src/cli/services/AlephaCliUtils.ts +23 -150
  93. package/src/command/providers/CliProvider.ts +76 -5
  94. package/src/core/providers/SchemaValidator.ts +23 -1
  95. package/src/mcp/errors/McpError.ts +72 -0
  96. package/src/mcp/helpers/jsonrpc.ts +163 -0
  97. package/src/mcp/index.ts +132 -0
  98. package/src/mcp/interfaces/McpTypes.ts +248 -0
  99. package/src/mcp/primitives/$prompt.ts +188 -0
  100. package/src/mcp/primitives/$resource.ts +171 -0
  101. package/src/mcp/primitives/$tool.ts +285 -0
  102. package/src/mcp/providers/McpServerProvider.ts +382 -0
  103. package/src/mcp/transports/SseMcpTransport.ts +172 -0
  104. package/src/mcp/transports/StdioMcpTransport.ts +126 -0
  105. package/src/orm/index.ts +12 -0
  106. package/src/orm/providers/drivers/CloudflareD1Provider.ts +164 -0
  107. package/src/orm/providers/drivers/NodeSqliteProvider.ts +3 -1
  108. package/src/vite/plugins/viteAlephaBuild.ts +8 -2
  109. package/src/vite/plugins/viteAlephaDev.ts +6 -2
  110. package/src/vite/tasks/buildServer.ts +1 -1
  111. package/src/vite/tasks/generateCloudflare.ts +43 -15
  112. package/src/vite/tasks/runAlepha.ts +1 -0
@@ -1,4 +1,5 @@
1
1
  import { access, readFile, unlink, writeFile } from "node:fs/promises";
2
+ import { createRequire } from "node:module";
2
3
  import { join } from "node:path";
3
4
  import { $env, $inject, OPTIONS, t } from "alepha";
4
5
  import { $command } from "alepha/command";
@@ -13,8 +14,8 @@ import {
13
14
  generateSitemap,
14
15
  generateVercel,
15
16
  prerenderPages,
16
- type ViteAlephaBuildOptions,
17
17
  } from "alepha/vite";
18
+ import type * as Vite from "vite";
18
19
  import { AlephaCliUtils } from "../services/AlephaCliUtils.ts";
19
20
 
20
21
  export class ViteCommands {
@@ -130,6 +131,7 @@ export class ViteCommands {
130
131
  handler: async ({ flags, args, run, root }) => {
131
132
  // Tell viteAlephaBuild plugin to skip - CLI handles all tasks
132
133
  process.env.ALEPHA_BUILD_MODE = "cli";
134
+ process.env.NODE_ENV = "production";
133
135
 
134
136
  if (await this.utils.hasExpo(root)) {
135
137
  // will coming soon
@@ -156,11 +158,14 @@ export class ViteCommands {
156
158
  alias: "clean dist",
157
159
  });
158
160
 
159
- const viteConfig = await import(join(root, "vite.config.ts"));
160
- const viteAlephaBuildOptions: ViteAlephaBuildOptions =
161
- viteConfig?.default?.plugins.find((it: any) => !!it[OPTIONS])?.[
162
- OPTIONS
163
- ] ?? {};
161
+ const vite: typeof Vite = createRequire(import.meta.url)("vite");
162
+ const config = await vite.resolveConfig({}, "build", "production");
163
+ const alephaPlugin: any = config.plugins.find(
164
+ (it) => it.name === "alepha:build",
165
+ );
166
+ const viteAlephaBuildOptions = alephaPlugin?.[OPTIONS] || {};
167
+
168
+ await this.utils.loadEnvFile(root, [".env", ".env.production"]);
164
169
 
165
170
  const stats = flags.stats ?? viteAlephaBuildOptions.stats ?? false;
166
171
  const hasServer = viteAlephaBuildOptions.serverEntry !== false;
@@ -173,6 +178,12 @@ export class ViteCommands {
173
178
  // No index.html
174
179
  }
175
180
 
181
+ // Extract client options
182
+ const clientOptions =
183
+ typeof viteAlephaBuildOptions.client === "object"
184
+ ? viteAlephaBuildOptions.client
185
+ : {};
186
+
176
187
  // Build client
177
188
  if (hasClient) {
178
189
  await run({
@@ -182,6 +193,7 @@ export class ViteCommands {
182
193
  silent: true,
183
194
  dist: `${distDir}/${clientDir}`,
184
195
  stats,
196
+ precompress: clientOptions.precompress,
185
197
  }),
186
198
  });
187
199
  }
@@ -224,11 +236,7 @@ export class ViteCommands {
224
236
 
225
237
  if (hasClient) {
226
238
  // Generate sitemap
227
- const sitemapBaseUrl =
228
- flags.sitemap ??
229
- (typeof viteAlephaBuildOptions.client === "object"
230
- ? viteAlephaBuildOptions.client.sitemap?.hostname
231
- : undefined);
239
+ const sitemapBaseUrl = flags.sitemap ?? clientOptions.sitemap?.hostname;
232
240
 
233
241
  if (sitemapBaseUrl) {
234
242
  await run({
@@ -246,11 +254,7 @@ export class ViteCommands {
246
254
  }
247
255
 
248
256
  // Pre-render static pages
249
- const shouldPrerender =
250
- flags.prerender ??
251
- (typeof viteAlephaBuildOptions.client === "object"
252
- ? viteAlephaBuildOptions.client.prerender
253
- : false);
257
+ const shouldPrerender = flags.prerender ?? clientOptions.prerender;
254
258
 
255
259
  if (shouldPrerender) {
256
260
  await run({
@@ -259,6 +263,7 @@ export class ViteCommands {
259
263
  await prerenderPages({
260
264
  dist: `${distDir}/${clientDir}`,
261
265
  entry: `${distDir}/index.js`,
266
+ compress: clientOptions.precompress,
262
267
  });
263
268
  },
264
269
  });
@@ -283,11 +288,16 @@ export class ViteCommands {
283
288
  }
284
289
 
285
290
  if (flags.cloudflare || viteAlephaBuildOptions.cloudflare) {
291
+ const config =
292
+ typeof viteAlephaBuildOptions.cloudflare === "boolean"
293
+ ? {}
294
+ : viteAlephaBuildOptions.cloudflare;
286
295
  await run({
287
296
  name: "add Cloudflare config",
288
297
  handler: () =>
289
298
  generateCloudflare({
290
299
  distDir,
300
+ config,
291
301
  }),
292
302
  });
293
303
  }
@@ -5,7 +5,6 @@ import { $inject, Alepha, AlephaError } from "alepha";
5
5
  import type { RunnerMethod } from "alepha/command";
6
6
  import { FileSystemProvider } from "alepha/file";
7
7
  import { $logger } from "alepha/logger";
8
- import type { DrizzleKitProvider, RepositoryProvider } from "alepha/orm";
9
8
  import { boot } from "alepha/vite";
10
9
  import { tsImport } from "tsx/esm/api";
11
10
  import { appRouterTs } from "../assets/appRouterTs.ts";
@@ -495,159 +494,33 @@ ${models.map((it: string) => `export const ${it} = models["${it}"];`).join("\n")
495
494
  }
496
495
 
497
496
  /**
498
- * Prepare Drizzle configuration files for a database provider.
497
+ * Load environment variables from a .env file.
499
498
  *
500
- * Creates temporary entities.js and drizzle.config.js files needed
501
- * for Drizzle Kit commands to run properly.
502
- *
503
- * @param options - Configuration options including kit, provider info, and paths
504
- * @returns Path to the generated drizzle.config.js file
499
+ * Reads the .env file in the specified root directory and sets
500
+ * the environment variables in process.env.
505
501
  */
506
- public async prepareDrizzleConfig(options: {
507
- kit: any;
508
- provider: any;
509
- providerName: string;
510
- providerUrl: string;
511
- dialect: string;
512
- entry: string;
513
- rootDir: string;
514
- }): Promise<string> {
515
- const models = Object.keys(options.kit.getModels(options.provider));
516
- const entitiesJs = this.generateEntitiesJs(
517
- options.entry,
518
- options.providerName,
519
- models,
520
- );
521
-
522
- const entitiesJsPath = await this.writeConfigFile(
523
- "entities.js",
524
- entitiesJs,
525
- options.rootDir,
526
- );
527
-
528
- const config: Record<string, any> = {
529
- schema: entitiesJsPath,
530
- out: `./migrations/${options.providerName}`,
531
- dialect: options.dialect,
532
- dbCredentials: {
533
- url: options.providerUrl,
534
- },
535
- };
536
-
537
- if (options.dialect === "sqlite") {
538
- let url = options.providerUrl;
539
- url = url.replace("sqlite://", "").replace("file://", "");
540
- url = join(options.rootDir, url);
541
-
542
- config.dbCredentials = {
543
- url,
544
- };
545
- }
546
-
547
- if (options.providerName === "pglite") {
548
- config.driver = "pglite";
549
- }
550
-
551
- const drizzleConfigJs = `export default ${JSON.stringify(config, null, 2)}`;
552
-
553
- return await this.writeConfigFile(
554
- "drizzle.config.js",
555
- drizzleConfigJs,
556
- options.rootDir,
557
- );
558
- }
559
-
560
- public async loadEnvFile(root: string): Promise<void> {
561
- const envPath = join(root, ".env");
562
- try {
563
- const envContent = await readFile(envPath, "utf8");
564
- const lines = envContent.split("\n");
565
- for (const line of lines) {
566
- const [key, ...rest] = line.split("=");
567
- if (key) {
568
- const value = rest.join("=");
569
- process.env[key.trim()] = value.trim();
502
+ public async loadEnvFile(
503
+ root: string,
504
+ files: string[] = [".env"],
505
+ ): Promise<void> {
506
+ for (const it of files) {
507
+ for (const file of [it, `${it}.local`]) {
508
+ const envPath = join(root, file);
509
+ try {
510
+ const envContent = await readFile(envPath, "utf8");
511
+ const lines = envContent.split("\n");
512
+ for (const line of lines) {
513
+ const [key, ...rest] = line.split("=");
514
+ if (key) {
515
+ const value = rest.join("=");
516
+ process.env[key.trim()] = value.trim();
517
+ }
518
+ }
519
+ this.log.debug(`Loaded environment variables from ${envPath}`);
520
+ } catch {
521
+ this.log.debug(`No ${file} file found at ${envPath}, skipping load.`);
570
522
  }
571
523
  }
572
- this.log.debug(`Loaded environment variables from ${envPath}`);
573
- } catch {
574
- this.log.debug(`No .env file found at ${envPath}, skipping load.`);
575
- }
576
- }
577
-
578
- /**
579
- * Run a drizzle-kit command for all database providers in an Alepha instance.
580
- *
581
- * Iterates through all repository providers, prepares Drizzle config for each,
582
- * and executes the specified drizzle-kit command.
583
- *
584
- * @param options - Configuration including command to run, flags, and logging
585
- */
586
- public async runDrizzleKitCommand(options: {
587
- root: string;
588
- args?: string;
589
- command: string;
590
- commandFlags?: string;
591
- provider?: string;
592
- logMessage: (providerName: string, dialect: string) => string;
593
- }): Promise<void> {
594
- const rootDir = options.root;
595
-
596
- await this.loadEnvFile(rootDir);
597
-
598
- this.log.debug(`Using project root: ${rootDir}`);
599
-
600
- const { alepha, entry } = await this.loadAlephaFromServerEntryFile(
601
- rootDir,
602
- options.args,
603
- );
604
-
605
- const drizzleKitProvider =
606
- alepha.inject<DrizzleKitProvider>("DrizzleKitProvider");
607
- const repositoryProvider =
608
- alepha.inject<RepositoryProvider>("RepositoryProvider");
609
- const accepted = new Set<string>([]);
610
-
611
- for (const primitive of repositoryProvider.getRepositories()) {
612
- const provider = primitive.provider;
613
- const providerName = provider.name;
614
- const dialect = provider.dialect;
615
-
616
- if (accepted.has(providerName)) {
617
- continue;
618
- }
619
- accepted.add(providerName);
620
-
621
- // Skip if provider filter is set and doesn't match
622
- if (options.provider && options.provider !== providerName) {
623
- this.log.debug(
624
- `Skipping provider '${providerName}' (filter: ${options.provider})`,
625
- );
626
- continue;
627
- }
628
-
629
- this.log.info("");
630
- this.log.info(options.logMessage(providerName, dialect));
631
-
632
- const drizzleConfigJsPath = await this.prepareDrizzleConfig({
633
- kit: drizzleKitProvider,
634
- provider,
635
- providerName,
636
- providerUrl: provider.url,
637
- dialect,
638
- entry,
639
- rootDir,
640
- });
641
-
642
- const flags = options.commandFlags ? ` ${options.commandFlags}` : "";
643
- await this.exec(
644
- `drizzle-kit ${options.command} --config=${drizzleConfigJsPath}${flags}`,
645
- {
646
- env: {
647
- NODE_OPTIONS: "--import tsx",
648
- },
649
- },
650
- );
651
524
  }
652
525
  }
653
526
 
@@ -146,6 +146,7 @@ export class CliProvider {
146
146
  argv,
147
147
  command.options.args,
148
148
  command.name === "",
149
+ command.flags,
149
150
  );
150
151
 
151
152
  await this.alepha.context.run(async () => {
@@ -297,9 +298,12 @@ export class CliProvider {
297
298
  ): Record<string, any> {
298
299
  const result: Record<string, any> = {};
299
300
 
300
- for (const arg of argv.filter((a) => a.startsWith("-"))) {
301
+ for (let i = 0; i < argv.length; i++) {
302
+ const arg = argv[i];
303
+ if (!arg.startsWith("-")) continue;
304
+
301
305
  const [rawKey, ...valueParts] = arg.replace(/^-{1,2}/, "").split("=");
302
- const value = valueParts.join("=");
306
+ let value = valueParts.join("=");
303
307
 
304
308
  const def = flagDefs.find((d) => d.aliases.includes(rawKey));
305
309
  if (!def) continue;
@@ -307,6 +311,7 @@ export class CliProvider {
307
311
  if (t.schema.isBoolean(def.schema)) {
308
312
  result[def.key] = true;
309
313
  } else if (value) {
314
+ // Value provided via --flag=value syntax
310
315
  try {
311
316
  if (t.schema.isObject(def.schema) || t.schema.isArray(def.schema)) {
312
317
  result[def.key] = JSON.parse(value);
@@ -317,24 +322,90 @@ export class CliProvider {
317
322
  throw new CommandError(`Invalid JSON value for flag --${rawKey}`);
318
323
  }
319
324
  } else {
320
- throw new CommandError(`Flag --${rawKey} requires a value.`);
325
+ // Check for space-separated value: --flag value
326
+ const nextArg = argv[i + 1];
327
+ if (nextArg && !nextArg.startsWith("-")) {
328
+ value = nextArg;
329
+ try {
330
+ if (t.schema.isObject(def.schema) || t.schema.isArray(def.schema)) {
331
+ result[def.key] = JSON.parse(value);
332
+ } else {
333
+ result[def.key] = value;
334
+ }
335
+ } catch {
336
+ throw new CommandError(`Invalid JSON value for flag --${rawKey}`);
337
+ }
338
+ } else {
339
+ throw new CommandError(`Flag --${rawKey} requires a value.`);
340
+ }
321
341
  }
322
342
  }
323
343
 
324
344
  return result;
325
345
  }
326
346
 
347
+ /**
348
+ * Get indices of argv elements that are consumed by flags (including space-separated values).
349
+ */
350
+ protected getFlagConsumedIndices(
351
+ argv: string[],
352
+ flagDefs: { key: string; aliases: string[]; schema: TSchema }[],
353
+ ): Set<number> {
354
+ const consumed = new Set<number>();
355
+
356
+ for (let i = 0; i < argv.length; i++) {
357
+ const arg = argv[i];
358
+ if (!arg.startsWith("-")) continue;
359
+
360
+ consumed.add(i);
361
+
362
+ const [rawKey, ...valueParts] = arg.replace(/^-{1,2}/, "").split("=");
363
+ const hasEqualValue = valueParts.length > 0;
364
+
365
+ const def = flagDefs.find((d) => d.aliases.includes(rawKey));
366
+ if (!def) continue;
367
+
368
+ // If not a boolean flag and no = value, the next arg is consumed as the value
369
+ if (!t.schema.isBoolean(def.schema) && !hasEqualValue) {
370
+ const nextArg = argv[i + 1];
371
+ if (nextArg && !nextArg.startsWith("-")) {
372
+ consumed.add(i + 1);
373
+ }
374
+ }
375
+ }
376
+
377
+ return consumed;
378
+ }
379
+
327
380
  protected parseCommandArgs(
328
381
  argv: string[],
329
382
  schema?: TSchema,
330
383
  isRootCommand = false,
384
+ flagSchema?: TObject,
331
385
  ): any {
332
386
  if (!schema) {
333
387
  return undefined;
334
388
  }
335
389
 
336
- // Extract positional arguments (non-flag arguments)
337
- const positionalArgs = argv.filter((arg) => !arg.startsWith("-"));
390
+ // Get indices consumed by flags (including space-separated values)
391
+ const flagDefs = flagSchema
392
+ ? Object.entries(flagSchema.properties).map(([key, value]) => ({
393
+ key,
394
+ aliases: [
395
+ key,
396
+ ...((value as any).aliases ??
397
+ ((value as any).alias ? [(value as any).alias] : undefined) ??
398
+ []),
399
+ ],
400
+ schema: value as TSchema,
401
+ }))
402
+ : [];
403
+ const consumedIndices = this.getFlagConsumedIndices(argv, flagDefs);
404
+
405
+ // Extract positional arguments (non-flag arguments that aren't consumed as flag values)
406
+ const positionalArgs = argv.filter(
407
+ (arg, idx) => !arg.startsWith("-") && !consumedIndices.has(idx),
408
+ );
338
409
  // For root commands, there's no command name to remove; otherwise slice off the command name
339
410
  const argsOnly = isRootCommand ? positionalArgs : positionalArgs.slice(1);
340
411
 
@@ -1,10 +1,12 @@
1
1
  import type { TSchema } from "typebox";
2
2
  import { Compile, type Validator } from "typebox/compile";
3
3
  import { TypeBoxError } from "../errors/TypeBoxError.ts";
4
- import type { Static } from "./TypeProvider.ts";
4
+ import { $hook } from "../primitives/$hook.ts";
5
+ import { type Static, t, Value } from "./TypeProvider.ts";
5
6
 
6
7
  export class SchemaValidator {
7
8
  protected cache = new Map<TSchema, Validator>();
9
+ protected useEval: boolean = true;
8
10
 
9
11
  /**
10
12
  * Validate the value against the provided schema.
@@ -23,6 +25,10 @@ export class SchemaValidator {
23
25
  });
24
26
 
25
27
  try {
28
+ //
29
+ if (!this.useEval) {
30
+ return Value.Parse(schema, newValue);
31
+ }
26
32
  return this.getValidator(schema).Parse(newValue) as Static<T>;
27
33
  } catch (error: any) {
28
34
  if (error.cause?.errors?.[0]) {
@@ -130,6 +136,22 @@ export class SchemaValidator {
130
136
  }
131
137
  return false;
132
138
  };
139
+
140
+ protected onConfigure = $hook({
141
+ on: "configure",
142
+ handler: () => {
143
+ this.useEval = this.canEval();
144
+ },
145
+ });
146
+
147
+ protected canEval(): boolean {
148
+ try {
149
+ Compile(t.object({ test: t.string() })).Parse({ test: "value" });
150
+ return true;
151
+ } catch {
152
+ return false;
153
+ }
154
+ }
133
155
  }
134
156
 
135
157
  export interface ValidateOptions {
@@ -0,0 +1,72 @@
1
+ import { JsonRpcErrorCodes } from "../helpers/jsonrpc.ts";
2
+
3
+ // ---------------------------------------------------------------------------------------------------------------------
4
+
5
+ export class McpError extends Error {
6
+ name = "McpError";
7
+ code: number;
8
+
9
+ constructor(
10
+ message: string,
11
+ code: number = JsonRpcErrorCodes.INTERNAL_ERROR,
12
+ ) {
13
+ super(message);
14
+ this.code = code;
15
+ }
16
+ }
17
+
18
+ // ---------------------------------------------------------------------------------------------------------------------
19
+
20
+ export class McpMethodNotFoundError extends McpError {
21
+ name = "McpMethodNotFoundError";
22
+
23
+ constructor(method: string) {
24
+ super(`Method not found: ${method}`, JsonRpcErrorCodes.METHOD_NOT_FOUND);
25
+ }
26
+ }
27
+
28
+ // ---------------------------------------------------------------------------------------------------------------------
29
+
30
+ export class McpToolNotFoundError extends McpError {
31
+ name = "McpToolNotFoundError";
32
+ tool: string;
33
+
34
+ constructor(tool: string) {
35
+ super(`Tool not found: ${tool}`, JsonRpcErrorCodes.METHOD_NOT_FOUND);
36
+ this.tool = tool;
37
+ }
38
+ }
39
+
40
+ // ---------------------------------------------------------------------------------------------------------------------
41
+
42
+ export class McpResourceNotFoundError extends McpError {
43
+ name = "McpResourceNotFoundError";
44
+ uri: string;
45
+
46
+ constructor(uri: string) {
47
+ super(`Resource not found: ${uri}`, JsonRpcErrorCodes.METHOD_NOT_FOUND);
48
+ this.uri = uri;
49
+ }
50
+ }
51
+
52
+ // ---------------------------------------------------------------------------------------------------------------------
53
+
54
+ export class McpPromptNotFoundError extends McpError {
55
+ name = "McpPromptNotFoundError";
56
+ prompt: string;
57
+
58
+ constructor(prompt: string) {
59
+ super(`Prompt not found: ${prompt}`, JsonRpcErrorCodes.METHOD_NOT_FOUND);
60
+ this.prompt = prompt;
61
+ }
62
+ }
63
+
64
+ // ---------------------------------------------------------------------------------------------------------------------
65
+
66
+ export class McpInvalidParamsError extends McpError {
67
+ name = "McpInvalidParamsError";
68
+
69
+ constructor(message: string) {
70
+ super(message, JsonRpcErrorCodes.INVALID_PARAMS);
71
+ }
72
+ }