skedyul 1.1.3 → 1.1.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/cli/commands/smoke-test.d.ts +1 -0
- package/dist/cli/index.js +258 -14
- package/dist/dockerfile.d.ts +1 -1
- package/dist/index.js +6 -3
- package/package.json +2 -2
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function smokeTestCommand(args: string[]): Promise<void>;
|
package/dist/cli/index.js
CHANGED
|
@@ -2280,11 +2280,11 @@ var CoreApiService = class {
|
|
|
2280
2280
|
setWebhookHandler(handler) {
|
|
2281
2281
|
this.webhookHandler = handler;
|
|
2282
2282
|
}
|
|
2283
|
-
async dispatchWebhook(
|
|
2283
|
+
async dispatchWebhook(request2) {
|
|
2284
2284
|
if (!this.webhookHandler) {
|
|
2285
2285
|
return { status: 404 };
|
|
2286
2286
|
}
|
|
2287
|
-
return this.webhookHandler(
|
|
2287
|
+
return this.webhookHandler(request2);
|
|
2288
2288
|
}
|
|
2289
2289
|
async callCreateChannel(channel) {
|
|
2290
2290
|
return this.service?.createCommunicationChannel(channel);
|
|
@@ -2600,25 +2600,25 @@ function createCallToolHandler(registry, state, onMaxRequests) {
|
|
|
2600
2600
|
};
|
|
2601
2601
|
} else {
|
|
2602
2602
|
const workplace = rawContext.workplace;
|
|
2603
|
-
const
|
|
2603
|
+
const request2 = rawContext.request;
|
|
2604
2604
|
const appInstallationId = rawContext.appInstallationId;
|
|
2605
2605
|
const envVars = process.env;
|
|
2606
2606
|
const modeValue = estimateMode ? "estimate" : "execute";
|
|
2607
2607
|
if (trigger === "field_change") {
|
|
2608
2608
|
const field = rawContext.field;
|
|
2609
|
-
executionContext = { trigger: "field_change", app, appInstallationId, workplace, request, env: envVars, mode: modeValue, field, invocation, log };
|
|
2609
|
+
executionContext = { trigger: "field_change", app, appInstallationId, workplace, request: request2, env: envVars, mode: modeValue, field, invocation, log };
|
|
2610
2610
|
} else if (trigger === "page_action") {
|
|
2611
2611
|
const page = rawContext.page;
|
|
2612
|
-
executionContext = { trigger: "page_action", app, appInstallationId, workplace, request, env: envVars, mode: modeValue, page, invocation, log };
|
|
2612
|
+
executionContext = { trigger: "page_action", app, appInstallationId, workplace, request: request2, env: envVars, mode: modeValue, page, invocation, log };
|
|
2613
2613
|
} else if (trigger === "form_submit") {
|
|
2614
2614
|
const form = rawContext.form;
|
|
2615
|
-
executionContext = { trigger: "form_submit", app, appInstallationId, workplace, request, env: envVars, mode: modeValue, form, invocation, log };
|
|
2615
|
+
executionContext = { trigger: "form_submit", app, appInstallationId, workplace, request: request2, env: envVars, mode: modeValue, form, invocation, log };
|
|
2616
2616
|
} else if (trigger === "workflow") {
|
|
2617
|
-
executionContext = { trigger: "workflow", app, appInstallationId, workplace, request, env: envVars, mode: modeValue, invocation, log };
|
|
2617
|
+
executionContext = { trigger: "workflow", app, appInstallationId, workplace, request: request2, env: envVars, mode: modeValue, invocation, log };
|
|
2618
2618
|
} else if (trigger === "page_context") {
|
|
2619
|
-
executionContext = { trigger: "agent", app, appInstallationId, workplace, request, env: envVars, mode: modeValue, invocation, log };
|
|
2619
|
+
executionContext = { trigger: "agent", app, appInstallationId, workplace, request: request2, env: envVars, mode: modeValue, invocation, log };
|
|
2620
2620
|
} else {
|
|
2621
|
-
executionContext = { trigger: "agent", app, appInstallationId, workplace, request, env: envVars, mode: modeValue, invocation, log };
|
|
2621
|
+
executionContext = { trigger: "agent", app, appInstallationId, workplace, request: request2, env: envVars, mode: modeValue, invocation, log };
|
|
2622
2622
|
}
|
|
2623
2623
|
}
|
|
2624
2624
|
const requestConfig = {
|
|
@@ -7019,8 +7019,8 @@ async function handleCreateMany(modelHandle, flags) {
|
|
|
7019
7019
|
console.error("Usage: skedyul instances create-many <model> --file data.json --workplace <subdomain>");
|
|
7020
7020
|
process.exit(1);
|
|
7021
7021
|
}
|
|
7022
|
-
const
|
|
7023
|
-
const fileContent =
|
|
7022
|
+
const fs14 = await import("fs");
|
|
7023
|
+
const fileContent = fs14.readFileSync(filePath, "utf-8");
|
|
7024
7024
|
const items = JSON.parse(fileContent);
|
|
7025
7025
|
if (!Array.isArray(items)) {
|
|
7026
7026
|
console.error("Error: File must contain a JSON array of items");
|
|
@@ -7047,8 +7047,8 @@ async function handleUpsertMany(modelHandle, flags) {
|
|
|
7047
7047
|
console.error("Usage: skedyul instances upsert-many <model> --file data.json --match-field <field> --workplace <subdomain>");
|
|
7048
7048
|
process.exit(1);
|
|
7049
7049
|
}
|
|
7050
|
-
const
|
|
7051
|
-
const fileContent =
|
|
7050
|
+
const fs14 = await import("fs");
|
|
7051
|
+
const fileContent = fs14.readFileSync(filePath, "utf-8");
|
|
7052
7052
|
const items = JSON.parse(fileContent);
|
|
7053
7053
|
if (!Array.isArray(items)) {
|
|
7054
7054
|
console.error("Error: File must contain a JSON array of items");
|
|
@@ -7124,7 +7124,7 @@ async function buildCommand(args2) {
|
|
|
7124
7124
|
console.log(`Loading config from ${path12.basename(configPath)}...`);
|
|
7125
7125
|
try {
|
|
7126
7126
|
const config = await loadConfig(configPath);
|
|
7127
|
-
const computeLayer = config.computeLayer ?? "serverless";
|
|
7127
|
+
const computeLayer = process.env.COMPUTE_LAYER ?? config.computeLayer ?? "serverless";
|
|
7128
7128
|
const format = computeLayer === "serverless" ? "esm" : "cjs";
|
|
7129
7129
|
const baseExternals = ["skedyul", `skedyul/${computeLayer}`, "zod"];
|
|
7130
7130
|
const userExternals = config.build && "external" in config.build ? config.build.external ?? [] : [];
|
|
@@ -7176,6 +7176,242 @@ async function buildCommand(args2) {
|
|
|
7176
7176
|
}
|
|
7177
7177
|
}
|
|
7178
7178
|
|
|
7179
|
+
// src/cli/commands/smoke-test.ts
|
|
7180
|
+
var import_child_process2 = require("child_process");
|
|
7181
|
+
var http3 = __toESM(require("http"));
|
|
7182
|
+
var fs13 = __toESM(require("fs"));
|
|
7183
|
+
var SMOKE_TEST_PORT = 3456;
|
|
7184
|
+
var HEALTH_CHECK_INTERVAL_MS = 500;
|
|
7185
|
+
var HEALTH_CHECK_MAX_RETRIES = 30;
|
|
7186
|
+
function printSmokeTestHelp() {
|
|
7187
|
+
console.log(`
|
|
7188
|
+
SKEDYUL SMOKE-TEST - Validate your built integration
|
|
7189
|
+
\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501
|
|
7190
|
+
|
|
7191
|
+
Spawns the built server and validates it responds to tools/list.
|
|
7192
|
+
This catches module-level errors that would crash the server on startup.
|
|
7193
|
+
|
|
7194
|
+
USAGE
|
|
7195
|
+
$ skedyul smoke-test [options]
|
|
7196
|
+
|
|
7197
|
+
OPTIONS
|
|
7198
|
+
--help, -h Show this help message
|
|
7199
|
+
|
|
7200
|
+
EXAMPLES
|
|
7201
|
+
# Run smoke test after building
|
|
7202
|
+
$ skedyul build && skedyul smoke-test
|
|
7203
|
+
|
|
7204
|
+
WHAT IT DOES
|
|
7205
|
+
1. Spawns node dist/server/mcp_server.js as a child process
|
|
7206
|
+
2. Waits for the /health endpoint to respond
|
|
7207
|
+
3. Calls POST /mcp with tools/list JSON-RPC request
|
|
7208
|
+
4. Validates the response contains at least one tool
|
|
7209
|
+
5. Exits with code 0 (success) or 1 (failure)
|
|
7210
|
+
`);
|
|
7211
|
+
}
|
|
7212
|
+
function makeRequest(port, path13, method, body) {
|
|
7213
|
+
return new Promise((resolve8, reject) => {
|
|
7214
|
+
const postData = body ? JSON.stringify(body) : void 0;
|
|
7215
|
+
const options = {
|
|
7216
|
+
hostname: "localhost",
|
|
7217
|
+
port,
|
|
7218
|
+
path: path13,
|
|
7219
|
+
method,
|
|
7220
|
+
headers: {
|
|
7221
|
+
"Content-Type": "application/json",
|
|
7222
|
+
Accept: "application/json",
|
|
7223
|
+
...postData ? { "Content-Length": Buffer.byteLength(postData) } : {}
|
|
7224
|
+
}
|
|
7225
|
+
};
|
|
7226
|
+
const req = http3.request(options, (res) => {
|
|
7227
|
+
let data = "";
|
|
7228
|
+
res.on("data", (chunk) => {
|
|
7229
|
+
data += chunk;
|
|
7230
|
+
});
|
|
7231
|
+
res.on("end", () => {
|
|
7232
|
+
try {
|
|
7233
|
+
const parsed = data ? JSON.parse(data) : {};
|
|
7234
|
+
resolve8({ status: res.statusCode ?? 0, body: parsed });
|
|
7235
|
+
} catch {
|
|
7236
|
+
resolve8({ status: res.statusCode ?? 0, body: data });
|
|
7237
|
+
}
|
|
7238
|
+
});
|
|
7239
|
+
});
|
|
7240
|
+
req.on("error", reject);
|
|
7241
|
+
if (postData) {
|
|
7242
|
+
req.write(postData);
|
|
7243
|
+
}
|
|
7244
|
+
req.end();
|
|
7245
|
+
});
|
|
7246
|
+
}
|
|
7247
|
+
async function waitForHealth(port) {
|
|
7248
|
+
for (let i = 0; i < HEALTH_CHECK_MAX_RETRIES; i++) {
|
|
7249
|
+
try {
|
|
7250
|
+
const response = await makeRequest(port, "/health", "GET");
|
|
7251
|
+
if (response.status === 200) {
|
|
7252
|
+
return true;
|
|
7253
|
+
}
|
|
7254
|
+
} catch {
|
|
7255
|
+
}
|
|
7256
|
+
await new Promise((resolve8) => setTimeout(resolve8, HEALTH_CHECK_INTERVAL_MS));
|
|
7257
|
+
}
|
|
7258
|
+
return false;
|
|
7259
|
+
}
|
|
7260
|
+
async function callToolsList(port) {
|
|
7261
|
+
try {
|
|
7262
|
+
const response = await makeRequest(port, "/mcp", "POST", {
|
|
7263
|
+
jsonrpc: "2.0",
|
|
7264
|
+
id: 1,
|
|
7265
|
+
method: "tools/list",
|
|
7266
|
+
params: {}
|
|
7267
|
+
});
|
|
7268
|
+
if (response.status !== 200) {
|
|
7269
|
+
return {
|
|
7270
|
+
success: false,
|
|
7271
|
+
error: `tools/list returned status ${response.status}`
|
|
7272
|
+
};
|
|
7273
|
+
}
|
|
7274
|
+
const body = response.body;
|
|
7275
|
+
if (body.error) {
|
|
7276
|
+
return {
|
|
7277
|
+
success: false,
|
|
7278
|
+
error: `tools/list error: ${body.error.message ?? JSON.stringify(body.error)}`
|
|
7279
|
+
};
|
|
7280
|
+
}
|
|
7281
|
+
if (!body.result?.tools) {
|
|
7282
|
+
return {
|
|
7283
|
+
success: false,
|
|
7284
|
+
error: "tools/list response missing result.tools"
|
|
7285
|
+
};
|
|
7286
|
+
}
|
|
7287
|
+
return {
|
|
7288
|
+
success: true,
|
|
7289
|
+
tools: body.result.tools
|
|
7290
|
+
};
|
|
7291
|
+
} catch (err) {
|
|
7292
|
+
return {
|
|
7293
|
+
success: false,
|
|
7294
|
+
error: `Failed to call tools/list: ${err instanceof Error ? err.message : String(err)}`
|
|
7295
|
+
};
|
|
7296
|
+
}
|
|
7297
|
+
}
|
|
7298
|
+
async function smokeTestCommand(args2) {
|
|
7299
|
+
if (args2.includes("--help") || args2.includes("-h")) {
|
|
7300
|
+
printSmokeTestHelp();
|
|
7301
|
+
process.exit(0);
|
|
7302
|
+
}
|
|
7303
|
+
const serverPath = "dist/server/mcp_server.js";
|
|
7304
|
+
if (!fs13.existsSync(serverPath)) {
|
|
7305
|
+
console.error("[SmokeTest] ERROR: dist/server/mcp_server.js not found");
|
|
7306
|
+
console.error('[SmokeTest] Run "skedyul build" first');
|
|
7307
|
+
process.exit(1);
|
|
7308
|
+
}
|
|
7309
|
+
console.log("[SmokeTest] Starting smoke test...");
|
|
7310
|
+
console.log(`[SmokeTest] Server path: ${serverPath}`);
|
|
7311
|
+
console.log(`[SmokeTest] Port: ${SMOKE_TEST_PORT}`);
|
|
7312
|
+
let server2 = null;
|
|
7313
|
+
let serverLogs = [];
|
|
7314
|
+
let serverExited = false;
|
|
7315
|
+
let serverExitCode = null;
|
|
7316
|
+
const cleanup = () => {
|
|
7317
|
+
if (server2 && !serverExited) {
|
|
7318
|
+
console.log("[SmokeTest] Stopping server...");
|
|
7319
|
+
server2.kill("SIGTERM");
|
|
7320
|
+
}
|
|
7321
|
+
};
|
|
7322
|
+
process.on("SIGINT", cleanup);
|
|
7323
|
+
process.on("SIGTERM", cleanup);
|
|
7324
|
+
try {
|
|
7325
|
+
console.log("[SmokeTest] Spawning server process...");
|
|
7326
|
+
server2 = (0, import_child_process2.spawn)("node", [serverPath], {
|
|
7327
|
+
env: {
|
|
7328
|
+
...process.env,
|
|
7329
|
+
PORT: String(SMOKE_TEST_PORT),
|
|
7330
|
+
NODE_ENV: "test"
|
|
7331
|
+
},
|
|
7332
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
7333
|
+
cwd: process.cwd()
|
|
7334
|
+
});
|
|
7335
|
+
server2.stdout?.on("data", (data) => {
|
|
7336
|
+
const line = data.toString().trim();
|
|
7337
|
+
if (line) {
|
|
7338
|
+
serverLogs.push(line);
|
|
7339
|
+
console.log(`[Server] ${line}`);
|
|
7340
|
+
}
|
|
7341
|
+
});
|
|
7342
|
+
server2.stderr?.on("data", (data) => {
|
|
7343
|
+
const line = data.toString().trim();
|
|
7344
|
+
if (line) {
|
|
7345
|
+
serverLogs.push(`[stderr] ${line}`);
|
|
7346
|
+
console.error(`[Server] ${line}`);
|
|
7347
|
+
}
|
|
7348
|
+
});
|
|
7349
|
+
server2.on("exit", (code) => {
|
|
7350
|
+
serverExited = true;
|
|
7351
|
+
serverExitCode = code;
|
|
7352
|
+
if (code !== null && code !== 0) {
|
|
7353
|
+
console.error(`[SmokeTest] Server exited with code ${code}`);
|
|
7354
|
+
}
|
|
7355
|
+
});
|
|
7356
|
+
server2.on("error", (err) => {
|
|
7357
|
+
console.error(`[SmokeTest] Failed to spawn server: ${err.message}`);
|
|
7358
|
+
});
|
|
7359
|
+
await new Promise((resolve8) => setTimeout(resolve8, 1e3));
|
|
7360
|
+
if (serverExited) {
|
|
7361
|
+
console.error("[SmokeTest] FAILED: Server crashed during startup");
|
|
7362
|
+
console.error(`[SmokeTest] Exit code: ${serverExitCode}`);
|
|
7363
|
+
console.error("[SmokeTest] Server logs:");
|
|
7364
|
+
serverLogs.forEach((log) => console.error(` ${log}`));
|
|
7365
|
+
process.exit(1);
|
|
7366
|
+
}
|
|
7367
|
+
console.log("[SmokeTest] Waiting for server to be ready...");
|
|
7368
|
+
const healthy = await waitForHealth(SMOKE_TEST_PORT);
|
|
7369
|
+
if (!healthy) {
|
|
7370
|
+
if (serverExited) {
|
|
7371
|
+
console.error("[SmokeTest] FAILED: Server crashed during startup");
|
|
7372
|
+
console.error(`[SmokeTest] Exit code: ${serverExitCode}`);
|
|
7373
|
+
} else {
|
|
7374
|
+
console.error("[SmokeTest] FAILED: Server did not become healthy");
|
|
7375
|
+
}
|
|
7376
|
+
console.error("[SmokeTest] Server logs:");
|
|
7377
|
+
serverLogs.forEach((log) => console.error(` ${log}`));
|
|
7378
|
+
cleanup();
|
|
7379
|
+
process.exit(1);
|
|
7380
|
+
}
|
|
7381
|
+
console.log("[SmokeTest] Server is healthy, calling tools/list...");
|
|
7382
|
+
const result = await callToolsList(SMOKE_TEST_PORT);
|
|
7383
|
+
if (!result.success) {
|
|
7384
|
+
console.error(`[SmokeTest] FAILED: ${result.error}`);
|
|
7385
|
+
console.error("[SmokeTest] Server logs:");
|
|
7386
|
+
serverLogs.forEach((log) => console.error(` ${log}`));
|
|
7387
|
+
cleanup();
|
|
7388
|
+
process.exit(1);
|
|
7389
|
+
}
|
|
7390
|
+
const toolCount = result.tools?.length ?? 0;
|
|
7391
|
+
console.log(`[SmokeTest] tools/list returned ${toolCount} tool(s)`);
|
|
7392
|
+
if (toolCount === 0) {
|
|
7393
|
+
console.error("[SmokeTest] FAILED: No tools registered");
|
|
7394
|
+
cleanup();
|
|
7395
|
+
process.exit(1);
|
|
7396
|
+
}
|
|
7397
|
+
const tools = result.tools;
|
|
7398
|
+
tools.forEach((tool) => {
|
|
7399
|
+
console.log(`[SmokeTest] - ${tool.name ?? "unnamed"}`);
|
|
7400
|
+
});
|
|
7401
|
+
console.log("[SmokeTest] PASSED: Server started and tools/list responded successfully");
|
|
7402
|
+
cleanup();
|
|
7403
|
+
process.exit(0);
|
|
7404
|
+
} catch (err) {
|
|
7405
|
+
console.error(
|
|
7406
|
+
`[SmokeTest] FAILED: ${err instanceof Error ? err.message : String(err)}`
|
|
7407
|
+
);
|
|
7408
|
+
console.error("[SmokeTest] Server logs:");
|
|
7409
|
+
serverLogs.forEach((log) => console.error(` ${log}`));
|
|
7410
|
+
cleanup();
|
|
7411
|
+
process.exit(1);
|
|
7412
|
+
}
|
|
7413
|
+
}
|
|
7414
|
+
|
|
7179
7415
|
// src/cli/index.ts
|
|
7180
7416
|
var args = process.argv.slice(2);
|
|
7181
7417
|
function printUsage2() {
|
|
@@ -7264,6 +7500,7 @@ COMMANDS
|
|
|
7264
7500
|
Building
|
|
7265
7501
|
\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
|
|
7266
7502
|
build Build your integration using skedyul.config.ts
|
|
7503
|
+
smoke-test Validate built server starts and responds to tools/list
|
|
7267
7504
|
|
|
7268
7505
|
Testing & Debugging
|
|
7269
7506
|
\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
|
|
@@ -7374,6 +7611,10 @@ async function main() {
|
|
|
7374
7611
|
await buildCommand(args.slice(1));
|
|
7375
7612
|
return;
|
|
7376
7613
|
}
|
|
7614
|
+
if (command === "smoke-test") {
|
|
7615
|
+
await smokeTestCommand(args.slice(1));
|
|
7616
|
+
return;
|
|
7617
|
+
}
|
|
7377
7618
|
if (command !== "dev") {
|
|
7378
7619
|
console.error(`Unknown command: ${command}`);
|
|
7379
7620
|
console.error(`Run 'skedyul --help' for usage information.`);
|
|
@@ -7416,6 +7657,9 @@ async function main() {
|
|
|
7416
7657
|
case "build":
|
|
7417
7658
|
await buildCommand(subArgs);
|
|
7418
7659
|
break;
|
|
7660
|
+
case "smoke-test":
|
|
7661
|
+
await smokeTestCommand(subArgs);
|
|
7662
|
+
break;
|
|
7419
7663
|
default:
|
|
7420
7664
|
console.error(`Unknown dev command: ${subCommand}`);
|
|
7421
7665
|
console.error(`Run 'skedyul dev --help' for usage information.`);
|
package/dist/dockerfile.d.ts
CHANGED
|
@@ -13,4 +13,4 @@
|
|
|
13
13
|
* - BUILD_EXTERNAL: comma-separated list of external dependencies (e.g., 'twilio,stripe')
|
|
14
14
|
* - MCP_ENV_JSON: JSON string of environment variables to bake into the image
|
|
15
15
|
*/
|
|
16
|
-
export declare const DEFAULT_DOCKERFILE = "# =============================================================================\n# BUILDER STAGE - Common build for all targets\n# =============================================================================\nFROM public.ecr.aws/docker/library/node:22-alpine AS builder\n\nARG COMPUTE_LAYER=serverless\nARG BUILD_EXTERNAL=\"\"\nWORKDIR /app\n\n# Install pnpm\nRUN corepack enable && corepack prepare pnpm@latest --activate\n\n# Copy package files (lockfile is optional)\nCOPY package.json tsconfig.json ./\nCOPY src ./src\n\n# Copy tsup.config.ts if it exists, otherwise generate based on COMPUTE_LAYER\n# BUILD_EXTERNAL is a comma-separated list of additional externals (e.g., \"twilio,stripe\")\nCOPY tsup.config.t[s] ./\nRUN if [ ! -f tsup.config.ts ]; then \\\n BASE_EXT=\"skedyul,zod\"; \\\n if [ \"$COMPUTE_LAYER\" = \"serverless\" ]; then \\\n BASE_EXT=\"skedyul,skedyul/serverless,zod\"; \\\n FORMAT=\"esm\"; \\\n else \\\n BASE_EXT=\"skedyul,skedyul/dedicated,zod\"; \\\n FORMAT=\"cjs\"; \\\n fi; \\\n if [ -n \"$BUILD_EXTERNAL\" ]; then \\\n ALL_EXT=\"$BASE_EXT,$BUILD_EXTERNAL\"; \\\n else \\\n ALL_EXT=\"$BASE_EXT\"; \\\n fi; \\\n EXT_ARRAY=$(echo \"$ALL_EXT\" | sed 's/,/\",\"/g'); \\\n printf 'import{defineConfig}from\"tsup\";export default defineConfig({entry:[\"src/server/mcp_server.ts\"],format:[\"%s\"],target:\"node22\",outDir:\"dist/server\",clean:true,splitting:false,dts:false,external:[\"%s\"]})' \"$FORMAT\" \"$EXT_ARRAY\" > tsup.config.ts; \\\n fi\n\n# Install dependencies (including dev deps for build), compile, then prune\n# Note: Using --no-frozen-lockfile since lockfile may not exist\nRUN pnpm install --no-frozen-lockfile && \\\n pnpm run build && \\\n pnpm prune --prod && \\\n pnpm store prune && \\\n rm -rf /tmp/* /var/cache/apk/* ~/.npm\n\n# =============================================================================\n# DEDICATED STAGE - For local Docker and ECS deployments (HTTP server)\n# =============================================================================\nFROM public.ecr.aws/docker/library/node:22-alpine AS dedicated\n\nWORKDIR /app\n\n# Copy built artifacts\nCOPY --from=builder /app/node_modules ./node_modules\nCOPY --from=builder /app/dist ./dist\nCOPY --from=builder /app/package.json ./package.json\n\n# Allow overriding the baked-in MCP env at runtime\nARG MCP_ENV_JSON=\"{}\"\nENV MCP_ENV_JSON=${MCP_ENV_JSON}\n\n# Expose the HTTP port\nEXPOSE 3000\n\n# Run as HTTP server (dedicated mode auto-detected by absence of AWS_LAMBDA_FUNCTION_NAME)\nCMD [\"node\", \"dist/server/mcp_server.js\"]\n\n# =============================================================================\n# SERVERLESS STAGE - For AWS Lambda deployments\n# =============================================================================\nFROM public.ecr.aws/lambda/nodejs:22 AS serverless\n\nWORKDIR ${LAMBDA_TASK_ROOT}\n\nCOPY --from=builder /app/node_modules ./node_modules\nCOPY --from=builder /app/dist ./dist\nCOPY --from=builder /app/package.json ./package.json\n\n# Allow overriding the baked-in MCP env at runtime\nARG MCP_ENV_JSON=\"{}\"\nENV MCP_ENV_JSON=${MCP_ENV_JSON}\n\n# Lambda handler format\nCMD [\"dist/server/mcp_server.handler\"]\n\n# =============================================================================\n# DEFAULT - Use dedicated for local development, override with --target for production\n# =============================================================================\nFROM dedicated\n";
|
|
16
|
+
export declare const DEFAULT_DOCKERFILE = "# =============================================================================\n# BUILDER STAGE - Common build for all targets\n# =============================================================================\nFROM public.ecr.aws/docker/library/node:22-alpine AS builder\n\nARG COMPUTE_LAYER=serverless\nARG BUILD_EXTERNAL=\"\"\nWORKDIR /app\n\n# Install pnpm\nRUN corepack enable && corepack prepare pnpm@latest --activate\n\n# Copy package files (lockfile is optional)\nCOPY package.json tsconfig.json skedyul.config.ts ./\nCOPY src ./src\n\n# Copy tsup.config.ts if it exists, otherwise generate based on COMPUTE_LAYER\n# BUILD_EXTERNAL is a comma-separated list of additional externals (e.g., \"twilio,stripe\")\nCOPY tsup.config.t[s] ./\nRUN if [ ! -f tsup.config.ts ]; then \\\n BASE_EXT=\"skedyul,zod\"; \\\n if [ \"$COMPUTE_LAYER\" = \"serverless\" ]; then \\\n BASE_EXT=\"skedyul,skedyul/serverless,zod\"; \\\n FORMAT=\"esm\"; \\\n else \\\n BASE_EXT=\"skedyul,skedyul/dedicated,zod\"; \\\n FORMAT=\"cjs\"; \\\n fi; \\\n if [ -n \"$BUILD_EXTERNAL\" ]; then \\\n ALL_EXT=\"$BASE_EXT,$BUILD_EXTERNAL\"; \\\n else \\\n ALL_EXT=\"$BASE_EXT\"; \\\n fi; \\\n EXT_ARRAY=$(echo \"$ALL_EXT\" | sed 's/,/\",\"/g'); \\\n printf 'import{defineConfig}from\"tsup\";export default defineConfig({entry:[\"src/server/mcp_server.ts\"],format:[\"%s\"],target:\"node22\",outDir:\"dist/server\",clean:true,splitting:false,dts:false,external:[\"%s\"]})' \"$FORMAT\" \"$EXT_ARRAY\" > tsup.config.ts; \\\n fi\n\n# Install dependencies (including dev deps for build), compile, smoke test, then prune\n# Note: Using --no-frozen-lockfile since lockfile may not exist\n# COMPUTE_LAYER env var tells skedyul build which format to use\n# Smoke test runs before pruning since skedyul CLI is a dev dependency\nRUN pnpm install --no-frozen-lockfile && \\\n COMPUTE_LAYER=$COMPUTE_LAYER pnpm run build && \\\n skedyul smoke-test && \\\n pnpm prune --prod && \\\n pnpm store prune && \\\n rm -rf /tmp/* /var/cache/apk/* ~/.npm\n\n# =============================================================================\n# DEDICATED STAGE - For local Docker and ECS deployments (HTTP server)\n# =============================================================================\nFROM public.ecr.aws/docker/library/node:22-alpine AS dedicated\n\nWORKDIR /app\n\n# Copy built artifacts\nCOPY --from=builder /app/node_modules ./node_modules\nCOPY --from=builder /app/dist ./dist\nCOPY --from=builder /app/package.json ./package.json\n\n# Allow overriding the baked-in MCP env at runtime\nARG MCP_ENV_JSON=\"{}\"\nENV MCP_ENV_JSON=${MCP_ENV_JSON}\n\n# Expose the HTTP port\nEXPOSE 3000\n\n# Run as HTTP server (dedicated mode auto-detected by absence of AWS_LAMBDA_FUNCTION_NAME)\nCMD [\"node\", \"dist/server/mcp_server.js\"]\n\n# =============================================================================\n# SERVERLESS STAGE - For AWS Lambda deployments\n# =============================================================================\nFROM public.ecr.aws/lambda/nodejs:22 AS serverless\n\nWORKDIR ${LAMBDA_TASK_ROOT}\n\nCOPY --from=builder /app/node_modules ./node_modules\nCOPY --from=builder /app/dist ./dist\nCOPY --from=builder /app/package.json ./package.json\n\n# Allow overriding the baked-in MCP env at runtime\nARG MCP_ENV_JSON=\"{}\"\nENV MCP_ENV_JSON=${MCP_ENV_JSON}\n\n# Lambda handler format\nCMD [\"dist/server/mcp_server.handler\"]\n\n# =============================================================================\n# DEFAULT - Use dedicated for local development, override with --target for production\n# =============================================================================\nFROM dedicated\n";
|
package/dist/index.js
CHANGED
|
@@ -4069,7 +4069,7 @@ WORKDIR /app
|
|
|
4069
4069
|
RUN corepack enable && corepack prepare pnpm@latest --activate
|
|
4070
4070
|
|
|
4071
4071
|
# Copy package files (lockfile is optional)
|
|
4072
|
-
COPY package.json tsconfig.json ./
|
|
4072
|
+
COPY package.json tsconfig.json skedyul.config.ts ./
|
|
4073
4073
|
COPY src ./src
|
|
4074
4074
|
|
|
4075
4075
|
# Copy tsup.config.ts if it exists, otherwise generate based on COMPUTE_LAYER
|
|
@@ -4093,10 +4093,13 @@ RUN if [ ! -f tsup.config.ts ]; then \\
|
|
|
4093
4093
|
printf 'import{defineConfig}from"tsup";export default defineConfig({entry:["src/server/mcp_server.ts"],format:["%s"],target:"node22",outDir:"dist/server",clean:true,splitting:false,dts:false,external:["%s"]})' "$FORMAT" "$EXT_ARRAY" > tsup.config.ts; \\
|
|
4094
4094
|
fi
|
|
4095
4095
|
|
|
4096
|
-
# Install dependencies (including dev deps for build), compile, then prune
|
|
4096
|
+
# Install dependencies (including dev deps for build), compile, smoke test, then prune
|
|
4097
4097
|
# Note: Using --no-frozen-lockfile since lockfile may not exist
|
|
4098
|
+
# COMPUTE_LAYER env var tells skedyul build which format to use
|
|
4099
|
+
# Smoke test runs before pruning since skedyul CLI is a dev dependency
|
|
4098
4100
|
RUN pnpm install --no-frozen-lockfile && \\
|
|
4099
|
-
pnpm run build && \\
|
|
4101
|
+
COMPUTE_LAYER=$COMPUTE_LAYER pnpm run build && \\
|
|
4102
|
+
skedyul smoke-test && \\
|
|
4100
4103
|
pnpm prune --prod && \\
|
|
4101
4104
|
pnpm store prune && \\
|
|
4102
4105
|
rm -rf /tmp/* /var/cache/apk/* ~/.npm
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "skedyul",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.7",
|
|
4
4
|
"description": "The Skedyul SDK for Node.js",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
},
|
|
16
16
|
"./serverless": {
|
|
17
17
|
"types": "./dist/server.d.ts",
|
|
18
|
-
"import": "./dist/serverless/server.
|
|
18
|
+
"import": "./dist/serverless/server.mjs"
|
|
19
19
|
},
|
|
20
20
|
"./dedicated": {
|
|
21
21
|
"types": "./dist/server.d.ts",
|