effortless-aws 0.33.0 → 0.34.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/{chunk-HGSMOO4A.js → chunk-6HFS224S.js} +173 -34
- package/dist/index.d.ts +230 -48
- package/dist/index.js +38 -2
- package/dist/index.js.map +1 -1
- package/dist/runtime/wrap-api.js +9 -2
- package/dist/runtime/wrap-bucket.js +14 -3
- package/dist/runtime/wrap-cron.js +1 -1
- package/dist/runtime/wrap-fifo-queue.js +1 -1
- package/dist/runtime/wrap-mcp.js +235 -0
- package/dist/runtime/wrap-table-stream.js +1 -1
- package/dist/runtime/wrap-worker.js +1 -1
- package/package.json +3 -2
package/dist/index.d.ts
CHANGED
|
@@ -263,6 +263,12 @@ type HttpResponse = {
|
|
|
263
263
|
contentType?: ContentType;
|
|
264
264
|
/** Response headers (use for custom content-types not covered by contentType) */
|
|
265
265
|
headers?: Record<string, string>;
|
|
266
|
+
/**
|
|
267
|
+
* Multiple Set-Cookie values. Used by Lambda Function URLs to set multiple cookies
|
|
268
|
+
* in a single response (e.g., session cookie + CloudFront signed cookies).
|
|
269
|
+
* When present, takes precedence over `set-cookie` in `headers`.
|
|
270
|
+
*/
|
|
271
|
+
cookies?: string[];
|
|
266
272
|
/**
|
|
267
273
|
* Set to `true` to return binary data.
|
|
268
274
|
* When enabled, `body` must be a base64-encoded string and the response
|
|
@@ -317,7 +323,37 @@ type BucketClient = {
|
|
|
317
323
|
/** The underlying S3 bucket name */
|
|
318
324
|
bucketName: string;
|
|
319
325
|
};
|
|
326
|
+
/**
|
|
327
|
+
* Typed client for a single entity stored as JSON in a bucket.
|
|
328
|
+
* Objects are stored at `{entityName}/{id}.json`.
|
|
329
|
+
*/
|
|
330
|
+
type StoreEntityClient<T> = {
|
|
331
|
+
/** Store a JSON document by id */
|
|
332
|
+
put(id: string, data: T): Promise<void>;
|
|
333
|
+
/** Retrieve a JSON document by id. Returns undefined if not found. */
|
|
334
|
+
get(id: string): Promise<T | undefined>;
|
|
335
|
+
/** Delete a document by id */
|
|
336
|
+
delete(id: string): Promise<void>;
|
|
337
|
+
/** List all documents for this entity */
|
|
338
|
+
list(): Promise<{
|
|
339
|
+
id: string;
|
|
340
|
+
data: T;
|
|
341
|
+
}[]>;
|
|
342
|
+
};
|
|
343
|
+
/**
|
|
344
|
+
* BucketClient extended with typed entity clients.
|
|
345
|
+
*/
|
|
346
|
+
type BucketClientWithEntities<Entities extends Record<string, any>> = BucketClient & {
|
|
347
|
+
[K in keyof Entities]: StoreEntityClient<Entities[K]>;
|
|
348
|
+
};
|
|
320
349
|
|
|
350
|
+
/**
|
|
351
|
+
* Per-entity configuration for typed JSON key-value storage within a bucket.
|
|
352
|
+
*/
|
|
353
|
+
type BucketEntityConfig = {
|
|
354
|
+
/** Cache duration for CloudFront/browser caching (e.g., "10s", "5m", "1h"). No caching if omitted. */
|
|
355
|
+
cache?: Duration;
|
|
356
|
+
};
|
|
321
357
|
/**
|
|
322
358
|
* Configuration options for defineBucket.
|
|
323
359
|
*/
|
|
@@ -333,6 +369,12 @@ type BucketConfig = {
|
|
|
333
369
|
prefix?: string;
|
|
334
370
|
/** S3 key suffix filter for event notifications (e.g., ".jpg") */
|
|
335
371
|
suffix?: string;
|
|
372
|
+
/** Typed JSON entity definitions for key-value storage */
|
|
373
|
+
entities?: Record<string, BucketEntityConfig>;
|
|
374
|
+
/** Local directory to seed into bucket on deploy (only uploads files that don't already exist) */
|
|
375
|
+
seed?: string;
|
|
376
|
+
/** Local directory to sync into bucket on every deploy (uploads new/changed, deletes removed) */
|
|
377
|
+
sync?: string;
|
|
336
378
|
};
|
|
337
379
|
/**
|
|
338
380
|
* S3 event record passed to onObjectCreated/onObjectRemoved callbacks.
|
|
@@ -354,8 +396,8 @@ type BucketEvent = {
|
|
|
354
396
|
/** Spread ctx into callback args (empty when no setup) */
|
|
355
397
|
type SpreadCtx$6<C> = [C] extends [undefined] ? {} : C & {};
|
|
356
398
|
/** Setup factory — receives bucket/deps/config/files based on what was declared */
|
|
357
|
-
type SetupArgs$6<D, P, HasFiles extends boolean> = {
|
|
358
|
-
bucket: BucketClient
|
|
399
|
+
type SetupArgs$6<D, P, HasFiles extends boolean, Entities extends Record<string, any> = {}> = {
|
|
400
|
+
bucket: {} extends Entities ? BucketClient : BucketClientWithEntities<Entities>;
|
|
359
401
|
} & ([D] extends [undefined] ? {} : {
|
|
360
402
|
deps: ResolveDeps<D>;
|
|
361
403
|
}) & ([P] extends [undefined] ? {} : {
|
|
@@ -379,7 +421,7 @@ type BucketObjectRemovedFn<C = undefined> = (args: {
|
|
|
379
421
|
* Internal handler object created by defineBucket
|
|
380
422
|
* @internal
|
|
381
423
|
*/
|
|
382
|
-
type BucketHandler$1<C = any> = {
|
|
424
|
+
type BucketHandler$1<C = any, Entities extends Record<string, any> = {}> = {
|
|
383
425
|
readonly __brand: "effortless-bucket";
|
|
384
426
|
readonly __spec: BucketConfig;
|
|
385
427
|
readonly onError?: (...args: any[]) => any;
|
|
@@ -397,32 +439,40 @@ type BucketOptions = {
|
|
|
397
439
|
prefix?: string;
|
|
398
440
|
/** S3 key suffix filter for event notifications (e.g., ".jpg") */
|
|
399
441
|
suffix?: string;
|
|
442
|
+
/** Local directory to seed into bucket on deploy (only uploads files that don't already exist) */
|
|
443
|
+
seed?: string;
|
|
444
|
+
/** Local directory to sync into bucket on every deploy (uploads new/changed, deletes removed) */
|
|
445
|
+
sync?: string;
|
|
400
446
|
};
|
|
401
|
-
interface BucketBuilder<D = undefined, P = undefined, C = undefined, HasFiles extends boolean = false> {
|
|
447
|
+
interface BucketBuilder<D = undefined, P = undefined, C = undefined, HasFiles extends boolean = false, Entities extends Record<string, any> = {}> {
|
|
402
448
|
/** Declare handler dependencies */
|
|
403
|
-
deps<D2 extends Record<string, AnyDepHandler>>(fn: () => D2): BucketBuilder<D2, P, C, HasFiles>;
|
|
449
|
+
deps<D2 extends Record<string, AnyDepHandler>>(fn: () => D2): BucketBuilder<D2, P, C, HasFiles, Entities>;
|
|
404
450
|
/** Declare SSM secrets */
|
|
405
|
-
config<P2 extends Record<string, AnySecretRef>>(fn: ConfigFactory<P2>): BucketBuilder<D, P2, C, HasFiles>;
|
|
451
|
+
config<P2 extends Record<string, AnySecretRef>>(fn: ConfigFactory<P2>): BucketBuilder<D, P2, C, HasFiles, Entities>;
|
|
406
452
|
/** Include static files in the Lambda ZIP */
|
|
407
|
-
include(glob: string): BucketBuilder<D, P, C, true>;
|
|
453
|
+
include(glob: string): BucketBuilder<D, P, C, true, Entities>;
|
|
454
|
+
/** Register a typed JSON entity stored as `{name}/{id}.json` in the bucket */
|
|
455
|
+
entity<N extends string, T>(name: N, options?: BucketEntityConfig): BucketBuilder<D, P, C, HasFiles, Entities & {
|
|
456
|
+
[K in N]: T;
|
|
457
|
+
}>;
|
|
408
458
|
/** Initialize shared state on cold start with lambda options */
|
|
409
|
-
setup(lambda: LambdaOptions): BucketBuilder<D, P, C, HasFiles>;
|
|
459
|
+
setup(lambda: LambdaOptions): BucketBuilder<D, P, C, HasFiles, Entities>;
|
|
410
460
|
/** Initialize shared state on cold start. Receives bucket (self-client), deps, config, files. */
|
|
411
|
-
setup<C2>(fn: (args: SetupArgs$6<D, P, HasFiles>) => C2 | Promise<C2>): BucketBuilder<D, P, C2, HasFiles>;
|
|
461
|
+
setup<C2>(fn: (args: SetupArgs$6<D, P, HasFiles, Entities>) => C2 | Promise<C2>): BucketBuilder<D, P, C2, HasFiles, Entities>;
|
|
412
462
|
/** Initialize shared state on cold start with lambda options. Receives bucket (self-client), deps, config, files. */
|
|
413
|
-
setup<C2>(fn: (args: SetupArgs$6<D, P, HasFiles>) => C2 | Promise<C2>, lambda: LambdaOptions): BucketBuilder<D, P, C2, HasFiles>;
|
|
463
|
+
setup<C2>(fn: (args: SetupArgs$6<D, P, HasFiles, Entities>) => C2 | Promise<C2>, lambda: LambdaOptions): BucketBuilder<D, P, C2, HasFiles, Entities>;
|
|
414
464
|
/** Handle errors thrown by callbacks */
|
|
415
465
|
onError(fn: (args: {
|
|
416
466
|
error: unknown;
|
|
417
|
-
} & SpreadCtx$6<C>) => void | Promise<void>): BucketBuilder<D, P, C, HasFiles>;
|
|
467
|
+
} & SpreadCtx$6<C>) => void | Promise<void>): BucketBuilder<D, P, C, HasFiles, Entities>;
|
|
418
468
|
/** Cleanup callback — runs after each invocation, before Lambda freezes */
|
|
419
|
-
onCleanup(fn: (args: SpreadCtx$6<C>) => void | Promise<void>): BucketBuilder<D, P, C, HasFiles>;
|
|
469
|
+
onCleanup(fn: (args: SpreadCtx$6<C>) => void | Promise<void>): BucketBuilder<D, P, C, HasFiles, Entities>;
|
|
420
470
|
/** Handle S3 ObjectCreated events (terminal — returns finalized handler) */
|
|
421
|
-
onObjectCreated(fn: BucketObjectCreatedFn<C>): BucketHandler$1<C>;
|
|
471
|
+
onObjectCreated(fn: BucketObjectCreatedFn<C>): BucketHandler$1<C, Entities>;
|
|
422
472
|
/** Handle S3 ObjectRemoved events (terminal — returns finalized handler) */
|
|
423
|
-
onObjectRemoved(fn: BucketObjectRemovedFn<C>): BucketHandler$1<C>;
|
|
473
|
+
onObjectRemoved(fn: BucketObjectRemovedFn<C>): BucketHandler$1<C, Entities>;
|
|
424
474
|
/** Finalize as resource-only bucket (no Lambda) */
|
|
425
|
-
build(): BucketHandler$1<C>;
|
|
475
|
+
build(): BucketHandler$1<C, Entities>;
|
|
426
476
|
}
|
|
427
477
|
/**
|
|
428
478
|
* Define an S3 bucket with optional event handlers.
|
|
@@ -926,10 +976,10 @@ type WorkerClient<T = unknown> = {
|
|
|
926
976
|
};
|
|
927
977
|
|
|
928
978
|
/** Dep value types supported by the deps declaration */
|
|
929
|
-
type AnyDepHandler = TableHandler$1<any, any> | BucketHandler$1<any> | MailerHandler | FifoQueueHandler$1<any, any> | WorkerHandler$1<any, any>;
|
|
979
|
+
type AnyDepHandler = TableHandler$1<any, any> | BucketHandler$1<any, any> | MailerHandler | FifoQueueHandler$1<any, any> | WorkerHandler$1<any, any>;
|
|
930
980
|
/** Maps a deps declaration to resolved runtime client types */
|
|
931
981
|
type ResolveDeps<D> = {
|
|
932
|
-
[K in keyof D]: D[K] extends TableHandler$1<infer T> ? TableClient<T> : D[K] extends BucketHandler$1 ? BucketClient : D[K] extends MailerHandler ? EmailClient : D[K] extends FifoQueueHandler$1<infer T> ? QueueClient<T> : D[K] extends WorkerHandler$1<infer T> ? WorkerClient<T> : never;
|
|
982
|
+
[K in keyof D]: D[K] extends TableHandler$1<infer T> ? TableClient<T> : D[K] extends BucketHandler$1<any, infer E> ? ({} extends E ? BucketClient : BucketClientWithEntities<E>) : D[K] extends MailerHandler ? EmailClient : D[K] extends FifoQueueHandler$1<infer T> ? QueueClient<T> : D[K] extends WorkerHandler$1<infer T> ? WorkerClient<T> : never;
|
|
933
983
|
};
|
|
934
984
|
|
|
935
985
|
/** DynamoDB Streams view type - determines what data is captured in stream records */
|
|
@@ -1160,6 +1210,18 @@ declare const defineApp: () => (options: AppConfig) => AppHandler;
|
|
|
1160
1210
|
type AnyRoutableHandler = {
|
|
1161
1211
|
readonly __brand: string;
|
|
1162
1212
|
};
|
|
1213
|
+
/** Route configuration for serving bucket content through CloudFront */
|
|
1214
|
+
type BucketRouteConfig = {
|
|
1215
|
+
bucket: {
|
|
1216
|
+
readonly __brand: "effortless-bucket";
|
|
1217
|
+
};
|
|
1218
|
+
/** Access control: "private" requires CloudFront signed cookies, "public" serves openly. Default: "public" */
|
|
1219
|
+
access?: "private" | "public";
|
|
1220
|
+
};
|
|
1221
|
+
/** A route value: either an API handler or a bucket route config */
|
|
1222
|
+
type RouteValue = AnyRoutableHandler | BucketRouteConfig;
|
|
1223
|
+
/** Type guard for bucket route entries */
|
|
1224
|
+
declare const isBucketRoute: (v: unknown) => v is BucketRouteConfig;
|
|
1163
1225
|
/** Simplified request object passed to middleware */
|
|
1164
1226
|
type MiddlewareRequest = {
|
|
1165
1227
|
uri: string;
|
|
@@ -1206,10 +1268,10 @@ type StaticSiteConfig = {
|
|
|
1206
1268
|
build?: string;
|
|
1207
1269
|
/** Custom domain name. Accepts a string (same domain for all stages) or a Record mapping stage names to domains (e.g., `{ prod: "example.com", dev: "dev.example.com" }`). Requires an ACM certificate in us-east-1. If the cert also covers www, a 301 redirect from www to non-www is set up automatically. */
|
|
1208
1270
|
domain?: string | Record<string, string>;
|
|
1209
|
-
/** CloudFront route overrides: path patterns forwarded to API Gateway
|
|
1210
|
-
* Keys are CloudFront path patterns (e.g., "/api/*"), values are HTTP handlers.
|
|
1211
|
-
* Example: `routes: { "/api/*": api }` */
|
|
1212
|
-
routes?: Record<string,
|
|
1271
|
+
/** CloudFront route overrides: path patterns forwarded to API Gateway or S3 bucket origins.
|
|
1272
|
+
* Keys are CloudFront path patterns (e.g., "/api/*"), values are HTTP handlers or bucket route configs.
|
|
1273
|
+
* Example: `routes: { "/api/*": api, "/files/*": { bucket: storage, access: "private" } }` */
|
|
1274
|
+
routes?: Record<string, RouteValue>;
|
|
1213
1275
|
/** Custom 404 error page path relative to `dir` (e.g. "404.html").
|
|
1214
1276
|
* For non-SPA sites only. If not set, a default page is generated automatically. */
|
|
1215
1277
|
errorPage?: string;
|
|
@@ -1236,17 +1298,27 @@ type StaticSiteHandler = {
|
|
|
1236
1298
|
*/
|
|
1237
1299
|
declare const defineStaticSite: () => (options: StaticSiteConfig) => StaticSiteHandler;
|
|
1238
1300
|
|
|
1301
|
+
/** Options for CloudFront signed cookie policy */
|
|
1302
|
+
type CdnPolicyOptions = {
|
|
1303
|
+
/** Path pattern to grant access to (e.g., "/files/users/123/*"). Supports `*` and `?` wildcards. */
|
|
1304
|
+
path: string;
|
|
1305
|
+
/** How long the CDN access is valid (e.g., "1h", "30m") */
|
|
1306
|
+
ttl: Duration;
|
|
1307
|
+
};
|
|
1239
1308
|
/** Options for creating a session */
|
|
1240
1309
|
type SessionOptions = {
|
|
1241
1310
|
expiresIn?: Duration;
|
|
1311
|
+
/** CloudFront signed cookie policy for CDN-level access control */
|
|
1312
|
+
cdnPolicy?: CdnPolicyOptions;
|
|
1242
1313
|
};
|
|
1243
|
-
/** Session response with Set-Cookie
|
|
1314
|
+
/** Session response with Set-Cookie headers */
|
|
1244
1315
|
type SessionResponse = {
|
|
1245
1316
|
status: 200;
|
|
1246
1317
|
body: {
|
|
1247
1318
|
ok: true;
|
|
1248
1319
|
};
|
|
1249
1320
|
headers: Record<string, string>;
|
|
1321
|
+
cookies?: string[];
|
|
1250
1322
|
};
|
|
1251
1323
|
/**
|
|
1252
1324
|
* Auth helpers injected into API handler callback args when `auth` is configured.
|
|
@@ -1300,12 +1372,28 @@ type OkHelper = (body?: unknown, status?: number) => HttpResponse;
|
|
|
1300
1372
|
/** Error response helper: `fail("message")` → `{ status: 400, body: { error: "message" } }` */
|
|
1301
1373
|
type FailHelper = (message: string, status?: number) => HttpResponse;
|
|
1302
1374
|
type HttpMethod = "GET" | "POST" | "PUT" | "PATCH" | "DELETE";
|
|
1375
|
+
/** Cache options for a GET route. Duration shorthand (e.g. "30s", "5m") or object for fine-grained control. */
|
|
1376
|
+
type CacheOptions = Duration | {
|
|
1377
|
+
ttl: Duration;
|
|
1378
|
+
swr?: Duration;
|
|
1379
|
+
scope?: "public" | "private";
|
|
1380
|
+
};
|
|
1381
|
+
/** Resolved cache config with numeric seconds */
|
|
1382
|
+
type ResolvedCache = {
|
|
1383
|
+
private?: false;
|
|
1384
|
+
ttl: number;
|
|
1385
|
+
swr: number;
|
|
1386
|
+
} | {
|
|
1387
|
+
private: true;
|
|
1388
|
+
ttl: number;
|
|
1389
|
+
};
|
|
1303
1390
|
/** Parsed route definition stored at runtime */
|
|
1304
1391
|
type RouteEntry = {
|
|
1305
1392
|
method: HttpMethod;
|
|
1306
1393
|
path: string;
|
|
1307
1394
|
onRequest: (...args: any[]) => any;
|
|
1308
1395
|
public?: boolean;
|
|
1396
|
+
cache?: ResolvedCache;
|
|
1309
1397
|
};
|
|
1310
1398
|
/** Spread ctx into route args: Omit auth config, add AuthHelpers if present */
|
|
1311
1399
|
type SpreadCtx$2<C> = ([C] extends [undefined] ? {} : Omit<C & {}, 'auth'>) & ([ExtractAuth<C>] extends [undefined] ? {} : {
|
|
@@ -1322,10 +1410,14 @@ type RouteArgs<C, ST> = SpreadCtx$2<C> & {
|
|
|
1322
1410
|
} : {});
|
|
1323
1411
|
/** Route handler function */
|
|
1324
1412
|
type RouteHandler<C, ST> = (args: RouteArgs<C, ST>) => Promise<HttpResponse | void> | HttpResponse | void;
|
|
1325
|
-
/** Route options
|
|
1413
|
+
/** Route options for all methods */
|
|
1326
1414
|
type RouteOptions = {
|
|
1327
1415
|
public?: boolean;
|
|
1328
1416
|
};
|
|
1417
|
+
/** Route options for GET — supports caching */
|
|
1418
|
+
type GetRouteOptions = RouteOptions & {
|
|
1419
|
+
cache?: CacheOptions;
|
|
1420
|
+
};
|
|
1329
1421
|
/** Setup factory — receives deps/config/files/enableAuth based on what was declared */
|
|
1330
1422
|
type SetupArgs$2<D, P, HasFiles extends boolean> = {
|
|
1331
1423
|
enableAuth: EnableAuth;
|
|
@@ -1375,7 +1467,7 @@ type ApiOptions = {
|
|
|
1375
1467
|
* Has `__brand` so CLI discovers it. Each `.get()/.post()` adds a route and returns self.
|
|
1376
1468
|
*/
|
|
1377
1469
|
interface ApiRoutes<C = undefined, ST extends boolean = false> extends ApiHandler<C> {
|
|
1378
|
-
get(path: `/${string}`, handler: RouteHandler<C, ST>, options?:
|
|
1470
|
+
get(path: `/${string}`, handler: RouteHandler<C, ST>, options?: GetRouteOptions): ApiRoutes<C, ST>;
|
|
1379
1471
|
post(path: `/${string}`, handler: RouteHandler<C, ST>, options?: RouteOptions): ApiRoutes<C, ST>;
|
|
1380
1472
|
put(path: `/${string}`, handler: RouteHandler<C, ST>, options?: RouteOptions): ApiRoutes<C, ST>;
|
|
1381
1473
|
patch(path: `/${string}`, handler: RouteHandler<C, ST>, options?: RouteOptions): ApiRoutes<C, ST>;
|
|
@@ -1410,7 +1502,7 @@ interface ApiBuilder<D = undefined, P = undefined, C = undefined, ST extends boo
|
|
|
1410
1502
|
/** Cleanup callback — runs after each invocation, before Lambda freezes */
|
|
1411
1503
|
onCleanup(fn: (args: SpreadCtx$2<C>) => void | Promise<void>): ApiBuilder<D, P, C, ST, HasFiles>;
|
|
1412
1504
|
/** Add a GET route (terminal — returns finalized handler with route methods) */
|
|
1413
|
-
get(path: `/${string}`, handler: RouteHandler<C, ST>, options?:
|
|
1505
|
+
get(path: `/${string}`, handler: RouteHandler<C, ST>, options?: GetRouteOptions): ApiRoutes<C, ST>;
|
|
1414
1506
|
/** Add a POST route (terminal) */
|
|
1415
1507
|
post(path: `/${string}`, handler: RouteHandler<C, ST>, options?: RouteOptions): ApiRoutes<C, ST>;
|
|
1416
1508
|
/** Add a PUT route (terminal) */
|
|
@@ -1565,6 +1657,8 @@ type McpConfig = {
|
|
|
1565
1657
|
name: string;
|
|
1566
1658
|
/** MCP server version (default: "1.0.0") */
|
|
1567
1659
|
version?: string;
|
|
1660
|
+
/** Human-readable description — sent to clients in initialize response as system prompt context */
|
|
1661
|
+
instructions?: string;
|
|
1568
1662
|
/** Lambda function settings (memory, timeout, permissions, etc.) */
|
|
1569
1663
|
lambda?: LambdaWithPermissions;
|
|
1570
1664
|
};
|
|
@@ -1595,8 +1689,93 @@ type McpToolResult = {
|
|
|
1595
1689
|
content: McpToolContent[];
|
|
1596
1690
|
isError?: boolean;
|
|
1597
1691
|
};
|
|
1692
|
+
/** Content returned when reading a resource */
|
|
1693
|
+
type McpResourceContent = {
|
|
1694
|
+
uri: string;
|
|
1695
|
+
mimeType?: string;
|
|
1696
|
+
text: string;
|
|
1697
|
+
} | {
|
|
1698
|
+
uri: string;
|
|
1699
|
+
mimeType?: string;
|
|
1700
|
+
blob: string;
|
|
1701
|
+
};
|
|
1702
|
+
/** A static resource definition */
|
|
1703
|
+
type McpResourceDef$1<C = undefined> = {
|
|
1704
|
+
/** Human-readable name */
|
|
1705
|
+
name: string;
|
|
1706
|
+
/** Optional description */
|
|
1707
|
+
description?: string;
|
|
1708
|
+
/** Optional MIME type */
|
|
1709
|
+
mimeType?: string;
|
|
1710
|
+
/** Handler called on resources/read */
|
|
1711
|
+
handler: (ctx: SpreadCtx<C>) => McpResourceContent | McpResourceContent[] | Promise<McpResourceContent | McpResourceContent[]>;
|
|
1712
|
+
};
|
|
1713
|
+
/** A parameterized resource template (URI template RFC 6570) */
|
|
1714
|
+
type McpResourceTemplateDef$1<C = undefined> = {
|
|
1715
|
+
/** Human-readable name */
|
|
1716
|
+
name: string;
|
|
1717
|
+
/** Optional description */
|
|
1718
|
+
description?: string;
|
|
1719
|
+
/** Optional MIME type */
|
|
1720
|
+
mimeType?: string;
|
|
1721
|
+
/** Handler called on resources/read — receives matched URI params */
|
|
1722
|
+
handler: (params: Record<string, string>, ctx: SpreadCtx<C>) => McpResourceContent | McpResourceContent[] | Promise<McpResourceContent | McpResourceContent[]>;
|
|
1723
|
+
};
|
|
1724
|
+
/** Map of uri → resource definition, or uriTemplate → template definition */
|
|
1725
|
+
type McpResourceMap$1<C = undefined> = {
|
|
1726
|
+
[uriOrTemplate: string]: McpResourceDef$1<C> | McpResourceTemplateDef$1<C>;
|
|
1727
|
+
};
|
|
1728
|
+
/** An argument accepted by a prompt */
|
|
1729
|
+
type McpPromptArgument = {
|
|
1730
|
+
/** Argument name */
|
|
1731
|
+
name: string;
|
|
1732
|
+
/** Optional description */
|
|
1733
|
+
description?: string;
|
|
1734
|
+
/** Whether the argument is required (default: false) */
|
|
1735
|
+
required?: boolean;
|
|
1736
|
+
};
|
|
1737
|
+
/** Content block inside a prompt message */
|
|
1738
|
+
type McpPromptContent = {
|
|
1739
|
+
type: "text";
|
|
1740
|
+
text: string;
|
|
1741
|
+
} | {
|
|
1742
|
+
type: "image";
|
|
1743
|
+
data: string;
|
|
1744
|
+
mimeType: string;
|
|
1745
|
+
} | {
|
|
1746
|
+
type: "audio";
|
|
1747
|
+
data: string;
|
|
1748
|
+
mimeType: string;
|
|
1749
|
+
} | {
|
|
1750
|
+
type: "resource";
|
|
1751
|
+
resource: {
|
|
1752
|
+
uri: string;
|
|
1753
|
+
mimeType?: string;
|
|
1754
|
+
text?: string;
|
|
1755
|
+
blob?: string;
|
|
1756
|
+
};
|
|
1757
|
+
};
|
|
1758
|
+
/** A single message returned by a prompt */
|
|
1759
|
+
type McpPromptMessage = {
|
|
1760
|
+
role: "user" | "assistant";
|
|
1761
|
+
content: McpPromptContent;
|
|
1762
|
+
};
|
|
1763
|
+
/** Result returned by a prompt handler */
|
|
1764
|
+
type McpPromptResult = {
|
|
1765
|
+
description?: string;
|
|
1766
|
+
messages: McpPromptMessage[];
|
|
1767
|
+
};
|
|
1768
|
+
/** A single prompt definition */
|
|
1769
|
+
type McpPromptDef$1<C = undefined> = {
|
|
1770
|
+
/** Human-readable description */
|
|
1771
|
+
description?: string;
|
|
1772
|
+
/** Arguments this prompt accepts */
|
|
1773
|
+
arguments?: McpPromptArgument[];
|
|
1774
|
+
/** Handler called on prompts/get — receives argument values */
|
|
1775
|
+
handler: (args: Record<string, string>, ctx: SpreadCtx<C>) => McpPromptResult | Promise<McpPromptResult>;
|
|
1776
|
+
};
|
|
1598
1777
|
/** A single MCP tool definition */
|
|
1599
|
-
type McpToolDef<C = undefined> = {
|
|
1778
|
+
type McpToolDef$1<C = undefined> = {
|
|
1600
1779
|
/** Human-readable description of the tool */
|
|
1601
1780
|
description: string;
|
|
1602
1781
|
/** JSON Schema describing the tool's input parameters */
|
|
@@ -1604,8 +1783,10 @@ type McpToolDef<C = undefined> = {
|
|
|
1604
1783
|
/** Handler function called when the tool is invoked */
|
|
1605
1784
|
handler: (input: any, ctx: SpreadCtx<C>) => McpToolResult | Promise<McpToolResult>;
|
|
1606
1785
|
};
|
|
1607
|
-
/** Setup factory — receives deps/config/files based on what was declared */
|
|
1608
|
-
type SetupArgs<D, P, HasFiles extends boolean> =
|
|
1786
|
+
/** Setup factory — receives deps/config/files/enableAuth based on what was declared */
|
|
1787
|
+
type SetupArgs<D, P, HasFiles extends boolean> = {
|
|
1788
|
+
enableAuth: EnableAuth;
|
|
1789
|
+
} & ([D] extends [undefined] ? {} : {
|
|
1609
1790
|
deps: ResolveDeps<D>;
|
|
1610
1791
|
}) & ([P] extends [undefined] ? {} : {
|
|
1611
1792
|
config: ResolveConfig<P & {}>;
|
|
@@ -1627,6 +1808,8 @@ type McpHandler$1<C = any> = {
|
|
|
1627
1808
|
readonly deps?: Record<string, unknown> | (() => Record<string, unknown>);
|
|
1628
1809
|
readonly config?: Record<string, unknown>;
|
|
1629
1810
|
readonly static?: string[];
|
|
1811
|
+
readonly resources?: (...args: any[]) => any;
|
|
1812
|
+
readonly prompts?: (...args: any[]) => any;
|
|
1630
1813
|
readonly tools?: (...args: any[]) => any;
|
|
1631
1814
|
};
|
|
1632
1815
|
/** Options passed to `defineMcp()` */
|
|
@@ -1635,6 +1818,8 @@ type McpOptions = {
|
|
|
1635
1818
|
name: string;
|
|
1636
1819
|
/** MCP server version (default: "1.0.0") */
|
|
1637
1820
|
version?: string;
|
|
1821
|
+
/** Human-readable description — sent to clients in initialize response as system prompt context */
|
|
1822
|
+
instructions?: string;
|
|
1638
1823
|
};
|
|
1639
1824
|
interface McpBuilder<D = undefined, P = undefined, C = undefined, HasFiles extends boolean = false> {
|
|
1640
1825
|
/** Declare handler dependencies (tables, queues, buckets, mailers, workers) */
|
|
@@ -1656,38 +1841,35 @@ interface McpBuilder<D = undefined, P = undefined, C = undefined, HasFiles exten
|
|
|
1656
1841
|
} & SpreadCtx<C>) => void | Promise<void>): McpBuilder<D, P, C, HasFiles>;
|
|
1657
1842
|
/** Cleanup callback — runs on shutdown */
|
|
1658
1843
|
onCleanup(fn: (args: SpreadCtx<C>) => void | Promise<void>): McpBuilder<D, P, C, HasFiles>;
|
|
1844
|
+
/** Define MCP resources (chainable) */
|
|
1845
|
+
resources(fn: (ctx: SpreadCtx<C>) => McpResourceMap$1<C>): McpBuilder<D, P, C, HasFiles>;
|
|
1846
|
+
/** Define MCP prompts (chainable) */
|
|
1847
|
+
prompts(fn: (ctx: SpreadCtx<C>) => Record<string, McpPromptDef$1<C>>): McpBuilder<D, P, C, HasFiles>;
|
|
1659
1848
|
/** Define MCP tools (terminal) */
|
|
1660
|
-
tools(fn: (ctx: SpreadCtx<C>) => Record<string, McpToolDef<C>>): McpHandler$1<C>;
|
|
1849
|
+
tools(fn: (ctx: SpreadCtx<C>) => Record<string, McpToolDef$1<C>>): McpHandler$1<C>;
|
|
1661
1850
|
}
|
|
1662
1851
|
/**
|
|
1663
1852
|
* Define an MCP (Model Context Protocol) server endpoint.
|
|
1664
1853
|
*
|
|
1665
|
-
* Creates a Lambda-backed MCP server that exposes tools
|
|
1666
|
-
* and MCP-compatible clients
|
|
1854
|
+
* Creates a Lambda-backed MCP server that exposes tools, resources, and prompts
|
|
1855
|
+
* for AI models and MCP-compatible clients via Streamable HTTP (JSON-RPC over POST).
|
|
1667
1856
|
*
|
|
1668
|
-
* @
|
|
1669
|
-
*
|
|
1670
|
-
* export const mcp = defineMcp({ name: "my-tools" })
|
|
1671
|
-
* .deps(() => ({ users: usersTable }))
|
|
1672
|
-
* .setup(({ deps }) => ({ db: deps.users }))
|
|
1673
|
-
* .tools(({ db }) => ({
|
|
1674
|
-
* get_user: {
|
|
1675
|
-
* description: "Get a user by ID",
|
|
1676
|
-
* input: { type: "object", properties: { id: { type: "string" } }, required: ["id"] },
|
|
1677
|
-
* handler: async (input) => ({
|
|
1678
|
-
* content: [{ type: "text", text: JSON.stringify(await db.get({ pk: input.id, sk: "profile" })) }]
|
|
1679
|
-
* })
|
|
1680
|
-
* }
|
|
1681
|
-
* }))
|
|
1682
|
-
* ```
|
|
1857
|
+
* @see https://modelcontextprotocol.io/specification/2025-03-26 — MCP specification
|
|
1858
|
+
* @see https://effortless-aws.com/use-cases/mcp-server/ — full documentation with examples
|
|
1683
1859
|
*/
|
|
1684
1860
|
declare function defineMcp(options: McpOptions): McpBuilder;
|
|
1685
1861
|
|
|
1862
|
+
type McpToolDef = McpToolDef$1;
|
|
1863
|
+
type McpResourceDef = McpResourceDef$1;
|
|
1864
|
+
type McpResourceTemplateDef = McpResourceTemplateDef$1;
|
|
1865
|
+
type McpResourceMap = McpResourceMap$1;
|
|
1866
|
+
type McpPromptDef = McpPromptDef$1;
|
|
1867
|
+
|
|
1686
1868
|
type TableHandler<T = Record<string, unknown>> = TableHandler$1<T, any>;
|
|
1687
1869
|
type FifoQueueHandler<T = unknown> = FifoQueueHandler$1<T, any>;
|
|
1688
|
-
type BucketHandler = BucketHandler$1<any>;
|
|
1870
|
+
type BucketHandler<Entities extends Record<string, any> = {}> = BucketHandler$1<any, Entities>;
|
|
1689
1871
|
type CronHandler = CronHandler$1<any>;
|
|
1690
1872
|
type WorkerHandler<T = any> = WorkerHandler$1<T, any>;
|
|
1691
1873
|
type McpHandler = McpHandler$1<any>;
|
|
1692
1874
|
|
|
1693
|
-
export { type ApiAuthConfig, type ApiConfig, type ApiHandler, type ApiRoutes, type AppConfig, type AppHandler, type AuthHelpers, type BucketClient, type BucketConfig, type BucketEvent, type BucketHandler, type ConfigHelpers, type ContentType, type CronConfig, type CronHandler, type DefineSecretFn, type Duration, type EffortlessConfig, type EmailClient, type FifoQueueConfig, type FifoQueueHandler, type FifoQueueMessage, type HttpMethod$1 as HttpMethod, type HttpRequest, type HttpResponse, type LogLevel, type MailerConfig, type MailerHandler, type McpConfig, type McpHandler, type McpInputSchema, type McpToolContent, type McpToolDef, type McpToolResult, type MiddlewareDeny, type MiddlewareHandler, type MiddlewareRedirect, type MiddlewareRequest, type MiddlewareResult, type ParamRef, type Permission, type PutInput, type PutOptions, type QueryByTagParams, type QueryParams, type QueueClient, type ResponseStream, type SecretRef, type SendEmailOptions, type SendMessageInput, type SkCondition, type StaticFiles, type StaticSiteConfig, type StaticSiteHandler, type StaticSiteSeo, type StreamView, type TableClient, type TableConfig, type TableHandler, type TableItem, type TableKey, type TableRecord, type Timezone, type UpdateActions, type WorkerClient, type WorkerConfig, type WorkerHandler, type WorkerSendOptions, defineApi, defineApp, defineBucket, defineConfig, defineCron, defineFifoQueue, defineMailer, defineMcp, defineSecret, defineStaticSite, defineTable, defineWorker, generateBase64, generateHex, generateUuid, param, secret, toSeconds };
|
|
1875
|
+
export { type ApiAuthConfig, type ApiConfig, type ApiHandler, type ApiRoutes, type AppConfig, type AppHandler, type AuthHelpers, type BucketClient, type BucketClientWithEntities, type BucketConfig, type BucketEntityConfig, type BucketEvent, type BucketHandler, type BucketRouteConfig, type CacheOptions, type CdnPolicyOptions, type ConfigHelpers, type ContentType, type CronConfig, type CronHandler, type DefineSecretFn, type Duration, type EffortlessConfig, type EmailClient, type FifoQueueConfig, type FifoQueueHandler, type FifoQueueMessage, type HttpMethod$1 as HttpMethod, type HttpRequest, type HttpResponse, type LogLevel, type MailerConfig, type MailerHandler, type McpConfig, type McpHandler, type McpInputSchema, type McpPromptArgument, type McpPromptContent, type McpPromptDef, type McpPromptMessage, type McpPromptResult, type McpResourceContent, type McpResourceDef, type McpResourceMap, type McpResourceTemplateDef, type McpToolContent, type McpToolDef, type McpToolResult, type MiddlewareDeny, type MiddlewareHandler, type MiddlewareRedirect, type MiddlewareRequest, type MiddlewareResult, type ParamRef, type Permission, type PutInput, type PutOptions, type QueryByTagParams, type QueryParams, type QueueClient, type ResponseStream, type SecretRef, type SendEmailOptions, type SendMessageInput, type SkCondition, type StaticFiles, type StaticSiteConfig, type StaticSiteHandler, type StaticSiteSeo, type StoreEntityClient, type StreamView, type TableClient, type TableConfig, type TableHandler, type TableItem, type TableKey, type TableRecord, type Timezone, type UpdateActions, type WorkerClient, type WorkerConfig, type WorkerHandler, type WorkerSendOptions, defineApi, defineApp, defineBucket, defineConfig, defineCron, defineFifoQueue, defineMailer, defineMcp, defineSecret, defineStaticSite, defineTable, defineWorker, generateBase64, generateHex, generateUuid, isBucketRoute, param, secret, toSeconds };
|
package/dist/index.js
CHANGED
|
@@ -116,6 +116,7 @@ var defineApp = () => (options) => ({
|
|
|
116
116
|
});
|
|
117
117
|
|
|
118
118
|
// src/handlers/define-static-site.ts
|
|
119
|
+
var isBucketRoute = (v) => v != null && typeof v === "object" && "bucket" in v && v.bucket != null && typeof v.bucket === "object" && v.bucket.__brand === "effortless-bucket";
|
|
119
120
|
var defineStaticSite = () => (options) => ({
|
|
120
121
|
__brand: "effortless-static-site",
|
|
121
122
|
__spec: options
|
|
@@ -231,6 +232,13 @@ function defineBucket(options) {
|
|
|
231
232
|
state.static = [...state.static ?? [], glob];
|
|
232
233
|
return builder;
|
|
233
234
|
},
|
|
235
|
+
entity(name, options2) {
|
|
236
|
+
state.spec = {
|
|
237
|
+
...state.spec,
|
|
238
|
+
entities: { ...state.spec.entities, [name]: options2 ?? {} }
|
|
239
|
+
};
|
|
240
|
+
return builder;
|
|
241
|
+
},
|
|
234
242
|
setup(fnOrLambda, maybeLambda) {
|
|
235
243
|
if (typeof fnOrLambda === "function") {
|
|
236
244
|
state.setup = fnOrLambda;
|
|
@@ -270,6 +278,20 @@ var defineMailer = () => (options) => ({
|
|
|
270
278
|
});
|
|
271
279
|
|
|
272
280
|
// src/handlers/define-api.ts
|
|
281
|
+
var resolveCache = (cache) => {
|
|
282
|
+
if (typeof cache === "number" || typeof cache === "string") {
|
|
283
|
+
const ttl2 = toSeconds(cache);
|
|
284
|
+
return { ttl: ttl2, swr: ttl2 * 2 };
|
|
285
|
+
}
|
|
286
|
+
const ttl = toSeconds(cache.ttl);
|
|
287
|
+
if (cache.scope === "private") {
|
|
288
|
+
return { private: true, ttl };
|
|
289
|
+
}
|
|
290
|
+
return {
|
|
291
|
+
ttl,
|
|
292
|
+
swr: cache.swr != null ? toSeconds(cache.swr) : ttl * 2
|
|
293
|
+
};
|
|
294
|
+
};
|
|
273
295
|
function defineApi(options) {
|
|
274
296
|
const { basePath, stream } = options;
|
|
275
297
|
const state = {
|
|
@@ -280,11 +302,13 @@ function defineApi(options) {
|
|
|
280
302
|
routes: []
|
|
281
303
|
};
|
|
282
304
|
const addRoute = (method, path, handler, opts) => {
|
|
305
|
+
const routeCache = opts?.cache != null ? resolveCache(opts.cache) : void 0;
|
|
283
306
|
state.routes.push({
|
|
284
307
|
method,
|
|
285
308
|
path,
|
|
286
309
|
onRequest: handler,
|
|
287
|
-
...opts?.public ? { public: true } : {}
|
|
310
|
+
...opts?.public ? { public: true } : {},
|
|
311
|
+
...routeCache ? { cache: routeCache } : {}
|
|
288
312
|
});
|
|
289
313
|
};
|
|
290
314
|
const applyLambdaOptions = (lambda) => {
|
|
@@ -495,7 +519,8 @@ function defineWorker(options) {
|
|
|
495
519
|
function defineMcp(options) {
|
|
496
520
|
const spec = {
|
|
497
521
|
name: options.name,
|
|
498
|
-
...options.version ? { version: options.version } : {}
|
|
522
|
+
...options.version ? { version: options.version } : {},
|
|
523
|
+
...options.instructions ? { instructions: options.instructions } : {}
|
|
499
524
|
};
|
|
500
525
|
const state = { spec };
|
|
501
526
|
const applyLambdaOptions = (lambda) => {
|
|
@@ -512,6 +537,8 @@ function defineMcp(options) {
|
|
|
512
537
|
...state.deps ? { deps: state.deps } : {},
|
|
513
538
|
...state.config ? { config: state.config } : {},
|
|
514
539
|
...state.static ? { static: state.static } : {},
|
|
540
|
+
...state.resources ? { resources: state.resources } : {},
|
|
541
|
+
...state.prompts ? { prompts: state.prompts } : {},
|
|
515
542
|
...state.tools ? { tools: state.tools } : {}
|
|
516
543
|
});
|
|
517
544
|
const builder = {
|
|
@@ -544,6 +571,14 @@ function defineMcp(options) {
|
|
|
544
571
|
state.onCleanup = fn;
|
|
545
572
|
return builder;
|
|
546
573
|
},
|
|
574
|
+
resources(fn) {
|
|
575
|
+
state.resources = fn;
|
|
576
|
+
return builder;
|
|
577
|
+
},
|
|
578
|
+
prompts(fn) {
|
|
579
|
+
state.prompts = fn;
|
|
580
|
+
return builder;
|
|
581
|
+
},
|
|
547
582
|
tools(fn) {
|
|
548
583
|
state.tools = fn;
|
|
549
584
|
return finalize();
|
|
@@ -567,6 +602,7 @@ export {
|
|
|
567
602
|
generateBase64,
|
|
568
603
|
generateHex,
|
|
569
604
|
generateUuid,
|
|
605
|
+
isBucketRoute,
|
|
570
606
|
param,
|
|
571
607
|
secret,
|
|
572
608
|
toSeconds
|