effortless-aws 0.34.0 → 0.36.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.
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  AUTH_COOKIE_NAME,
3
3
  createHandlerRuntime
4
- } from "../chunk-6HFS224S.js";
4
+ } from "../chunk-Q3ZDMZF3.js";
5
5
 
6
6
  // src/runtime/wrap-api.ts
7
7
  var CONTENT_TYPE_MAP = {
@@ -131,7 +131,7 @@ var wrapApi = (handler) => {
131
131
  }
132
132
  const { entry, params: routeParams } = routeMatch;
133
133
  const query = event.queryStringParameters ?? {};
134
- const params = { ...event.pathParameters ?? {}, ...routeParams };
134
+ const params = { ...event.pathParameters, ...routeParams };
135
135
  const merged = {
136
136
  ...query,
137
137
  ...typeof body === "object" && body !== null ? body : {},
@@ -162,10 +162,26 @@ var wrapApi = (handler) => {
162
162
  return unauthorized();
163
163
  }
164
164
  }
165
+ let validatedInput = merged;
166
+ if (entry.schema && typeof entry.schema === "object" && "~standard" in entry.schema) {
167
+ const schema = entry.schema;
168
+ if (typeof schema["~standard"].validate === "function") {
169
+ const result = await schema["~standard"].validate(merged);
170
+ if (result.issues) {
171
+ const issues = result.issues.map((i) => {
172
+ const path2 = i.path?.map((p) => typeof p === "object" ? p.key : p).join(".");
173
+ return path2 ? `${path2}: ${i.message}` : i.message;
174
+ });
175
+ rt.logExecution(startTime, logInput, { status: 400 });
176
+ return { statusCode: 400, headers: { "Content-Type": "application/json" }, body: JSON.stringify({ error: "Validation failed", issues }) };
177
+ }
178
+ validatedInput = result.value;
179
+ }
180
+ }
165
181
  const { ctx, auth, ...rest } = sharedArgs;
166
182
  ctxProps = ctx && typeof ctx === "object" ? { ...ctx } : {};
167
183
  delete ctxProps.auth;
168
- const args = { ...ctxProps, req, input: merged, ok, fail, ...rest };
184
+ const args = { ...ctxProps, req, input: validatedInput, ok, fail, ...rest };
169
185
  if (auth) args.auth = auth;
170
186
  if (streamCtx) args.stream = streamCtx.stream;
171
187
  try {
@@ -3,7 +3,7 @@ import {
3
3
  createBucketClientWithEntities,
4
4
  createHandlerRuntime,
5
5
  toSeconds
6
- } from "../chunk-6HFS224S.js";
6
+ } from "../chunk-Q3ZDMZF3.js";
7
7
 
8
8
  // src/runtime/wrap-bucket.ts
9
9
  var ENV_DEP_SELF = "EFF_DEP_SELF";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  createHandlerRuntime
3
- } from "../chunk-6HFS224S.js";
3
+ } from "../chunk-Q3ZDMZF3.js";
4
4
 
5
5
  // src/runtime/wrap-cron.ts
6
6
  var wrapCron = (handler) => {
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  createHandlerRuntime
3
- } from "../chunk-6HFS224S.js";
3
+ } from "../chunk-Q3ZDMZF3.js";
4
4
 
5
5
  // src/runtime/wrap-fifo-queue.ts
6
6
  var parseMessages = (rawRecords, schema) => {
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  createHandlerRuntime
3
- } from "../chunk-6HFS224S.js";
3
+ } from "../chunk-Q3ZDMZF3.js";
4
4
 
5
5
  // src/runtime/wrap-mcp.ts
6
6
  var ErrorCode = {
@@ -39,6 +39,39 @@ var jsonResponse = (body, status = 200) => ({
39
39
  body: JSON.stringify(body)
40
40
  });
41
41
  var RESOURCE_NOT_FOUND = -32002;
42
+ var isStandardSchema = (input) => input != null && typeof input === "object" && "~standard" in input && typeof input["~standard"]?.jsonSchema?.input === "function";
43
+ var validateInput = async (schema, rawArgs, toolName) => {
44
+ const validate = schema["~standard"].validate;
45
+ if (typeof validate !== "function") return rawArgs;
46
+ const result = await validate(rawArgs);
47
+ if (result.issues) {
48
+ const messages = result.issues.map((i) => {
49
+ const path = i.path?.map((p) => typeof p === "object" ? p.key : p).join(".");
50
+ return path ? `${path}: ${i.message}` : i.message;
51
+ });
52
+ throw new Error(`Validation failed for tool "${toolName}": ${messages.join("; ")}`);
53
+ }
54
+ return result.value;
55
+ };
56
+ var wrapResourceResult = (raw, uri) => {
57
+ if (raw == null) return [{ uri, text: "null" }];
58
+ if (Array.isArray(raw)) {
59
+ if (raw.length > 0 && typeof raw[0] === "object" && raw[0] !== null && "uri" in raw[0]) return raw;
60
+ return [{ uri, text: JSON.stringify(raw) }];
61
+ }
62
+ if (typeof raw === "object" && "uri" in raw && ("text" in raw || "blob" in raw)) {
63
+ return [raw];
64
+ }
65
+ const text = typeof raw === "string" ? raw : JSON.stringify(raw);
66
+ return [{ uri, text }];
67
+ };
68
+ var wrapToolResult = (raw) => {
69
+ if (raw != null && typeof raw === "object" && "content" in raw && Array.isArray(raw.content)) {
70
+ return raw;
71
+ }
72
+ const text = typeof raw === "string" ? raw : JSON.stringify(raw ?? null);
73
+ return { content: [{ type: "text", text }] };
74
+ };
42
75
  var wrapMcp = (handler) => {
43
76
  const rt = createHandlerRuntime(handler, "mcp", handler.__spec.lambda?.logLevel ?? "info");
44
77
  const serverName = handler.__spec.name;
@@ -138,7 +171,7 @@ async function handleMethod(req, ctx, tools, resourceMap, prompts, serverName, s
138
171
  tools: Object.entries(tools).map(([name, def]) => ({
139
172
  name,
140
173
  description: def.description,
141
- inputSchema: def.input
174
+ inputSchema: isStandardSchema(def.input) ? def.input["~standard"].jsonSchema.input({ target: "draft-07" }) : def.input
142
175
  }))
143
176
  }
144
177
  };
@@ -149,8 +182,10 @@ async function handleMethod(req, ctx, tools, resourceMap, prompts, serverName, s
149
182
  }
150
183
  const tool = tools[toolName];
151
184
  try {
152
- const result = await tool.handler(req.params?.arguments ?? {}, ctx);
153
- return { jsonrpc: "2.0", id: req.id, result };
185
+ const rawArgs = req.params?.arguments ?? {};
186
+ const input = isStandardSchema(tool.input) ? await validateInput(tool.input, rawArgs, toolName) : rawArgs;
187
+ const raw = await tool.handler(input, ctx);
188
+ return { jsonrpc: "2.0", id: req.id, result: wrapToolResult(raw) };
154
189
  } catch (error) {
155
190
  return {
156
191
  jsonrpc: "2.0",
@@ -188,28 +223,47 @@ async function handleMethod(req, ctx, tools, resourceMap, prompts, serverName, s
188
223
  }
189
224
  const staticDef = resourceMap[uri];
190
225
  if (staticDef && !isTemplate(uri)) {
191
- const result = await staticDef.handler(ctx);
192
- const contents = Array.isArray(result) ? result : [result];
193
- return { jsonrpc: "2.0", id: req.id, result: { contents } };
226
+ const raw = await staticDef.handler(ctx);
227
+ return { jsonrpc: "2.0", id: req.id, result: { contents: wrapResourceResult(raw, uri) } };
194
228
  }
195
229
  for (const [template, def] of Object.entries(resourceMap)) {
196
230
  if (!isTemplate(template)) continue;
197
- const params = matchTemplate(template, uri);
198
- if (params) {
199
- const result = await def.handler(params, ctx);
200
- const contents = Array.isArray(result) ? result : [result];
201
- return { jsonrpc: "2.0", id: req.id, result: { contents } };
231
+ const rawParams = matchTemplate(template, uri);
232
+ if (rawParams) {
233
+ const defAny = def;
234
+ const params = defAny.params && typeof defAny.params === "object" && "~standard" in defAny.params ? await validateInput(defAny.params, rawParams, `resource ${template}`) : rawParams;
235
+ const raw = await def.handler(params, ctx);
236
+ return { jsonrpc: "2.0", id: req.id, result: { contents: wrapResourceResult(raw, uri) } };
202
237
  }
203
238
  }
204
239
  return { jsonrpc: "2.0", id: req.id, error: { code: RESOURCE_NOT_FOUND, message: "Resource not found", data: { uri } } };
205
240
  }
206
241
  // ── Prompts ──
207
242
  case "prompts/list": {
208
- const promptList = Object.entries(prompts).map(([name, def]) => ({
209
- name,
210
- ...def.description ? { description: def.description } : {},
211
- ...def.arguments ? { arguments: def.arguments } : {}
212
- }));
243
+ const promptList = Object.entries(prompts).map(([name, def]) => {
244
+ const defAny = def;
245
+ let args;
246
+ if (defAny.args && typeof defAny.args === "object" && "~standard" in defAny.args) {
247
+ const jsonSchema = defAny.args["~standard"].jsonSchema?.input?.({ target: "draft-07" });
248
+ if (jsonSchema?.properties) {
249
+ const required = new Set(jsonSchema.required ?? []);
250
+ args = Object.entries(jsonSchema.properties).map(([key, prop]) => ({
251
+ name: key,
252
+ ...prop.description ? { description: prop.description } : {},
253
+ ...required.has(key) ? { required: true } : {}
254
+ }));
255
+ }
256
+ } else if (Array.isArray(defAny.args)) {
257
+ args = defAny.args;
258
+ } else if (defAny.arguments) {
259
+ args = defAny.arguments;
260
+ }
261
+ return {
262
+ name,
263
+ ...def.description ? { description: def.description } : {},
264
+ ...args ? { arguments: args } : {}
265
+ };
266
+ });
213
267
  return { jsonrpc: "2.0", id: req.id, result: { prompts: promptList } };
214
268
  }
215
269
  case "prompts/get": {
@@ -218,9 +272,12 @@ async function handleMethod(req, ctx, tools, resourceMap, prompts, serverName, s
218
272
  return { jsonrpc: "2.0", id: req.id, error: { code: ErrorCode.InvalidParams, message: `Unknown prompt: ${promptName}` } };
219
273
  }
220
274
  const prompt = prompts[promptName];
221
- const args = req.params?.arguments ?? {};
275
+ const rawArgs = req.params?.arguments ?? {};
222
276
  try {
223
- const result = await prompt.handler(args, ctx);
277
+ const defAny = prompt;
278
+ const args = defAny.args && typeof defAny.args === "object" && "~standard" in defAny.args ? await validateInput(defAny.args, rawArgs, `prompt ${promptName}`) : rawArgs;
279
+ const raw = await prompt.handler(args, ctx);
280
+ const result = typeof raw === "string" ? { messages: [{ role: "user", content: { type: "text", text: raw } }] } : raw;
224
281
  return { jsonrpc: "2.0", id: req.id, result };
225
282
  } catch (error) {
226
283
  return { jsonrpc: "2.0", id: req.id, error: { code: ErrorCode.InternalError, message: error instanceof Error ? error.message : String(error) } };
@@ -78,7 +78,7 @@ var wrapMiddlewareFn = (middleware) => {
78
78
  };
79
79
  };
80
80
  var wrapMiddleware = (handler) => {
81
- const middleware = handler.__spec.middleware;
81
+ const middleware = handler.middleware;
82
82
  return wrapMiddlewareFn(middleware);
83
83
  };
84
84
  export {
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  createHandlerRuntime,
3
3
  createTableClient
4
- } from "../chunk-6HFS224S.js";
4
+ } from "../chunk-Q3ZDMZF3.js";
5
5
 
6
6
  // src/runtime/wrap-table-stream.ts
7
7
  import { unmarshall } from "@aws-sdk/util-dynamodb";
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  buildDeps,
3
3
  buildParams
4
- } from "../chunk-6HFS224S.js";
4
+ } from "../chunk-Q3ZDMZF3.js";
5
5
 
6
6
  // src/runtime/wrap-worker.ts
7
7
  import { SQS } from "@aws-sdk/client-sqs";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "effortless-aws",
3
- "version": "0.34.0",
3
+ "version": "0.36.0",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "description": "Code-first AWS Lambda framework. Export handlers, deploy with one command.",
@@ -49,6 +49,7 @@
49
49
  "typescript": "^5.9.3",
50
50
  "vite-tsconfig-paths": "^6.1.1",
51
51
  "@modelcontextprotocol/sdk": "^1.29.0",
52
+ "@standard-schema/spec": "^1.1.0",
52
53
  "vitest": "^4.0.18"
53
54
  },
54
55
  "scripts": {