@awsless/awsless 0.0.501 โ†’ 0.0.503

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
@@ -4,10 +4,8 @@
4
4
 
5
5
  [![npm version](https://img.shields.io/npm/v/@awsless/awsless.svg?style=flat-square)](https://www.npmjs.org/package/@awsless/awsless)
6
6
 
7
-
8
7
  [![npm downloads](https://img.shields.io/npm/dm/@awsless/awsless.svg?style=flat-square)](https://npm-stat.com/charts.html?package=@awsless/awsless)
9
8
 
10
-
11
9
  </div>
12
10
 
13
11
  ## Table of Contents
@@ -83,7 +81,7 @@ $ pnpm i @awsless/awsless
83
81
 
84
82
 
85
83
  ## 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.
84
+ 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
85
 
88
86
 
89
87
  ### Base Configuration
@@ -161,7 +159,7 @@ $ pnpm awsless deploy base
161
159
  ```
162
160
 
163
161
  ### Stack Updates
164
- AWSless makes it simple to remove infrastructure when it's no longer needed.
162
+ Awsless makes it simple to remove infrastructure when it's no longer needed.
165
163
 
166
164
  ๐Ÿงผ Delete a Specific Stack
167
165
  ```bash
@@ -175,7 +173,7 @@ pnpm awsless delete
175
173
  โš ๏ธ This will remove all deployed resources associated with your stacks. Use with caution!
176
174
 
177
175
  โ™ป๏ธ Updating or Replacing Resources
178
- When you modify a stack file and run a deployment again, AWSless will:
176
+ When you modify a stack file and run a deployment again, Awsless will:
179
177
 
180
178
  * Update existing resources if changes are detected.
181
179
 
@@ -186,7 +184,7 @@ When you modify a stack file and run a deployment again, AWSless will:
186
184
  * This ensures your infrastructure always reflects the current state of your stack configuration โ€” no manual cleanup required.
187
185
 
188
186
  ### 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.
187
+ 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
188
 
191
189
  To enable full type support for these resources, run:
192
190
  ```bash
@@ -212,7 +210,7 @@ await Queue.notifications.send({ userId: 123 })
212
210
 
213
211
 
214
212
  ## Testing Stacks
215
- AWSless supports built-in testing for your stacks to ensure everything works as expected before deployment.
213
+ Awsless supports built-in testing for your stacks to ensure everything works as expected before deployment.
216
214
 
217
215
  You can define test folder in each stack
218
216
  ```json
@@ -240,7 +238,7 @@ $ pnpm awsless test rate
240
238
  This will look for a defined test folder inside the rate stack directory and run any defined tests inside here.
241
239
 
242
240
  ๐Ÿ›ก๏ธ Tests Run Automatically Before Deploy
243
- Whenever you run `pnpm awsless deploy`, AWSless will automatically:
241
+ Whenever you run `pnpm awsless deploy`, Awsless will automatically:
244
242
 
245
243
  * Check if a test/ folder exists for each stack
246
244
 
@@ -273,7 +271,7 @@ You can also customize your Lambda function with additional parameters like memo
273
271
  ```
274
272
 
275
273
  ### 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.
274
+ 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.
277
275
 
278
276
 
279
277
  #### Basic usage
@@ -298,7 +296,7 @@ You can also customize your Lambda function with additional parameters like memo
298
296
  ```
299
297
 
300
298
  ### Table
301
- The tables feature in AWSless allows you to define fully managed, serverless DynamoDB tables directly in your stack configuration.
299
+ The tables feature in Awsless allows you to define fully managed, serverless DynamoDB tables directly in your stack configuration.
302
300
 
303
301
 
304
302
  #### Usage
@@ -358,7 +356,7 @@ This allows you to define a topic along with the subscriber lambda.
358
356
  ```
359
357
 
360
358
  ### Crons
361
- AWSless uses AWS EventBridge to provide fully managed, serverless cron jobs โ€” perfect for running scheduled tasks like cleanups, reports, or recurring syncs.
359
+ Awsless uses AWS EventBridge to provide fully managed, serverless cron jobs โ€” perfect for running scheduled tasks like cleanups, reports, or recurring syncs.
362
360
 
363
361
  #### Usage
364
362
  ```json
@@ -379,7 +377,7 @@ AWSless uses AWS EventBridge to provide fully managed, serverless cron jobs โ€”
379
377
 
380
378
 
381
379
  #### RPC
382
- AWSless allows you to easily expose any Lambda function as a type-safe RPC (Remote Procedure Call) endpoint for your frontend.
380
+ Awsless allows you to easily expose any Lambda function as a type-safe RPC (Remote Procedure Call) endpoint for your frontend.
383
381
 
384
382
  The request and response types are automatically inferred from your Lambda function's payload and return value, giving you end-to-end type safety.
385
383
 
package/dist/bin.js CHANGED
@@ -3220,26 +3220,53 @@ var createLambdaFunction = (parentGroup, ctx, ns, id, local) => {
3220
3220
  statements.push(...local.permissions);
3221
3221
  }
3222
3222
  if (props.warm) {
3223
- const rule = new $3.aws.cloudwatch.EventRule(group, "warm", {
3223
+ const scheduleRole = new $3.aws.iam.Role(group, "warm", {
3224
3224
  name: `${shortName}--warm`,
3225
- description: name,
3226
- scheduleExpression: "rate(5 minutes)",
3227
- isEnabled: true
3228
- });
3229
- new $3.aws.cloudwatch.EventTarget(group, "warm", {
3230
- rule: rule.name,
3231
- targetId: "warmer",
3232
- arn: lambda.arn,
3233
- input: JSON.stringify({
3234
- warmer: true,
3235
- concurrency: props.warm
3236
- })
3225
+ description: `${name} warmer`,
3226
+ assumeRolePolicy: JSON.stringify({
3227
+ Version: "2012-10-17",
3228
+ Statement: [
3229
+ {
3230
+ Action: "sts:AssumeRole",
3231
+ Effect: "Allow",
3232
+ Principal: {
3233
+ Service: "scheduler.amazonaws.com"
3234
+ }
3235
+ }
3236
+ ]
3237
+ }),
3238
+ inlinePolicy: [
3239
+ {
3240
+ name: "InvokeFunction",
3241
+ policy: lambda.arn.pipe(
3242
+ (arn) => JSON.stringify({
3243
+ Version: "2012-10-17",
3244
+ Statement: [
3245
+ {
3246
+ Action: ["lambda:InvokeFunction"],
3247
+ Effect: "Allow",
3248
+ Resource: arn
3249
+ }
3250
+ ]
3251
+ })
3252
+ )
3253
+ }
3254
+ ]
3237
3255
  });
3238
- new $3.aws.lambda.Permission(group, `warm`, {
3239
- action: "lambda:InvokeFunction",
3240
- principal: "events.amazonaws.com",
3241
- functionName: lambda.functionName,
3242
- sourceArn: rule.arn
3256
+ new $3.aws.scheduler.Schedule(group, "warm", {
3257
+ name: shortName,
3258
+ groupName: ctx.shared.get("function", "warm-group-name"),
3259
+ description: `${name} warmer`,
3260
+ scheduleExpression: "rate(5 minutes)",
3261
+ flexibleTimeWindow: { mode: "OFF" },
3262
+ target: {
3263
+ arn: lambda.arn,
3264
+ roleArn: scheduleRole.arn,
3265
+ input: JSON.stringify({
3266
+ warmer: true,
3267
+ concurrency: props.warm
3268
+ })
3269
+ }
3243
3270
  });
3244
3271
  }
3245
3272
  return {
@@ -3257,7 +3284,7 @@ var createLambdaFunction = (parentGroup, ctx, ns, id, local) => {
3257
3284
  };
3258
3285
  };
3259
3286
  var createAsyncLambdaFunction = (group, ctx, ns, id, local) => {
3260
- const result = createLambdaFunction(group, ctx, ns, id, local);
3287
+ const result = createLambdaFunction(group, ctx, ns, id, { ...local, warm: 0 });
3261
3288
  const props = deepmerge(ctx.appConfig.defaults.function, local);
3262
3289
  result.setEnvironment("LOG_VIEWABLE_ERROR", "1");
3263
3290
  const onFailure = getGlobalOnFailure(ctx);
@@ -3287,36 +3314,77 @@ var createAsyncLambdaFunction = (group, ctx, ns, id, local) => {
3287
3314
  // src/feature/cron/index.ts
3288
3315
  var cronFeature = defineFeature({
3289
3316
  name: "cron",
3317
+ onApp(ctx) {
3318
+ const found = ctx.stackConfigs.find((stackConfig) => Object.keys(stackConfig.crons ?? {}).length > 0);
3319
+ if (found) {
3320
+ const group = new $4.aws.scheduler.ScheduleGroup(ctx.base, "cron", {
3321
+ name: formatGlobalResourceName({
3322
+ appName: ctx.app.name,
3323
+ resourceType: "cron",
3324
+ resourceName: "group"
3325
+ }),
3326
+ tags: {
3327
+ app: ctx.app.name
3328
+ }
3329
+ });
3330
+ ctx.shared.set("cron", "group-name", group.name);
3331
+ }
3332
+ },
3290
3333
  onStack(ctx) {
3291
3334
  for (const [id, props] of Object.entries(ctx.stackConfig.crons ?? {})) {
3292
3335
  const group = new Group4(ctx.stack, "cron", id);
3293
- const { lambda } = createAsyncLambdaFunction(group, ctx, "cron", id, {
3294
- ...props.consumer,
3295
- // Never warm cronjob lambda's
3296
- warm: 0
3336
+ const { lambda } = createAsyncLambdaFunction(group, ctx, "cron", id, props.consumer);
3337
+ const name = formatLocalResourceName({
3338
+ appName: ctx.app.name,
3339
+ stackName: ctx.stack.name,
3340
+ resourceType: "cron",
3341
+ resourceName: shortId(id)
3297
3342
  });
3298
- const rule = new $4.aws.cloudwatch.EventRule(group, "rule", {
3299
- name: formatLocalResourceName({
3300
- appName: ctx.app.name,
3301
- stackName: ctx.stack.name,
3302
- resourceType: "cron",
3303
- resourceName: shortId(id)
3304
- }),
3343
+ const scheduleRole = new $4.aws.iam.Role(group, "warm", {
3344
+ name,
3305
3345
  description: `Cron ${ctx.stack.name} ${id}`,
3306
- scheduleExpression: props.schedule,
3307
- isEnabled: props.enabled,
3308
- forceDestroy: true
3309
- });
3310
- new $4.aws.cloudwatch.EventTarget(group, "target", {
3311
- rule: rule.name,
3312
- arn: lambda.arn,
3313
- input: JSON.stringify(props.payload)
3346
+ assumeRolePolicy: JSON.stringify({
3347
+ Version: "2012-10-17",
3348
+ Statement: [
3349
+ {
3350
+ Action: "sts:AssumeRole",
3351
+ Effect: "Allow",
3352
+ Principal: {
3353
+ Service: "scheduler.amazonaws.com"
3354
+ }
3355
+ }
3356
+ ]
3357
+ }),
3358
+ inlinePolicy: [
3359
+ {
3360
+ name: "InvokeFunction",
3361
+ policy: lambda.arn.pipe(
3362
+ (arn) => JSON.stringify({
3363
+ Version: "2012-10-17",
3364
+ Statement: [
3365
+ {
3366
+ Action: ["lambda:InvokeFunction"],
3367
+ Effect: "Allow",
3368
+ Resource: arn
3369
+ }
3370
+ ]
3371
+ })
3372
+ )
3373
+ }
3374
+ ]
3314
3375
  });
3315
- new $4.aws.lambda.Permission(group, "permission", {
3316
- action: "lambda:InvokeFunction",
3317
- principal: "events.amazonaws.com",
3318
- functionName: lambda.functionName,
3319
- sourceArn: rule.arn
3376
+ new $4.aws.scheduler.Schedule(group, "warm", {
3377
+ name,
3378
+ state: props.enabled ? "ENABLED" : "DISABLED",
3379
+ groupName: ctx.shared.get("cron", "group-name"),
3380
+ description: `${ctx.stack.name} ${id}`,
3381
+ scheduleExpression: props.schedule,
3382
+ flexibleTimeWindow: { mode: "OFF" },
3383
+ target: {
3384
+ arn: lambda.arn,
3385
+ roleArn: scheduleRole.arn,
3386
+ input: JSON.stringify(props.payload)
3387
+ }
3320
3388
  });
3321
3389
  }
3322
3390
  }
@@ -3590,6 +3658,14 @@ var functionFeature = defineFeature({
3590
3658
  // forceDelete: true,
3591
3659
  });
3592
3660
  ctx.shared.set("function", "bucket-name", bucket.bucket);
3661
+ const warmGroup = new $6.aws.scheduler.ScheduleGroup(ctx.base, "warm", {
3662
+ name: formatGlobalResourceName({
3663
+ appName: ctx.app.name,
3664
+ resourceType: "function",
3665
+ resourceName: "warm"
3666
+ })
3667
+ });
3668
+ ctx.shared.set("function", "warm-group-name", warmGroup.name);
3593
3669
  },
3594
3670
  onApp(ctx) {
3595
3671
  ctx.addGlobalPermission({
@@ -5523,6 +5599,49 @@ var taskFeature = defineFeature({
5523
5599
  types2.addInterface("TaskMockResponse", mockResponses);
5524
5600
  await ctx.write("task.d.ts", types2, true);
5525
5601
  },
5602
+ // onApp(ctx) {
5603
+ // const group = new Group(ctx.base, 'task', 'main')
5604
+ // const scheduleRole = new $.aws.iam.Role(group, 'schedule', {
5605
+ // name: formatGlobalResourceName({
5606
+ // appName: ctx.app.name,
5607
+ // resourceType: 'task',
5608
+ // resourceName: 'schedule',
5609
+ // }),
5610
+ // description: `Task schedule ${ctx.app.name}`,
5611
+ // assumeRolePolicy: JSON.stringify({
5612
+ // Version: '2012-10-17',
5613
+ // Statement: [
5614
+ // {
5615
+ // Action: 'sts:AssumeRole',
5616
+ // Effect: 'Allow',
5617
+ // Principal: {
5618
+ // Service: 'scheduler.amazonaws.com',
5619
+ // },
5620
+ // },
5621
+ // ],
5622
+ // }),
5623
+ // inlinePolicy: [
5624
+ // {
5625
+ // name: 'Invoke function',
5626
+ // policy: JSON.stringify({
5627
+ // Version: '2012-10-17',
5628
+ // Statement: [
5629
+ // {
5630
+ // Action: ['lambda:InvokeFunction'],
5631
+ // Effect: 'Allow',
5632
+ // Resource: [`arn:aws:lambda:*:*:function:${ctx.appConfig.name}--*--task--*`],
5633
+ // },
5634
+ // ],
5635
+ // }),
5636
+ // },
5637
+ // ],
5638
+ // })
5639
+ // ctx.addGlobalPermission({
5640
+ // actions: ['schedule:CreateSchedule'],
5641
+ // resources: [`arn:aws:schedule:*:*:schedule:${ctx.appConfig.name}--*`],
5642
+ // })
5643
+ // ctx.addEnv('TASK_SCHEDULE_ROLE', scheduleRole.arn)
5644
+ // },
5526
5645
  onStack(ctx) {
5527
5646
  for (const [id, props] of Object.entries(ctx.stackConfig.tasks ?? {})) {
5528
5647
  const group = new Group18(ctx.stack, "task", id);
@@ -5782,7 +5901,7 @@ var alertFeature = defineFeature({
5782
5901
  });
5783
5902
  }
5784
5903
  }
5785
- ctx.addAppPermission({
5904
+ ctx.addGlobalPermission({
5786
5905
  actions: ["sns:Publish"],
5787
5906
  resources: [
5788
5907
  `arn:aws:sns:${ctx.appConfig.region}:${ctx.accountId}:${formatGlobalResourceName({
@@ -1 +1 @@
1
- dd3c7bd5899f5a7229c7dbcf35bfc838756004d7
1
+ 581067396e660b14247f0da7ac7979a71a1ea798
Binary file
@@ -1 +1 @@
1
- c8bc865ae78809bcecaa432f89aa387b3584c479
1
+ 067ac22da538619c808461cfb4c14803a7a8917d
Binary file
package/dist/server.js CHANGED
@@ -116,15 +116,15 @@ var Function = /* @__PURE__ */ createProxy((stackName) => {
116
116
  }
117
117
  };
118
118
  const call = ctx[name];
119
- call.cached = async (payload, options = {}) => {
119
+ call.cached = (payload, options = {}) => {
120
120
  const cacheKey = JSON.stringify({ name, payload, options });
121
121
  if (!cache.has(cacheKey)) {
122
- const result = await invoke({
122
+ const promise = invoke({
123
123
  ...options,
124
124
  name,
125
125
  payload
126
126
  });
127
- cache.set(cacheKey, result);
127
+ cache.set(cacheKey, promise);
128
128
  }
129
129
  return cache.get(cacheKey);
130
130
  };
@@ -1,7 +1,9 @@
1
1
  // src/test/test-global-setup.ts
2
2
  import { BigFloat, eq } from "@awsless/big-float";
3
+ import { $mockdate, setGlobalTypes } from "@awsless/json";
3
4
  beforeAll(() => {
4
5
  process.env.TZ = "UTC";
6
+ setGlobalTypes({ $mockdate });
5
7
  expect.addEqualityTesters([areBigFloatsEqual]);
6
8
  });
7
9
  var areBigFloatsEqual = (a, b) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@awsless/awsless",
3
- "version": "0.0.501",
3
+ "version": "0.0.503",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "sideEffects": false,
@@ -35,17 +35,17 @@
35
35
  "peerDependencies": {
36
36
  "@awsless/big-float": "^0.0.6",
37
37
  "@awsless/dynamodb": "^0.1.5",
38
- "@awsless/json": "^0.0.8",
39
- "@awsless/lambda": "^0.0.32",
38
+ "@awsless/json": "^0.0.10",
40
39
  "@awsless/iot": "^0.0.3",
40
+ "@awsless/lambda": "^0.0.33",
41
41
  "@awsless/mqtt": "^0.0.2",
42
- "@awsless/s3": "^0.0.21",
43
- "@awsless/open-search": "^0.0.17",
44
42
  "@awsless/redis": "^0.0.14",
45
- "@awsless/validate": "^0.0.19",
43
+ "@awsless/open-search": "^0.0.17",
46
44
  "@awsless/sns": "^0.0.10",
47
- "@awsless/sqs": "^0.0.8",
45
+ "@awsless/s3": "^0.0.21",
46
+ "@awsless/validate": "^0.0.19",
48
47
  "@awsless/ssm": "^0.0.7",
48
+ "@awsless/sqs": "^0.0.8",
49
49
  "@awsless/weak-cache": "^0.0.1"
50
50
  },
51
51
  "dependencies": {
@@ -127,14 +127,14 @@
127
127
  "zip-a-folder": "^3.1.6",
128
128
  "zod": "^3.24.2",
129
129
  "zod-to-json-schema": "^3.24.3",
130
- "@awsless/big-float": "^0.0.6",
131
130
  "@awsless/formation": "^0.0.77",
131
+ "@awsless/duration": "^0.0.3",
132
132
  "@awsless/graphql": "^0.0.9",
133
+ "@awsless/json": "^0.0.10",
134
+ "@awsless/big-float": "^0.0.6",
133
135
  "@awsless/size": "^0.0.2",
134
- "@awsless/json": "^0.0.8",
135
136
  "@awsless/validate": "^0.0.19",
136
137
  "@awsless/ts-file-cache": "^0.0.12",
137
- "@awsless/duration": "^0.0.3",
138
138
  "@awsless/code": "^0.0.10"
139
139
  },
140
140
  "devDependencies": {