effortless-aws 0.0.2 → 0.1.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/README.md +153 -0
- package/dist/chunk-I5TS7O5S.js +163 -0
- package/dist/cli/index.js +453 -98
- package/dist/cli/index.js.map +1 -1
- package/dist/index.d.ts +359 -214
- package/dist/index.js +21 -4
- package/dist/index.js.map +1 -1
- package/dist/runtime/wrap-http.js +86 -0
- package/dist/runtime/wrap-table-stream.js +143 -0
- package/package.json +3 -8
package/dist/index.d.ts
CHANGED
|
@@ -86,170 +86,115 @@ declare const defineConfig: (config: EffortlessConfig) => EffortlessConfig;
|
|
|
86
86
|
type AwsService = "dynamodb" | "s3" | "sqs" | "sns" | "ses" | "ssm" | "lambda" | "events" | "secretsmanager" | "cognito-idp" | "logs";
|
|
87
87
|
type Permission = `${AwsService}:${string}` | (string & {});
|
|
88
88
|
|
|
89
|
-
/** HTTP methods supported by API Gateway */
|
|
90
|
-
type HttpMethod = "GET" | "POST" | "PUT" | "DELETE" | "PATCH";
|
|
91
|
-
/**
|
|
92
|
-
* Incoming HTTP request object passed to the handler
|
|
93
|
-
*/
|
|
94
|
-
type HttpRequest = {
|
|
95
|
-
/** HTTP method (GET, POST, etc.) */
|
|
96
|
-
method: string;
|
|
97
|
-
/** Request path (e.g., "/users/123") */
|
|
98
|
-
path: string;
|
|
99
|
-
/** Request headers */
|
|
100
|
-
headers: Record<string, string | undefined>;
|
|
101
|
-
/** Query string parameters */
|
|
102
|
-
query: Record<string, string | undefined>;
|
|
103
|
-
/** Path parameters extracted from route (e.g., {id} -> params.id) */
|
|
104
|
-
params: Record<string, string | undefined>;
|
|
105
|
-
/** Parsed request body (JSON parsed if Content-Type is application/json) */
|
|
106
|
-
body: unknown;
|
|
107
|
-
/** Raw unparsed request body */
|
|
108
|
-
rawBody?: string;
|
|
109
|
-
};
|
|
110
89
|
/**
|
|
111
|
-
*
|
|
90
|
+
* Query parameters for TableClient.query()
|
|
112
91
|
*/
|
|
113
|
-
type
|
|
114
|
-
/**
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
92
|
+
type QueryParams = {
|
|
93
|
+
/** Partition key name and value */
|
|
94
|
+
pk: {
|
|
95
|
+
name: string;
|
|
96
|
+
value: unknown;
|
|
97
|
+
};
|
|
98
|
+
/** Optional sort key condition */
|
|
99
|
+
sk?: {
|
|
100
|
+
name: string;
|
|
101
|
+
condition: "=" | "begins_with" | "<" | ">" | "<=" | ">=";
|
|
102
|
+
value: unknown;
|
|
103
|
+
};
|
|
104
|
+
/** Maximum number of items to return */
|
|
105
|
+
limit?: number;
|
|
106
|
+
/** Sort order (true = ascending, false = descending) */
|
|
107
|
+
scanIndexForward?: boolean;
|
|
120
108
|
};
|
|
109
|
+
/** Extract keys of T whose values are arrays */
|
|
110
|
+
type ArrayKeys<T> = {
|
|
111
|
+
[K in keyof T]: T[K] extends unknown[] ? K : never;
|
|
112
|
+
}[keyof T];
|
|
121
113
|
/**
|
|
122
|
-
*
|
|
114
|
+
* Update actions for TableClient.update()
|
|
115
|
+
*
|
|
116
|
+
* @typeParam T - Type of the table items
|
|
123
117
|
*/
|
|
124
|
-
type
|
|
125
|
-
/**
|
|
126
|
-
|
|
127
|
-
/**
|
|
128
|
-
|
|
129
|
-
/**
|
|
130
|
-
|
|
131
|
-
/** Lambda memory in MB (default: 256) */
|
|
132
|
-
memory?: number;
|
|
133
|
-
/** Lambda timeout in seconds (default: 30) */
|
|
134
|
-
timeout?: number;
|
|
135
|
-
/** Additional IAM permissions for the Lambda */
|
|
136
|
-
permissions?: Permission[];
|
|
118
|
+
type UpdateActions<T> = {
|
|
119
|
+
/** Set attribute values (overwrites existing) */
|
|
120
|
+
set?: Partial<T>;
|
|
121
|
+
/** Append elements to list attributes (creates the list if it doesn't exist) */
|
|
122
|
+
append?: Pick<Partial<T>, ArrayKeys<T>>;
|
|
123
|
+
/** Remove attributes from the item */
|
|
124
|
+
remove?: (keyof T)[];
|
|
137
125
|
};
|
|
138
126
|
/**
|
|
139
|
-
*
|
|
127
|
+
* Typed DynamoDB table client injected via deps.
|
|
140
128
|
*
|
|
141
|
-
* @typeParam
|
|
129
|
+
* @typeParam T - Type of the table items
|
|
142
130
|
*/
|
|
143
|
-
type
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
131
|
+
type TableClient<T = Record<string, unknown>> = {
|
|
132
|
+
/** Put a full item into the table */
|
|
133
|
+
put(item: T): Promise<void>;
|
|
134
|
+
/** Get an item by its key attributes */
|
|
135
|
+
get(key: Partial<T>): Promise<T | undefined>;
|
|
136
|
+
/** Delete an item by its key attributes */
|
|
137
|
+
delete(key: Partial<T>): Promise<void>;
|
|
138
|
+
/** Update specific attributes without reading the full item */
|
|
139
|
+
update(key: Partial<T>, actions: UpdateActions<T>): Promise<void>;
|
|
140
|
+
/** Query by partition key with optional sort key condition */
|
|
141
|
+
query(params: QueryParams): Promise<T[]>;
|
|
142
|
+
/** The underlying DynamoDB table name */
|
|
143
|
+
tableName: string;
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
type AnyParamRef = ParamRef<any>;
|
|
149
147
|
/**
|
|
150
|
-
*
|
|
151
|
-
*
|
|
152
|
-
* @typeParam C - Type of the context/dependencies returned by context function
|
|
153
|
-
*
|
|
154
|
-
* @example Without context
|
|
155
|
-
* ```typescript
|
|
156
|
-
* export const getUsers = defineHttp({
|
|
157
|
-
* method: "GET",
|
|
158
|
-
* path: "/api/users",
|
|
159
|
-
* onRequest: async ({ req }) => ({
|
|
160
|
-
* status: 200,
|
|
161
|
-
* body: { users: [] }
|
|
162
|
-
* })
|
|
163
|
-
* });
|
|
164
|
-
* ```
|
|
148
|
+
* Reference to an SSM Parameter Store parameter.
|
|
165
149
|
*
|
|
166
|
-
* @
|
|
167
|
-
* ```typescript
|
|
168
|
-
* export const createOrder = defineHttp<typeof orderRuntime>({
|
|
169
|
-
* method: "POST",
|
|
170
|
-
* path: "/api/orders",
|
|
171
|
-
* context: () => ManagedRuntime.make(
|
|
172
|
-
* Layer.mergeAll(ConfigLive, DbClientLive)
|
|
173
|
-
* ),
|
|
174
|
-
* onRequest: async ({ req, ctx }) => {
|
|
175
|
-
* const result = await ctx.runPromise(createOrderEffect(req.body));
|
|
176
|
-
* return { status: 201, body: result };
|
|
177
|
-
* }
|
|
178
|
-
* });
|
|
179
|
-
* ```
|
|
150
|
+
* @typeParam T - The resolved type after optional transform (default: string)
|
|
180
151
|
*/
|
|
181
|
-
type
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
*/
|
|
186
|
-
context?: () => C;
|
|
187
|
-
/** HTTP request handler function */
|
|
188
|
-
onRequest: HttpHandlerFn<C>;
|
|
152
|
+
type ParamRef<T = string> = {
|
|
153
|
+
readonly __brand: "effortless-param";
|
|
154
|
+
readonly key: string;
|
|
155
|
+
readonly transform?: (raw: string) => T;
|
|
189
156
|
};
|
|
190
157
|
/**
|
|
191
|
-
*
|
|
192
|
-
*
|
|
158
|
+
* Maps a params declaration to resolved value types.
|
|
159
|
+
*
|
|
160
|
+
* @typeParam P - Record of param names to ParamRef instances
|
|
193
161
|
*/
|
|
194
|
-
type
|
|
195
|
-
|
|
196
|
-
readonly config: HttpConfig;
|
|
197
|
-
readonly context?: () => C;
|
|
198
|
-
readonly onRequest: HttpHandlerFn<C>;
|
|
162
|
+
type ResolveParams<P> = {
|
|
163
|
+
[K in keyof P]: P[K] extends ParamRef<infer T> ? T : never;
|
|
199
164
|
};
|
|
200
165
|
/**
|
|
201
|
-
*
|
|
166
|
+
* Declare an SSM Parameter Store parameter.
|
|
202
167
|
*
|
|
203
|
-
*
|
|
204
|
-
*
|
|
205
|
-
* @returns Handler object used by the deployment system
|
|
168
|
+
* The key is combined with project and stage at deploy time to form the full
|
|
169
|
+
* SSM path: `/${project}/${stage}/${key}`.
|
|
206
170
|
*
|
|
207
|
-
* @
|
|
208
|
-
*
|
|
209
|
-
*
|
|
210
|
-
* method: "GET",
|
|
211
|
-
* path: "/hello",
|
|
212
|
-
* onRequest: async ({ req }) => ({
|
|
213
|
-
* status: 200,
|
|
214
|
-
* body: { message: "Hello World!" }
|
|
215
|
-
* })
|
|
216
|
-
* });
|
|
217
|
-
* ```
|
|
171
|
+
* @param key - Parameter key (e.g., "database-url")
|
|
172
|
+
* @param transform - Optional function to transform the raw string value
|
|
173
|
+
* @returns A ParamRef used by the deployment and runtime systems
|
|
218
174
|
*
|
|
219
|
-
* @example
|
|
175
|
+
* @example Simple string parameter
|
|
220
176
|
* ```typescript
|
|
221
|
-
*
|
|
222
|
-
*
|
|
223
|
-
*
|
|
224
|
-
* memory: 512,
|
|
225
|
-
* timeout: 30,
|
|
226
|
-
* onRequest: async ({ req }) => {
|
|
227
|
-
* const { name, email } = req.body as { name: string; email: string };
|
|
228
|
-
* // ... create user
|
|
229
|
-
* return { status: 201, body: { id: "123", name, email } };
|
|
230
|
-
* }
|
|
231
|
-
* });
|
|
177
|
+
* params: {
|
|
178
|
+
* dbUrl: param("database-url"),
|
|
179
|
+
* }
|
|
232
180
|
* ```
|
|
233
181
|
*
|
|
234
|
-
* @example With
|
|
182
|
+
* @example With transform (e.g., TOML parsing)
|
|
235
183
|
* ```typescript
|
|
236
|
-
*
|
|
237
|
-
*
|
|
238
|
-
*
|
|
239
|
-
*
|
|
240
|
-
*
|
|
241
|
-
* ),
|
|
242
|
-
* onRequest: async ({ req, ctx }) => {
|
|
243
|
-
* const result = await ctx.runPromise(
|
|
244
|
-
* processPaymentEffect(req.body)
|
|
245
|
-
* );
|
|
246
|
-
* return { status: 200, body: result };
|
|
247
|
-
* }
|
|
248
|
-
* });
|
|
184
|
+
* import TOML from "smol-toml";
|
|
185
|
+
*
|
|
186
|
+
* params: {
|
|
187
|
+
* config: param("app-config", TOML.parse),
|
|
188
|
+
* }
|
|
249
189
|
* ```
|
|
250
190
|
*/
|
|
251
|
-
declare const
|
|
191
|
+
declare const param: <T = string>(key: string, transform?: (raw: string) => T) => ParamRef<T>;
|
|
252
192
|
|
|
193
|
+
type AnyTableHandler$1 = TableHandler<any, any, any, any, any>;
|
|
194
|
+
/** Maps a deps declaration to resolved runtime client types */
|
|
195
|
+
type ResolveDeps$1<D> = {
|
|
196
|
+
[K in keyof D]: D[K] extends TableHandler<infer T, any, any, any, any> ? TableClient<T> : never;
|
|
197
|
+
};
|
|
253
198
|
/** DynamoDB attribute types for keys */
|
|
254
199
|
type KeyType = "string" | "number" | "binary";
|
|
255
200
|
/**
|
|
@@ -322,99 +267,127 @@ type FailedRecord<T = Record<string, unknown>> = {
|
|
|
322
267
|
/** The error that occurred */
|
|
323
268
|
error: unknown;
|
|
324
269
|
};
|
|
270
|
+
/**
|
|
271
|
+
* Context factory type — conditional on whether params are declared.
|
|
272
|
+
* Without params: `() => C | Promise<C>`
|
|
273
|
+
* With params: `(args: { params: ResolveParams<P> }) => C | Promise<C>`
|
|
274
|
+
*/
|
|
275
|
+
type ContextFactory$1<C, P> = [P] extends [undefined] ? () => C | Promise<C> : (args: {
|
|
276
|
+
params: ResolveParams<P & {}>;
|
|
277
|
+
}) => C | Promise<C>;
|
|
325
278
|
/**
|
|
326
279
|
* Callback function type for processing a single DynamoDB stream record
|
|
327
|
-
*
|
|
328
|
-
* @typeParam T - Type of the table items
|
|
329
|
-
* @typeParam C - Type of the context/dependencies (from context function)
|
|
330
|
-
* @typeParam R - Return type (can be void or a value to accumulate)
|
|
331
280
|
*/
|
|
332
|
-
type TableRecordFn<T = Record<string, unknown>, C = undefined, R = void
|
|
333
|
-
record: TableRecord<T>;
|
|
334
|
-
}) => Promise<R> : (args: {
|
|
281
|
+
type TableRecordFn<T = Record<string, unknown>, C = undefined, R = void, D = undefined, P = undefined> = (args: {
|
|
335
282
|
record: TableRecord<T>;
|
|
283
|
+
table: TableClient<T>;
|
|
284
|
+
} & ([C] extends [undefined] ? {} : {
|
|
336
285
|
ctx: C;
|
|
337
|
-
})
|
|
286
|
+
}) & ([D] extends [undefined] ? {} : {
|
|
287
|
+
deps: ResolveDeps$1<D>;
|
|
288
|
+
}) & ([P] extends [undefined] ? {} : {
|
|
289
|
+
params: ResolveParams<P>;
|
|
290
|
+
})) => Promise<R>;
|
|
338
291
|
/**
|
|
339
292
|
* Callback function type for processing accumulated batch results
|
|
340
|
-
*
|
|
341
|
-
* @typeParam T - Type of the table items
|
|
342
|
-
* @typeParam C - Type of the context/dependencies
|
|
343
|
-
* @typeParam R - Type of results accumulated from onRecord
|
|
344
293
|
*/
|
|
345
|
-
type TableBatchCompleteFn<T = Record<string, unknown>, C = undefined, R = void
|
|
346
|
-
results: R[];
|
|
347
|
-
failures: FailedRecord<T>[];
|
|
348
|
-
}) => Promise<void> : (args: {
|
|
294
|
+
type TableBatchCompleteFn<T = Record<string, unknown>, C = undefined, R = void, D = undefined, P = undefined> = (args: {
|
|
349
295
|
results: R[];
|
|
350
296
|
failures: FailedRecord<T>[];
|
|
297
|
+
table: TableClient<T>;
|
|
298
|
+
} & ([C] extends [undefined] ? {} : {
|
|
351
299
|
ctx: C;
|
|
352
|
-
})
|
|
300
|
+
}) & ([D] extends [undefined] ? {} : {
|
|
301
|
+
deps: ResolveDeps$1<D>;
|
|
302
|
+
}) & ([P] extends [undefined] ? {} : {
|
|
303
|
+
params: ResolveParams<P>;
|
|
304
|
+
})) => Promise<void>;
|
|
353
305
|
/**
|
|
354
|
-
*
|
|
355
|
-
*
|
|
356
|
-
* @typeParam T - Type of the table items for type-safe record access
|
|
357
|
-
* @typeParam C - Type of the context/dependencies returned by context function
|
|
358
|
-
*
|
|
359
|
-
* @example Without context
|
|
360
|
-
* ```typescript
|
|
361
|
-
* export const users = defineTable<User>({
|
|
362
|
-
* pk: { name: "id", type: "string" },
|
|
363
|
-
* onRecord: async ({ record }) => {
|
|
364
|
-
* console.log(record.new?.name);
|
|
365
|
-
* }
|
|
366
|
-
* });
|
|
367
|
-
* ```
|
|
368
|
-
*
|
|
369
|
-
* @example With context (e.g., Effect runtime)
|
|
370
|
-
* ```typescript
|
|
371
|
-
* export const orders = defineTable<Order, ManagedRuntime<...>>({
|
|
372
|
-
* pk: { name: "id", type: "string" },
|
|
373
|
-
* context: () => ManagedRuntime.make(
|
|
374
|
-
* Layer.mergeAll(ConfigLive, DbClientLive)
|
|
375
|
-
* ),
|
|
376
|
-
* onRecord: async ({ record, ctx }) => {
|
|
377
|
-
* await ctx.runPromise(processOrder(record));
|
|
378
|
-
* }
|
|
379
|
-
* });
|
|
380
|
-
* ```
|
|
306
|
+
* Callback function type for processing all records in a batch at once
|
|
381
307
|
*/
|
|
382
|
-
type
|
|
308
|
+
type TableBatchFn<T = Record<string, unknown>, C = undefined, D = undefined, P = undefined> = (args: {
|
|
309
|
+
records: TableRecord<T>[];
|
|
310
|
+
table: TableClient<T>;
|
|
311
|
+
} & ([C] extends [undefined] ? {} : {
|
|
312
|
+
ctx: C;
|
|
313
|
+
}) & ([D] extends [undefined] ? {} : {
|
|
314
|
+
deps: ResolveDeps$1<D>;
|
|
315
|
+
}) & ([P] extends [undefined] ? {} : {
|
|
316
|
+
params: ResolveParams<P>;
|
|
317
|
+
})) => Promise<void>;
|
|
318
|
+
/** Base options shared by all defineTable variants */
|
|
319
|
+
type DefineTableBase<T = Record<string, unknown>, C = undefined, D = undefined, P = undefined> = TableConfig & {
|
|
320
|
+
/**
|
|
321
|
+
* Decode/validate function for stream record items (new/old images).
|
|
322
|
+
* Called with the unmarshalled DynamoDB item; should return typed data or throw on validation failure.
|
|
323
|
+
* When provided, T is inferred from the return type — no need to specify generic parameters.
|
|
324
|
+
*/
|
|
325
|
+
schema?: (input: unknown) => T;
|
|
383
326
|
/**
|
|
384
|
-
*
|
|
327
|
+
* Error handler called when onRecord, onBatch, or onBatchComplete throws.
|
|
328
|
+
* Receives the error. If not provided, defaults to `console.error`.
|
|
329
|
+
*/
|
|
330
|
+
onError?: (error: unknown) => void;
|
|
331
|
+
/**
|
|
332
|
+
* Factory function to create context/dependencies for callbacks.
|
|
385
333
|
* Called once on cold start, result is cached and reused across invocations.
|
|
334
|
+
* When params are declared, receives resolved params as argument.
|
|
335
|
+
* Supports both sync and async return values.
|
|
336
|
+
*/
|
|
337
|
+
context?: ContextFactory$1<C, P>;
|
|
338
|
+
/**
|
|
339
|
+
* Dependencies on other handlers (tables, queues, etc.).
|
|
340
|
+
* Typed clients are injected into the handler via the `deps` argument.
|
|
386
341
|
*/
|
|
387
|
-
|
|
388
|
-
/** Stream record callback. If omitted, only the table is created (no Lambda) */
|
|
389
|
-
onRecord?: TableRecordFn<T, C, R>;
|
|
342
|
+
deps?: D;
|
|
390
343
|
/**
|
|
391
|
-
*
|
|
392
|
-
*
|
|
344
|
+
* SSM Parameter Store parameters.
|
|
345
|
+
* Declare with `param()` helper. Values are fetched and cached at cold start.
|
|
346
|
+
* Typed values are injected into the handler via the `params` argument.
|
|
393
347
|
*/
|
|
394
|
-
|
|
348
|
+
params?: P;
|
|
395
349
|
};
|
|
350
|
+
/** Per-record processing: onRecord with optional onBatchComplete */
|
|
351
|
+
type DefineTableWithOnRecord<T = Record<string, unknown>, C = undefined, R = void, D = undefined, P = undefined> = DefineTableBase<T, C, D, P> & {
|
|
352
|
+
onRecord: TableRecordFn<T, C, R, D, P>;
|
|
353
|
+
onBatchComplete?: TableBatchCompleteFn<T, C, R, D, P>;
|
|
354
|
+
onBatch?: never;
|
|
355
|
+
};
|
|
356
|
+
/** Batch processing: onBatch processes all records at once */
|
|
357
|
+
type DefineTableWithOnBatch<T = Record<string, unknown>, C = undefined, D = undefined, P = undefined> = DefineTableBase<T, C, D, P> & {
|
|
358
|
+
onBatch: TableBatchFn<T, C, D, P>;
|
|
359
|
+
onRecord?: never;
|
|
360
|
+
onBatchComplete?: never;
|
|
361
|
+
};
|
|
362
|
+
/** Resource-only: no handler, just creates the table */
|
|
363
|
+
type DefineTableResourceOnly<T = Record<string, unknown>, C = undefined, D = undefined, P = undefined> = DefineTableBase<T, C, D, P> & {
|
|
364
|
+
onRecord?: never;
|
|
365
|
+
onBatch?: never;
|
|
366
|
+
onBatchComplete?: never;
|
|
367
|
+
};
|
|
368
|
+
type DefineTableOptions<T = Record<string, unknown>, C = undefined, R = void, D extends Record<string, AnyTableHandler$1> | undefined = undefined, P extends Record<string, AnyParamRef> | undefined = undefined> = DefineTableWithOnRecord<T, C, R, D, P> | DefineTableWithOnBatch<T, C, D, P> | DefineTableResourceOnly<T, C, D, P>;
|
|
396
369
|
/**
|
|
397
370
|
* Internal handler object created by defineTable
|
|
398
371
|
* @internal
|
|
399
372
|
*/
|
|
400
|
-
type TableHandler<T = Record<string, unknown>, C = undefined, R = void> = {
|
|
373
|
+
type TableHandler<T = Record<string, unknown>, C = undefined, R = void, D = undefined, P = undefined> = {
|
|
401
374
|
readonly __brand: "effortless-table";
|
|
402
375
|
readonly config: TableConfig;
|
|
403
|
-
readonly
|
|
404
|
-
readonly
|
|
405
|
-
readonly
|
|
376
|
+
readonly schema?: (input: unknown) => T;
|
|
377
|
+
readonly onError?: (error: unknown) => void;
|
|
378
|
+
readonly context?: (...args: any[]) => C | Promise<C>;
|
|
379
|
+
readonly deps?: D;
|
|
380
|
+
readonly params?: P;
|
|
381
|
+
readonly onRecord?: TableRecordFn<T, C, R, D, P>;
|
|
382
|
+
readonly onBatchComplete?: TableBatchCompleteFn<T, C, R, D, P>;
|
|
383
|
+
readonly onBatch?: TableBatchFn<T, C, D, P>;
|
|
406
384
|
};
|
|
407
385
|
/**
|
|
408
386
|
* Define a DynamoDB table with optional stream handler
|
|
409
387
|
*
|
|
410
388
|
* Creates:
|
|
411
389
|
* - DynamoDB table with specified key schema
|
|
412
|
-
* - (If onRecord provided) DynamoDB Stream + Lambda + Event Source Mapping
|
|
413
|
-
*
|
|
414
|
-
* @typeParam T - Type of the table items for type-safe record access
|
|
415
|
-
* @typeParam C - Type of the context/dependencies (inferred from context function)
|
|
416
|
-
* @param options - Table configuration, optional context factory, and optional onRecord callback
|
|
417
|
-
* @returns Handler object used by the deployment system
|
|
390
|
+
* - (If onRecord or onBatch provided) DynamoDB Stream + Lambda + Event Source Mapping
|
|
418
391
|
*
|
|
419
392
|
* @example Table with stream handler (typed)
|
|
420
393
|
* ```typescript
|
|
@@ -432,19 +405,6 @@ type TableHandler<T = Record<string, unknown>, C = undefined, R = void> = {
|
|
|
432
405
|
* });
|
|
433
406
|
* ```
|
|
434
407
|
*
|
|
435
|
-
* @example With Effect runtime context
|
|
436
|
-
* ```typescript
|
|
437
|
-
* export const expenses = defineTable<Expense, typeof expenseRuntime>({
|
|
438
|
-
* pk: { name: "pk", type: "string" },
|
|
439
|
-
* context: () => ManagedRuntime.make(
|
|
440
|
-
* Layer.mergeAll(ConfigLive, DynamoDBClient.Default())
|
|
441
|
-
* ),
|
|
442
|
-
* onRecord: async ({ record, ctx }) => {
|
|
443
|
-
* await ctx.runPromise(processExpense(record));
|
|
444
|
-
* }
|
|
445
|
-
* });
|
|
446
|
-
* ```
|
|
447
|
-
*
|
|
448
408
|
* @example Table only (no Lambda)
|
|
449
409
|
* ```typescript
|
|
450
410
|
* export const users = defineTable({
|
|
@@ -453,6 +413,191 @@ type TableHandler<T = Record<string, unknown>, C = undefined, R = void> = {
|
|
|
453
413
|
* });
|
|
454
414
|
* ```
|
|
455
415
|
*/
|
|
456
|
-
declare const defineTable: <T = Record<string, unknown>, C = undefined, R = void>(options: DefineTableOptions<T, C, R>) => TableHandler<T, C, R>;
|
|
416
|
+
declare const defineTable: <T = Record<string, unknown>, C = undefined, R = void, D extends Record<string, AnyTableHandler$1> | undefined = undefined, P extends Record<string, AnyParamRef> | undefined = undefined>(options: DefineTableOptions<T, C, R, D, P>) => TableHandler<T, C, R, D, P>;
|
|
417
|
+
|
|
418
|
+
type AnyTableHandler = TableHandler<any, any, any, any, any>;
|
|
419
|
+
/** Maps a deps declaration to resolved runtime client types */
|
|
420
|
+
type ResolveDeps<D> = {
|
|
421
|
+
[K in keyof D]: D[K] extends TableHandler<infer T, any, any, any, any> ? TableClient<T> : never;
|
|
422
|
+
};
|
|
423
|
+
/** HTTP methods supported by API Gateway */
|
|
424
|
+
type HttpMethod = "GET" | "POST" | "PUT" | "DELETE" | "PATCH";
|
|
425
|
+
/**
|
|
426
|
+
* Incoming HTTP request object passed to the handler
|
|
427
|
+
*/
|
|
428
|
+
type HttpRequest = {
|
|
429
|
+
/** HTTP method (GET, POST, etc.) */
|
|
430
|
+
method: string;
|
|
431
|
+
/** Request path (e.g., "/users/123") */
|
|
432
|
+
path: string;
|
|
433
|
+
/** Request headers */
|
|
434
|
+
headers: Record<string, string | undefined>;
|
|
435
|
+
/** Query string parameters */
|
|
436
|
+
query: Record<string, string | undefined>;
|
|
437
|
+
/** Path parameters extracted from route (e.g., {id} -> params.id) */
|
|
438
|
+
params: Record<string, string | undefined>;
|
|
439
|
+
/** Parsed request body (JSON parsed if Content-Type is application/json) */
|
|
440
|
+
body: unknown;
|
|
441
|
+
/** Raw unparsed request body */
|
|
442
|
+
rawBody?: string;
|
|
443
|
+
};
|
|
444
|
+
/**
|
|
445
|
+
* HTTP response returned from the handler
|
|
446
|
+
*/
|
|
447
|
+
type HttpResponse = {
|
|
448
|
+
/** HTTP status code (e.g., 200, 404, 500) */
|
|
449
|
+
status: number;
|
|
450
|
+
/** Response body (will be JSON serialized) */
|
|
451
|
+
body?: unknown;
|
|
452
|
+
/** Response headers */
|
|
453
|
+
headers?: Record<string, string>;
|
|
454
|
+
};
|
|
455
|
+
/**
|
|
456
|
+
* Configuration options extracted from DefineHttpOptions (without onRequest callback)
|
|
457
|
+
*/
|
|
458
|
+
type HttpConfig = {
|
|
459
|
+
/** Handler name. Defaults to export name if not specified */
|
|
460
|
+
name?: string;
|
|
461
|
+
/** HTTP method for the route */
|
|
462
|
+
method: HttpMethod;
|
|
463
|
+
/** Route path (e.g., "/api/users", "/api/users/{id}") */
|
|
464
|
+
path: string;
|
|
465
|
+
/** Lambda memory in MB (default: 256) */
|
|
466
|
+
memory?: number;
|
|
467
|
+
/** Lambda timeout in seconds (default: 30) */
|
|
468
|
+
timeout?: number;
|
|
469
|
+
/** Additional IAM permissions for the Lambda */
|
|
470
|
+
permissions?: Permission[];
|
|
471
|
+
};
|
|
472
|
+
/**
|
|
473
|
+
* Handler function type for HTTP endpoints
|
|
474
|
+
*
|
|
475
|
+
* @typeParam T - Type of the validated request body (from schema function)
|
|
476
|
+
* @typeParam C - Type of the context/dependencies (from context function)
|
|
477
|
+
* @typeParam D - Type of the deps (from deps declaration)
|
|
478
|
+
* @typeParam P - Type of the params (from params declaration)
|
|
479
|
+
*/
|
|
480
|
+
type HttpHandlerFn<T = undefined, C = undefined, D = undefined, P = undefined> = (args: {
|
|
481
|
+
req: HttpRequest;
|
|
482
|
+
} & ([T] extends [undefined] ? {} : {
|
|
483
|
+
data: T;
|
|
484
|
+
}) & ([C] extends [undefined] ? {} : {
|
|
485
|
+
ctx: C;
|
|
486
|
+
}) & ([D] extends [undefined] ? {} : {
|
|
487
|
+
deps: ResolveDeps<D>;
|
|
488
|
+
}) & ([P] extends [undefined] ? {} : {
|
|
489
|
+
params: ResolveParams<P>;
|
|
490
|
+
})) => Promise<HttpResponse>;
|
|
491
|
+
/**
|
|
492
|
+
* Context factory type — conditional on whether params are declared.
|
|
493
|
+
* Without params: `() => C | Promise<C>`
|
|
494
|
+
* With params: `(args: { params: ResolveParams<P> }) => C | Promise<C>`
|
|
495
|
+
*/
|
|
496
|
+
type ContextFactory<C, P> = [P] extends [undefined] ? () => C | Promise<C> : (args: {
|
|
497
|
+
params: ResolveParams<P & {}>;
|
|
498
|
+
}) => C | Promise<C>;
|
|
499
|
+
/**
|
|
500
|
+
* Options for defining an HTTP endpoint
|
|
501
|
+
*
|
|
502
|
+
* @typeParam T - Type of the validated request body (inferred from schema function)
|
|
503
|
+
* @typeParam C - Type of the context/dependencies returned by context function
|
|
504
|
+
* @typeParam D - Type of the deps (from deps declaration)
|
|
505
|
+
* @typeParam P - Type of the params (from params declaration)
|
|
506
|
+
*/
|
|
507
|
+
type DefineHttpOptions<T = undefined, C = undefined, D extends Record<string, AnyTableHandler> | undefined = undefined, P extends Record<string, AnyParamRef> | undefined = undefined> = HttpConfig & {
|
|
508
|
+
/**
|
|
509
|
+
* Decode/validate function for the request body.
|
|
510
|
+
* Called with the parsed body; should return typed data or throw on validation failure.
|
|
511
|
+
* When provided, the handler receives validated `data` and invalid requests get a 400 response.
|
|
512
|
+
*
|
|
513
|
+
* Works with any validation library:
|
|
514
|
+
* - Effect: `S.decodeUnknownSync(MySchema)`
|
|
515
|
+
* - Zod: `(body) => myZodSchema.parse(body)`
|
|
516
|
+
*/
|
|
517
|
+
schema?: (input: unknown) => T;
|
|
518
|
+
/**
|
|
519
|
+
* Error handler called when schema validation or onRequest throws.
|
|
520
|
+
* Receives the error and request, returns an HttpResponse.
|
|
521
|
+
* If not provided, defaults to 400 for validation errors and 500 for handler errors.
|
|
522
|
+
*/
|
|
523
|
+
onError?: (error: unknown, req: HttpRequest) => HttpResponse;
|
|
524
|
+
/**
|
|
525
|
+
* Factory function to create context/dependencies for the request handler.
|
|
526
|
+
* Called once on cold start, result is cached and reused across invocations.
|
|
527
|
+
* When params are declared, receives resolved params as argument.
|
|
528
|
+
* Supports both sync and async return values.
|
|
529
|
+
*/
|
|
530
|
+
context?: ContextFactory<C, P>;
|
|
531
|
+
/**
|
|
532
|
+
* Dependencies on other handlers (tables, queues, etc.).
|
|
533
|
+
* Typed clients are injected into the handler via the `deps` argument.
|
|
534
|
+
*/
|
|
535
|
+
deps?: D;
|
|
536
|
+
/**
|
|
537
|
+
* SSM Parameter Store parameters.
|
|
538
|
+
* Declare with `param()` helper. Values are fetched and cached at cold start.
|
|
539
|
+
* Typed values are injected into the handler via the `params` argument.
|
|
540
|
+
*/
|
|
541
|
+
params?: P;
|
|
542
|
+
/** HTTP request handler function */
|
|
543
|
+
onRequest: HttpHandlerFn<T, C, D, P>;
|
|
544
|
+
};
|
|
545
|
+
/**
|
|
546
|
+
* Internal handler object created by defineHttp
|
|
547
|
+
* @internal
|
|
548
|
+
*/
|
|
549
|
+
type HttpHandler<T = undefined, C = undefined, D = undefined, P = undefined> = {
|
|
550
|
+
readonly __brand: "effortless-http";
|
|
551
|
+
readonly config: HttpConfig;
|
|
552
|
+
readonly schema?: (input: unknown) => T;
|
|
553
|
+
readonly onError?: (error: unknown, req: HttpRequest) => HttpResponse;
|
|
554
|
+
readonly context?: (...args: any[]) => C | Promise<C>;
|
|
555
|
+
readonly deps?: D;
|
|
556
|
+
readonly params?: P;
|
|
557
|
+
readonly onRequest: HttpHandlerFn<T, C, D, P>;
|
|
558
|
+
};
|
|
559
|
+
/**
|
|
560
|
+
* Define an HTTP endpoint that creates an API Gateway route + Lambda function
|
|
561
|
+
*
|
|
562
|
+
* @typeParam T - Type of the validated request body (inferred from schema function)
|
|
563
|
+
* @typeParam C - Type of the context/dependencies (inferred from context function)
|
|
564
|
+
* @typeParam D - Type of the deps (from deps declaration)
|
|
565
|
+
* @typeParam P - Type of the params (from params declaration)
|
|
566
|
+
* @param options - Configuration, optional schema, optional context factory, and request handler
|
|
567
|
+
* @returns Handler object used by the deployment system
|
|
568
|
+
*
|
|
569
|
+
* @example Basic GET endpoint
|
|
570
|
+
* ```typescript
|
|
571
|
+
* export const hello = defineHttp({
|
|
572
|
+
* method: "GET",
|
|
573
|
+
* path: "/hello",
|
|
574
|
+
* onRequest: async ({ req }) => ({
|
|
575
|
+
* status: 200,
|
|
576
|
+
* body: { message: "Hello World!" }
|
|
577
|
+
* })
|
|
578
|
+
* });
|
|
579
|
+
* ```
|
|
580
|
+
*
|
|
581
|
+
* @example With SSM parameters
|
|
582
|
+
* ```typescript
|
|
583
|
+
* import { param } from "effortless-aws";
|
|
584
|
+
*
|
|
585
|
+
* export const api = defineHttp({
|
|
586
|
+
* method: "GET",
|
|
587
|
+
* path: "/orders",
|
|
588
|
+
* params: {
|
|
589
|
+
* dbUrl: param("database-url"),
|
|
590
|
+
* },
|
|
591
|
+
* context: async ({ params }) => ({
|
|
592
|
+
* pool: createPool(params.dbUrl),
|
|
593
|
+
* }),
|
|
594
|
+
* onRequest: async ({ req, ctx, params }) => ({
|
|
595
|
+
* status: 200,
|
|
596
|
+
* body: { dbUrl: params.dbUrl }
|
|
597
|
+
* })
|
|
598
|
+
* });
|
|
599
|
+
* ```
|
|
600
|
+
*/
|
|
601
|
+
declare const defineHttp: <T = undefined, C = undefined, D extends Record<string, AnyTableHandler> | undefined = undefined, P extends Record<string, AnyParamRef> | undefined = undefined>(options: DefineHttpOptions<T, C, D, P>) => HttpHandler<T, C, D, P>;
|
|
457
602
|
|
|
458
|
-
export { type DefineHttpOptions, type DefineTableOptions, type EffortlessConfig, type FailedRecord, type HttpConfig, type HttpHandler, type HttpHandlerFn, type HttpMethod, type HttpRequest, type HttpResponse, type KeyType, type StreamView, type TableBatchCompleteFn, type TableConfig, type TableHandler, type TableKey, type TableRecord, type TableRecordFn, defineConfig, defineHttp, defineTable };
|
|
603
|
+
export { type DefineHttpOptions, type DefineTableOptions, type EffortlessConfig, type FailedRecord, type HttpConfig, type HttpHandler, type HttpHandlerFn, type HttpMethod, type HttpRequest, type HttpResponse, type KeyType, type ParamRef, type QueryParams, type ResolveDeps, type ResolveParams, type StreamView, type TableBatchCompleteFn, type TableBatchFn, type TableClient, type TableConfig, type TableHandler, type TableKey, type TableRecord, type TableRecordFn, defineConfig, defineHttp, defineTable, param };
|