@alzulejos/laranja-docs 0.2.4
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/content/getting-started/how-it-works.md +52 -0
- package/content/getting-started/installation.md +58 -0
- package/content/getting-started/introduction.md +97 -0
- package/content/getting-started/quickstart.md +164 -0
- package/content/guides/cron-jobs.md +129 -0
- package/content/guides/environment-variables.md +108 -0
- package/content/guides/http-apps.md +131 -0
- package/content/guides/queues.md +143 -0
- package/content/guides/schedules.md +117 -0
- package/content/guides/stages-and-environments.md +88 -0
- package/content/index.md +44 -0
- package/content/reference/commands.md +193 -0
- package/content/reference/config-file.md +114 -0
- package/content/reference/decorators-and-markers.md +310 -0
- package/content/reference/what-gets-deployed.md +84 -0
- package/dist/index.d.ts +29 -0
- package/dist/index.js +38 -0
- package/package.json +30 -0
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: CLI commands
|
|
3
|
+
description: Every laranja command and flag.
|
|
4
|
+
order: 1
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# CLI commands
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
laranja <command> [project-dir] [flags]
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
`project-dir` defaults to the current directory, so most of the time you just run
|
|
14
|
+
`laranja deploy`. Run `laranja --help` for a summary.
|
|
15
|
+
|
|
16
|
+
> **Most commands need your account.** `plan`, `deploy`, and `eject` build your
|
|
17
|
+
> template on the laranja server, so they need a `LARANJA_API_KEY` and a
|
|
18
|
+
> `projectId` in your config. Run [`laranja init`](#init) once to sign in and link
|
|
19
|
+
> a project; the key is stored in `~/.laranja/auth.json` so you don't re-export
|
|
20
|
+
> it. Your **source code never leaves your machine** — only a description of your
|
|
21
|
+
> infrastructure does
|
|
22
|
+
> (see [how it works](../getting-started/how-it-works.md)).
|
|
23
|
+
|
|
24
|
+
## Global flags
|
|
25
|
+
|
|
26
|
+
| Flag | Applies to | Description |
|
|
27
|
+
|---|---|---|
|
|
28
|
+
| `--stage`, `-s <name>` | deploy, plan, destroy, logs, eject | Target [stage](../guides/stages-and-environments.md); overrides `config.stage`. |
|
|
29
|
+
| `--verbose`, `-v` | deploy | Stream full CDK/CloudFormation output instead of the compact UI. |
|
|
30
|
+
| `--strict` | deploy | Fail if any [`env()`](../guides/environment-variables.md#values-from-your-environment--env) value is unset (default: warn). |
|
|
31
|
+
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
## `init`
|
|
35
|
+
|
|
36
|
+
Sign in and scaffold a `laranja.config.ts` in the project directory.
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
laranja init
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
`init` prompts for your **laranja API key** (from the dashboard) and validates it
|
|
43
|
+
against the server before writing anything, then stores it in
|
|
44
|
+
`~/.laranja/auth.json` so later commands don't need it re-exported. It then lets
|
|
45
|
+
you **pick or create a dashboard project** and fills the scaffolded config's
|
|
46
|
+
`name` and `projectId` for you. Edit the file afterwards to set your `region`,
|
|
47
|
+
`env`, and `compute`. See the [config reference](./config-file.md).
|
|
48
|
+
|
|
49
|
+
---
|
|
50
|
+
|
|
51
|
+
## `logout`
|
|
52
|
+
|
|
53
|
+
Remove the stored API key (`~/.laranja/auth.json`).
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
laranja logout
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
After this, commands that talk to the server (`init`, `plan`, `deploy`, `eject`)
|
|
60
|
+
need `LARANJA_API_KEY` in the environment again, or another `laranja init`.
|
|
61
|
+
|
|
62
|
+
---
|
|
63
|
+
|
|
64
|
+
## `plan`
|
|
65
|
+
|
|
66
|
+
Preview what a deploy would do — laranja synthesizes your template on the server,
|
|
67
|
+
diffs it against the stack **currently deployed** in your AWS account, and prints
|
|
68
|
+
your app's resources tagged **created / changed / unchanged**. Nothing is applied.
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
laranja plan
|
|
72
|
+
laranja plan --stage prod
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
```
|
|
76
|
+
Plan for "my-api-dev"
|
|
77
|
+
|
|
78
|
+
= http HTTP 2 routes → proxy Lambda + Function URL
|
|
79
|
+
+ daily Cron Lambda + EventBridge rule
|
|
80
|
+
~ emails Queue SQS + consumer Lambda
|
|
81
|
+
|
|
82
|
+
8 AWS resources +3 created ~2 changed =3 unchanged
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
`+` is new, `~` changed, `=` unchanged. The bottom line tallies the underlying
|
|
86
|
+
AWS resources.
|
|
87
|
+
|
|
88
|
+
`plan` needs `LARANJA_API_KEY` (run [`laranja init`](#init) first) to synthesize,
|
|
89
|
+
and a working **AWS credential chain** to read your live stack. It is
|
|
90
|
+
**read-only** — it never creates a deployment or counts against your deploy limit.
|
|
91
|
+
|
|
92
|
+
| Flag | Description |
|
|
93
|
+
|---|---|
|
|
94
|
+
| `--stage`, `-s` | Target stage. |
|
|
95
|
+
|
|
96
|
+
---
|
|
97
|
+
|
|
98
|
+
## `deploy`
|
|
99
|
+
|
|
100
|
+
Deploy into your AWS account using your **local** AWS credentials. The template is
|
|
101
|
+
synthesized on the laranja server first, then applied with your own credentials —
|
|
102
|
+
so deploy needs both `LARANJA_API_KEY` (run [`laranja init`](#init) first) and a
|
|
103
|
+
working AWS credential chain.
|
|
104
|
+
|
|
105
|
+
```bash
|
|
106
|
+
laranja deploy
|
|
107
|
+
laranja deploy --stage prod
|
|
108
|
+
laranja deploy --verbose
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
- The first deploy to a new account/region prompts to **bootstrap** (a one-time
|
|
112
|
+
setup in your account).
|
|
113
|
+
- On success it prints your outputs — the HTTPS URL, queue URLs, and the cron
|
|
114
|
+
jobs deployed.
|
|
115
|
+
|
|
116
|
+
| Flag | Description |
|
|
117
|
+
|---|---|
|
|
118
|
+
| `--stage`, `-s` | Target stage. |
|
|
119
|
+
| `--verbose`, `-v` | Stream full CDK output. |
|
|
120
|
+
| `--strict` | Fail the deploy if any [`env()`](../guides/environment-variables.md#values-from-your-environment--env) value is unset. By default these are deployed with a warning. |
|
|
121
|
+
|
|
122
|
+
---
|
|
123
|
+
|
|
124
|
+
## `destroy`
|
|
125
|
+
|
|
126
|
+
Tear down the deployed stack and all its resources. Prompts for confirmation.
|
|
127
|
+
|
|
128
|
+
```bash
|
|
129
|
+
laranja destroy
|
|
130
|
+
laranja destroy --stage prod
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
> Targets the stack for the resolved stage — make sure `--stage` matches the
|
|
134
|
+
> environment you intend to remove.
|
|
135
|
+
|
|
136
|
+
| Flag | Description |
|
|
137
|
+
|---|---|
|
|
138
|
+
| `--stage`, `-s` | Target stage. |
|
|
139
|
+
|
|
140
|
+
---
|
|
141
|
+
|
|
142
|
+
## `logs`
|
|
143
|
+
|
|
144
|
+
Tail CloudWatch logs for your deployed functions. The live stack is the source of
|
|
145
|
+
truth — no local state needed.
|
|
146
|
+
|
|
147
|
+
```bash
|
|
148
|
+
laranja logs # interactive picker (TTY)
|
|
149
|
+
laranja logs sendEmail # tail a specific function by name
|
|
150
|
+
laranja logs --all # tail every function, multiplexed
|
|
151
|
+
laranja logs --no-follow # print recent history and exit
|
|
152
|
+
laranja logs --since 30m # history look-back window
|
|
153
|
+
laranja logs --stage prod # functions for the prod stack
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
| Flag / arg | Description |
|
|
157
|
+
|---|---|
|
|
158
|
+
| `<name>` (positional) | Function to tail (matched against its short label or full name). |
|
|
159
|
+
| `--all` | Tail every function in the stack, multiplexed. |
|
|
160
|
+
| `--no-follow` | Print the recent history window and exit (no live tail). |
|
|
161
|
+
| `--since <dur>` | History look-back, e.g. `30s`, `15m`, `1h`, `2d` (default `1h`). |
|
|
162
|
+
| `--stage`, `-s` | Target stage. |
|
|
163
|
+
|
|
164
|
+
Both a directory and a function name can be passed as positionals —
|
|
165
|
+
`laranja logs ./app sendEmail` works.
|
|
166
|
+
|
|
167
|
+
---
|
|
168
|
+
|
|
169
|
+
## `eject`
|
|
170
|
+
|
|
171
|
+
Generate a standalone, owned **CDK project** from your app and stop — for when
|
|
172
|
+
you've outgrown the abstraction and want full control. **Paid feature.**
|
|
173
|
+
|
|
174
|
+
```bash
|
|
175
|
+
laranja eject
|
|
176
|
+
laranja eject --force # overwrite an existing ./infra
|
|
177
|
+
laranja eject --stage prod
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
The CDK project is generated **on the laranja server** (which gates the paid
|
|
181
|
+
entitlement) and written to `./infra` — a complete project you own and run
|
|
182
|
+
yourself (`cd infra && npm install && npm run deploy`). Requires `LARANJA_API_KEY`
|
|
183
|
+
and a `projectId`; if your account can't eject, the server returns a clear error.
|
|
184
|
+
|
|
185
|
+
| Flag | Description |
|
|
186
|
+
|---|---|
|
|
187
|
+
| `--force` | Overwrite an existing `infra/` directory. |
|
|
188
|
+
| `--stage`, `-s` | Target stage (baked into the generated project). |
|
|
189
|
+
|
|
190
|
+
## Related
|
|
191
|
+
|
|
192
|
+
- [Stages & environments](../guides/stages-and-environments.md)
|
|
193
|
+
- [How it works](../getting-started/how-it-works.md)
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Config file
|
|
3
|
+
description: Every field in laranja.config.ts, with defaults and behavior.
|
|
4
|
+
order: 2
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# `laranja.config.ts`
|
|
8
|
+
|
|
9
|
+
Every project has a `laranja.config.ts` at its root that `export default`s a
|
|
10
|
+
config object. It's a TypeScript module (loaded via `tsx`), so you get full type
|
|
11
|
+
checking and can compute values if you need to.
|
|
12
|
+
|
|
13
|
+
```ts
|
|
14
|
+
import type { LaranjaConfig } from "@alzulejos/laranja-decorators";
|
|
15
|
+
|
|
16
|
+
const config: LaranjaConfig = {
|
|
17
|
+
name: "my-api",
|
|
18
|
+
// From your laranja dashboard — identifies this project on the server.
|
|
19
|
+
projectId: "proj_…",
|
|
20
|
+
region: "us-east-1",
|
|
21
|
+
env: { LOG_LEVEL: "info" },
|
|
22
|
+
// Default compute for every function (the HTTP proxy + each cron/queue).
|
|
23
|
+
compute: { memory: 256, timeout: 30 },
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
export default config;
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
The config stays minimal because the HTTP app is declared in code with the
|
|
30
|
+
[`http()`](./decorators-and-markers.md#http) marker — there's no config field for
|
|
31
|
+
it. For a deploy with no HTTP app, just omit the marker (see
|
|
32
|
+
[workers-only deployments](../guides/http-apps.md#workers-only-deployments)). Run
|
|
33
|
+
[`laranja init`](./commands.md#init) to scaffold this file — it fills in
|
|
34
|
+
`name` and `projectId` from the dashboard project you pick.
|
|
35
|
+
|
|
36
|
+
## Fields
|
|
37
|
+
|
|
38
|
+
| Field | Required | Default | Description |
|
|
39
|
+
|---|---|---|---|
|
|
40
|
+
| `name` | ✅ | — | App name. Used for the CloudFormation stack and all resource names. |
|
|
41
|
+
| `region` | | `AWS_REGION` / `AWS_DEFAULT_REGION` | AWS region to deploy to. |
|
|
42
|
+
| `stage` | | `"dev"` | Deployment stage. Part of the stack + resource names and injected as the `STAGE` env var. Override per-run with [`--stage`](../guides/stages-and-environments.md). |
|
|
43
|
+
| `profile` | | — | AWS named profile to deploy with. |
|
|
44
|
+
| `framework` | | _auto-detected_ | Override framework detection (e.g. `"express"`). |
|
|
45
|
+
| `env` | | `{}` | Plain environment variables injected into every Lambda. See [Environment variables](../guides/environment-variables.md). |
|
|
46
|
+
| `compute` | | `{ memory: 256, timeout: 30 }` | Default memory (MB) and timeout (s) for **every** function. See [compute](#compute). |
|
|
47
|
+
| `resources` | | `{}` | Per-resource overrides keyed by resource id (`http`, or a cron/queue id). See [resources](#resources). |
|
|
48
|
+
| `projectId` | ✅ | — | Project id from the laranja dashboard. Required by the server-side build (`plan`/`deploy`/`eject`); `laranja init` fills it in. |
|
|
49
|
+
| `provider` | | `"aws"` | Target cloud. Only `"aws"` is implemented today. |
|
|
50
|
+
|
|
51
|
+
### `name`
|
|
52
|
+
|
|
53
|
+
Drives the stack name (`‹name›-‹stage›`) and every resource name
|
|
54
|
+
(`‹name›-‹fn›-‹stage›`). Choose something short and stable — renaming it after a
|
|
55
|
+
deploy creates a _new_ stack rather than renaming the old one.
|
|
56
|
+
|
|
57
|
+
### `region` and `profile`
|
|
58
|
+
|
|
59
|
+
`region` falls back to `AWS_REGION`, then `AWS_DEFAULT_REGION`. If none is set,
|
|
60
|
+
the CLI errors with a clear message. `profile` selects a named profile from your
|
|
61
|
+
AWS credentials file; otherwise the default credential chain is used.
|
|
62
|
+
|
|
63
|
+
### `stage`
|
|
64
|
+
|
|
65
|
+
The default is `"dev"`. It's part of resource names and is injected into every
|
|
66
|
+
Lambda as `process.env.STAGE`. The [`--stage`](../guides/stages-and-environments.md)
|
|
67
|
+
flag overrides it per command — the recommended way to drive multiple
|
|
68
|
+
environments from one config.
|
|
69
|
+
|
|
70
|
+
### `compute`
|
|
71
|
+
|
|
72
|
+
The default **memory** (MB) and **timeout** (seconds) applied to every function —
|
|
73
|
+
the HTTP proxy and each cron/queue consumer. The scaffold sets
|
|
74
|
+
`{ memory: 256, timeout: 30 }`:
|
|
75
|
+
|
|
76
|
+
```ts
|
|
77
|
+
const config: LaranjaConfig = {
|
|
78
|
+
name: "my-api",
|
|
79
|
+
projectId: "proj_…",
|
|
80
|
+
compute: { memory: 512, timeout: 20 },
|
|
81
|
+
};
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
### `resources`
|
|
85
|
+
|
|
86
|
+
Per-resource overrides, keyed by **resource id** — `http` for the proxy, or the
|
|
87
|
+
[`id`](./decorators-and-markers.md#cron) of a cron/queue. Each entry
|
|
88
|
+
merges field-by-field on top of `compute`, and queue/cron entries also accept
|
|
89
|
+
their kind-specific knobs (e.g. a queue's `visibilityTimeout`). An unknown id is
|
|
90
|
+
a hard error, so a typo can't silently no-op:
|
|
91
|
+
|
|
92
|
+
```ts
|
|
93
|
+
const config: LaranjaConfig = {
|
|
94
|
+
name: "my-api",
|
|
95
|
+
projectId: "proj_…",
|
|
96
|
+
compute: { memory: 256, timeout: 30 },
|
|
97
|
+
resources: {
|
|
98
|
+
http: { memory: 512 }, // beefier proxy
|
|
99
|
+
cleanup: { timeout: 60 }, // a slow cron by its id
|
|
100
|
+
emails: { visibilityTimeout: 180 }, // a queue by its name/id
|
|
101
|
+
},
|
|
102
|
+
};
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### Workers-only deployments
|
|
106
|
+
|
|
107
|
+
To deploy only your workers (`@Cron` / `@Queue`) with no HTTP app — for teams
|
|
108
|
+
whose API is hosted elsewhere — simply don't add an `http()` marker. No flag is
|
|
109
|
+
needed. See [workers-only deployments](../guides/http-apps.md#workers-only-deployments).
|
|
110
|
+
|
|
111
|
+
## Related
|
|
112
|
+
|
|
113
|
+
- [Environment variables](../guides/environment-variables.md)
|
|
114
|
+
- [Stages & environments](../guides/stages-and-environments.md)
|
|
@@ -0,0 +1,310 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Decorators & markers
|
|
3
|
+
description: API reference for @Cron, @Queue, cron, queue, getQueue, and http.
|
|
4
|
+
order: 3
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Decorators & markers
|
|
8
|
+
|
|
9
|
+
All of these are imported from `@alzulejos/laranja-decorators`. They are **static markers**
|
|
10
|
+
— the [scanner](../getting-started/how-it-works.md#1-scan) reads them at build time to
|
|
11
|
+
shape your infrastructure. At runtime they are near-no-ops (they don't wrap or
|
|
12
|
+
intercept your functions), so they're safe to leave in place.
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
npm install @alzulejos/laranja-decorators
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
The schedule builders [`rate`](../guides/schedules.md#ratevalue-unit) and
|
|
19
|
+
[`every`](../guides/schedules.md#everyunit) are re-exported here too, so you can
|
|
20
|
+
import them alongside `@Cron`. For `@nestjs/schedule` compatibility, the
|
|
21
|
+
`CronExpression` enum, `@Interval`, and `@Timeout` are re-exported as well — so a
|
|
22
|
+
Nest app can repoint its import at `@alzulejos/laranja-decorators` unchanged.
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
## `@Cron`
|
|
27
|
+
|
|
28
|
+
Schedules a class method. Each `@Cron` becomes [its own Lambda + EventBridge
|
|
29
|
+
rule](./what-gets-deployed.md#cron--lambda--eventbridge-rule).
|
|
30
|
+
|
|
31
|
+
```ts
|
|
32
|
+
function Cron(schedule: ScheduleInput): MethodDecorator
|
|
33
|
+
function Cron(options: CronOptions): MethodDecorator
|
|
34
|
+
function Cron(expression: string, options?: NestCronOptions): MethodDecorator // @nestjs/schedule form
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
```ts
|
|
38
|
+
import { Cron, rate, CronExpression } from "@alzulejos/laranja-decorators";
|
|
39
|
+
|
|
40
|
+
export class Jobs {
|
|
41
|
+
@Cron(rate(5, "minutes"))
|
|
42
|
+
async refreshCache() {}
|
|
43
|
+
|
|
44
|
+
@Cron({ schedule: "cron(0 12 * * ? *)", id: "daily-report" })
|
|
45
|
+
async report() {}
|
|
46
|
+
|
|
47
|
+
// @nestjs/schedule style — a node-cron string or CronExpression, translated for you
|
|
48
|
+
@Cron("0 3 * * *", { name: "nightly", timeZone: "Europe/Lisbon" })
|
|
49
|
+
async nightly() {}
|
|
50
|
+
|
|
51
|
+
@Cron(CronExpression.EVERY_30_MINUTES)
|
|
52
|
+
async sweep() {}
|
|
53
|
+
}
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
**`CronOptions`** (laranja form)
|
|
57
|
+
|
|
58
|
+
| Field | Type | Description |
|
|
59
|
+
|---|---|---|
|
|
60
|
+
| `schedule` | `ScheduleInput` | A [`rate()`/`every()`](../guides/schedules.md) result, a `Schedule`, or a raw string. |
|
|
61
|
+
| `id` | `string` _(optional)_ | Stable logical id. Defaults to `‹Class›-‹method›`; also drives the Lambda name. |
|
|
62
|
+
|
|
63
|
+
**`NestCronOptions`** (the second argument in the `@nestjs/schedule` form)
|
|
64
|
+
|
|
65
|
+
| Field | Type | Description |
|
|
66
|
+
|---|---|---|
|
|
67
|
+
| `name` | `string` _(optional)_ | Used as the resource `id`. |
|
|
68
|
+
| `timeZone` | `string` _(optional)_ | IANA timezone the schedule is evaluated in. |
|
|
69
|
+
|
|
70
|
+
See [Schedules → node-cron expressions](../guides/schedules.md#node-cron-expressions-nestjsschedule-compatibility)
|
|
71
|
+
for the accepted syntax and what's rejected. Nest providers resolve through DI —
|
|
72
|
+
declare your module with [`workers()`](#workers).
|
|
73
|
+
|
|
74
|
+
---
|
|
75
|
+
|
|
76
|
+
## `cron()` marker
|
|
77
|
+
|
|
78
|
+
Function-style counterpart to `@Cron`, for codebases that don't use classes.
|
|
79
|
+
Registers a standalone exported function on a schedule.
|
|
80
|
+
|
|
81
|
+
```ts
|
|
82
|
+
function cron(schedule: ScheduleInput, handler: JobHandler): void
|
|
83
|
+
function cron(options: CronOptions, handler: JobHandler): void
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
```ts
|
|
87
|
+
import { cron, rate } from "@alzulejos/laranja-decorators";
|
|
88
|
+
|
|
89
|
+
export async function refreshCache() {}
|
|
90
|
+
|
|
91
|
+
cron(rate(5, "minutes"), refreshCache);
|
|
92
|
+
cron({ schedule: rate(1, "hour"), id: "hourly-sync" }, refreshCache);
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
The function's name becomes the resource id unless you pass an explicit `id`.
|
|
96
|
+
|
|
97
|
+
---
|
|
98
|
+
|
|
99
|
+
## `@Interval`
|
|
100
|
+
|
|
101
|
+
`@nestjs/schedule`-compatible. Runs a method every _N_ milliseconds; laranja
|
|
102
|
+
lowers it to a `rate(...)`, so the interval must be a whole number of minutes
|
|
103
|
+
(EventBridge's 1-minute floor).
|
|
104
|
+
|
|
105
|
+
```ts
|
|
106
|
+
function Interval(milliseconds: number): MethodDecorator
|
|
107
|
+
function Interval(name: string, milliseconds: number): MethodDecorator
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
```ts
|
|
111
|
+
import { Interval } from "@alzulejos/laranja-decorators";
|
|
112
|
+
|
|
113
|
+
export class Jobs {
|
|
114
|
+
@Interval(300000) // every 5 minutes
|
|
115
|
+
async poll() {}
|
|
116
|
+
}
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
---
|
|
120
|
+
|
|
121
|
+
## `@Timeout`
|
|
122
|
+
|
|
123
|
+
Re-exported for `@nestjs/schedule` source compatibility, but a one-shot timer
|
|
124
|
+
relative to process start has no serverless equivalent — laranja **rejects it at
|
|
125
|
+
build time** with a clear message. Use [`@Cron`](#cron) or [`@Interval`](#interval)
|
|
126
|
+
instead.
|
|
127
|
+
|
|
128
|
+
---
|
|
129
|
+
|
|
130
|
+
## `@Queue`
|
|
131
|
+
|
|
132
|
+
Consumes messages from an SQS queue. Each `@Queue` becomes [an SQS queue +
|
|
133
|
+
consumer Lambda](./what-gets-deployed.md#queue--sqs-queue--consumer-lambda).
|
|
134
|
+
The handler is called once per message with the JSON-parsed body.
|
|
135
|
+
|
|
136
|
+
```ts
|
|
137
|
+
function Queue(options: QueueOptions): MethodDecorator
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
```ts
|
|
141
|
+
import { Queue } from "@alzulejos/laranja-decorators";
|
|
142
|
+
|
|
143
|
+
export class Workers {
|
|
144
|
+
@Queue({ name: "emails", batchSize: 10 })
|
|
145
|
+
async sendEmail(body: unknown) {}
|
|
146
|
+
|
|
147
|
+
@Queue({ name: "orders.fifo", fifo: true })
|
|
148
|
+
async processOrder(body: unknown) {}
|
|
149
|
+
}
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
**`QueueOptions`**
|
|
153
|
+
|
|
154
|
+
| Field | Type | Default | Description |
|
|
155
|
+
|---|---|---|---|
|
|
156
|
+
| `name` | `string` | _required_ | Queue name. A `.fifo` suffix marks a FIFO queue. |
|
|
157
|
+
| `batchSize` | `number` | `10` | Max messages per consumer invocation. |
|
|
158
|
+
| `fifo` | `boolean` | `false` | Force a FIFO queue (or end `name` with `.fifo`). When set, laranja appends `.fifo` to `name` if you left it off. |
|
|
159
|
+
|
|
160
|
+
---
|
|
161
|
+
|
|
162
|
+
## `queue()` marker
|
|
163
|
+
|
|
164
|
+
Function-style counterpart to `@Queue`.
|
|
165
|
+
|
|
166
|
+
```ts
|
|
167
|
+
function queue(options: QueueOptions, handler: JobHandler): void
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
```ts
|
|
171
|
+
import { queue } from "@alzulejos/laranja-decorators";
|
|
172
|
+
|
|
173
|
+
export async function sendEmail(body: unknown) {}
|
|
174
|
+
|
|
175
|
+
queue({ name: "emails", batchSize: 10 }, sendEmail);
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
---
|
|
179
|
+
|
|
180
|
+
## `getQueue()`
|
|
181
|
+
|
|
182
|
+
The queue **producer** — get a handle to a declared queue and `.send()` messages
|
|
183
|
+
to it. The counterpart to the [`@Queue`](#queue) / [`queue()`](#queue-marker)
|
|
184
|
+
consumers. Unlike the markers, this does real work at runtime (a single SQS
|
|
185
|
+
`SendMessage`); laranja injects the queue URL and grants `sqs:SendMessage` to
|
|
186
|
+
every function, so there's nothing to configure.
|
|
187
|
+
|
|
188
|
+
```ts
|
|
189
|
+
function getQueue(name: string): LaranjaQueue
|
|
190
|
+
|
|
191
|
+
interface LaranjaQueue {
|
|
192
|
+
readonly url: string;
|
|
193
|
+
send(payload: unknown, options?: SendOptions): Promise<{ messageId?: string }>;
|
|
194
|
+
}
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
```ts
|
|
198
|
+
import { getQueue } from "@alzulejos/laranja-decorators";
|
|
199
|
+
|
|
200
|
+
await getQueue("emails").send({ to, subject });
|
|
201
|
+
await getQueue("orders.fifo").send(order, { groupId: order.customerId });
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
`payload` is JSON-serialized (strings are sent as-is). `name` is the queue's
|
|
205
|
+
declared `name`; a send to an undeclared queue throws.
|
|
206
|
+
|
|
207
|
+
**`SendOptions`**
|
|
208
|
+
|
|
209
|
+
| Field | Type | Applies to | Description |
|
|
210
|
+
|---|---|---|---|
|
|
211
|
+
| `groupId` | `string` | FIFO (**required**) | `MessageGroupId` — orders messages within a group. A FIFO send throws without it. |
|
|
212
|
+
| `dedupId` | `string` | FIFO | `MessageDeduplicationId` — only needed when content-based dedup is off. |
|
|
213
|
+
| `delaySeconds` | `number` | Standard | Delay (0–900s) before the message becomes visible. Ignored by FIFO. |
|
|
214
|
+
|
|
215
|
+
See [Queues → Sending messages](../guides/queues.md#sending-messages).
|
|
216
|
+
|
|
217
|
+
---
|
|
218
|
+
|
|
219
|
+
## `http()`
|
|
220
|
+
|
|
221
|
+
Marks the HTTP app (the proxy target) in code — the only way to declare one.
|
|
222
|
+
Export the result so the scanner can find it.
|
|
223
|
+
|
|
224
|
+
```ts
|
|
225
|
+
function http<T>(app: T): T
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
```ts
|
|
229
|
+
import express from "express";
|
|
230
|
+
import { http } from "@alzulejos/laranja-decorators";
|
|
231
|
+
|
|
232
|
+
const app = express();
|
|
233
|
+
export default http(app); // or: export const api = http(app);
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
It returns its argument untouched — purely a static marker. Omit it for a
|
|
237
|
+
[workers-only](../guides/http-apps.md#workers-only-deployments) deployment.
|
|
238
|
+
|
|
239
|
+
For **NestJS**, wrap your async `bootstrap` factory (which `return`s the app)
|
|
240
|
+
instead of an app instance — see [HTTP apps → NestJS](../guides/http-apps.md#nestjs):
|
|
241
|
+
|
|
242
|
+
```ts
|
|
243
|
+
export default http(bootstrap); // bootstrap: () => Promise<INestApplication>
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
---
|
|
247
|
+
|
|
248
|
+
## `workers()`
|
|
249
|
+
|
|
250
|
+
**NestJS only.** Declares the module laranja builds a dependency-injection
|
|
251
|
+
context from, so class-based [`@Cron`](#cron) / [`@Queue`](#queue) providers
|
|
252
|
+
resolve their injected dependencies at runtime (via
|
|
253
|
+
`NestFactory.createApplicationContext`) instead of a bare `new`. The DI
|
|
254
|
+
counterpart to [`http()`](#http); export it so the scanner can find it.
|
|
255
|
+
|
|
256
|
+
```ts
|
|
257
|
+
function workers<T>(module: T): T
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
```ts
|
|
261
|
+
import { workers } from "@alzulejos/laranja-decorators";
|
|
262
|
+
import { AppModule } from "./app.module";
|
|
263
|
+
|
|
264
|
+
export default workers(AppModule); // or: export const jobs = workers(AppModule);
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
Pass `AppModule` for the whole graph, or a leaner module for a smaller cold
|
|
268
|
+
start. There's exactly one per project. Required when a Nest project has
|
|
269
|
+
class-based workers; standalone [`cron()`](#cron-marker)/[`queue()`](#queue-marker)
|
|
270
|
+
functions don't need it (no DI). Returns its argument untouched — a static marker.
|
|
271
|
+
|
|
272
|
+
---
|
|
273
|
+
|
|
274
|
+
## `env()`
|
|
275
|
+
|
|
276
|
+
Declares an environment variable your code needs. At runtime it just returns
|
|
277
|
+
`process.env[name]`; laranja discovers each call and populates that variable on
|
|
278
|
+
every deployed function, with the value supplied from your shell or CI at deploy
|
|
279
|
+
time.
|
|
280
|
+
|
|
281
|
+
```ts
|
|
282
|
+
function env(name: string): string | undefined
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
```ts
|
|
286
|
+
import { env } from "@alzulejos/laranja-decorators";
|
|
287
|
+
|
|
288
|
+
const dbUrl = env("DATABASE_URL");
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
The name must be a **string literal** so it can be found statically. See
|
|
292
|
+
[environment variables](../guides/environment-variables.md#values-from-your-environment--env)
|
|
293
|
+
for supplying values, the `--strict` flag, and per-stage usage.
|
|
294
|
+
|
|
295
|
+
---
|
|
296
|
+
|
|
297
|
+
## Types
|
|
298
|
+
|
|
299
|
+
| Type | Description |
|
|
300
|
+
|---|---|
|
|
301
|
+
| `ScheduleInput` | `Schedule \| string` — anything accepted where a schedule is expected. |
|
|
302
|
+
| `Schedule` | Provider-neutral schedule: `{ kind: "rate", value, unit }` or `{ kind: "cron", expression, dialect }`. |
|
|
303
|
+
| `RateUnit` | `"minute" \| "minutes" \| "hour" \| "hours" \| "day" \| "days"`. |
|
|
304
|
+
| `CronExpression` | Enum of common cron strings, mirrored from `@nestjs/schedule`. |
|
|
305
|
+
| `JobHandler` | `(...args) => unknown \| Promise<unknown>` — a `cron()`/`queue()` handler. |
|
|
306
|
+
|
|
307
|
+
## Related
|
|
308
|
+
|
|
309
|
+
- [Cron jobs](../guides/cron-jobs.md) · [Queues](../guides/queues.md) · [Schedules](../guides/schedules.md)
|
|
310
|
+
- [HTTP apps](../guides/http-apps.md)
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: What gets deployed
|
|
3
|
+
description: The exact AWS resources laranja creates and how they're named.
|
|
4
|
+
order: 4
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# What gets deployed
|
|
8
|
+
|
|
9
|
+
laranja maps each thing it finds in your code to a small, predictable set of AWS
|
|
10
|
+
resources — all in your own account.
|
|
11
|
+
|
|
12
|
+
## HTTP app → proxy Lambda + Function URL
|
|
13
|
+
|
|
14
|
+
Your entire Express app is deployed as **one Lambda function** fronted by a
|
|
15
|
+
**Lambda Function URL**. There is no API Gateway.
|
|
16
|
+
|
|
17
|
+
- All routes are served by this single proxy Lambda.
|
|
18
|
+
- The Function URL is **public** (`authType: NONE`) and CORS is open
|
|
19
|
+
(`*` origins, all methods, all headers) — your app handles auth/CORS as it
|
|
20
|
+
sees fit.
|
|
21
|
+
- Memory and timeout come from [`compute`](./config-file.md#compute)
|
|
22
|
+
in your config (the scaffold sets `{ memory: 256, timeout: 30 }`), overridable
|
|
23
|
+
per-resource under the `http` key in [`resources`](./config-file.md#resources).
|
|
24
|
+
- The public HTTPS URL is emitted as the `HttpUrl` stack output.
|
|
25
|
+
|
|
26
|
+
```
|
|
27
|
+
GET https://‹id›.lambda-url.‹region›.on.aws/
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## `@Cron` → Lambda + EventBridge rule
|
|
31
|
+
|
|
32
|
+
Each cron handler becomes **its own Lambda** plus an **EventBridge rule** that
|
|
33
|
+
invokes it on schedule.
|
|
34
|
+
|
|
35
|
+
- Memory and timeout come from [`compute`](./config-file.md#compute)
|
|
36
|
+
(default `{ memory: 256, timeout: 30 }`), overridable per cron id in
|
|
37
|
+
[`resources`](./config-file.md#resources).
|
|
38
|
+
- The schedule comes from your [`rate()`/`every()`](../guides/schedules.md)
|
|
39
|
+
builder or raw expression.
|
|
40
|
+
|
|
41
|
+
## `@Queue` → SQS queue + consumer Lambda
|
|
42
|
+
|
|
43
|
+
Each queue handler becomes an **SQS queue** and a **consumer Lambda** wired to it.
|
|
44
|
+
|
|
45
|
+
- Encryption: **SQS-managed (SSE-SQS)**.
|
|
46
|
+
- **FIFO** queues are created when the name ends in `.fifo` or `fifo: true` is
|
|
47
|
+
set (content-based deduplication is enabled for FIFO).
|
|
48
|
+
- Default **batch size**: 10. Your handler is invoked per message with the
|
|
49
|
+
JSON-parsed body.
|
|
50
|
+
- **Partial-batch failures** are enabled: throwing for one message fails only
|
|
51
|
+
that message; the rest of the batch still succeeds.
|
|
52
|
+
- Consumer memory/timeout come from [`compute`](./config-file.md#compute)
|
|
53
|
+
(default `{ memory: 256, timeout: 30 }`). The queue's **visibility timeout** is
|
|
54
|
+
derived to satisfy AWS's rule that it be ≥ the consumer timeout, and can be set
|
|
55
|
+
explicitly per queue via [`resources`](./config-file.md#resources).
|
|
56
|
+
- The queue URL is emitted as a stack output.
|
|
57
|
+
|
|
58
|
+
## Naming
|
|
59
|
+
|
|
60
|
+
Everything is named deterministically — no random suffixes:
|
|
61
|
+
|
|
62
|
+
| Resource | Pattern | Example |
|
|
63
|
+
|---|---|---|
|
|
64
|
+
| CloudFormation stack | `‹name›-‹stage›` | `my-api-prod` |
|
|
65
|
+
| Lambda functions | `‹name›-‹fn›-‹stage›` | `my-api-app-prod`, `my-api-sendEmail-prod` |
|
|
66
|
+
|
|
67
|
+
`‹fn›` is the handler's name (the method/function name), or the explicit `id` you
|
|
68
|
+
set on `@Cron`/`@Queue`. The HTTP proxy uses `app`. Names are truncated to AWS's
|
|
69
|
+
64-character limit and sanitized to allowed characters.
|
|
70
|
+
|
|
71
|
+
Because the stage is part of the names, multiple stages can live in one account
|
|
72
|
+
without colliding — see [Stages & environments](../guides/stages-and-environments.md).
|
|
73
|
+
|
|
74
|
+
## Supporting resources
|
|
75
|
+
|
|
76
|
+
Each Lambda gets an **IAM execution role** (and the queue consumers get the
|
|
77
|
+
permissions to read their queue / EventBridge to invoke crons). The first deploy
|
|
78
|
+
to an account/region also creates the one-time CDK **bootstrap** resources (an S3
|
|
79
|
+
asset bucket and roles).
|
|
80
|
+
|
|
81
|
+
## Related
|
|
82
|
+
|
|
83
|
+
- [How it works](../getting-started/how-it-works.md)
|
|
84
|
+
- [HTTP apps](../guides/http-apps.md) · [Cron jobs](../guides/cron-jobs.md) · [Queues](../guides/queues.md)
|