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.
@@ -0,0 +1 @@
1
+ export declare function transpileConfigMetadata(configPath: string): Promise<string>;
@@ -2025,13 +2025,13 @@ function mergeRuntimeEnv() {
2025
2025
 
2026
2026
  // src/server/utils/http.ts
2027
2027
  function readRawRequestBody(req) {
2028
- return new Promise((resolve4, reject) => {
2028
+ return new Promise((resolve5, reject) => {
2029
2029
  let body = "";
2030
2030
  req.on("data", (chunk) => {
2031
2031
  body += chunk.toString();
2032
2032
  });
2033
2033
  req.on("end", () => {
2034
- resolve4(body);
2034
+ resolve5(body);
2035
2035
  });
2036
2036
  req.on("error", reject);
2037
2037
  });
@@ -3844,7 +3844,7 @@ function printStartupLog(config, tools, port) {
3844
3844
 
3845
3845
  // src/server/route-handlers/adapters.ts
3846
3846
  function fromLambdaEvent(event2) {
3847
- const path6 = event2.path || event2.rawPath || "/";
3847
+ const path7 = event2.path || event2.rawPath || "/";
3848
3848
  const method = event2.httpMethod || event2.requestContext?.http?.method || "POST";
3849
3849
  const forwardedProto = event2.headers?.["x-forwarded-proto"] ?? event2.headers?.["X-Forwarded-Proto"];
3850
3850
  const protocol = forwardedProto ?? "https";
@@ -3852,9 +3852,9 @@ function fromLambdaEvent(event2) {
3852
3852
  const queryString = event2.queryStringParameters ? "?" + new URLSearchParams(
3853
3853
  event2.queryStringParameters
3854
3854
  ).toString() : "";
3855
- const url = `${protocol}://${host}${path6}${queryString}`;
3855
+ const url = `${protocol}://${host}${path7}${queryString}`;
3856
3856
  return {
3857
- path: path6,
3857
+ path: path7,
3858
3858
  method,
3859
3859
  headers: event2.headers,
3860
3860
  query: event2.queryStringParameters ?? {},
@@ -4404,7 +4404,7 @@ async function handleOAuthCallback(parsedBody, hooks) {
4404
4404
  }
4405
4405
 
4406
4406
  // src/server/handlers/webhook-handler.ts
4407
- function parseWebhookRequest(parsedBody, method, url, path6, headers, query, rawBody, appIdHeader, appVersionIdHeader) {
4407
+ function parseWebhookRequest(parsedBody, method, url, path7, headers, query, rawBody, appIdHeader, appVersionIdHeader) {
4408
4408
  const isEnvelope = typeof parsedBody === "object" && parsedBody !== null && "env" in parsedBody && "request" in parsedBody && "context" in parsedBody;
4409
4409
  if (isEnvelope) {
4410
4410
  const envelope = parsedBody;
@@ -4458,7 +4458,7 @@ function parseWebhookRequest(parsedBody, method, url, path6, headers, query, raw
4458
4458
  const webhookRequest = {
4459
4459
  method,
4460
4460
  url,
4461
- path: path6,
4461
+ path: path7,
4462
4462
  headers,
4463
4463
  query,
4464
4464
  body: parsedBody,
@@ -4907,9 +4907,9 @@ async function handleMcpBatchRoute(req, ctx) {
4907
4907
  }
4908
4908
  const perCallTimeoutMs = deadline ? Math.min(deadline, 25e3) : 25e3;
4909
4909
  const executeWithTimeout = async (call2, timeoutMs) => {
4910
- return new Promise(async (resolve4) => {
4910
+ return new Promise(async (resolve5) => {
4911
4911
  const timeoutHandle = setTimeout(() => {
4912
- resolve4({
4912
+ resolve5({
4913
4913
  id: call2.id,
4914
4914
  success: false,
4915
4915
  error: "Timeout",
@@ -4922,7 +4922,7 @@ async function handleMcpBatchRoute(req, ctx) {
4922
4922
  const found = findToolInRegistry(ctx.registry, toolName);
4923
4923
  if (!found) {
4924
4924
  clearTimeout(timeoutHandle);
4925
- resolve4({
4925
+ resolve5({
4926
4926
  id: call2.id,
4927
4927
  success: false,
4928
4928
  error: `Tool "${toolName}" not found`
@@ -4940,13 +4940,13 @@ async function handleMcpBatchRoute(req, ctx) {
4940
4940
  clearTimeout(timeoutHandle);
4941
4941
  const isFailure2 = "success" in toolResult && toolResult.success === false || "error" in toolResult && toolResult.error != null;
4942
4942
  if (isFailure2) {
4943
- resolve4({
4943
+ resolve5({
4944
4944
  id: call2.id,
4945
4945
  success: false,
4946
4946
  error: "error" in toolResult && toolResult.error ? typeof toolResult.error === "string" ? toolResult.error : JSON.stringify(toolResult.error) : "Tool execution failed"
4947
4947
  });
4948
4948
  } else {
4949
- resolve4({
4949
+ resolve5({
4950
4950
  id: call2.id,
4951
4951
  success: true,
4952
4952
  result: "output" in toolResult ? toolResult.output : toolResult
@@ -4954,7 +4954,7 @@ async function handleMcpBatchRoute(req, ctx) {
4954
4954
  }
4955
4955
  } catch (err) {
4956
4956
  clearTimeout(timeoutHandle);
4957
- resolve4({
4957
+ resolve5({
4958
4958
  id: call2.id,
4959
4959
  success: false,
4960
4960
  error: err instanceof Error ? err.message : String(err)
@@ -5140,21 +5140,21 @@ function createDedicatedServerInstance(config, tools, callTool, state, mcpServer
5140
5140
  return {
5141
5141
  async listen(listenPort) {
5142
5142
  const finalPort = listenPort ?? port;
5143
- return new Promise((resolve4, reject) => {
5143
+ return new Promise((resolve5, reject) => {
5144
5144
  httpServer.listen(finalPort, () => {
5145
5145
  printStartupLog(config, tools, finalPort);
5146
- resolve4();
5146
+ resolve5();
5147
5147
  });
5148
5148
  httpServer.once("error", reject);
5149
5149
  });
5150
5150
  },
5151
5151
  async close() {
5152
- return new Promise((resolve4, reject) => {
5152
+ return new Promise((resolve5, reject) => {
5153
5153
  const closable = httpServer;
5154
5154
  closable.closeAllConnections?.();
5155
5155
  httpServer.close((err) => {
5156
5156
  if (err) reject(err);
5157
- else resolve4();
5157
+ else resolve5();
5158
5158
  });
5159
5159
  });
5160
5160
  },
@@ -5510,49 +5510,109 @@ function defineNavigation(navigation) {
5510
5510
  }
5511
5511
 
5512
5512
  // src/config/loader.ts
5513
+ import * as fs4 from "fs";
5514
+ import * as path4 from "path";
5515
+ import * as os from "os";
5516
+
5517
+ // src/config/transpileConfigMetadata.ts
5518
+ import * as esbuild from "esbuild";
5513
5519
  import * as fs3 from "fs";
5514
5520
  import * as path3 from "path";
5515
- import * as os from "os";
5521
+ var SKEDYUL_SHIM_NAMESPACE = "skedyul-shim";
5522
+ var METADATA_STUB_NAMESPACE = "metadata-stub";
5523
+ function prepareConfigSource(content) {
5524
+ return content.replace(/import\s*\(\s*(['"])([^'"]+)\1\s*\)/g, "Promise.resolve(null)");
5525
+ }
5526
+ function isJsonImport(importPath) {
5527
+ return importPath.endsWith(".json");
5528
+ }
5529
+ async function transpileConfigMetadata(configPath) {
5530
+ const absolutePath = path3.resolve(configPath);
5531
+ const configDir = path3.dirname(absolutePath);
5532
+ const configBasename = path3.basename(absolutePath);
5533
+ const result = await esbuild.build({
5534
+ absWorkingDir: configDir,
5535
+ entryPoints: [absolutePath],
5536
+ bundle: true,
5537
+ format: "cjs",
5538
+ platform: "node",
5539
+ target: "node22",
5540
+ write: false,
5541
+ logLevel: "silent",
5542
+ plugins: [
5543
+ {
5544
+ name: "prepare-config-entry",
5545
+ setup(build2) {
5546
+ build2.onLoad({ filter: new RegExp(`/${configBasename.replace(".", "\\.")}$`) }, () => ({
5547
+ contents: prepareConfigSource(fs3.readFileSync(absolutePath, "utf-8")),
5548
+ loader: "ts"
5549
+ }));
5550
+ }
5551
+ },
5552
+ {
5553
+ name: "skedyul-shim",
5554
+ setup(build2) {
5555
+ build2.onResolve({ filter: /^skedyul$/ }, () => ({
5556
+ path: "skedyul-shim",
5557
+ namespace: SKEDYUL_SHIM_NAMESPACE
5558
+ }));
5559
+ build2.onLoad({ filter: /.*/, namespace: SKEDYUL_SHIM_NAMESPACE }, () => ({
5560
+ contents: [
5561
+ "function defineConfig(config) { return config; }",
5562
+ "module.exports = { defineConfig };"
5563
+ ].join("\n"),
5564
+ loader: "js"
5565
+ }));
5566
+ }
5567
+ },
5568
+ {
5569
+ name: "metadata-stub-imports",
5570
+ setup(build2) {
5571
+ build2.onResolve({ filter: /^\.{1,2}\// }, (args) => {
5572
+ if (isJsonImport(args.path)) {
5573
+ return void 0;
5574
+ }
5575
+ return {
5576
+ path: args.path,
5577
+ namespace: METADATA_STUB_NAMESPACE
5578
+ };
5579
+ });
5580
+ build2.onLoad({ filter: /.*/, namespace: METADATA_STUB_NAMESPACE }, () => ({
5581
+ contents: "module.exports = {};\n",
5582
+ loader: "js"
5583
+ }));
5584
+ }
5585
+ }
5586
+ ]
5587
+ });
5588
+ if (result.errors.length > 0) {
5589
+ throw new Error(result.errors.map((error) => error.text).join("\n"));
5590
+ }
5591
+ if (result.outputFiles.length === 0) {
5592
+ throw new Error("Config transpile produced no output");
5593
+ }
5594
+ return result.outputFiles[0].text;
5595
+ }
5596
+
5597
+ // src/config/loader.ts
5516
5598
  var CONFIG_FILE_NAMES = [
5517
5599
  "skedyul.config.ts",
5518
5600
  "skedyul.config.js",
5519
5601
  "skedyul.config.mjs",
5520
5602
  "skedyul.config.cjs"
5521
5603
  ];
5522
- async function transpileTypeScript(filePath) {
5523
- const content = fs3.readFileSync(filePath, "utf-8");
5524
- const configDir = path3.dirname(path3.resolve(filePath));
5525
- 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*$/, "}");
5526
- transpiled = transpiled.replace(
5527
- /import\s+(\w+)\s+from\s+['"](\.[^'"]+)['"]\s*(?:with\s*\{[^}]*\})?/g,
5528
- (_match, varName, relativePath) => {
5529
- const absolutePath = path3.resolve(configDir, relativePath);
5530
- return `const ${varName} = require('${absolutePath.replace(/\\/g, "/")}')`;
5531
- }
5532
- );
5533
- transpiled = transpiled.replace(
5534
- /import\s+\{\s*([^}]+)\s*\}\s+from\s+['"](\.[^'"]+)['"]\s*;?\n?/g,
5535
- (_match, namedImports, relativePath) => {
5536
- const absolutePath = path3.resolve(configDir, relativePath);
5537
- return `const { ${namedImports.trim()} } = require('${absolutePath.replace(/\\/g, "/")}')
5538
- `;
5539
- }
5540
- );
5541
- transpiled = transpiled.replace(/import\s*\(\s*['"][^'"]+['"]\s*\)/g, "null");
5542
- return transpiled;
5543
- }
5544
5604
  async function loadConfig(configPath) {
5545
- const absolutePath = path3.resolve(configPath);
5546
- if (!fs3.existsSync(absolutePath)) {
5605
+ const absolutePath = path4.resolve(configPath);
5606
+ if (!fs4.existsSync(absolutePath)) {
5547
5607
  throw new Error(`Config file not found: ${absolutePath}`);
5548
5608
  }
5549
5609
  const isTypeScript = absolutePath.endsWith(".ts");
5550
5610
  try {
5551
5611
  if (isTypeScript) {
5552
5612
  try {
5553
- const transpiled = await transpileTypeScript(absolutePath);
5554
- const tempFile = path3.join(os.tmpdir(), `skedyul-config-${Date.now()}.cjs`);
5555
- fs3.writeFileSync(tempFile, transpiled);
5613
+ const transpiled = await transpileConfigMetadata(absolutePath);
5614
+ const tempFile = path4.join(os.tmpdir(), `skedyul-config-${Date.now()}.cjs`);
5615
+ fs4.writeFileSync(tempFile, transpiled);
5556
5616
  try {
5557
5617
  const module2 = __require(tempFile);
5558
5618
  const config2 = module2.default || module2;
@@ -5565,7 +5625,7 @@ async function loadConfig(configPath) {
5565
5625
  return config2;
5566
5626
  } finally {
5567
5627
  try {
5568
- fs3.unlinkSync(tempFile);
5628
+ fs4.unlinkSync(tempFile);
5569
5629
  } catch {
5570
5630
  }
5571
5631
  }
@@ -5605,13 +5665,13 @@ function validateConfig(config) {
5605
5665
  }
5606
5666
 
5607
5667
  // src/config/schema-loader.ts
5608
- import * as fs4 from "fs";
5609
- import * as path4 from "path";
5668
+ import * as fs5 from "fs";
5669
+ import * as path5 from "path";
5610
5670
  import * as os2 from "os";
5611
5671
 
5612
5672
  // src/config/resolver.ts
5613
- import * as fs5 from "fs";
5614
- import * as path5 from "path";
5673
+ import * as fs6 from "fs";
5674
+ import * as path6 from "path";
5615
5675
 
5616
5676
  // src/config/utils.ts
5617
5677
  function getAllEnvKeys(config) {
@@ -5714,7 +5774,7 @@ function getApiToken() {
5714
5774
  const config = getConfig();
5715
5775
  return config.apiToken || process.env.SKEDYUL_API_TOKEN || "";
5716
5776
  }
5717
- async function callRateLimitApi(path6, body) {
5777
+ async function callRateLimitApi(path7, body) {
5718
5778
  const baseUrl = getApiBaseUrl();
5719
5779
  const token2 = getApiToken();
5720
5780
  if (!baseUrl || !token2) {
@@ -5722,7 +5782,7 @@ async function callRateLimitApi(path6, body) {
5722
5782
  "SKEDYUL_API_URL and SKEDYUL_API_TOKEN are required for platform queue coordination"
5723
5783
  );
5724
5784
  }
5725
- const response = await fetch(`${baseUrl}/api/internal/ratelimit/${path6}`, {
5785
+ const response = await fetch(`${baseUrl}/api/internal/ratelimit/${path7}`, {
5726
5786
  method: "POST",
5727
5787
  headers: {
5728
5788
  Authorization: `Bearer ${token2}`,
@@ -5732,11 +5792,11 @@ async function callRateLimitApi(path6, body) {
5732
5792
  });
5733
5793
  const payload = await response.json().catch(() => null);
5734
5794
  if (!response.ok || payload?.success === false) {
5735
- const message = payload?.errors?.[0]?.message ?? `Queue coordination API ${path6} failed with status ${response.status}`;
5795
+ const message = payload?.errors?.[0]?.message ?? `Queue coordination API ${path7} failed with status ${response.status}`;
5736
5796
  throw new RateLimitBackendError(message, response.status);
5737
5797
  }
5738
5798
  if (!payload?.data) {
5739
- throw new RateLimitBackendError(`Queue coordination API ${path6} returned empty data`);
5799
+ throw new RateLimitBackendError(`Queue coordination API ${path7} returned empty data`);
5740
5800
  }
5741
5801
  return payload.data;
5742
5802
  }
@@ -5863,9 +5923,9 @@ var MemoryRateLimitBackend = class {
5863
5923
  if (canAcquire(state, limits)) {
5864
5924
  return this.grant(state, queueKey, limits);
5865
5925
  }
5866
- return new Promise((resolve4, reject) => {
5926
+ return new Promise((resolve5, reject) => {
5867
5927
  const waiter = {
5868
- resolve: resolve4,
5928
+ resolve: resolve5,
5869
5929
  reject,
5870
5930
  timer: null,
5871
5931
  limits
@@ -5894,7 +5954,7 @@ var MemoryRateLimitBackend = class {
5894
5954
  if (waiter.timer) {
5895
5955
  clearTimeout(waiter.timer);
5896
5956
  }
5897
- resolve4(this.grant(state, queueKey, limits));
5957
+ resolve5(this.grant(state, queueKey, limits));
5898
5958
  return;
5899
5959
  }
5900
5960
  setTimeout(retry, Math.max(getMinTime(limits), 10));
@@ -6015,7 +6075,7 @@ function defaultShouldRetry(error, _attempt) {
6015
6075
  return false;
6016
6076
  }
6017
6077
  function sleep(ms) {
6018
- return new Promise((resolve4) => setTimeout(resolve4, ms));
6078
+ return new Promise((resolve5) => setTimeout(resolve5, ms));
6019
6079
  }
6020
6080
 
6021
6081
  // src/ratelimit/queued-fetch.ts
@@ -6295,16 +6355,16 @@ function evaluateTemplate(template, context) {
6295
6355
  const templateRegex = /\{\{\s*([^}]+)\s*\}\}/g;
6296
6356
  const singleMatch = template.match(/^\{\{\s*([^}]+)\s*\}\}$/);
6297
6357
  if (singleMatch) {
6298
- const path6 = singleMatch[1].trim();
6299
- return resolvePath(context, path6);
6358
+ const path7 = singleMatch[1].trim();
6359
+ return resolvePath(context, path7);
6300
6360
  }
6301
- return template.replace(templateRegex, (_, path6) => {
6302
- const value = resolvePath(context, path6.trim());
6361
+ return template.replace(templateRegex, (_, path7) => {
6362
+ const value = resolvePath(context, path7.trim());
6303
6363
  return value === void 0 || value === null ? "" : String(value);
6304
6364
  });
6305
6365
  }
6306
- function resolvePath(obj, path6) {
6307
- const parts = path6.split(".");
6366
+ function resolvePath(obj, path7) {
6367
+ const parts = path7.split(".");
6308
6368
  let current = obj;
6309
6369
  for (const part of parts) {
6310
6370
  if (current === null || current === void 0) {
@@ -6325,14 +6385,14 @@ function evaluateCondition(condition, context) {
6325
6385
  const expression = match[1].trim();
6326
6386
  const eqMatch = expression.match(/^(.+?)\s*==\s*['"](.+)['"]$/);
6327
6387
  if (eqMatch) {
6328
- const [, path6, expectedValue] = eqMatch;
6329
- const actualValue = resolvePath(context, path6.trim());
6388
+ const [, path7, expectedValue] = eqMatch;
6389
+ const actualValue = resolvePath(context, path7.trim());
6330
6390
  return actualValue === expectedValue;
6331
6391
  }
6332
6392
  const neqMatch = expression.match(/^(.+?)\s*!=\s*['"](.+)['"]$/);
6333
6393
  if (neqMatch) {
6334
- const [, path6, expectedValue] = neqMatch;
6335
- const actualValue = resolvePath(context, path6.trim());
6394
+ const [, path7, expectedValue] = neqMatch;
6395
+ const actualValue = resolvePath(context, path7.trim());
6336
6396
  return actualValue !== expectedValue;
6337
6397
  }
6338
6398
  const value = resolvePath(context, expression);