skedyul 1.4.11 → 1.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -2353,13 +2353,13 @@ function mergeRuntimeEnv() {
2353
2353
 
2354
2354
  // src/server/utils/http.ts
2355
2355
  function readRawRequestBody(req) {
2356
- return new Promise((resolve4, reject) => {
2356
+ return new Promise((resolve5, reject) => {
2357
2357
  let body = "";
2358
2358
  req.on("data", (chunk) => {
2359
2359
  body += chunk.toString();
2360
2360
  });
2361
2361
  req.on("end", () => {
2362
- resolve4(body);
2362
+ resolve5(body);
2363
2363
  });
2364
2364
  req.on("error", reject);
2365
2365
  });
@@ -4172,7 +4172,7 @@ function printStartupLog(config, tools, port) {
4172
4172
 
4173
4173
  // src/server/route-handlers/adapters.ts
4174
4174
  function fromLambdaEvent(event2) {
4175
- const path6 = event2.path || event2.rawPath || "/";
4175
+ const path7 = event2.path || event2.rawPath || "/";
4176
4176
  const method = event2.httpMethod || event2.requestContext?.http?.method || "POST";
4177
4177
  const forwardedProto = event2.headers?.["x-forwarded-proto"] ?? event2.headers?.["X-Forwarded-Proto"];
4178
4178
  const protocol = forwardedProto ?? "https";
@@ -4180,9 +4180,9 @@ function fromLambdaEvent(event2) {
4180
4180
  const queryString = event2.queryStringParameters ? "?" + new URLSearchParams(
4181
4181
  event2.queryStringParameters
4182
4182
  ).toString() : "";
4183
- const url = `${protocol}://${host}${path6}${queryString}`;
4183
+ const url = `${protocol}://${host}${path7}${queryString}`;
4184
4184
  return {
4185
- path: path6,
4185
+ path: path7,
4186
4186
  method,
4187
4187
  headers: event2.headers,
4188
4188
  query: event2.queryStringParameters ?? {},
@@ -4732,7 +4732,7 @@ async function handleOAuthCallback(parsedBody, hooks) {
4732
4732
  }
4733
4733
 
4734
4734
  // src/server/handlers/webhook-handler.ts
4735
- function parseWebhookRequest(parsedBody, method, url, path6, headers, query, rawBody, appIdHeader, appVersionIdHeader) {
4735
+ function parseWebhookRequest(parsedBody, method, url, path7, headers, query, rawBody, appIdHeader, appVersionIdHeader) {
4736
4736
  const isEnvelope = typeof parsedBody === "object" && parsedBody !== null && "env" in parsedBody && "request" in parsedBody && "context" in parsedBody;
4737
4737
  if (isEnvelope) {
4738
4738
  const envelope = parsedBody;
@@ -4786,7 +4786,7 @@ function parseWebhookRequest(parsedBody, method, url, path6, headers, query, raw
4786
4786
  const webhookRequest = {
4787
4787
  method,
4788
4788
  url,
4789
- path: path6,
4789
+ path: path7,
4790
4790
  headers,
4791
4791
  query,
4792
4792
  body: parsedBody,
@@ -5235,9 +5235,9 @@ async function handleMcpBatchRoute(req, ctx) {
5235
5235
  }
5236
5236
  const perCallTimeoutMs = deadline ? Math.min(deadline, 25e3) : 25e3;
5237
5237
  const executeWithTimeout = async (call2, timeoutMs) => {
5238
- return new Promise(async (resolve4) => {
5238
+ return new Promise(async (resolve5) => {
5239
5239
  const timeoutHandle = setTimeout(() => {
5240
- resolve4({
5240
+ resolve5({
5241
5241
  id: call2.id,
5242
5242
  success: false,
5243
5243
  error: "Timeout",
@@ -5250,7 +5250,7 @@ async function handleMcpBatchRoute(req, ctx) {
5250
5250
  const found = findToolInRegistry(ctx.registry, toolName);
5251
5251
  if (!found) {
5252
5252
  clearTimeout(timeoutHandle);
5253
- resolve4({
5253
+ resolve5({
5254
5254
  id: call2.id,
5255
5255
  success: false,
5256
5256
  error: `Tool "${toolName}" not found`
@@ -5268,13 +5268,13 @@ async function handleMcpBatchRoute(req, ctx) {
5268
5268
  clearTimeout(timeoutHandle);
5269
5269
  const isFailure2 = "success" in toolResult && toolResult.success === false || "error" in toolResult && toolResult.error != null;
5270
5270
  if (isFailure2) {
5271
- resolve4({
5271
+ resolve5({
5272
5272
  id: call2.id,
5273
5273
  success: false,
5274
5274
  error: "error" in toolResult && toolResult.error ? typeof toolResult.error === "string" ? toolResult.error : JSON.stringify(toolResult.error) : "Tool execution failed"
5275
5275
  });
5276
5276
  } else {
5277
- resolve4({
5277
+ resolve5({
5278
5278
  id: call2.id,
5279
5279
  success: true,
5280
5280
  result: "output" in toolResult ? toolResult.output : toolResult
@@ -5282,7 +5282,7 @@ async function handleMcpBatchRoute(req, ctx) {
5282
5282
  }
5283
5283
  } catch (err) {
5284
5284
  clearTimeout(timeoutHandle);
5285
- resolve4({
5285
+ resolve5({
5286
5286
  id: call2.id,
5287
5287
  success: false,
5288
5288
  error: err instanceof Error ? err.message : String(err)
@@ -5468,21 +5468,21 @@ function createDedicatedServerInstance(config, tools, callTool, state, mcpServer
5468
5468
  return {
5469
5469
  async listen(listenPort) {
5470
5470
  const finalPort = listenPort ?? port;
5471
- return new Promise((resolve4, reject) => {
5471
+ return new Promise((resolve5, reject) => {
5472
5472
  httpServer.listen(finalPort, () => {
5473
5473
  printStartupLog(config, tools, finalPort);
5474
- resolve4();
5474
+ resolve5();
5475
5475
  });
5476
5476
  httpServer.once("error", reject);
5477
5477
  });
5478
5478
  },
5479
5479
  async close() {
5480
- return new Promise((resolve4, reject) => {
5480
+ return new Promise((resolve5, reject) => {
5481
5481
  const closable = httpServer;
5482
5482
  closable.closeAllConnections?.();
5483
5483
  httpServer.close((err) => {
5484
5484
  if (err) reject(err);
5485
- else resolve4();
5485
+ else resolve5();
5486
5486
  });
5487
5487
  });
5488
5488
  },
@@ -5838,49 +5838,109 @@ function defineNavigation(navigation) {
5838
5838
  }
5839
5839
 
5840
5840
  // src/config/loader.ts
5841
+ var fs4 = __toESM(require("fs"));
5842
+ var path4 = __toESM(require("path"));
5843
+ var os = __toESM(require("os"));
5844
+
5845
+ // src/config/transpileConfigMetadata.ts
5846
+ var esbuild = __toESM(require("esbuild"));
5841
5847
  var fs3 = __toESM(require("fs"));
5842
5848
  var path3 = __toESM(require("path"));
5843
- var os = __toESM(require("os"));
5849
+ var SKEDYUL_SHIM_NAMESPACE = "skedyul-shim";
5850
+ var METADATA_STUB_NAMESPACE = "metadata-stub";
5851
+ function prepareConfigSource(content) {
5852
+ return content.replace(/import\s*\(\s*(['"])([^'"]+)\1\s*\)/g, "Promise.resolve(null)");
5853
+ }
5854
+ function isJsonImport(importPath) {
5855
+ return importPath.endsWith(".json");
5856
+ }
5857
+ async function transpileConfigMetadata(configPath) {
5858
+ const absolutePath = path3.resolve(configPath);
5859
+ const configDir = path3.dirname(absolutePath);
5860
+ const configBasename = path3.basename(absolutePath);
5861
+ const result = await esbuild.build({
5862
+ absWorkingDir: configDir,
5863
+ entryPoints: [absolutePath],
5864
+ bundle: true,
5865
+ format: "cjs",
5866
+ platform: "node",
5867
+ target: "node22",
5868
+ write: false,
5869
+ logLevel: "silent",
5870
+ plugins: [
5871
+ {
5872
+ name: "prepare-config-entry",
5873
+ setup(build2) {
5874
+ build2.onLoad({ filter: new RegExp(`/${configBasename.replace(".", "\\.")}$`) }, () => ({
5875
+ contents: prepareConfigSource(fs3.readFileSync(absolutePath, "utf-8")),
5876
+ loader: "ts"
5877
+ }));
5878
+ }
5879
+ },
5880
+ {
5881
+ name: "skedyul-shim",
5882
+ setup(build2) {
5883
+ build2.onResolve({ filter: /^skedyul$/ }, () => ({
5884
+ path: "skedyul-shim",
5885
+ namespace: SKEDYUL_SHIM_NAMESPACE
5886
+ }));
5887
+ build2.onLoad({ filter: /.*/, namespace: SKEDYUL_SHIM_NAMESPACE }, () => ({
5888
+ contents: [
5889
+ "function defineConfig(config) { return config; }",
5890
+ "module.exports = { defineConfig };"
5891
+ ].join("\n"),
5892
+ loader: "js"
5893
+ }));
5894
+ }
5895
+ },
5896
+ {
5897
+ name: "metadata-stub-imports",
5898
+ setup(build2) {
5899
+ build2.onResolve({ filter: /^\.{1,2}\// }, (args) => {
5900
+ if (isJsonImport(args.path)) {
5901
+ return void 0;
5902
+ }
5903
+ return {
5904
+ path: args.path,
5905
+ namespace: METADATA_STUB_NAMESPACE
5906
+ };
5907
+ });
5908
+ build2.onLoad({ filter: /.*/, namespace: METADATA_STUB_NAMESPACE }, () => ({
5909
+ contents: "module.exports = {};\n",
5910
+ loader: "js"
5911
+ }));
5912
+ }
5913
+ }
5914
+ ]
5915
+ });
5916
+ if (result.errors.length > 0) {
5917
+ throw new Error(result.errors.map((error) => error.text).join("\n"));
5918
+ }
5919
+ if (result.outputFiles.length === 0) {
5920
+ throw new Error("Config transpile produced no output");
5921
+ }
5922
+ return result.outputFiles[0].text;
5923
+ }
5924
+
5925
+ // src/config/loader.ts
5844
5926
  var CONFIG_FILE_NAMES = [
5845
5927
  "skedyul.config.ts",
5846
5928
  "skedyul.config.js",
5847
5929
  "skedyul.config.mjs",
5848
5930
  "skedyul.config.cjs"
5849
5931
  ];
5850
- async function transpileTypeScript(filePath) {
5851
- const content = fs3.readFileSync(filePath, "utf-8");
5852
- const configDir = path3.dirname(path3.resolve(filePath));
5853
- let transpiled = content.replace(/import\s+type\s+\{[^}]+\}\s+from\s+['"][^'"]+['"]\s*;?\n?/g, "").replace(/import\s+\{\s*defineConfig\s*\}\s+from\s+['"]skedyul['"]\s*;?\n?/g, "").replace(/:\s*SkedyulConfig/g, "").replace(/export\s+default\s+/, "module.exports = ").replace(/defineConfig\s*\(\s*\{/, "{").replace(/\}\s*\)\s*;?\s*$/, "}");
5854
- transpiled = transpiled.replace(
5855
- /import\s+(\w+)\s+from\s+['"](\.[^'"]+)['"]\s*(?:with\s*\{[^}]*\})?/g,
5856
- (_match, varName, relativePath) => {
5857
- const absolutePath = path3.resolve(configDir, relativePath);
5858
- return `const ${varName} = require('${absolutePath.replace(/\\/g, "/")}')`;
5859
- }
5860
- );
5861
- transpiled = transpiled.replace(
5862
- /import\s+\{\s*([^}]+)\s*\}\s+from\s+['"](\.[^'"]+)['"]\s*;?\n?/g,
5863
- (_match, namedImports, relativePath) => {
5864
- const absolutePath = path3.resolve(configDir, relativePath);
5865
- return `const { ${namedImports.trim()} } = require('${absolutePath.replace(/\\/g, "/")}')
5866
- `;
5867
- }
5868
- );
5869
- transpiled = transpiled.replace(/import\s*\(\s*['"][^'"]+['"]\s*\)/g, "null");
5870
- return transpiled;
5871
- }
5872
5932
  async function loadConfig(configPath) {
5873
- const absolutePath = path3.resolve(configPath);
5874
- if (!fs3.existsSync(absolutePath)) {
5933
+ const absolutePath = path4.resolve(configPath);
5934
+ if (!fs4.existsSync(absolutePath)) {
5875
5935
  throw new Error(`Config file not found: ${absolutePath}`);
5876
5936
  }
5877
5937
  const isTypeScript = absolutePath.endsWith(".ts");
5878
5938
  try {
5879
5939
  if (isTypeScript) {
5880
5940
  try {
5881
- const transpiled = await transpileTypeScript(absolutePath);
5882
- const tempFile = path3.join(os.tmpdir(), `skedyul-config-${Date.now()}.cjs`);
5883
- fs3.writeFileSync(tempFile, transpiled);
5941
+ const transpiled = await transpileConfigMetadata(absolutePath);
5942
+ const tempFile = path4.join(os.tmpdir(), `skedyul-config-${Date.now()}.cjs`);
5943
+ fs4.writeFileSync(tempFile, transpiled);
5884
5944
  try {
5885
5945
  const module3 = require(tempFile);
5886
5946
  const config2 = module3.default || module3;
@@ -5893,7 +5953,7 @@ async function loadConfig(configPath) {
5893
5953
  return config2;
5894
5954
  } finally {
5895
5955
  try {
5896
- fs3.unlinkSync(tempFile);
5956
+ fs4.unlinkSync(tempFile);
5897
5957
  } catch {
5898
5958
  }
5899
5959
  }
@@ -5933,13 +5993,13 @@ function validateConfig(config) {
5933
5993
  }
5934
5994
 
5935
5995
  // src/config/schema-loader.ts
5936
- var fs4 = __toESM(require("fs"));
5937
- var path4 = __toESM(require("path"));
5996
+ var fs5 = __toESM(require("fs"));
5997
+ var path5 = __toESM(require("path"));
5938
5998
  var os2 = __toESM(require("os"));
5939
5999
 
5940
6000
  // src/config/resolver.ts
5941
- var fs5 = __toESM(require("fs"));
5942
- var path5 = __toESM(require("path"));
6001
+ var fs6 = __toESM(require("fs"));
6002
+ var path6 = __toESM(require("path"));
5943
6003
 
5944
6004
  // src/config/utils.ts
5945
6005
  function getAllEnvKeys(config) {
@@ -6042,7 +6102,7 @@ function getApiToken() {
6042
6102
  const config = getConfig();
6043
6103
  return config.apiToken || process.env.SKEDYUL_API_TOKEN || "";
6044
6104
  }
6045
- async function callRateLimitApi(path6, body) {
6105
+ async function callRateLimitApi(path7, body) {
6046
6106
  const baseUrl = getApiBaseUrl();
6047
6107
  const token2 = getApiToken();
6048
6108
  if (!baseUrl || !token2) {
@@ -6050,7 +6110,7 @@ async function callRateLimitApi(path6, body) {
6050
6110
  "SKEDYUL_API_URL and SKEDYUL_API_TOKEN are required for platform queue coordination"
6051
6111
  );
6052
6112
  }
6053
- const response = await fetch(`${baseUrl}/api/internal/ratelimit/${path6}`, {
6113
+ const response = await fetch(`${baseUrl}/api/internal/ratelimit/${path7}`, {
6054
6114
  method: "POST",
6055
6115
  headers: {
6056
6116
  Authorization: `Bearer ${token2}`,
@@ -6060,11 +6120,11 @@ async function callRateLimitApi(path6, body) {
6060
6120
  });
6061
6121
  const payload = await response.json().catch(() => null);
6062
6122
  if (!response.ok || payload?.success === false) {
6063
- const message = payload?.errors?.[0]?.message ?? `Queue coordination API ${path6} failed with status ${response.status}`;
6123
+ const message = payload?.errors?.[0]?.message ?? `Queue coordination API ${path7} failed with status ${response.status}`;
6064
6124
  throw new RateLimitBackendError(message, response.status);
6065
6125
  }
6066
6126
  if (!payload?.data) {
6067
- throw new RateLimitBackendError(`Queue coordination API ${path6} returned empty data`);
6127
+ throw new RateLimitBackendError(`Queue coordination API ${path7} returned empty data`);
6068
6128
  }
6069
6129
  return payload.data;
6070
6130
  }
@@ -6191,9 +6251,9 @@ var MemoryRateLimitBackend = class {
6191
6251
  if (canAcquire(state, limits)) {
6192
6252
  return this.grant(state, queueKey, limits);
6193
6253
  }
6194
- return new Promise((resolve4, reject) => {
6254
+ return new Promise((resolve5, reject) => {
6195
6255
  const waiter = {
6196
- resolve: resolve4,
6256
+ resolve: resolve5,
6197
6257
  reject,
6198
6258
  timer: null,
6199
6259
  limits
@@ -6222,7 +6282,7 @@ var MemoryRateLimitBackend = class {
6222
6282
  if (waiter.timer) {
6223
6283
  clearTimeout(waiter.timer);
6224
6284
  }
6225
- resolve4(this.grant(state, queueKey, limits));
6285
+ resolve5(this.grant(state, queueKey, limits));
6226
6286
  return;
6227
6287
  }
6228
6288
  setTimeout(retry, Math.max(getMinTime(limits), 10));
@@ -6343,7 +6403,7 @@ function defaultShouldRetry(error, _attempt) {
6343
6403
  return false;
6344
6404
  }
6345
6405
  function sleep(ms) {
6346
- return new Promise((resolve4) => setTimeout(resolve4, ms));
6406
+ return new Promise((resolve5) => setTimeout(resolve5, ms));
6347
6407
  }
6348
6408
 
6349
6409
  // src/ratelimit/queued-fetch.ts
@@ -6623,16 +6683,16 @@ function evaluateTemplate(template, context) {
6623
6683
  const templateRegex = /\{\{\s*([^}]+)\s*\}\}/g;
6624
6684
  const singleMatch = template.match(/^\{\{\s*([^}]+)\s*\}\}$/);
6625
6685
  if (singleMatch) {
6626
- const path6 = singleMatch[1].trim();
6627
- return resolvePath(context, path6);
6686
+ const path7 = singleMatch[1].trim();
6687
+ return resolvePath(context, path7);
6628
6688
  }
6629
- return template.replace(templateRegex, (_, path6) => {
6630
- const value = resolvePath(context, path6.trim());
6689
+ return template.replace(templateRegex, (_, path7) => {
6690
+ const value = resolvePath(context, path7.trim());
6631
6691
  return value === void 0 || value === null ? "" : String(value);
6632
6692
  });
6633
6693
  }
6634
- function resolvePath(obj, path6) {
6635
- const parts = path6.split(".");
6694
+ function resolvePath(obj, path7) {
6695
+ const parts = path7.split(".");
6636
6696
  let current = obj;
6637
6697
  for (const part of parts) {
6638
6698
  if (current === null || current === void 0) {
@@ -6653,14 +6713,14 @@ function evaluateCondition(condition, context) {
6653
6713
  const expression = match[1].trim();
6654
6714
  const eqMatch = expression.match(/^(.+?)\s*==\s*['"](.+)['"]$/);
6655
6715
  if (eqMatch) {
6656
- const [, path6, expectedValue] = eqMatch;
6657
- const actualValue = resolvePath(context, path6.trim());
6716
+ const [, path7, expectedValue] = eqMatch;
6717
+ const actualValue = resolvePath(context, path7.trim());
6658
6718
  return actualValue === expectedValue;
6659
6719
  }
6660
6720
  const neqMatch = expression.match(/^(.+?)\s*!=\s*['"](.+)['"]$/);
6661
6721
  if (neqMatch) {
6662
- const [, path6, expectedValue] = neqMatch;
6663
- const actualValue = resolvePath(context, path6.trim());
6722
+ const [, path7, expectedValue] = neqMatch;
6723
+ const actualValue = resolvePath(context, path7.trim());
6664
6724
  return actualValue !== expectedValue;
6665
6725
  }
6666
6726
  const value = resolvePath(context, expression);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "skedyul",
3
- "version": "1.4.11",
3
+ "version": "1.5.0",
4
4
  "description": "The Skedyul SDK for Node.js",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -64,7 +64,7 @@
64
64
  "build": "rm -rf dist tsconfig.tsbuildinfo && tsc --emitDeclarationOnly && tsup",
65
65
  "db:generate": "echo 'No database generation needed for this package'",
66
66
  "dev": "npx nodemon --watch src --ext js,ts --exec \"pnpm run build\"",
67
- "test": "tsc --project tsconfig.tests.json && node --test dist-tests/tests/server.test.js dist-tests/tests/cli.test.js dist-tests/tests/agent-schema-v3.test.js dist-tests/tests/ratelimit.test.js"
67
+ "test": "tsc --project tsconfig.tests.json && node --test dist-tests/tests/server.test.js dist-tests/tests/cli.test.js dist-tests/tests/agent-schema-v3.test.js dist-tests/tests/ratelimit.test.js dist-tests/tests/config-loader.test.js"
68
68
  },
69
69
  "keywords": [
70
70
  "mcp",
@@ -81,6 +81,7 @@
81
81
  "license": "MIT",
82
82
  "dependencies": {
83
83
  "@modelcontextprotocol/sdk": "^1.23.0",
84
+ "esbuild": "^0.27.7",
84
85
  "tsx": "^4.19.0",
85
86
  "yaml": "^2.3.1",
86
87
  "zod": "^4.0.0"