effortless-aws 0.27.1 → 0.29.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-UXSZNW5A.js → chunk-ISJC6CHC.js} +77 -42
- package/dist/index.d.ts +274 -362
- package/dist/index.js +66 -73
- package/dist/index.js.map +1 -1
- package/dist/runtime/wrap-api.js +72 -81
- package/dist/runtime/wrap-bucket.js +9 -5
- package/dist/runtime/wrap-fifo-queue.js +17 -9
- package/dist/runtime/wrap-table-stream.js +44 -38
- package/package.json +6 -3
package/dist/index.d.ts
CHANGED
|
@@ -95,6 +95,8 @@ type EffortlessConfig = {
|
|
|
95
95
|
*/
|
|
96
96
|
declare const defineConfig: (config: EffortlessConfig) => EffortlessConfig;
|
|
97
97
|
|
|
98
|
+
/** Generator spec for auto-creating secrets at deploy time. */
|
|
99
|
+
type GenerateSpec = `hex:${number}` | `base64:${number}` | "uuid";
|
|
98
100
|
type AwsService = "dynamodb" | "s3" | "sqs" | "sns" | "ses" | "ssm" | "lambda" | "events" | "secretsmanager" | "cognito-idp" | "logs";
|
|
99
101
|
type Permission = `${AwsService}:${string}` | (string & {});
|
|
100
102
|
/**
|
|
@@ -143,7 +145,7 @@ type AnySecretRef = SecretRef<any>;
|
|
|
143
145
|
type SecretRef<T = string> = {
|
|
144
146
|
readonly __brand: "effortless-secret";
|
|
145
147
|
readonly key?: string;
|
|
146
|
-
readonly generate?:
|
|
148
|
+
readonly generate?: GenerateSpec;
|
|
147
149
|
readonly transform?: (raw: string) => T;
|
|
148
150
|
};
|
|
149
151
|
/**
|
|
@@ -155,76 +157,46 @@ type SecretRef<T = string> = {
|
|
|
155
157
|
type ResolveConfig<P> = {
|
|
156
158
|
[K in keyof P]: P[K] extends SecretRef<infer T> ? T : string;
|
|
157
159
|
};
|
|
158
|
-
/** Options for `
|
|
159
|
-
type
|
|
160
|
+
/** Options for `defineSecret()` without a transform. */
|
|
161
|
+
type DefineSecretOptions = {
|
|
160
162
|
/** Custom SSM key (default: derived from config property name in kebab-case) */
|
|
161
163
|
key?: string;
|
|
162
|
-
/** Generator
|
|
163
|
-
generate?:
|
|
164
|
+
/** Generator spec for auto-creating the secret at deploy time: `"hex:32"`, `"base64:32"`, `"uuid"` */
|
|
165
|
+
generate?: GenerateSpec;
|
|
164
166
|
};
|
|
165
|
-
/** Options for `
|
|
166
|
-
type
|
|
167
|
+
/** Options for `defineSecret()` with a transform. */
|
|
168
|
+
type DefineSecretOptionsWithTransform<T> = DefineSecretOptions & {
|
|
167
169
|
/** Transform the raw SSM string value into a typed value */
|
|
168
170
|
transform: (raw: string) => T;
|
|
169
171
|
};
|
|
170
|
-
/**
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
*
|
|
187
|
-
* @example Auto-generated secret
|
|
188
|
-
* ```typescript
|
|
189
|
-
* config: {
|
|
190
|
-
* authSecret: secret({ generate: generateHex(64) }),
|
|
191
|
-
* // → auto-creates SSM param if missing
|
|
192
|
-
* }
|
|
193
|
-
* ```
|
|
194
|
-
*
|
|
195
|
-
* @example With transform
|
|
196
|
-
* ```typescript
|
|
197
|
-
* config: {
|
|
198
|
-
* appConfig: secret({ transform: TOML.parse }),
|
|
199
|
-
* }
|
|
200
|
-
* ```
|
|
201
|
-
*/
|
|
202
|
-
declare function secret(): SecretRef<string>;
|
|
203
|
-
declare function secret(options: SecretOptions): SecretRef<string>;
|
|
204
|
-
declare function secret<T>(options: SecretOptionsWithTransform<T>): SecretRef<T>;
|
|
205
|
-
/**
|
|
206
|
-
* Returns a generator that produces a random hex string.
|
|
207
|
-
* @param bytes - Number of random bytes (output will be 2x this length in hex chars)
|
|
208
|
-
*/
|
|
209
|
-
declare const generateHex: (bytes: number) => () => string;
|
|
210
|
-
/**
|
|
211
|
-
* Returns a generator that produces a random base64url string.
|
|
212
|
-
* @param bytes - Number of random bytes
|
|
213
|
-
*/
|
|
214
|
-
declare const generateBase64: (bytes: number) => () => string;
|
|
215
|
-
/**
|
|
216
|
-
* Returns a generator that produces a random UUID v4.
|
|
217
|
-
*/
|
|
218
|
-
declare const generateUuid: () => () => string;
|
|
172
|
+
/** The defineSecret helper function type, injected into config callbacks. */
|
|
173
|
+
type DefineSecretFn = {
|
|
174
|
+
(): SecretRef<string>;
|
|
175
|
+
(options: DefineSecretOptions): SecretRef<string>;
|
|
176
|
+
<T>(options: DefineSecretOptionsWithTransform<T>): SecretRef<T>;
|
|
177
|
+
};
|
|
178
|
+
/** Helpers injected into the `config` callback. */
|
|
179
|
+
type ConfigHelpers = {
|
|
180
|
+
defineSecret: DefineSecretFn;
|
|
181
|
+
};
|
|
182
|
+
/** Config factory: a function receiving helpers and returning a record of SecretRefs. */
|
|
183
|
+
type ConfigFactory<P> = (helpers: ConfigHelpers) => P;
|
|
184
|
+
/** The `defineSecret` implementation, passed to config callbacks. */
|
|
185
|
+
declare const defineSecret: DefineSecretFn;
|
|
186
|
+
/** @deprecated Use `defineSecret()` inside a config callback instead. */
|
|
187
|
+
declare const secret: DefineSecretFn;
|
|
219
188
|
/** @deprecated Use `SecretRef` instead */
|
|
220
189
|
type ParamRef<T = string> = SecretRef<T>;
|
|
221
190
|
/** @deprecated Use `AnySecretRef` instead */
|
|
222
191
|
type AnyParamRef = AnySecretRef;
|
|
223
|
-
/**
|
|
224
|
-
|
|
225
|
-
*/
|
|
226
|
-
declare
|
|
227
|
-
|
|
192
|
+
/** @deprecated Use `defineSecret()` instead. */
|
|
193
|
+
declare const param: <T = string>(key: string, transform?: (raw: string) => T) => SecretRef<T>;
|
|
194
|
+
/** @deprecated Use `defineSecret({ generate: "hex:N" })` instead. */
|
|
195
|
+
declare const generateHex: (bytes: number) => string;
|
|
196
|
+
/** @deprecated Use `defineSecret({ generate: "base64:N" })` instead. */
|
|
197
|
+
declare const generateBase64: (bytes: number) => string;
|
|
198
|
+
/** @deprecated Use `defineSecret({ generate: "uuid" })` instead. */
|
|
199
|
+
declare const generateUuid: () => string;
|
|
228
200
|
/**
|
|
229
201
|
* DynamoDB table key (always pk + sk strings in single-table design).
|
|
230
202
|
*/
|
|
@@ -387,7 +359,7 @@ type TableClient<T = Record<string, unknown>> = {
|
|
|
387
359
|
};
|
|
388
360
|
|
|
389
361
|
/** HTTP methods supported by Lambda Function URLs */
|
|
390
|
-
type HttpMethod = "GET" | "POST" | "PUT" | "DELETE" | "PATCH" | "ANY";
|
|
362
|
+
type HttpMethod$1 = "GET" | "POST" | "PUT" | "DELETE" | "PATCH" | "ANY";
|
|
391
363
|
/** Short content-type aliases for common response formats */
|
|
392
364
|
type ContentType = "json" | "html" | "text" | "css" | "js" | "xml" | "csv" | "svg";
|
|
393
365
|
/**
|
|
@@ -493,21 +465,6 @@ type BucketClient = {
|
|
|
493
465
|
bucketName: string;
|
|
494
466
|
};
|
|
495
467
|
|
|
496
|
-
/**
|
|
497
|
-
* Common conditional args injected into handler callbacks.
|
|
498
|
-
* Resolves ctx, deps, config, and files based on whether each generic is defined.
|
|
499
|
-
* @internal
|
|
500
|
-
*/
|
|
501
|
-
type HandlerArgs<C = undefined, D = undefined, P = undefined, S extends string[] | undefined = undefined> = ([C] extends [undefined] ? {} : {
|
|
502
|
-
ctx: C;
|
|
503
|
-
}) & ([D] extends [undefined] ? {} : {
|
|
504
|
-
deps: ResolveDeps<D>;
|
|
505
|
-
}) & ([P] extends [undefined] ? {} : {
|
|
506
|
-
config: ResolveConfig<P>;
|
|
507
|
-
}) & ([S] extends [undefined] ? {} : {
|
|
508
|
-
files: StaticFiles;
|
|
509
|
-
});
|
|
510
|
-
|
|
511
468
|
/**
|
|
512
469
|
* Configuration options for defineBucket.
|
|
513
470
|
*/
|
|
@@ -536,20 +493,20 @@ type BucketEvent = {
|
|
|
536
493
|
/** S3 bucket name */
|
|
537
494
|
bucketName: string;
|
|
538
495
|
};
|
|
496
|
+
/** Spread ctx into callback args (empty when no setup) */
|
|
497
|
+
type SpreadCtx$3<C> = [C] extends [undefined] ? {} : C & {};
|
|
539
498
|
/**
|
|
540
499
|
* Callback function type for S3 ObjectCreated events
|
|
541
500
|
*/
|
|
542
|
-
type BucketObjectCreatedFn<C = undefined
|
|
501
|
+
type BucketObjectCreatedFn<C = undefined> = (args: {
|
|
543
502
|
event: BucketEvent;
|
|
544
|
-
|
|
545
|
-
} & HandlerArgs<C, D, P, S>) => Promise<void>;
|
|
503
|
+
} & SpreadCtx$3<C>) => Promise<void>;
|
|
546
504
|
/**
|
|
547
505
|
* Callback function type for S3 ObjectRemoved events
|
|
548
506
|
*/
|
|
549
|
-
type BucketObjectRemovedFn<C = undefined
|
|
507
|
+
type BucketObjectRemovedFn<C = undefined> = (args: {
|
|
550
508
|
event: BucketEvent;
|
|
551
|
-
|
|
552
|
-
} & HandlerArgs<C, D, P, S>) => Promise<void>;
|
|
509
|
+
} & SpreadCtx$3<C>) => Promise<void>;
|
|
553
510
|
/**
|
|
554
511
|
* Setup factory type for bucket handlers.
|
|
555
512
|
* Always receives `bucket: BucketClient` (self-client for the handler's own bucket).
|
|
@@ -572,16 +529,16 @@ type DefineBucketBase<C = undefined, D = undefined, P = undefined, S extends str
|
|
|
572
529
|
*/
|
|
573
530
|
onError?: (args: {
|
|
574
531
|
error: unknown;
|
|
575
|
-
} &
|
|
532
|
+
} & SpreadCtx$3<C>) => void;
|
|
576
533
|
/** Called after each invocation completes, right before Lambda freezes the process */
|
|
577
|
-
onAfterInvoke?: (args:
|
|
534
|
+
onAfterInvoke?: (args: SpreadCtx$3<C>) => void | Promise<void>;
|
|
578
535
|
/**
|
|
579
536
|
* Factory function to initialize shared state for callbacks.
|
|
580
537
|
* Called once on cold start, result is cached and reused across invocations.
|
|
581
538
|
* Always receives `bucket: BucketClient` (self-client). When deps/config
|
|
582
539
|
* are declared, receives them as well.
|
|
583
540
|
*/
|
|
584
|
-
setup?: SetupFactory$3<C, D
|
|
541
|
+
setup?: SetupFactory$3<C, NoInfer<D>, NoInfer<P>, NoInfer<S>>;
|
|
585
542
|
/**
|
|
586
543
|
* Dependencies on other handlers (tables, buckets, etc.).
|
|
587
544
|
* Typed clients are injected into the handler via the `deps` argument.
|
|
@@ -590,9 +547,9 @@ type DefineBucketBase<C = undefined, D = undefined, P = undefined, S extends str
|
|
|
590
547
|
deps?: () => D & {};
|
|
591
548
|
/**
|
|
592
549
|
* SSM Parameter Store parameters.
|
|
593
|
-
* Declare with `
|
|
550
|
+
* Declare with `defineSecret()` helper. Values are fetched and cached at cold start.
|
|
594
551
|
*/
|
|
595
|
-
config?: P
|
|
552
|
+
config?: ConfigFactory<P>;
|
|
596
553
|
/**
|
|
597
554
|
* Static file glob patterns to bundle into the Lambda ZIP.
|
|
598
555
|
* Files are accessible at runtime via the `files` callback argument.
|
|
@@ -601,15 +558,15 @@ type DefineBucketBase<C = undefined, D = undefined, P = undefined, S extends str
|
|
|
601
558
|
};
|
|
602
559
|
/** With event handlers (at least one callback) */
|
|
603
560
|
type DefineBucketWithHandlers<C = undefined, D = undefined, P = undefined, S extends string[] | undefined = undefined> = DefineBucketBase<C, D, P, S> & {
|
|
604
|
-
onObjectCreated?: BucketObjectCreatedFn<C
|
|
605
|
-
onObjectRemoved?: BucketObjectRemovedFn<C
|
|
561
|
+
onObjectCreated?: BucketObjectCreatedFn<C>;
|
|
562
|
+
onObjectRemoved?: BucketObjectRemovedFn<C>;
|
|
606
563
|
};
|
|
607
564
|
/** Resource-only: no Lambda, just creates the bucket */
|
|
608
565
|
type DefineBucketResourceOnly<C = undefined, D = undefined, P = undefined, S extends string[] | undefined = undefined> = DefineBucketBase<C, D, P, S> & {
|
|
609
566
|
onObjectCreated?: never;
|
|
610
567
|
onObjectRemoved?: never;
|
|
611
568
|
};
|
|
612
|
-
type DefineBucketOptions<C = undefined, D extends Record<string, AnyDepHandler> | undefined = undefined, P extends Record<string,
|
|
569
|
+
type DefineBucketOptions<C = undefined, D extends Record<string, AnyDepHandler> | undefined = undefined, P extends Record<string, AnySecretRef> | undefined = undefined, S extends string[] | undefined = undefined> = DefineBucketWithHandlers<C, D, P, S> | DefineBucketResourceOnly<C, D, P, S>;
|
|
613
570
|
/**
|
|
614
571
|
* Internal handler object created by defineBucket
|
|
615
572
|
* @internal
|
|
@@ -661,7 +618,7 @@ type BucketHandler<C = any> = {
|
|
|
661
618
|
* });
|
|
662
619
|
* ```
|
|
663
620
|
*/
|
|
664
|
-
declare const defineBucket: <C = undefined, D extends Record<string, AnyDepHandler> | undefined = undefined, P extends Record<string,
|
|
621
|
+
declare const defineBucket: () => <C = undefined, D extends Record<string, AnyDepHandler> | undefined = undefined, P extends Record<string, AnySecretRef> | undefined = undefined, S extends string[] | undefined = undefined>(options: DefineBucketOptions<C, D, P, S>) => BucketHandler<C>;
|
|
665
622
|
|
|
666
623
|
/**
|
|
667
624
|
* Configuration options for defining a mailer (SES email identity)
|
|
@@ -709,7 +666,7 @@ type MailerHandler = {
|
|
|
709
666
|
* });
|
|
710
667
|
* ```
|
|
711
668
|
*/
|
|
712
|
-
declare const defineMailer: (options: MailerConfig) => MailerHandler;
|
|
669
|
+
declare const defineMailer: () => (options: MailerConfig) => MailerHandler;
|
|
713
670
|
|
|
714
671
|
/**
|
|
715
672
|
* Parsed SQS FIFO message passed to the handler callbacks.
|
|
@@ -773,20 +730,25 @@ type SetupFactory$2<C, D, P, S extends string[] | undefined = undefined> = (args
|
|
|
773
730
|
}) & ([S] extends [undefined] ? {} : {
|
|
774
731
|
files: StaticFiles;
|
|
775
732
|
})) => C | Promise<C>;
|
|
733
|
+
/** Spread ctx into callback args (empty when no setup) */
|
|
734
|
+
type SpreadCtx$2<C> = [C] extends [undefined] ? {} : C & {};
|
|
776
735
|
/**
|
|
777
736
|
* Per-message handler function.
|
|
778
737
|
* Called once per message in the batch. Failures are reported individually.
|
|
779
738
|
*/
|
|
780
|
-
type FifoQueueMessageFn<T = unknown, C = undefined
|
|
739
|
+
type FifoQueueMessageFn<T = unknown, C = undefined> = (args: {
|
|
781
740
|
message: FifoQueueMessage<T>;
|
|
782
|
-
} &
|
|
741
|
+
} & SpreadCtx$2<C>) => Promise<void>;
|
|
783
742
|
/**
|
|
784
743
|
* Batch handler function.
|
|
785
744
|
* Called once with all messages in the batch.
|
|
745
|
+
* Return `{ failures: string[] }` (messageIds) for partial batch failure reporting.
|
|
786
746
|
*/
|
|
787
|
-
type FifoQueueBatchFn<T = unknown, C = undefined
|
|
747
|
+
type FifoQueueBatchFn<T = unknown, C = undefined> = (args: {
|
|
788
748
|
messages: FifoQueueMessage<T>[];
|
|
789
|
-
} &
|
|
749
|
+
} & SpreadCtx$2<C>) => Promise<void | {
|
|
750
|
+
failures: string[];
|
|
751
|
+
}>;
|
|
790
752
|
/** Base options shared by all defineFifoQueue variants */
|
|
791
753
|
type DefineFifoQueueBase<T = unknown, C = undefined, D = undefined, P = undefined, S extends string[] | undefined = undefined> = FifoQueueConfig & {
|
|
792
754
|
/**
|
|
@@ -795,20 +757,20 @@ type DefineFifoQueueBase<T = unknown, C = undefined, D = undefined, P = undefine
|
|
|
795
757
|
*/
|
|
796
758
|
schema?: (input: unknown) => T;
|
|
797
759
|
/**
|
|
798
|
-
* Error handler called when onMessage or
|
|
760
|
+
* Error handler called when onMessage or onMessageBatch throws.
|
|
799
761
|
* If not provided, defaults to `console.error`.
|
|
800
762
|
*/
|
|
801
763
|
onError?: (args: {
|
|
802
764
|
error: unknown;
|
|
803
|
-
} &
|
|
765
|
+
} & SpreadCtx$2<C>) => void;
|
|
804
766
|
/** Called after each invocation completes, right before Lambda freezes the process */
|
|
805
|
-
onAfterInvoke?: (args:
|
|
767
|
+
onAfterInvoke?: (args: SpreadCtx$2<C>) => void | Promise<void>;
|
|
806
768
|
/**
|
|
807
769
|
* Factory function to initialize shared state for the handler.
|
|
808
770
|
* Called once on cold start, result is cached and reused across invocations.
|
|
809
771
|
* When deps/params are declared, receives them as argument.
|
|
810
772
|
*/
|
|
811
|
-
setup?: SetupFactory$2<C, D
|
|
773
|
+
setup?: SetupFactory$2<C, NoInfer<D>, NoInfer<P>, NoInfer<S>>;
|
|
812
774
|
/**
|
|
813
775
|
* Dependencies on other handlers (tables, queues, etc.).
|
|
814
776
|
* Typed clients are injected into the handler via the `deps` argument.
|
|
@@ -817,9 +779,9 @@ type DefineFifoQueueBase<T = unknown, C = undefined, D = undefined, P = undefine
|
|
|
817
779
|
deps?: () => D & {};
|
|
818
780
|
/**
|
|
819
781
|
* SSM Parameter Store parameters.
|
|
820
|
-
* Declare with `
|
|
782
|
+
* Declare with `defineSecret()` helper. Values are fetched and cached at cold start.
|
|
821
783
|
*/
|
|
822
|
-
config?: P
|
|
784
|
+
config?: ConfigFactory<P>;
|
|
823
785
|
/**
|
|
824
786
|
* Static file glob patterns to bundle into the Lambda ZIP.
|
|
825
787
|
* Files are accessible at runtime via the `files` callback argument.
|
|
@@ -828,15 +790,15 @@ type DefineFifoQueueBase<T = unknown, C = undefined, D = undefined, P = undefine
|
|
|
828
790
|
};
|
|
829
791
|
/** Per-message processing */
|
|
830
792
|
type DefineFifoQueueWithOnMessage<T = unknown, C = undefined, D = undefined, P = undefined, S extends string[] | undefined = undefined> = DefineFifoQueueBase<T, C, D, P, S> & {
|
|
831
|
-
onMessage: FifoQueueMessageFn<T, C
|
|
832
|
-
|
|
793
|
+
onMessage: FifoQueueMessageFn<T, C>;
|
|
794
|
+
onMessageBatch?: never;
|
|
833
795
|
};
|
|
834
796
|
/** Batch processing: all messages at once */
|
|
835
797
|
type DefineFifoQueueWithOnBatch<T = unknown, C = undefined, D = undefined, P = undefined, S extends string[] | undefined = undefined> = DefineFifoQueueBase<T, C, D, P, S> & {
|
|
836
|
-
|
|
798
|
+
onMessageBatch: FifoQueueBatchFn<T, C>;
|
|
837
799
|
onMessage?: never;
|
|
838
800
|
};
|
|
839
|
-
type DefineFifoQueueOptions<T = unknown, C = undefined, D extends Record<string, AnyDepHandler> | undefined = undefined, P extends Record<string,
|
|
801
|
+
type DefineFifoQueueOptions<T = unknown, C = undefined, D extends Record<string, AnyDepHandler> | undefined = undefined, P extends Record<string, AnySecretRef> | undefined = undefined, S extends string[] | undefined = undefined> = DefineFifoQueueWithOnMessage<T, C, D, P, S> | DefineFifoQueueWithOnBatch<T, C, D, P, S>;
|
|
840
802
|
/**
|
|
841
803
|
* Internal handler object created by defineFifoQueue
|
|
842
804
|
* @internal
|
|
@@ -852,7 +814,7 @@ type FifoQueueHandler<T = unknown, C = any> = {
|
|
|
852
814
|
readonly config?: Record<string, unknown>;
|
|
853
815
|
readonly static?: string[];
|
|
854
816
|
readonly onMessage?: (...args: any[]) => any;
|
|
855
|
-
readonly
|
|
817
|
+
readonly onMessageBatch?: (...args: any[]) => any;
|
|
856
818
|
};
|
|
857
819
|
/**
|
|
858
820
|
* Define a FIFO SQS queue with a Lambda message handler
|
|
@@ -878,13 +840,13 @@ type FifoQueueHandler<T = unknown, C = any> = {
|
|
|
878
840
|
* export const notifications = defineFifoQueue({
|
|
879
841
|
* schema: (input) => NotificationSchema.parse(input),
|
|
880
842
|
* batchSize: 5,
|
|
881
|
-
*
|
|
843
|
+
* onMessageBatch: async ({ messages }) => {
|
|
882
844
|
* await sendAll(messages.map(m => m.body));
|
|
883
845
|
* }
|
|
884
846
|
* });
|
|
885
847
|
* ```
|
|
886
848
|
*/
|
|
887
|
-
declare const defineFifoQueue: <T = unknown
|
|
849
|
+
declare const defineFifoQueue: <T = unknown>() => <C = undefined, D extends Record<string, AnyDepHandler> | undefined = undefined, P extends Record<string, AnySecretRef> | undefined = undefined, S extends string[] | undefined = undefined>(options: DefineFifoQueueOptions<T, C, D, P, S>) => FifoQueueHandler<T, C>;
|
|
888
850
|
|
|
889
851
|
/**
|
|
890
852
|
* Options for sending an email via EmailClient.send()
|
|
@@ -973,18 +935,12 @@ type TableConfig = {
|
|
|
973
935
|
batchWindow?: Duration;
|
|
974
936
|
/** Where to start reading the stream (default: "LATEST") */
|
|
975
937
|
startingPosition?: "LATEST" | "TRIM_HORIZON";
|
|
938
|
+
/** Number of records to process concurrently within a batch (default: 1 — sequential) */
|
|
939
|
+
concurrency?: number;
|
|
976
940
|
/**
|
|
977
941
|
* Name of the field in `data` that serves as the entity type discriminant.
|
|
978
942
|
* Effortless auto-copies `data[tagField]` to the top-level DynamoDB `tag` attribute on `put()`.
|
|
979
943
|
* Defaults to `"tag"`.
|
|
980
|
-
*
|
|
981
|
-
* @example
|
|
982
|
-
* ```typescript
|
|
983
|
-
* export const orders = defineTable<{ type: "order"; amount: number }>({
|
|
984
|
-
* tagField: "type",
|
|
985
|
-
* onRecord: async ({ record }) => { ... }
|
|
986
|
-
* });
|
|
987
|
-
* ```
|
|
988
944
|
*/
|
|
989
945
|
tagField?: string;
|
|
990
946
|
};
|
|
@@ -1012,20 +968,9 @@ type TableRecord<T = Record<string, unknown>> = {
|
|
|
1012
968
|
/** Approximate timestamp when the modification occurred */
|
|
1013
969
|
timestamp?: number;
|
|
1014
970
|
};
|
|
1015
|
-
/**
|
|
1016
|
-
* Information about a failed record during batch processing
|
|
1017
|
-
*
|
|
1018
|
-
* @typeParam T - Type of the domain data
|
|
1019
|
-
*/
|
|
1020
|
-
type FailedRecord<T = Record<string, unknown>> = {
|
|
1021
|
-
/** The record that failed to process */
|
|
1022
|
-
record: TableRecord<T>;
|
|
1023
|
-
/** The error that occurred */
|
|
1024
|
-
error: unknown;
|
|
1025
|
-
};
|
|
1026
971
|
/**
|
|
1027
972
|
* Setup factory type for table handlers.
|
|
1028
|
-
*
|
|
973
|
+
* Receives `table: TableClient<T>` (self-client for the handler's own table).
|
|
1029
974
|
* Also receives `deps` and/or `config` when declared.
|
|
1030
975
|
*/
|
|
1031
976
|
type SetupFactory$1<C, T, D, P, S extends string[] | undefined = undefined> = (args: {
|
|
@@ -1037,28 +982,26 @@ type SetupFactory$1<C, T, D, P, S extends string[] | undefined = undefined> = (a
|
|
|
1037
982
|
}) & ([S] extends [undefined] ? {} : {
|
|
1038
983
|
files: StaticFiles;
|
|
1039
984
|
})) => C | Promise<C>;
|
|
985
|
+
/** Spread ctx into callback args (empty when no setup) */
|
|
986
|
+
type SpreadCtx$1<C> = [C] extends [undefined] ? {} : C & {};
|
|
1040
987
|
/**
|
|
1041
|
-
* Callback function type for processing a single DynamoDB stream record
|
|
988
|
+
* Callback function type for processing a single DynamoDB stream record.
|
|
989
|
+
* Receives the current record and the full batch for context.
|
|
1042
990
|
*/
|
|
1043
|
-
type TableRecordFn<T = Record<string, unknown>, C = undefined
|
|
991
|
+
type TableRecordFn<T = Record<string, unknown>, C = undefined> = (args: {
|
|
1044
992
|
record: TableRecord<T>;
|
|
1045
|
-
|
|
1046
|
-
} &
|
|
1047
|
-
/**
|
|
1048
|
-
*
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
} &
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
*/
|
|
1058
|
-
type TableBatchFn<T = Record<string, unknown>, C = undefined, D = undefined, P = undefined, S extends string[] | undefined = undefined> = (args: {
|
|
1059
|
-
records: TableRecord<T>[];
|
|
1060
|
-
table: TableClient<T>;
|
|
1061
|
-
} & HandlerArgs<C, D, P, S>) => Promise<void>;
|
|
993
|
+
batch: readonly TableRecord<T>[];
|
|
994
|
+
} & SpreadCtx$1<C>) => Promise<void>;
|
|
995
|
+
/**
|
|
996
|
+
* Batch handler function for DynamoDB stream records.
|
|
997
|
+
* Called once with all records in the batch.
|
|
998
|
+
* Return `{ failures: string[] }` (sequence numbers) for partial batch failure reporting.
|
|
999
|
+
*/
|
|
1000
|
+
type TableBatchFn<T = Record<string, unknown>, C = undefined> = (args: {
|
|
1001
|
+
records: readonly TableRecord<T>[];
|
|
1002
|
+
} & SpreadCtx$1<C>) => Promise<void | {
|
|
1003
|
+
failures: string[];
|
|
1004
|
+
}>;
|
|
1062
1005
|
/** Base options shared by all defineTable variants */
|
|
1063
1006
|
type DefineTableBase<T = Record<string, unknown>, C = undefined, D = undefined, P = undefined, S extends string[] | undefined = undefined> = Omit<TableConfig, "tagField"> & {
|
|
1064
1007
|
/** Name of the field in `data` that serves as the entity type discriminant (default: `"tag"`). */
|
|
@@ -1070,58 +1013,60 @@ type DefineTableBase<T = Record<string, unknown>, C = undefined, D = undefined,
|
|
|
1070
1013
|
*/
|
|
1071
1014
|
schema?: (input: unknown) => T;
|
|
1072
1015
|
/**
|
|
1073
|
-
* Error handler called when onRecord
|
|
1074
|
-
*
|
|
1016
|
+
* Error handler called when onRecord/onRecordBatch throws.
|
|
1017
|
+
* If not provided, defaults to `console.error`.
|
|
1075
1018
|
*/
|
|
1076
1019
|
onError?: (args: {
|
|
1077
1020
|
error: unknown;
|
|
1078
|
-
} &
|
|
1021
|
+
} & SpreadCtx$1<C>) => void;
|
|
1079
1022
|
/** Called after each invocation completes, right before Lambda freezes the process */
|
|
1080
|
-
onAfterInvoke?: (args:
|
|
1023
|
+
onAfterInvoke?: (args: SpreadCtx$1<C>) => void | Promise<void>;
|
|
1081
1024
|
/**
|
|
1082
1025
|
* Factory function to initialize shared state for callbacks.
|
|
1083
1026
|
* Called once on cold start, result is cached and reused across invocations.
|
|
1084
|
-
*
|
|
1085
|
-
* Supports both sync and async return values.
|
|
1027
|
+
* Receives `table` (self-client), plus `deps`/`config`/`files` when declared.
|
|
1086
1028
|
*/
|
|
1087
|
-
setup?: SetupFactory$1<C, T, D
|
|
1029
|
+
setup?: SetupFactory$1<C, T, NoInfer<D>, NoInfer<P>, NoInfer<S>>;
|
|
1088
1030
|
/**
|
|
1089
1031
|
* Dependencies on other handlers (tables, queues, etc.).
|
|
1090
|
-
* Typed clients are injected into
|
|
1032
|
+
* Typed clients are injected into setup via the `deps` argument.
|
|
1091
1033
|
* Pass a function returning the deps object: `deps: () => ({ orders })`.
|
|
1092
1034
|
*/
|
|
1093
1035
|
deps?: () => D & {};
|
|
1094
1036
|
/**
|
|
1095
1037
|
* SSM Parameter Store parameters.
|
|
1096
|
-
* Declare with `
|
|
1097
|
-
* Typed values are injected into the handler via the `config` argument.
|
|
1038
|
+
* Declare with `defineSecret()` helper. Values are fetched and cached at cold start.
|
|
1098
1039
|
*/
|
|
1099
|
-
config?: P
|
|
1040
|
+
config?: ConfigFactory<P>;
|
|
1100
1041
|
/**
|
|
1101
1042
|
* Static file glob patterns to bundle into the Lambda ZIP.
|
|
1102
|
-
* Files are accessible at runtime via the `files`
|
|
1043
|
+
* Files are accessible at runtime via the `files` argument in setup.
|
|
1103
1044
|
*/
|
|
1104
1045
|
static?: S;
|
|
1105
1046
|
};
|
|
1106
|
-
/**
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1047
|
+
/**
|
|
1048
|
+
* Options for defineTable.
|
|
1049
|
+
* `onRecord` and `onRecordBatch` are mutually exclusive. Both are optional (table-only mode).
|
|
1050
|
+
*/
|
|
1051
|
+
type DefineTableOptions<T = Record<string, unknown>, C = undefined, D = undefined, P = undefined, S extends string[] | undefined = undefined> = DefineTableBase<T, C, D, P, S> & ({
|
|
1052
|
+
/**
|
|
1053
|
+
* Per-record stream handler. Called once per record in the batch.
|
|
1054
|
+
* Runtime handles partial batch failure reporting automatically.
|
|
1055
|
+
* Records are processed with configurable `concurrency` (default: 1 — sequential).
|
|
1056
|
+
*/
|
|
1057
|
+
onRecord?: TableRecordFn<T, C>;
|
|
1058
|
+
onRecordBatch?: never;
|
|
1059
|
+
} | {
|
|
1060
|
+
/**
|
|
1061
|
+
* Batch stream handler. Called once with all records in the batch.
|
|
1062
|
+
* Return `{ failures: string[] }` with sequence numbers for partial batch failure.
|
|
1063
|
+
*/
|
|
1064
|
+
onRecordBatch?: TableBatchFn<T, C>;
|
|
1115
1065
|
onRecord?: never;
|
|
1116
|
-
|
|
1117
|
-
};
|
|
1118
|
-
/** Resource-only: no handler, just creates the table */
|
|
1119
|
-
type DefineTableResourceOnly<T = Record<string, unknown>, C = undefined, D = undefined, P = undefined, S extends string[] | undefined = undefined> = DefineTableBase<T, C, D, P, S> & {
|
|
1066
|
+
} | {
|
|
1120
1067
|
onRecord?: never;
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
};
|
|
1124
|
-
type DefineTableOptions<T = Record<string, unknown>, C = undefined, R = void, D extends Record<string, AnyDepHandler> | undefined = undefined, P extends Record<string, AnyParamRef> | undefined = undefined, S extends string[] | undefined = undefined> = DefineTableWithOnRecord<T, C, R, D, P, S> | DefineTableWithOnBatch<T, C, D, P, S> | DefineTableResourceOnly<T, C, D, P, S>;
|
|
1068
|
+
onRecordBatch?: never;
|
|
1069
|
+
});
|
|
1125
1070
|
/**
|
|
1126
1071
|
* Internal handler object created by defineTable
|
|
1127
1072
|
* @internal
|
|
@@ -1137,8 +1082,7 @@ type TableHandler<T = Record<string, unknown>, C = any> = {
|
|
|
1137
1082
|
readonly config?: Record<string, unknown>;
|
|
1138
1083
|
readonly static?: string[];
|
|
1139
1084
|
readonly onRecord?: (...args: any[]) => any;
|
|
1140
|
-
readonly
|
|
1141
|
-
readonly onBatch?: (...args: any[]) => any;
|
|
1085
|
+
readonly onRecordBatch?: (...args: any[]) => any;
|
|
1142
1086
|
};
|
|
1143
1087
|
/**
|
|
1144
1088
|
* Define a DynamoDB table with optional stream handler (single-table design).
|
|
@@ -1148,25 +1092,32 @@ type TableHandler<T = Record<string, unknown>, C = any> = {
|
|
|
1148
1092
|
*
|
|
1149
1093
|
* @example Table with stream handler
|
|
1150
1094
|
* ```typescript
|
|
1151
|
-
*
|
|
1152
|
-
*
|
|
1153
|
-
* export const orders = defineTable<OrderData>({
|
|
1154
|
-
* streamView: "NEW_AND_OLD_IMAGES",
|
|
1095
|
+
* export const orders = defineTable<OrderData>()({
|
|
1155
1096
|
* batchSize: 10,
|
|
1156
|
-
*
|
|
1097
|
+
* concurrency: 5,
|
|
1098
|
+
* setup: ({ table }) => ({ table }),
|
|
1099
|
+
* onRecord: async ({ record, batch, table }) => {
|
|
1157
1100
|
* if (record.eventName === "INSERT") {
|
|
1158
|
-
* console.log("New order:", record.new?.data
|
|
1101
|
+
* console.log("New order:", record.new?.data);
|
|
1159
1102
|
* }
|
|
1160
1103
|
* }
|
|
1161
1104
|
* });
|
|
1162
1105
|
* ```
|
|
1163
1106
|
*
|
|
1107
|
+
* @example Table with runtime validation
|
|
1108
|
+
* ```typescript
|
|
1109
|
+
* export const orders = defineTable<OrderData>()({
|
|
1110
|
+
* schema: (input) => OrderSchema.parse(input),
|
|
1111
|
+
* onRecord: async ({ record }) => { ... }
|
|
1112
|
+
* });
|
|
1113
|
+
* ```
|
|
1114
|
+
*
|
|
1164
1115
|
* @example Table only (no Lambda)
|
|
1165
1116
|
* ```typescript
|
|
1166
|
-
* export const users = defineTable({});
|
|
1117
|
+
* export const users = defineTable()({});
|
|
1167
1118
|
* ```
|
|
1168
1119
|
*/
|
|
1169
|
-
declare const defineTable: <T = Record<string, unknown
|
|
1120
|
+
declare const defineTable: <T = Record<string, unknown>>() => <C = undefined, D = undefined, P = undefined, S extends string[] | undefined = undefined>(options: DefineTableOptions<T, C, D, P, S>) => TableHandler<T, C>;
|
|
1170
1121
|
|
|
1171
1122
|
/**
|
|
1172
1123
|
* Configuration for deploying an SSR framework (Nuxt, Astro, etc.)
|
|
@@ -1223,81 +1174,7 @@ type AppHandler = {
|
|
|
1223
1174
|
* });
|
|
1224
1175
|
* ```
|
|
1225
1176
|
*/
|
|
1226
|
-
declare const defineApp: (options: AppConfig) => AppHandler;
|
|
1227
|
-
|
|
1228
|
-
type CookieAuthConfig<_T = undefined> = {
|
|
1229
|
-
/** Path to redirect unauthenticated users to */
|
|
1230
|
-
loginPath: string;
|
|
1231
|
-
/** Paths that don't require authentication. Supports trailing `*` wildcard. */
|
|
1232
|
-
public?: string[];
|
|
1233
|
-
/** Default session lifetime (default: "7d"). Accepts seconds or duration string. */
|
|
1234
|
-
expiresIn?: Duration;
|
|
1235
|
-
};
|
|
1236
|
-
/**
|
|
1237
|
-
* Branded cookie auth object returned by `defineAuth()`.
|
|
1238
|
-
* Pass to `defineApi({ auth })` and `defineStaticSite({ auth })`.
|
|
1239
|
-
*/
|
|
1240
|
-
type CookieAuth<T = undefined> = CookieAuthConfig<T> & {
|
|
1241
|
-
readonly __brand: "effortless-cookie-auth";
|
|
1242
|
-
/** @internal phantom type marker for session data */
|
|
1243
|
-
readonly __session?: T;
|
|
1244
|
-
};
|
|
1245
|
-
/**
|
|
1246
|
-
* Define cookie-based authentication using HMAC-signed tokens.
|
|
1247
|
-
*
|
|
1248
|
-
* - Middleware (Lambda@Edge) verifies cookie signatures without external calls
|
|
1249
|
-
* - API handler gets `auth.grant()` / `auth.revoke()` / `auth.session` helpers
|
|
1250
|
-
* - Secret is auto-generated and stored in SSM Parameter Store
|
|
1251
|
-
*
|
|
1252
|
-
* @typeParam T - Session data type. When provided, `grant(data)` requires typed payload
|
|
1253
|
-
* and `auth.session` is typed as `T` in handler args.
|
|
1254
|
-
*
|
|
1255
|
-
* @example
|
|
1256
|
-
* ```typescript
|
|
1257
|
-
* type Session = { userId: string; role: "admin" | "user" };
|
|
1258
|
-
*
|
|
1259
|
-
* const protect = defineAuth<Session>({
|
|
1260
|
-
* loginPath: '/login',
|
|
1261
|
-
* public: ['/login', '/assets/*'],
|
|
1262
|
-
* expiresIn: '7d',
|
|
1263
|
-
* })
|
|
1264
|
-
*
|
|
1265
|
-
* export const api = defineApi({ auth: protect, ... })
|
|
1266
|
-
* export const webapp = defineStaticSite({ auth: protect, ... })
|
|
1267
|
-
* ```
|
|
1268
|
-
*/
|
|
1269
|
-
declare const defineAuth: <T = undefined>(options: CookieAuthConfig<T>) => CookieAuth<T>;
|
|
1270
|
-
/** Grant options for creating a session */
|
|
1271
|
-
type GrantOptions = {
|
|
1272
|
-
expiresIn?: Duration;
|
|
1273
|
-
};
|
|
1274
|
-
/** Grant response with Set-Cookie header */
|
|
1275
|
-
type GrantResponse = {
|
|
1276
|
-
status: 200;
|
|
1277
|
-
body: {
|
|
1278
|
-
ok: true;
|
|
1279
|
-
};
|
|
1280
|
-
headers: Record<string, string>;
|
|
1281
|
-
};
|
|
1282
|
-
/**
|
|
1283
|
-
* Auth helpers injected into API handler callback args when `auth` is configured.
|
|
1284
|
-
* @typeParam T - Session data type (undefined = no custom data)
|
|
1285
|
-
*/
|
|
1286
|
-
type AuthHelpers<T = undefined> = {
|
|
1287
|
-
revoke(): {
|
|
1288
|
-
status: 200;
|
|
1289
|
-
body: {
|
|
1290
|
-
ok: true;
|
|
1291
|
-
};
|
|
1292
|
-
headers: Record<string, string>;
|
|
1293
|
-
};
|
|
1294
|
-
/** The current session data (decoded from cookie). Undefined if no valid session. */
|
|
1295
|
-
session: T extends undefined ? undefined : T | undefined;
|
|
1296
|
-
} & ([T] extends [undefined] ? {
|
|
1297
|
-
grant(options?: GrantOptions): GrantResponse;
|
|
1298
|
-
} : {
|
|
1299
|
-
grant(data: T, options?: GrantOptions): GrantResponse;
|
|
1300
|
-
});
|
|
1177
|
+
declare const defineApp: () => (options: AppConfig) => AppHandler;
|
|
1301
1178
|
|
|
1302
1179
|
/** Any branded handler that deploys to API Gateway (HttpHandler, ApiHandler, etc.) */
|
|
1303
1180
|
type AnyRoutableHandler = {
|
|
@@ -1358,8 +1235,6 @@ type StaticSiteConfig = {
|
|
|
1358
1235
|
errorPage?: string;
|
|
1359
1236
|
/** Lambda@Edge middleware that runs before serving pages. Use for auth checks, redirects, etc. */
|
|
1360
1237
|
middleware?: MiddlewareHandler;
|
|
1361
|
-
/** Cookie-based authentication. Auto-generates Lambda@Edge middleware that verifies signed cookies. */
|
|
1362
|
-
auth?: CookieAuth<any>;
|
|
1363
1238
|
/** SEO: auto-generate sitemap.xml and robots.txt at deploy time, optionally submit URLs to Google Indexing API */
|
|
1364
1239
|
seo?: StaticSiteSeo;
|
|
1365
1240
|
};
|
|
@@ -1394,48 +1269,107 @@ type StaticSiteHandler = {
|
|
|
1394
1269
|
* });
|
|
1395
1270
|
* ```
|
|
1396
1271
|
*
|
|
1397
|
-
* @example Protected site with middleware (Lambda@Edge)
|
|
1398
|
-
* ```typescript
|
|
1399
|
-
* export const admin = defineStaticSite({
|
|
1400
|
-
* dir: "admin/dist",
|
|
1401
|
-
* middleware: async (request) => {
|
|
1402
|
-
* if (!request.cookies.session) {
|
|
1403
|
-
* return { redirect: "/login" };
|
|
1404
|
-
* }
|
|
1405
|
-
* },
|
|
1406
|
-
* });
|
|
1407
|
-
* ```
|
|
1408
1272
|
*/
|
|
1409
|
-
declare const defineStaticSite: (options: StaticSiteConfig) => StaticSiteHandler;
|
|
1273
|
+
declare const defineStaticSite: () => (options: StaticSiteConfig) => StaticSiteHandler;
|
|
1410
1274
|
|
|
1411
|
-
/**
|
|
1412
|
-
type
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
}
|
|
1421
|
-
|
|
1422
|
-
|
|
1275
|
+
/** Options for creating a session */
|
|
1276
|
+
type SessionOptions = {
|
|
1277
|
+
expiresIn?: Duration;
|
|
1278
|
+
};
|
|
1279
|
+
/** Session response with Set-Cookie header */
|
|
1280
|
+
type SessionResponse = {
|
|
1281
|
+
status: 200;
|
|
1282
|
+
body: {
|
|
1283
|
+
ok: true;
|
|
1284
|
+
};
|
|
1285
|
+
headers: Record<string, string>;
|
|
1286
|
+
};
|
|
1287
|
+
/**
|
|
1288
|
+
* Auth helpers injected into API handler callback args when `auth` is configured.
|
|
1289
|
+
* @typeParam T - Session data type (from `AuthOptions<T>`)
|
|
1290
|
+
*/
|
|
1291
|
+
type AuthHelpers<T = unknown> = {
|
|
1292
|
+
/** Create a signed session cookie with typed data. */
|
|
1293
|
+
createSession(data: T, options?: SessionOptions): SessionResponse;
|
|
1294
|
+
/** Clear the session cookie. */
|
|
1295
|
+
clearSession(): {
|
|
1296
|
+
status: 200;
|
|
1297
|
+
body: {
|
|
1298
|
+
ok: true;
|
|
1299
|
+
};
|
|
1300
|
+
headers: Record<string, string>;
|
|
1301
|
+
};
|
|
1302
|
+
/** The current session data (from cookie or API token). Undefined if no valid session. */
|
|
1303
|
+
session: T | undefined;
|
|
1304
|
+
};
|
|
1305
|
+
|
|
1306
|
+
/** Auth config options (user-facing) */
|
|
1307
|
+
type AuthOptions<A = unknown> = {
|
|
1308
|
+
/** HMAC secret for signing session cookies. Use `secret()` or `param()` in config. */
|
|
1309
|
+
secret: string;
|
|
1310
|
+
/** Default session lifetime (default: "7d"). */
|
|
1311
|
+
expiresIn?: Duration;
|
|
1312
|
+
/** Optional API token strategy for external clients. */
|
|
1313
|
+
apiToken?: {
|
|
1314
|
+
/** HTTP header to read the token from. Default: "authorization" (strips "Bearer " prefix). */
|
|
1315
|
+
header?: string;
|
|
1316
|
+
/** Verify the token value and return session data, or null if invalid. */
|
|
1317
|
+
verify: (value: string) => A | null | Promise<A | null>;
|
|
1318
|
+
/** Cache verified token results for this duration. */
|
|
1319
|
+
cacheTtl?: Duration;
|
|
1320
|
+
};
|
|
1321
|
+
};
|
|
1322
|
+
/** Branded auth config — created by `enableAuth<A>()` helper, carries session type A */
|
|
1323
|
+
type ApiAuthConfig<A = unknown> = AuthOptions<A> & {
|
|
1324
|
+
readonly __sessionType: A;
|
|
1325
|
+
};
|
|
1326
|
+
/** Type of the `enableAuth` helper injected into setup args */
|
|
1327
|
+
type EnableAuth = <A = unknown>(options: AuthOptions<A>) => ApiAuthConfig<A>;
|
|
1328
|
+
/** Extract session type A from ctx.auth if present */
|
|
1329
|
+
type ExtractAuth<C> = C extends {
|
|
1330
|
+
auth: ApiAuthConfig<infer A>;
|
|
1331
|
+
} ? A : undefined;
|
|
1332
|
+
/** Property names reserved by the framework — cannot be used in setup return */
|
|
1333
|
+
type ReservedKeys = 'req' | 'input' | 'stream';
|
|
1334
|
+
type HttpMethod = "GET" | "POST" | "PUT" | "PATCH" | "DELETE";
|
|
1335
|
+
/** Parsed route definition stored at runtime */
|
|
1336
|
+
type RouteEntry = {
|
|
1337
|
+
method: HttpMethod;
|
|
1338
|
+
path: string;
|
|
1339
|
+
onRequest: (...args: any[]) => any;
|
|
1340
|
+
public?: boolean;
|
|
1341
|
+
};
|
|
1342
|
+
/** Spread ctx into route args: Omit auth config, add AuthHelpers if present */
|
|
1343
|
+
type SpreadCtx<C> = ([C] extends [undefined] ? {} : Omit<C & {}, 'auth'>) & ([ExtractAuth<C>] extends [undefined] ? {} : {
|
|
1344
|
+
auth: AuthHelpers<ExtractAuth<C>>;
|
|
1345
|
+
});
|
|
1346
|
+
/** Callback args available inside each route — ctx is spread into args */
|
|
1347
|
+
type RouteArgs<C, ST> = SpreadCtx<C> & {
|
|
1423
1348
|
req: HttpRequest;
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
}) & HandlerArgs<C, D, P, S> & ([ST] extends [true] ? {
|
|
1349
|
+
input: unknown;
|
|
1350
|
+
} & ([ST] extends [true] ? {
|
|
1427
1351
|
stream: ResponseStream;
|
|
1428
|
-
} : {})
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1352
|
+
} : {});
|
|
1353
|
+
/** Route definition with typed args */
|
|
1354
|
+
type RouteDefinition<C, ST> = {
|
|
1355
|
+
path: `${HttpMethod} /${string}`;
|
|
1356
|
+
onRequest: (args: RouteArgs<C, ST>) => Promise<HttpResponse | void> | HttpResponse | void;
|
|
1357
|
+
public?: boolean;
|
|
1358
|
+
};
|
|
1359
|
+
/** Validate that setup return type does not use reserved property names */
|
|
1360
|
+
type ValidateSetupReturn<C> = C & {
|
|
1361
|
+
[K in ReservedKeys]?: never;
|
|
1362
|
+
};
|
|
1363
|
+
/** Setup factory — receives deps/config/files/enableAuth when declared */
|
|
1364
|
+
type SetupFactory<C, D, P, S extends string[] | undefined = undefined> = (args: {
|
|
1365
|
+
enableAuth: EnableAuth;
|
|
1366
|
+
} & ([D] extends [undefined] ? {} : {
|
|
1433
1367
|
deps: ResolveDeps<D>;
|
|
1434
1368
|
}) & ([P] extends [undefined] ? {} : {
|
|
1435
1369
|
config: ResolveConfig<P & {}>;
|
|
1436
1370
|
}) & ([S] extends [undefined] ? {} : {
|
|
1437
1371
|
files: StaticFiles;
|
|
1438
|
-
})) => C | Promise<C
|
|
1372
|
+
})) => ValidateSetupReturn<C> | Promise<ValidateSetupReturn<C>>;
|
|
1439
1373
|
/** Static config extracted by AST (no runtime callbacks) */
|
|
1440
1374
|
type ApiConfig = {
|
|
1441
1375
|
/** Lambda function settings (memory, timeout, permissions, etc.) */
|
|
@@ -1445,101 +1379,79 @@ type ApiConfig = {
|
|
|
1445
1379
|
/** Enable response streaming. When true, the Lambda Function URL uses RESPONSE_STREAM invoke mode. */
|
|
1446
1380
|
stream?: boolean;
|
|
1447
1381
|
};
|
|
1448
|
-
|
|
1449
|
-
* Options for defining a CQRS-style API endpoint.
|
|
1450
|
-
*
|
|
1451
|
-
* - `get` routes handle queries (path-based routing, no body)
|
|
1452
|
-
* - `post` handles commands (single entry point, discriminated union via `schema`)
|
|
1453
|
-
*/
|
|
1454
|
-
type DefineApiOptions<T = undefined, C = undefined, D extends Record<string, AnyDepHandler> | undefined = undefined, P extends Record<string, AnyParamRef> | undefined = undefined, S extends string[] | undefined = undefined, ST extends boolean | undefined = undefined, A extends CookieAuth<any> | undefined = undefined> = {
|
|
1382
|
+
type DefineApiOptions<C = undefined, D extends Record<string, AnyDepHandler> | undefined = undefined, P extends Record<string, AnySecretRef> | undefined = undefined, S extends string[] | undefined = undefined, ST extends boolean | undefined = undefined> = {
|
|
1455
1383
|
/** Lambda function settings (memory, timeout, permissions, etc.) */
|
|
1456
1384
|
lambda?: LambdaWithPermissions;
|
|
1457
1385
|
/** Base path prefix for all routes (e.g., "/api") */
|
|
1458
1386
|
basePath: `/${string}`;
|
|
1459
|
-
/** Enable response streaming. When true, routes receive a `stream` arg for SSE.
|
|
1387
|
+
/** Enable response streaming. When true, routes receive a `stream` arg for SSE. */
|
|
1460
1388
|
stream?: ST;
|
|
1461
|
-
/**
|
|
1462
|
-
|
|
1463
|
-
/**
|
|
1464
|
-
* Factory function to initialize shared state.
|
|
1465
|
-
* Called once on cold start, result is cached and reused across invocations.
|
|
1466
|
-
*/
|
|
1467
|
-
setup?: SetupFactory<C, D, P, S>;
|
|
1389
|
+
/** Factory function to initialize shared state. Called once on cold start. */
|
|
1390
|
+
setup?: SetupFactory<C, NoInfer<D>, NoInfer<P>, NoInfer<S>>;
|
|
1468
1391
|
/** Dependencies on other handlers (tables, queues, etc.): `deps: () => ({ users })` */
|
|
1469
1392
|
deps?: () => D & {};
|
|
1470
|
-
/** SSM Parameter Store parameters */
|
|
1471
|
-
config?: P
|
|
1393
|
+
/** SSM Parameter Store parameters. Receives `{ defineSecret }` helper. */
|
|
1394
|
+
config?: ConfigFactory<P>;
|
|
1472
1395
|
/** Static file glob patterns to bundle into the Lambda ZIP */
|
|
1473
1396
|
static?: S;
|
|
1474
|
-
/** Error handler called when
|
|
1397
|
+
/** Error handler called when a route throws */
|
|
1475
1398
|
onError?: (args: {
|
|
1476
1399
|
error: unknown;
|
|
1477
1400
|
req: HttpRequest;
|
|
1478
|
-
} &
|
|
1479
|
-
/** Called after each invocation completes
|
|
1480
|
-
onAfterInvoke?: (args:
|
|
1481
|
-
/**
|
|
1482
|
-
|
|
1483
|
-
/**
|
|
1484
|
-
* Schema for POST body validation. Use with discriminated unions:
|
|
1485
|
-
* ```typescript
|
|
1486
|
-
* schema: Action.parse,
|
|
1487
|
-
* post: async ({ data }) => { switch (data.action) { ... } }
|
|
1488
|
-
* ```
|
|
1489
|
-
*/
|
|
1490
|
-
schema?: (input: unknown) => T;
|
|
1491
|
-
/** POST handler — single entry point for commands */
|
|
1492
|
-
post?: ApiPostHandlerFn<T, C, D, P, S, ST, A>;
|
|
1401
|
+
} & SpreadCtx<C>) => HttpResponse;
|
|
1402
|
+
/** Called after each invocation completes */
|
|
1403
|
+
onAfterInvoke?: (args: SpreadCtx<C>) => void | Promise<void>;
|
|
1404
|
+
/** Route definitions — plain array of route objects */
|
|
1405
|
+
routes?: RouteDefinition<C, ST>[];
|
|
1493
1406
|
};
|
|
1494
1407
|
/** Internal handler object created by defineApi */
|
|
1495
|
-
type ApiHandler<
|
|
1408
|
+
type ApiHandler<C = undefined> = {
|
|
1496
1409
|
readonly __brand: "effortless-api";
|
|
1497
1410
|
readonly __spec: ApiConfig;
|
|
1498
|
-
readonly schema?: (input: unknown) => T;
|
|
1499
1411
|
readonly onError?: (...args: any[]) => any;
|
|
1500
1412
|
readonly onAfterInvoke?: (...args: any[]) => any;
|
|
1501
1413
|
readonly setup?: (...args: any[]) => C | Promise<C>;
|
|
1502
1414
|
readonly deps?: Record<string, unknown> | (() => Record<string, unknown>);
|
|
1503
1415
|
readonly config?: Record<string, unknown>;
|
|
1504
1416
|
readonly static?: string[];
|
|
1505
|
-
readonly
|
|
1506
|
-
readonly get?: Record<`/${string}`, (...args: any[]) => any>;
|
|
1507
|
-
readonly post?: (...args: any[]) => any;
|
|
1417
|
+
readonly routes?: RouteEntry[];
|
|
1508
1418
|
};
|
|
1509
1419
|
/**
|
|
1510
|
-
* Define
|
|
1420
|
+
* Define an API with typed routes.
|
|
1511
1421
|
*
|
|
1512
|
-
*
|
|
1513
|
-
*
|
|
1514
|
-
*
|
|
1422
|
+
* Setup return is spread into route args — all properties are directly accessible.
|
|
1423
|
+
* Reserved names (`req`, `input`, `stream`) cannot be used in setup return.
|
|
1424
|
+
* Auth is configured via an `auth` property in setup return — runtime replaces it with `AuthHelpers`.
|
|
1515
1425
|
*
|
|
1516
1426
|
* @example
|
|
1517
1427
|
* ```typescript
|
|
1518
1428
|
* export default defineApi({
|
|
1519
1429
|
* basePath: "/api",
|
|
1520
|
-
* deps: { users },
|
|
1521
|
-
*
|
|
1522
|
-
*
|
|
1523
|
-
*
|
|
1524
|
-
*
|
|
1525
|
-
*
|
|
1526
|
-
*
|
|
1527
|
-
*
|
|
1528
|
-
*
|
|
1529
|
-
*
|
|
1530
|
-
*
|
|
1531
|
-
*
|
|
1532
|
-
*
|
|
1533
|
-
*
|
|
1534
|
-
*
|
|
1535
|
-
*
|
|
1536
|
-
*
|
|
1537
|
-
*
|
|
1538
|
-
*
|
|
1539
|
-
*
|
|
1430
|
+
* deps: () => ({ users }),
|
|
1431
|
+
* setup: ({ deps }) => ({
|
|
1432
|
+
* users: deps.users,
|
|
1433
|
+
* auth: {
|
|
1434
|
+
* schema: unsafeAs<Session>(),
|
|
1435
|
+
* apiToken: {
|
|
1436
|
+
* verify: async (value) => {
|
|
1437
|
+
* const user = await deps.users.query({ pk: value });
|
|
1438
|
+
* return user[0] ? { userId: user[0].sk } : null;
|
|
1439
|
+
* },
|
|
1440
|
+
* },
|
|
1441
|
+
* },
|
|
1442
|
+
* }),
|
|
1443
|
+
* routes: [
|
|
1444
|
+
* {
|
|
1445
|
+
* path: "GET /me",
|
|
1446
|
+
* onRequest: async ({ users, auth }) => ({
|
|
1447
|
+
* status: 200,
|
|
1448
|
+
* body: { user: await users.get(auth.session.userId) },
|
|
1449
|
+
* }),
|
|
1450
|
+
* },
|
|
1451
|
+
* ],
|
|
1540
1452
|
* })
|
|
1541
1453
|
* ```
|
|
1542
1454
|
*/
|
|
1543
|
-
declare const defineApi:
|
|
1455
|
+
declare const defineApi: () => <C = undefined, D extends Record<string, AnyDepHandler> | undefined = undefined, P extends Record<string, AnySecretRef> | undefined = undefined, S extends string[] | undefined = undefined, ST extends boolean | undefined = undefined>(options: DefineApiOptions<C, D, P, S, ST>) => ApiHandler<C>;
|
|
1544
1456
|
|
|
1545
|
-
export { type AnyParamRef, type AnySecretRef, type ApiConfig, type ApiHandler, type AppConfig, type AppHandler, type AuthHelpers, type BucketClient, type BucketConfig, type BucketEvent, type BucketHandler, type
|
|
1457
|
+
export { type AnyParamRef, type AnySecretRef, type ApiAuthConfig, type ApiConfig, type ApiHandler, type AppConfig, type AppHandler, type AuthHelpers, type BucketClient, type BucketConfig, type BucketEvent, type BucketHandler, type ConfigHelpers, type ContentType, type DefineSecretFn, type Duration, type EffortlessConfig, type EmailClient, type FifoQueueConfig, type FifoQueueHandler, type FifoQueueMessage, type GenerateSpec, type HttpMethod$1 as HttpMethod, type HttpRequest, type HttpResponse, type LambdaConfig, type LambdaWithPermissions, type LogLevel, type MailerConfig, type MailerHandler, 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 UpdateActions, defineApi, defineApp, defineBucket, defineConfig, defineFifoQueue, defineMailer, defineSecret, defineStaticSite, defineTable, generateBase64, generateHex, generateUuid, param, result, secret, toSeconds, unsafeAs };
|