@awsless/awsless 0.0.444 โ†’ 0.0.446

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 CHANGED
@@ -1,210 +1,366 @@
1
+ <p align="center">Awsless - Infrastructure as a code</p>
1
2
 
3
+ <div align="center">
2
4
 
3
- # TODO:
4
- - add fargate container stuff for long lived services
5
- - add check for existing graphql resolver field in schema
6
- - add check for conflicting types inside graphql (Like duplicate type names)
7
- - Types should probably only allowed to defined once. And should be extended after that.
8
-
9
-
10
- # BUGS
11
- - Container Lambda's don't update the lambda correctly when ever the container code updates.
12
- - GraphQL resolver code doesn't update correctly.
13
- - S3 bucket doesn't delete propertly when files are inside.
14
- - Cleanup unused network interfaces on VPC delete.
15
- - ECR Repo doesn't delete propertly when images are inside.
16
-
17
- ---
18
- ---
19
- ---
20
-
21
- # Features
22
-
23
- - VPC
24
- - Tests
25
- - Commands
26
- - Auth
27
- - Config
28
- - Domains
29
- - Sites
30
- - Functions
31
- - Tasks
32
- - Instances
33
- - Database
34
- - Tables
35
- - Stores
36
- - Caches
37
- - Searchs
38
- - Queues
39
- - Topics
40
- - Realtime
41
- - Crons
42
- - API
43
- - HTTP
44
- - GraphQL
45
- - Process Failure Capture
46
-
47
- ## Domains
48
-
49
- We use AWS Route53 to provide domain management.
5
+ [![npm version](https://img.shields.io/npm/v/@awsless/awsless.svg?style=flat-square)](https://www.npmjs.org/package/@awsless/awsless)
50
6
 
51
- ```json
52
- {
53
- "domains": {
54
- "main": {
55
- "domain": "example.com",
56
- "dns": [{
57
- "name": "sub",
58
- "type": "A",
59
- "records": [ ... ],
60
- }]
61
- },
62
- }
63
- }
7
+
8
+ [![npm downloads](https://img.shields.io/npm/dm/@awsless/awsless.svg?style=flat-square)](https://npm-stat.com/charts.html?package=@awsless/awsless)
9
+
10
+
11
+ </div>
12
+
13
+ ## Table of Contents
14
+
15
+ - [Table of Contents](#table-of-contents)
16
+ - [Features](#features)
17
+ - [Installing](#installing)
18
+ - [Package manager](#package-manager)
19
+ - [Getting Started](#getting-started)
20
+ - [Base Configuration](#base-configuration)
21
+ - [Modular Stacks](#modular-stacks)
22
+ - [Deploying](#deploying)
23
+ - [Stack Updates](#stack-updates)
24
+ - [Smart Helpers: Call Your Infra Like Functions](#smart-helpers-call-your-infra-like-functions)
25
+ - [Testing Stacks](#testing-stacks)
26
+ - [Core Resources](#core-resources)
27
+ - [Function - AWS Lambda](#function---aws-lambda)
28
+ - [Basic usage](#basic-usage)
29
+ - [Advanced usage](#advanced-usage)
30
+ - [Task](#task)
31
+ - [Basic usage](#basic-usage-1)
32
+ - [Advanced usage](#advanced-usage-1)
33
+ - [Table](#table)
34
+ - [Usage](#usage)
35
+ - [Queue](#queue)
36
+ - [Usage](#usage-1)
37
+ - [Topics](#topics)
38
+ - [Usage](#usage-2)
39
+ - [Crons](#crons)
40
+ - [Usage](#usage-3)
41
+ - [RPC](#rpc)
42
+ - [Smart Functions - Call your infra from code](#smart-functions---call-your-infra-from-code)
43
+ - [Examples](#examples)
44
+ - [Lambda Function](#lambda-function)
45
+ - [Task](#task-1)
46
+ - [Queue](#queue-1)
47
+ - [Topic](#topic)
48
+ - [Config](#config)
49
+
50
+ ## Features
51
+
52
+ ๐Ÿชถ AWS development using JSON config with best practices baked in
53
+
54
+ โšก Deploy APIs, functions, databases, queues, and more โ€” all in one place
55
+
56
+ ๐Ÿ”’ Secure by default with IAM-based permissions and least privilege
57
+
58
+ ๐ŸŒ First-class support for AWS Lambda, DynamoDB, SQS, EventBridge, and more
59
+
60
+ ๐Ÿงช Built-in local development and testing utilities
61
+
62
+ ๐Ÿ”„ Automatic function bundling with support for ES modules and TypeScript
63
+
64
+ ๐Ÿ”„ Types generatation for all resources that can be acessed anywhere in the code
65
+
66
+
67
+ ## Installing
68
+
69
+ ### Package manager
70
+
71
+ Using npm:
72
+
73
+ ```bash
74
+ $ npm i @awsless/awsless
64
75
  ```
65
76
 
66
- ## Functions
67
77
 
68
- We use AWS Lambda to provide serverless functions.
78
+ Using pnpm:
69
79
 
70
- ```json
80
+ ```bash
81
+ $ pnpm i @awsless/awsless
82
+ ```
83
+
84
+
85
+ ## Getting Started
86
+ In an AWSless project, your infrastructure is organized into modular stack files, each with its own purpose, and a shared base configuration. Before you begin, make sure you have the AWS CLI installed.
87
+
88
+
89
+ ### Base Configuration
90
+ This is your shared app configuration, which acts as the base stack for the entire project. This should exist in the root of your project.
91
+ `app.json`
92
+ ```
71
93
  {
72
- "functions": {
73
- "FUNCTION_NAME": "function.ts"
94
+ "name": "hello-world",
95
+ "region": "eu-west-1",
96
+ "profile": "test",
97
+ "defaults": {
98
+ "alerts": {
99
+ "debug": "hello@gmail.com"
100
+ }
74
101
  }
75
102
  }
76
103
  ```
104
+ ๐Ÿ”‘ Key Fields
105
+ * name: Name of your application.
77
106
 
78
- ## Tasks
107
+ * region: AWS region where you want to deploy your infrastructure.
79
108
 
80
- We use AWS Async Lambda to provide serverless async tasks.
81
- Tasks are an lower cost alternative to queues.
109
+ * profile: Your AWS CLI profile to use for deployment.
82
110
 
83
- ```json
111
+
112
+
113
+ ### Modular Stacks
114
+ Each feature/module of your application can be defined as a separate stack file. These live in their own folders and are completely independent.
115
+
116
+ Example - `auth/stack.json`
117
+ ```
84
118
  {
85
- "tasks": {
86
- "TASK_NAME": "task.ts"
87
- }
119
+ "name": "auth",
120
+ "functions": {
121
+ "verify": "./src/lambda.ts" // AWS Lambda
122
+ },
123
+
124
+ }
125
+ ```
126
+
127
+ Example - `rate/stack.json`
128
+ ```
129
+ {
130
+ "name": "rate",
131
+ "functions": {
132
+ "limit": "./src/lambda.ts" // AWS Lambda
133
+ },
134
+
88
135
  }
89
136
  ```
90
137
 
91
- ## Instances
138
+ You can create as many stack files as needed, each targeting different parts of your application.
139
+
140
+ ### Deploying
141
+
142
+
143
+ Deploy all stacks
144
+ ```bash
145
+ $ pnpm awsless deploy
146
+ ```
147
+
148
+ Deploy individual stack
149
+ ```bash
150
+ $ pnpm awsless deploy rate
151
+ ```
152
+
153
+ Deploy multiple stacks
154
+ ```bash
155
+ $ pnpm awsless deploy rate auth
156
+ ```
157
+
158
+ Deploy base stack
159
+ ```bash
160
+ $ pnpm awsless deploy base
161
+ ```
162
+
163
+ ### Stack Updates
164
+ AWSless makes it simple to remove infrastructure when it's no longer needed.
165
+
166
+ ๐Ÿงผ Delete a Specific Stack
167
+ ```bash
168
+ $ pnpm awsless delete rate
169
+ ```
170
+
171
+ ๐Ÿ’ฃ Delete All Stacks
172
+ ```bash
173
+ pnpm awsless delete
174
+ ```
175
+ โš ๏ธ This will remove all deployed resources associated with your stacks. Use with caution!
176
+
177
+ โ™ป๏ธ Updating or Replacing Resources
178
+ When you modify a stack file and run a deployment again, AWSless will:
179
+
180
+ * Update existing resources if changes are detected.
181
+
182
+ * Delete resources that are removed from the stack file.
183
+
184
+ * Create new resources as needed.
185
+
186
+ * This ensures your infrastructure always reflects the current state of your stack configuration โ€” no manual cleanup required.
187
+
188
+ ### Smart Helpers: Call Your Infra Like Functions
189
+ Once your stacks are defined, AWSless provides built-in helpers like Fn, Queue, and Task to let you interact with your infrastructure directly from your application code โ€” no wiring or manual setup needed.
190
+
191
+ To enable full type support for these resources, run:
192
+ ```bash
193
+ $ pnpm run dev
194
+ ```
195
+ This will watch your project and automatically generate type definitions for all the resources you've created.
196
+
197
+ You can then use them seamlessly inside your Lambda functions:
198
+
199
+ Now from one lambda function we can all any infra like
200
+ ```typescript
201
+
202
+ import { Queue, Fn } from '@awsless/awsless'
203
+
204
+ // Call a Lambda function from another stack
205
+ await Fn.rate.limit()
206
+
207
+ // Push a message to a queue
208
+ await Queue.notifications.send({ userId: 123 })
209
+ ```
210
+ ๐Ÿ’ก These helpers are fully typed and auto-wired, making your code clean, safe, and easy to maintain.
211
+
92
212
 
93
- We use AWS EC2 Instances to provide low level server instances.
94
- Tasks are an lower cost alternative to queues.
95
213
 
214
+ ## Testing Stacks
215
+ AWSless supports built-in testing for your stacks to ensure everything works as expected before deployment.
216
+
217
+ You can define test folder in each stack
96
218
  ```json
97
219
  {
98
- "instances": {
99
- "INSTANCE_NAME": {
100
- "type": "t4g.nano",
101
- "image": "ami-000000",
102
- "code": "./src",
103
- "command": "sh ./startup.sh",
104
- }
105
- }
220
+ "name": "rate",
221
+ "test": "./path/to/test/folder"
106
222
  }
107
223
  ```
108
224
 
109
- ## Tables
225
+ exmaple test case
226
+ `rate/test/utils.ts`
227
+ ```typescript
228
+ describe('test', () => {
229
+ it('hello world', async () => {
230
+ expect(1 + 2).toStrictEqual(3)
231
+ })
232
+ })
233
+ ```
234
+
235
+ ๐Ÿ” Run Tests Manually
236
+ ```bash
237
+ $ pnpm awsless test rate
238
+ ```
239
+
240
+ This will look for a defined test folder inside the rate stack directory and run any defined tests inside here.
241
+
242
+ ๐Ÿ›ก๏ธ Tests Run Automatically Before Deploy
243
+ Whenever you run `pnpm awsless deploy`, AWSless will automatically:
244
+
245
+ * Check if a test/ folder exists for each stack
246
+
247
+ * Run the tests for that stack
248
+
249
+ * Block the deployment if any tests fail
110
250
 
111
- We use AWS DynamoDB to provide serverless tables.
251
+ ## Core Resources
112
252
 
253
+ ### Function - AWS Lambda
254
+ #### Basic usage
113
255
  ```json
114
256
  {
115
- "tables": {
116
- "TABLE_NAME": {
117
- "hash": "id",
118
- "fields": {
119
- "id": "number",
120
- }
121
- }
257
+ "functions": {
258
+ "FUNCTION_NAME": "/path/to/function"
122
259
  }
123
260
  }
124
261
  ```
125
262
 
126
- ## Stores
127
-
128
- We use AWS S3 to provide serverless key-value storage.
263
+ #### Advanced usage
129
264
 
265
+ You can also customize your Lambda function with additional parameters like memory size, timeout, environment variables, and more:
130
266
  ```json
131
- {
132
- "stores": [ "STORE_NAME" ]
133
- }
267
+ "functions": {
268
+ "test": {
269
+ "code": "/path/to/function",
270
+ "memorySize": 512
271
+ }
272
+ },
134
273
  ```
135
274
 
136
- ## Caches
275
+ ### Task
276
+ A Task in AWSless is an asynchronous Lambda function designed for background processing. You can trigger a task and immediately move on โ€” AWSless handles the execution in the background, including retries and logging on failure.
137
277
 
138
- We use AWS MemoryDB to provide a __redis compatible__ in-memory storage.
139
278
 
279
+ #### Basic usage
140
280
  ```json
141
281
  {
142
- "caches": {
143
- "CACHE_NAME": {
144
- "type": "t4g.small"
145
- }
282
+ "tasks": {
283
+ "FUNCTION_NAME": "/path/to/function"
146
284
  }
147
285
  }
148
286
  ```
149
287
 
150
- ## Searchs
288
+ #### Advanced usage
289
+
290
+ You can also customize your Lambda function with additional parameters like memory size, timeout, environment variables, and more:
291
+ ```json
292
+ "tasks": {
293
+ "test": {
294
+ "code": "/path/to/function",
295
+ "memorySize": 512
296
+ }
297
+ },
298
+ ```
299
+
300
+ ### Table
301
+ The tables feature in AWSless allows you to define fully managed, serverless DynamoDB tables directly in your stack configuration.
151
302
 
152
- We use AWS Open Search to provide a serverless search api.
153
303
 
304
+ #### Usage
154
305
  ```json
155
306
  {
156
- "searchs": {
157
- "SEARCH_NAME": {
158
- "type": "t3.small"
307
+ "tables": {
308
+ "TABLE_NAME": {
309
+ "hash": "id",
310
+ "sort": "user",
311
+ "indexes": {
312
+ "list": {
313
+ "hash": "createdAt",
314
+ "sort": "id"
315
+ }
316
+ },
159
317
  }
160
318
  }
161
319
  }
162
320
  ```
163
321
 
164
- ## Queues
322
+ ๐Ÿ”‘ Key Fields:
323
+ * `hash` - Primary key
324
+ * `sort` - Sort key
325
+ * `indexes` - Define secondary index here
165
326
 
166
- We use AWS SQS to provide serverless queues.
167
327
 
328
+ ### Queue
329
+ This allows you to define a queue along with the consumer lambda.
330
+
331
+ #### Usage
168
332
  ```json
169
333
  {
170
- "queues": {
171
- "QUEUE_NAME": "queue-consumer.ts"
172
- }
334
+ "queues": {
335
+ "sendMail": {
336
+ "consumer": "/path/to/lambda/file",
337
+ "maxConcurrency": 2,
338
+ "batchSize": 5,
339
+ }
340
+ },
173
341
  }
174
342
  ```
175
343
 
176
- ## Topics
177
344
 
178
- We use AWS SNS to provide serverless pubsub topics.
345
+ ### Topics
346
+ This allows you to define a topic along with the subscriber lambda.
179
347
 
348
+ #### Usage
180
349
  ```json
181
350
  {
351
+ {
182
352
  "topics": [ "TOPIC_NAME" ],
183
353
  "subscribers": {
184
354
  "TOPIC_NAME": "topic-consumer.ts",
185
355
  }
186
356
  }
187
- ```
188
-
189
- ## Pubsub
190
-
191
- We use AWS IoT to provide a serverless mqtt pubsub channel.
192
-
193
- ```json
194
- {
195
- "pubsub": {
196
- "PUBSUB_NAME": {
197
- "sql": "SELECT * FROM '$aws/events/presence/connected/+'",
198
- "consumer": "pubsub-consumer.ts",
199
- }
200
- }
201
357
  }
202
358
  ```
203
359
 
204
- ## Crons
205
-
206
- We use AWS Event Bridge to provide serverless cron jobs.
360
+ ### Crons
361
+ AWSless uses AWS EventBridge to provide fully managed, serverless cron jobs โ€” perfect for running scheduled tasks like cleanups, reports, or recurring syncs.
207
362
 
363
+ #### Usage
208
364
  ```json
209
365
  {
210
366
  "crons": {
@@ -216,83 +372,88 @@ We use AWS Event Bridge to provide serverless cron jobs.
216
372
  }
217
373
  ```
218
374
 
219
- ## HTTP
375
+ ๐Ÿ”‘ Key Options:
376
+ * `schedule`: The interval or cron expression to define when the job should run (e.g., "1 day" or "cron(0 12 * * ? *)").
220
377
 
221
- We use AWS ELB to provide a HTTP API.
378
+ * `consumer`: Path to the Lambda function that should be triggered on schedule.
379
+
380
+
381
+ #### RPC
382
+ AWSless allows you to easily expose any Lambda function as a type-safe RPC (Remote Procedure Call) endpoint for your frontend.
383
+
384
+ The request and response types are automatically inferred from your Lambda function's payload and return value, giving you end-to-end type safety.
222
385
 
223
386
  ```json
224
387
  {
225
- "http": {
226
- "HTTP_API_NAME": {
227
- "GET /posts": "list-posts.ts",
228
- "POST /posts": "create-post.ts",
388
+ "rpc": {
389
+ "base": { // base resource defined in app.json
390
+ "SendFriendRequest": "/path/to/lambda"
229
391
  }
230
392
  }
231
393
  }
232
394
  ```
233
395
 
234
- ## REST
396
+ ## Smart Functions - Call your infra from code
397
+ With awsless, you can interact with your infrastructure directly from your code. awsless generates all necessary types for you, allowing seamless access to your resources.
235
398
 
236
- We use AWS ApiGatewayV2 to provide a serverless REST API.
399
+ To set up, define your stacks and run:
237
400
 
238
- ```json
239
- {
240
- "rest": {
241
- "REST_API_NAME": {
242
- "GET /posts/{id}": "get-posts.ts",
243
- "DELETE /posts/{id}": "delete-post.ts",
244
- }
245
- }
246
- }
401
+ ```bash
402
+ $ pnpm awsless dev
247
403
  ```
248
404
 
249
- ## GraphQL
405
+ This command will generate the required types and mappings, enabling you to access infrastructure components in your code effortlessly.
250
406
 
251
- We use AWS AppSync to provide a serverless GraphQL API.
407
+ Resources are accessible via their stack name and resource name.
408
+ For instance, if a Lambda function exists within a stack named player, you can access its resources using:
252
409
 
253
- ```json
254
- {
255
- "graphql": {
256
- "GRAPHQL_API_NAME": {
257
- "schema": "schema.gql",
258
- "resolvers": {
259
- "Query": {
260
- "posts": "list-posts.ts",
261
- },
262
- "Mutation": {
263
- "createPost": "create-post.ts",
264
- }
265
- }
266
- }
267
- }
268
- }
410
+ `player.{resourceName}`
411
+
412
+
413
+ ### Examples
414
+
415
+ #### Lambda Function
416
+
417
+ Calling a function named `limit` inside the `rate` stack:
418
+
419
+ ```typescript
420
+ import { Fn } from '@awsless/awsless'
421
+
422
+ await Fn.rate.limit({userId: "test"})
269
423
  ```
270
424
 
271
- ## Auth
272
425
 
273
- We use AWS Cognito to provide a serverless Authentication API.
426
+ #### Task
274
427
 
275
- ```json
276
- {
277
- "auth": {
278
- "AUTH_USER_POOL_NAME": {
279
- "allowUserRegistration": false,
280
- "password": {
281
- "minLength": 24
282
- }
283
- }
284
- }
285
- }
428
+ ```typescript
429
+ import { Task } from '@awsless/awsless'
430
+
431
+ await Task.mail.send({msg: "hi", userId: "test"})
286
432
  ```
287
433
 
288
- ## Commands
434
+ #### Queue
435
+ Sending a message to a queue
436
+ ```typescript
437
+ import { Queue } from '@awsless/awsless'
289
438
 
290
- You can define custom cli commands that you can run from the awsless cli tool.
439
+ await Queue.mail.send({msg: "hi", userId: "test"})
440
+ ```
291
441
 
292
- ```json
293
- {
294
- "commands": {
295
- "COMMAND_NAME": "./cli/your-command.ts"
296
- }
297
- }
442
+
443
+ #### Topic
444
+ Publish a message to SNS topic
445
+
446
+ ```typescript
447
+ import { Topic } from '@awsless/awsless'
448
+
449
+ await Topic.transaction.credit({amount: 10, userId: "test"})
450
+ ```
451
+
452
+ #### Config
453
+ Reading a secret configuration value:
454
+
455
+ ```typescript
456
+ import { Config } from '@awsless/awsless'
457
+
458
+ const key = await Config.API_KEY
298
459
  ```