fakecloud 0.5.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 ADDED
@@ -0,0 +1,143 @@
1
+ # fakecloud
2
+
3
+ TypeScript client SDK for [fakecloud](https://github.com/faiscadev/fakecloud) — a local AWS cloud emulator.
4
+
5
+ Provides typed access to the fakecloud introspection and simulation API (`/_fakecloud/*` endpoints), letting you inspect emulator state and trigger time-based processors in tests.
6
+
7
+ ## Installation
8
+
9
+ ```bash
10
+ npm install fakecloud
11
+ ```
12
+
13
+ ## Quick start
14
+
15
+ ```typescript
16
+ import { FakeCloud } from "fakecloud";
17
+
18
+ const fc = new FakeCloud("http://localhost:4566");
19
+
20
+ // Check server health
21
+ const health = await fc.health();
22
+ console.log(health.version, health.services);
23
+
24
+ // Reset all state between tests
25
+ await fc.reset();
26
+
27
+ // Inspect SES emails sent during a test
28
+ const { emails } = await fc.ses.getEmails();
29
+ console.log(`Sent ${emails.length} emails`);
30
+
31
+ // Inspect SNS messages
32
+ const { messages } = await fc.sns.getMessages();
33
+
34
+ // Inspect SQS messages across all queues
35
+ const { queues } = await fc.sqs.getMessages();
36
+
37
+ // Advance DynamoDB TTL processor
38
+ const { expiredItems } = await fc.dynamodb.tickTtl();
39
+
40
+ // Advance S3 lifecycle processor
41
+ const { expiredObjects } = await fc.s3.tickLifecycle();
42
+ ```
43
+
44
+ ## API reference
45
+
46
+ ### `FakeCloud`
47
+
48
+ ```typescript
49
+ const fc = new FakeCloud(baseUrl?: string);
50
+ ```
51
+
52
+ Top-level client. Defaults to `http://localhost:4566`.
53
+
54
+ | Method | Description |
55
+ | ----------------------- | ----------------------- |
56
+ | `health()` | Server health check |
57
+ | `reset()` | Reset all service state |
58
+ | `resetService(service)` | Reset a single service |
59
+
60
+ ### `fc.lambda`
61
+
62
+ | Method | Description |
63
+ | ------------------------------ | ------------------------------------ |
64
+ | `getInvocations()` | List recorded Lambda invocations |
65
+ | `getWarmContainers()` | List warm (cached) Lambda containers |
66
+ | `evictContainer(functionName)` | Evict a warm container |
67
+
68
+ ### `fc.ses`
69
+
70
+ | Method | Description |
71
+ | ---------------------- | ----------------------------------------- |
72
+ | `getEmails()` | List all sent emails |
73
+ | `simulateInbound(req)` | Simulate an inbound email (receipt rules) |
74
+
75
+ ### `fc.sns`
76
+
77
+ | Method | Description |
78
+ | --------------------------- | --------------------------------------- |
79
+ | `getMessages()` | List all published messages |
80
+ | `getPendingConfirmations()` | List subscriptions pending confirmation |
81
+ | `confirmSubscription(req)` | Confirm a pending subscription |
82
+
83
+ ### `fc.sqs`
84
+
85
+ | Method | Description |
86
+ | --------------------- | ------------------------------------- |
87
+ | `getMessages()` | List all messages across all queues |
88
+ | `tickExpiration()` | Tick the message expiration processor |
89
+ | `forceDlq(queueName)` | Force all messages to the queue's DLQ |
90
+
91
+ ### `fc.events`
92
+
93
+ | Method | Description |
94
+ | --------------- | -------------------------------------- |
95
+ | `getHistory()` | Get event history and delivery records |
96
+ | `fireRule(req)` | Fire an EventBridge rule manually |
97
+
98
+ ### `fc.s3`
99
+
100
+ | Method | Description |
101
+ | -------------------- | ---------------------------- |
102
+ | `getNotifications()` | List S3 notification events |
103
+ | `tickLifecycle()` | Tick the lifecycle processor |
104
+
105
+ ### `fc.dynamodb`
106
+
107
+ | Method | Description |
108
+ | ----------- | ---------------------- |
109
+ | `tickTtl()` | Tick the TTL processor |
110
+
111
+ ### `fc.secretsmanager`
112
+
113
+ | Method | Description |
114
+ | ---------------- | --------------------------- |
115
+ | `tickRotation()` | Tick the rotation scheduler |
116
+
117
+ ### `fc.cognito`
118
+
119
+ | Method | Description |
120
+ | -------------------------------- | ------------------------------------ |
121
+ | `getUserCodes(poolId, username)` | Get confirmation codes for a user |
122
+ | `getConfirmationCodes()` | List all confirmation codes |
123
+ | `confirmUser(req)` | Confirm a user (bypass verification) |
124
+ | `getTokens()` | List all active tokens |
125
+ | `expireTokens(req)` | Expire tokens (optionally filtered) |
126
+ | `getAuthEvents()` | List auth events |
127
+
128
+ ### Error handling
129
+
130
+ All methods throw `FakeCloudError` on non-2xx responses:
131
+
132
+ ```typescript
133
+ import { FakeCloudError } from "fakecloud";
134
+
135
+ try {
136
+ await fc.cognito.confirmUser({ userPoolId: "pool-1", username: "nobody" });
137
+ } catch (err) {
138
+ if (err instanceof FakeCloudError) {
139
+ console.log(err.status); // 404
140
+ console.log(err.body); // "user not found"
141
+ }
142
+ }
143
+ ```
@@ -0,0 +1,90 @@
1
+ import type { HealthResponse, ResetResponse, ResetServiceResponse, LambdaInvocationsResponse, WarmContainersResponse, EvictContainerResponse, SesEmailsResponse, InboundEmailRequest, InboundEmailResponse, SnsMessagesResponse, PendingConfirmationsResponse, ConfirmSubscriptionRequest, ConfirmSubscriptionResponse, SqsMessagesResponse, ExpirationTickResponse, ForceDlqResponse, EventHistoryResponse, FireRuleRequest, FireRuleResponse, S3NotificationsResponse, LifecycleTickResponse, TtlTickResponse, RotationTickResponse, UserConfirmationCodes, ConfirmationCodesResponse, ConfirmUserRequest, ConfirmUserResponse, TokensResponse, ExpireTokensRequest, ExpireTokensResponse, AuthEventsResponse } from "./types.js";
2
+ export declare class FakeCloudError extends Error {
3
+ readonly status: number;
4
+ readonly body: string;
5
+ constructor(status: number, body: string);
6
+ }
7
+ export declare class LambdaClient {
8
+ private baseUrl;
9
+ constructor(baseUrl: string);
10
+ getInvocations(): Promise<LambdaInvocationsResponse>;
11
+ getWarmContainers(): Promise<WarmContainersResponse>;
12
+ evictContainer(functionName: string): Promise<EvictContainerResponse>;
13
+ }
14
+ export declare class SesClient {
15
+ private baseUrl;
16
+ constructor(baseUrl: string);
17
+ getEmails(): Promise<SesEmailsResponse>;
18
+ simulateInbound(req: InboundEmailRequest): Promise<InboundEmailResponse>;
19
+ }
20
+ export declare class SnsClient {
21
+ private baseUrl;
22
+ constructor(baseUrl: string);
23
+ getMessages(): Promise<SnsMessagesResponse>;
24
+ getPendingConfirmations(): Promise<PendingConfirmationsResponse>;
25
+ confirmSubscription(req: ConfirmSubscriptionRequest): Promise<ConfirmSubscriptionResponse>;
26
+ }
27
+ export declare class SqsClient {
28
+ private baseUrl;
29
+ constructor(baseUrl: string);
30
+ getMessages(): Promise<SqsMessagesResponse>;
31
+ tickExpiration(): Promise<ExpirationTickResponse>;
32
+ forceDlq(queueName: string): Promise<ForceDlqResponse>;
33
+ }
34
+ export declare class EventsClient {
35
+ private baseUrl;
36
+ constructor(baseUrl: string);
37
+ getHistory(): Promise<EventHistoryResponse>;
38
+ fireRule(req: FireRuleRequest): Promise<FireRuleResponse>;
39
+ }
40
+ export declare class S3Client {
41
+ private baseUrl;
42
+ constructor(baseUrl: string);
43
+ getNotifications(): Promise<S3NotificationsResponse>;
44
+ tickLifecycle(): Promise<LifecycleTickResponse>;
45
+ }
46
+ export declare class DynamoDbClient {
47
+ private baseUrl;
48
+ constructor(baseUrl: string);
49
+ tickTtl(): Promise<TtlTickResponse>;
50
+ }
51
+ export declare class SecretsManagerClient {
52
+ private baseUrl;
53
+ constructor(baseUrl: string);
54
+ tickRotation(): Promise<RotationTickResponse>;
55
+ }
56
+ export declare class CognitoClient {
57
+ private baseUrl;
58
+ constructor(baseUrl: string);
59
+ getUserCodes(poolId: string, username: string): Promise<UserConfirmationCodes>;
60
+ getConfirmationCodes(): Promise<ConfirmationCodesResponse>;
61
+ confirmUser(req: ConfirmUserRequest): Promise<ConfirmUserResponse>;
62
+ getTokens(): Promise<TokensResponse>;
63
+ expireTokens(req: ExpireTokensRequest): Promise<ExpireTokensResponse>;
64
+ getAuthEvents(): Promise<AuthEventsResponse>;
65
+ }
66
+ export declare class FakeCloud {
67
+ private readonly baseUrl;
68
+ private readonly _lambda;
69
+ private readonly _ses;
70
+ private readonly _sns;
71
+ private readonly _sqs;
72
+ private readonly _events;
73
+ private readonly _s3;
74
+ private readonly _dynamodb;
75
+ private readonly _secretsmanager;
76
+ private readonly _cognito;
77
+ constructor(baseUrl?: string);
78
+ health(): Promise<HealthResponse>;
79
+ reset(): Promise<ResetResponse>;
80
+ resetService(service: string): Promise<ResetServiceResponse>;
81
+ get lambda(): LambdaClient;
82
+ get ses(): SesClient;
83
+ get sns(): SnsClient;
84
+ get sqs(): SqsClient;
85
+ get events(): EventsClient;
86
+ get s3(): S3Client;
87
+ get dynamodb(): DynamoDbClient;
88
+ get secretsmanager(): SecretsManagerClient;
89
+ get cognito(): CognitoClient;
90
+ }
package/dist/client.js ADDED
@@ -0,0 +1,269 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.FakeCloud = exports.CognitoClient = exports.SecretsManagerClient = exports.DynamoDbClient = exports.S3Client = exports.EventsClient = exports.SqsClient = exports.SnsClient = exports.SesClient = exports.LambdaClient = exports.FakeCloudError = void 0;
4
+ class FakeCloudError extends Error {
5
+ status;
6
+ body;
7
+ constructor(status, body) {
8
+ super(`fakecloud API error (${status}): ${body}`);
9
+ this.status = status;
10
+ this.body = body;
11
+ this.name = "FakeCloudError";
12
+ }
13
+ }
14
+ exports.FakeCloudError = FakeCloudError;
15
+ async function parse(resp) {
16
+ if (!resp.ok) {
17
+ const body = await resp.text().catch(() => "");
18
+ throw new FakeCloudError(resp.status, body);
19
+ }
20
+ return resp.json();
21
+ }
22
+ // ── Sub-clients ────────────────────────────────────────────────────
23
+ class LambdaClient {
24
+ baseUrl;
25
+ constructor(baseUrl) {
26
+ this.baseUrl = baseUrl;
27
+ }
28
+ async getInvocations() {
29
+ const resp = await fetch(`${this.baseUrl}/_fakecloud/lambda/invocations`);
30
+ return parse(resp);
31
+ }
32
+ async getWarmContainers() {
33
+ const resp = await fetch(`${this.baseUrl}/_fakecloud/lambda/warm-containers`);
34
+ return parse(resp);
35
+ }
36
+ async evictContainer(functionName) {
37
+ const resp = await fetch(`${this.baseUrl}/_fakecloud/lambda/${encodeURIComponent(functionName)}/evict-container`, { method: "POST" });
38
+ return parse(resp);
39
+ }
40
+ }
41
+ exports.LambdaClient = LambdaClient;
42
+ class SesClient {
43
+ baseUrl;
44
+ constructor(baseUrl) {
45
+ this.baseUrl = baseUrl;
46
+ }
47
+ async getEmails() {
48
+ const resp = await fetch(`${this.baseUrl}/_fakecloud/ses/emails`);
49
+ return parse(resp);
50
+ }
51
+ async simulateInbound(req) {
52
+ const resp = await fetch(`${this.baseUrl}/_fakecloud/ses/inbound`, {
53
+ method: "POST",
54
+ headers: { "Content-Type": "application/json" },
55
+ body: JSON.stringify(req),
56
+ });
57
+ return parse(resp);
58
+ }
59
+ }
60
+ exports.SesClient = SesClient;
61
+ class SnsClient {
62
+ baseUrl;
63
+ constructor(baseUrl) {
64
+ this.baseUrl = baseUrl;
65
+ }
66
+ async getMessages() {
67
+ const resp = await fetch(`${this.baseUrl}/_fakecloud/sns/messages`);
68
+ return parse(resp);
69
+ }
70
+ async getPendingConfirmations() {
71
+ const resp = await fetch(`${this.baseUrl}/_fakecloud/sns/pending-confirmations`);
72
+ return parse(resp);
73
+ }
74
+ async confirmSubscription(req) {
75
+ const resp = await fetch(`${this.baseUrl}/_fakecloud/sns/confirm-subscription`, {
76
+ method: "POST",
77
+ headers: { "Content-Type": "application/json" },
78
+ body: JSON.stringify(req),
79
+ });
80
+ return parse(resp);
81
+ }
82
+ }
83
+ exports.SnsClient = SnsClient;
84
+ class SqsClient {
85
+ baseUrl;
86
+ constructor(baseUrl) {
87
+ this.baseUrl = baseUrl;
88
+ }
89
+ async getMessages() {
90
+ const resp = await fetch(`${this.baseUrl}/_fakecloud/sqs/messages`);
91
+ return parse(resp);
92
+ }
93
+ async tickExpiration() {
94
+ const resp = await fetch(`${this.baseUrl}/_fakecloud/sqs/expiration-processor/tick`, { method: "POST" });
95
+ return parse(resp);
96
+ }
97
+ async forceDlq(queueName) {
98
+ const resp = await fetch(`${this.baseUrl}/_fakecloud/sqs/${encodeURIComponent(queueName)}/force-dlq`, { method: "POST" });
99
+ return parse(resp);
100
+ }
101
+ }
102
+ exports.SqsClient = SqsClient;
103
+ class EventsClient {
104
+ baseUrl;
105
+ constructor(baseUrl) {
106
+ this.baseUrl = baseUrl;
107
+ }
108
+ async getHistory() {
109
+ const resp = await fetch(`${this.baseUrl}/_fakecloud/events/history`);
110
+ return parse(resp);
111
+ }
112
+ async fireRule(req) {
113
+ const resp = await fetch(`${this.baseUrl}/_fakecloud/events/fire-rule`, {
114
+ method: "POST",
115
+ headers: { "Content-Type": "application/json" },
116
+ body: JSON.stringify(req),
117
+ });
118
+ return parse(resp);
119
+ }
120
+ }
121
+ exports.EventsClient = EventsClient;
122
+ class S3Client {
123
+ baseUrl;
124
+ constructor(baseUrl) {
125
+ this.baseUrl = baseUrl;
126
+ }
127
+ async getNotifications() {
128
+ const resp = await fetch(`${this.baseUrl}/_fakecloud/s3/notifications`);
129
+ return parse(resp);
130
+ }
131
+ async tickLifecycle() {
132
+ const resp = await fetch(`${this.baseUrl}/_fakecloud/s3/lifecycle-processor/tick`, { method: "POST" });
133
+ return parse(resp);
134
+ }
135
+ }
136
+ exports.S3Client = S3Client;
137
+ class DynamoDbClient {
138
+ baseUrl;
139
+ constructor(baseUrl) {
140
+ this.baseUrl = baseUrl;
141
+ }
142
+ async tickTtl() {
143
+ const resp = await fetch(`${this.baseUrl}/_fakecloud/dynamodb/ttl-processor/tick`, { method: "POST" });
144
+ return parse(resp);
145
+ }
146
+ }
147
+ exports.DynamoDbClient = DynamoDbClient;
148
+ class SecretsManagerClient {
149
+ baseUrl;
150
+ constructor(baseUrl) {
151
+ this.baseUrl = baseUrl;
152
+ }
153
+ async tickRotation() {
154
+ const resp = await fetch(`${this.baseUrl}/_fakecloud/secretsmanager/rotation-scheduler/tick`, { method: "POST" });
155
+ return parse(resp);
156
+ }
157
+ }
158
+ exports.SecretsManagerClient = SecretsManagerClient;
159
+ class CognitoClient {
160
+ baseUrl;
161
+ constructor(baseUrl) {
162
+ this.baseUrl = baseUrl;
163
+ }
164
+ async getUserCodes(poolId, username) {
165
+ const resp = await fetch(`${this.baseUrl}/_fakecloud/cognito/confirmation-codes/${encodeURIComponent(poolId)}/${encodeURIComponent(username)}`);
166
+ return parse(resp);
167
+ }
168
+ async getConfirmationCodes() {
169
+ const resp = await fetch(`${this.baseUrl}/_fakecloud/cognito/confirmation-codes`);
170
+ return parse(resp);
171
+ }
172
+ async confirmUser(req) {
173
+ const resp = await fetch(`${this.baseUrl}/_fakecloud/cognito/confirm-user`, {
174
+ method: "POST",
175
+ headers: { "Content-Type": "application/json" },
176
+ body: JSON.stringify(req),
177
+ });
178
+ // This endpoint returns 404 for missing users but still has a JSON body
179
+ if (resp.status === 404) {
180
+ const body = await resp.json();
181
+ throw new FakeCloudError(404, body.error ?? "user not found");
182
+ }
183
+ return parse(resp);
184
+ }
185
+ async getTokens() {
186
+ const resp = await fetch(`${this.baseUrl}/_fakecloud/cognito/tokens`);
187
+ return parse(resp);
188
+ }
189
+ async expireTokens(req) {
190
+ const resp = await fetch(`${this.baseUrl}/_fakecloud/cognito/expire-tokens`, {
191
+ method: "POST",
192
+ headers: { "Content-Type": "application/json" },
193
+ body: JSON.stringify(req),
194
+ });
195
+ return parse(resp);
196
+ }
197
+ async getAuthEvents() {
198
+ const resp = await fetch(`${this.baseUrl}/_fakecloud/cognito/auth-events`);
199
+ return parse(resp);
200
+ }
201
+ }
202
+ exports.CognitoClient = CognitoClient;
203
+ // ── Main client ────────────────────────────────────────────────────
204
+ class FakeCloud {
205
+ baseUrl;
206
+ _lambda;
207
+ _ses;
208
+ _sns;
209
+ _sqs;
210
+ _events;
211
+ _s3;
212
+ _dynamodb;
213
+ _secretsmanager;
214
+ _cognito;
215
+ constructor(baseUrl = "http://localhost:4566") {
216
+ this.baseUrl = baseUrl.replace(/\/+$/, "");
217
+ this._lambda = new LambdaClient(this.baseUrl);
218
+ this._ses = new SesClient(this.baseUrl);
219
+ this._sns = new SnsClient(this.baseUrl);
220
+ this._sqs = new SqsClient(this.baseUrl);
221
+ this._events = new EventsClient(this.baseUrl);
222
+ this._s3 = new S3Client(this.baseUrl);
223
+ this._dynamodb = new DynamoDbClient(this.baseUrl);
224
+ this._secretsmanager = new SecretsManagerClient(this.baseUrl);
225
+ this._cognito = new CognitoClient(this.baseUrl);
226
+ }
227
+ // ── Health & Reset ─────────────────────────────────────────────
228
+ async health() {
229
+ const resp = await fetch(`${this.baseUrl}/_fakecloud/health`);
230
+ return parse(resp);
231
+ }
232
+ async reset() {
233
+ const resp = await fetch(`${this.baseUrl}/_reset`, { method: "POST" });
234
+ return parse(resp);
235
+ }
236
+ async resetService(service) {
237
+ const resp = await fetch(`${this.baseUrl}/_fakecloud/reset/${encodeURIComponent(service)}`, { method: "POST" });
238
+ return parse(resp);
239
+ }
240
+ // ── Sub-clients ────────────────────────────────────────────────
241
+ get lambda() {
242
+ return this._lambda;
243
+ }
244
+ get ses() {
245
+ return this._ses;
246
+ }
247
+ get sns() {
248
+ return this._sns;
249
+ }
250
+ get sqs() {
251
+ return this._sqs;
252
+ }
253
+ get events() {
254
+ return this._events;
255
+ }
256
+ get s3() {
257
+ return this._s3;
258
+ }
259
+ get dynamodb() {
260
+ return this._dynamodb;
261
+ }
262
+ get secretsmanager() {
263
+ return this._secretsmanager;
264
+ }
265
+ get cognito() {
266
+ return this._cognito;
267
+ }
268
+ }
269
+ exports.FakeCloud = FakeCloud;
@@ -0,0 +1,3 @@
1
+ export { FakeCloud, FakeCloudError } from "./client.js";
2
+ export { LambdaClient, SesClient, SnsClient, SqsClient, EventsClient, S3Client, DynamoDbClient, SecretsManagerClient, CognitoClient, } from "./client.js";
3
+ export type * from "./types.js";
package/dist/index.js ADDED
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.CognitoClient = exports.SecretsManagerClient = exports.DynamoDbClient = exports.S3Client = exports.EventsClient = exports.SqsClient = exports.SnsClient = exports.SesClient = exports.LambdaClient = exports.FakeCloudError = exports.FakeCloud = void 0;
4
+ var client_js_1 = require("./client.js");
5
+ Object.defineProperty(exports, "FakeCloud", { enumerable: true, get: function () { return client_js_1.FakeCloud; } });
6
+ Object.defineProperty(exports, "FakeCloudError", { enumerable: true, get: function () { return client_js_1.FakeCloudError; } });
7
+ var client_js_2 = require("./client.js");
8
+ Object.defineProperty(exports, "LambdaClient", { enumerable: true, get: function () { return client_js_2.LambdaClient; } });
9
+ Object.defineProperty(exports, "SesClient", { enumerable: true, get: function () { return client_js_2.SesClient; } });
10
+ Object.defineProperty(exports, "SnsClient", { enumerable: true, get: function () { return client_js_2.SnsClient; } });
11
+ Object.defineProperty(exports, "SqsClient", { enumerable: true, get: function () { return client_js_2.SqsClient; } });
12
+ Object.defineProperty(exports, "EventsClient", { enumerable: true, get: function () { return client_js_2.EventsClient; } });
13
+ Object.defineProperty(exports, "S3Client", { enumerable: true, get: function () { return client_js_2.S3Client; } });
14
+ Object.defineProperty(exports, "DynamoDbClient", { enumerable: true, get: function () { return client_js_2.DynamoDbClient; } });
15
+ Object.defineProperty(exports, "SecretsManagerClient", { enumerable: true, get: function () { return client_js_2.SecretsManagerClient; } });
16
+ Object.defineProperty(exports, "CognitoClient", { enumerable: true, get: function () { return client_js_2.CognitoClient; } });