@projectdochelp/s3te 1.0.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/LICENSE +21 -0
- package/README.md +442 -0
- package/bin/s3te.mjs +2 -0
- package/package.json +66 -0
- package/packages/aws-adapter/src/aws-cli.mjs +102 -0
- package/packages/aws-adapter/src/deploy.mjs +433 -0
- package/packages/aws-adapter/src/features.mjs +16 -0
- package/packages/aws-adapter/src/index.mjs +7 -0
- package/packages/aws-adapter/src/manifest.mjs +88 -0
- package/packages/aws-adapter/src/package.mjs +323 -0
- package/packages/aws-adapter/src/runtime/common.mjs +917 -0
- package/packages/aws-adapter/src/runtime/content-mirror.mjs +301 -0
- package/packages/aws-adapter/src/runtime/invalidation-executor.mjs +61 -0
- package/packages/aws-adapter/src/runtime/invalidation-scheduler.mjs +59 -0
- package/packages/aws-adapter/src/runtime/render-worker.mjs +83 -0
- package/packages/aws-adapter/src/runtime/source-dispatcher.mjs +106 -0
- package/packages/aws-adapter/src/template.mjs +578 -0
- package/packages/aws-adapter/src/zip.mjs +111 -0
- package/packages/cli/bin/s3te.mjs +383 -0
- package/packages/cli/src/fs-adapters.mjs +221 -0
- package/packages/cli/src/project.mjs +535 -0
- package/packages/core/src/config.mjs +464 -0
- package/packages/core/src/content-query.mjs +176 -0
- package/packages/core/src/errors.mjs +14 -0
- package/packages/core/src/index.mjs +24 -0
- package/packages/core/src/mime.mjs +29 -0
- package/packages/core/src/minify.mjs +82 -0
- package/packages/core/src/render.mjs +537 -0
- package/packages/testkit/src/index.mjs +136 -0
- package/src/index.mjs +3 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2022 Heinz Olaf Klöppel
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,442 @@
|
|
|
1
|
+
# S3TemplateEngine
|
|
2
|
+
|
|
3
|
+
S3TemplateEngine is a lightweight serverless template engine for people who want to keep writing HTML and still publish through AWS. You write templates and assets, S3TE renders and publishes the static result.
|
|
4
|
+
|
|
5
|
+
This README is the user guide for the rewrite generation. The deeper implementation specs still live in [`docs/`](./docs/), but this file is intentionally written for users first.
|
|
6
|
+
|
|
7
|
+
## Table of Contents
|
|
8
|
+
|
|
9
|
+
1. [Motivation](#motivation)
|
|
10
|
+
2. [Support](#support)
|
|
11
|
+
3. [Concept](#concept)
|
|
12
|
+
4. [Installation (AWS)](#installation-aws)
|
|
13
|
+
5. [Installation (VSCode)](#installation-vscode)
|
|
14
|
+
6. [Installation (S3TE)](#installation-s3te)
|
|
15
|
+
7. [Usage](#usage)
|
|
16
|
+
8. [Optional: Webiny CMS](#optional-webiny-cms)
|
|
17
|
+
|
|
18
|
+
## Motivation
|
|
19
|
+
|
|
20
|
+
AWS S3 and CloudFront are a great platform for websites: cheap, fast and low-maintenance. The annoying part usually starts before hosting. You still need reusable HTML, a safe deployment flow, and maybe a way for editors to maintain content without turning your project into a full framework.
|
|
21
|
+
|
|
22
|
+
**S3TemplateEngine is for you if** you want to keep writing HTML by hand, but still want to:
|
|
23
|
+
|
|
24
|
+
- reuse snippets like headers, navigation and footer blocks
|
|
25
|
+
- generate many pages from one template
|
|
26
|
+
- publish multiple languages or variants from one project
|
|
27
|
+
- keep AWS hosting simple and low-cost
|
|
28
|
+
- optionally let editors maintain content in Webiny
|
|
29
|
+
- deploy without hand-editing Lambda settings or uploading ZIP files yourself
|
|
30
|
+
|
|
31
|
+
## Support
|
|
32
|
+
|
|
33
|
+
If S3TE saves you time and you want to buy me a tea, you can do that here:
|
|
34
|
+
|
|
35
|
+
[](https://ko-fi.com/hokcomics)
|
|
36
|
+
|
|
37
|
+
If you need help, found a bug, or want to contribute, open an issue or pull request on GitHub.
|
|
38
|
+
|
|
39
|
+
## Concept
|
|
40
|
+
|
|
41
|
+
S3TE keeps one simple promise: you write source templates, S3TE turns them into static files, AWS serves the result.
|
|
42
|
+
|
|
43
|
+

|
|
44
|
+
|
|
45
|
+
<details>
|
|
46
|
+
<summary>What is the difference between the code bucket and the website bucket?</summary>
|
|
47
|
+
|
|
48
|
+
The code bucket receives your source project files: `.html`, `.part`, CSS, JavaScript, images and everything else you deploy from your project.
|
|
49
|
+
|
|
50
|
+
The website bucket contains the finished result that visitors actually receive through CloudFront. That split is what makes incremental rendering, generated pages and safe re-deploys possible.
|
|
51
|
+
|
|
52
|
+
</details>
|
|
53
|
+
|
|
54
|
+
<details>
|
|
55
|
+
<summary>What happens when I deploy?</summary>
|
|
56
|
+
|
|
57
|
+
`s3te deploy` validates the project, packages the AWS runtime, creates or updates one persistent CloudFormation environment stack, creates one temporary CloudFormation deploy stack for packaging artifacts, synchronizes your current source files into the code bucket, and removes the temporary stack again after the real deploy run.
|
|
58
|
+
|
|
59
|
+
The persistent environment stack contains the long-lived AWS resources such as buckets, Lambda functions, DynamoDB tables, CloudFront distributions and the runtime manifest parameter. The temporary deploy stack exists only so CloudFormation can consume the packaged Lambda artifacts cleanly.
|
|
60
|
+
|
|
61
|
+
</details>
|
|
62
|
+
|
|
63
|
+
## Installation (AWS)
|
|
64
|
+
|
|
65
|
+
This section is only about the AWS things you need before you touch S3TE. The actual click-by-click screens are best left to the official AWS documentation, because the console changes over time. The goal here is to tell you exactly what S3TE needs from AWS, why it needs it, and which official page gets you there.
|
|
66
|
+
|
|
67
|
+
<details>
|
|
68
|
+
<summary>What you need before your first S3TE deploy</summary>
|
|
69
|
+
|
|
70
|
+
| Item | Why S3TE needs it | Official guide |
|
|
71
|
+
| --- | --- | --- |
|
|
72
|
+
| AWS account | S3TE deploys into your own AWS account. | [Create an AWS account](https://portal.aws.amazon.com/billing/signup) |
|
|
73
|
+
| Daily-work AWS access | `s3te deploy` needs credentials that can create CloudFormation stacks and related resources. | [Create an IAM user](https://docs.aws.amazon.com/console/iam/add-users), [Manage access keys](https://docs.aws.amazon.com/IAM/latest/UserGuide/access-keys-admin-managed.html) |
|
|
74
|
+
| AWS CLI v2 | The S3TE CLI shells out to the official `aws` CLI. | [Install AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html), [Get started with AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-getting-started.html) |
|
|
75
|
+
| Domain name you control | CloudFront and TLS only make sense for domains you can point to AWS. | Use your registrar of choice |
|
|
76
|
+
| ACM certificate in `us-east-1` | CloudFront requires its public certificate in `us-east-1`. | [Public certificates in ACM](https://docs.aws.amazon.com/acm/latest/userguide/acm-public-certificates.html) |
|
|
77
|
+
| Optional Route53 hosted zone | Needed only if S3TE should create DNS alias records automatically. | [Create a public hosted zone](https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/CreatingHostedZone.html) |
|
|
78
|
+
|
|
79
|
+
</details>
|
|
80
|
+
|
|
81
|
+
<details>
|
|
82
|
+
<summary>Recommended AWS order for first-time users</summary>
|
|
83
|
+
|
|
84
|
+
1. Create the AWS account.
|
|
85
|
+
2. Stop using the root user for daily work.
|
|
86
|
+
3. Create one deployment identity for yourself.
|
|
87
|
+
4. Install AWS CLI v2 locally.
|
|
88
|
+
5. Run `aws configure` and verify it with `aws sts get-caller-identity`.
|
|
89
|
+
6. Request the ACM certificate in `us-east-1`.
|
|
90
|
+
7. If you want automatic DNS records, create or locate the Route53 hosted zone.
|
|
91
|
+
|
|
92
|
+
For a first personal setup, the easiest route is usually one IAM user with console access and access keys. If you already work with AWS Identity Center or another federated login, that is fine too. S3TE uses the standard AWS credential chain.
|
|
93
|
+
|
|
94
|
+
</details>
|
|
95
|
+
|
|
96
|
+
## Installation (VSCode)
|
|
97
|
+
|
|
98
|
+
This section is only about the local editing experience. S3TE does not require VSCode, but VSCode is the reference editor workflow and the easiest path for most users.
|
|
99
|
+
|
|
100
|
+
<details>
|
|
101
|
+
<summary>Install the local tools you need</summary>
|
|
102
|
+
|
|
103
|
+
| Tool | Why you want it | Official guide |
|
|
104
|
+
| --- | --- | --- |
|
|
105
|
+
| Visual Studio Code | Comfortable editor with integrated terminal and extension support. | [VS Code setup overview](https://code.visualstudio.com/docs/setup/setup-overview), [Get started with VS Code](https://code.visualstudio.com/docs/getstarted/getting-started) |
|
|
106
|
+
| Node.js 20 or newer | Required for the S3TE CLI and local rendering. | [Download Node.js](https://nodejs.org/en/download) |
|
|
107
|
+
|
|
108
|
+
</details>
|
|
109
|
+
|
|
110
|
+
<details>
|
|
111
|
+
<summary>What to verify before you continue</summary>
|
|
112
|
+
|
|
113
|
+
Open VSCode, open the integrated terminal, and run:
|
|
114
|
+
|
|
115
|
+
```bash
|
|
116
|
+
node --version
|
|
117
|
+
npm --version
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
If both commands print a version number, your local machine is ready for S3TE.
|
|
121
|
+
|
|
122
|
+
</details>
|
|
123
|
+
|
|
124
|
+
## Installation (S3TE)
|
|
125
|
+
|
|
126
|
+
This is the S3TE-specific part. No AWS console links, no editor tutorial, just the steps that actually create and run an S3TE project.
|
|
127
|
+
|
|
128
|
+
<details>
|
|
129
|
+
<summary>1. Create your project folder</summary>
|
|
130
|
+
|
|
131
|
+
```bash
|
|
132
|
+
mkdir mywebsite
|
|
133
|
+
cd mywebsite
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
</details>
|
|
137
|
+
|
|
138
|
+
<details>
|
|
139
|
+
<summary>2. Scaffold the project once</summary>
|
|
140
|
+
|
|
141
|
+
If `@projectdochelp/s3te` is already published on npm, scaffold the project once with a temporary `npx` run:
|
|
142
|
+
|
|
143
|
+
```bash
|
|
144
|
+
npx --package @projectdochelp/s3te s3te init --project-name mywebsite --base-url example.com
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
That command only works after a real npm publish. A GitHub repository on its own is not enough.
|
|
148
|
+
|
|
149
|
+
If you are still working from this repository before the first npm publish, run the CLI directly from the repo root instead:
|
|
150
|
+
|
|
151
|
+
```bash
|
|
152
|
+
node packages/cli/bin/s3te.mjs init --dir ./mywebsite --project-name mywebsite --base-url example.com
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
</details>
|
|
156
|
+
|
|
157
|
+
<details>
|
|
158
|
+
<summary>3. What the scaffold creates</summary>
|
|
159
|
+
|
|
160
|
+
The default scaffold creates:
|
|
161
|
+
|
|
162
|
+
```text
|
|
163
|
+
mywebsite/
|
|
164
|
+
package.json
|
|
165
|
+
s3te.config.json
|
|
166
|
+
app/
|
|
167
|
+
part/
|
|
168
|
+
head.part
|
|
169
|
+
website/
|
|
170
|
+
index.html
|
|
171
|
+
offline/
|
|
172
|
+
content/
|
|
173
|
+
en.json
|
|
174
|
+
schemas/
|
|
175
|
+
s3te.config.schema.json
|
|
176
|
+
tests/
|
|
177
|
+
project.test.mjs
|
|
178
|
+
.vscode/
|
|
179
|
+
extensions.json
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
</details>
|
|
183
|
+
|
|
184
|
+
<details>
|
|
185
|
+
<summary>4. Install S3TE locally in the project</summary>
|
|
186
|
+
|
|
187
|
+
```bash
|
|
188
|
+
npm install --save-dev @projectdochelp/s3te
|
|
189
|
+
npx s3te --help
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
This is the recommended everyday setup. From this point on, you run the project-local version with `npx s3te ...`.
|
|
193
|
+
|
|
194
|
+
If you want to use the built-in test helpers in your own project tests, import them from the same package via `@projectdochelp/s3te/testkit`.
|
|
195
|
+
|
|
196
|
+
</details>
|
|
197
|
+
|
|
198
|
+
<details>
|
|
199
|
+
<summary>5. Fill in the real AWS values in <code>s3te.config.json</code></summary>
|
|
200
|
+
|
|
201
|
+
The most important fields for a first deployment are:
|
|
202
|
+
|
|
203
|
+
```json
|
|
204
|
+
{
|
|
205
|
+
"environments": {
|
|
206
|
+
"dev": {
|
|
207
|
+
"awsRegion": "eu-central-1",
|
|
208
|
+
"stackPrefix": "DEV",
|
|
209
|
+
"certificateArn": "arn:aws:acm:us-east-1:123456789012:certificate/replace-me",
|
|
210
|
+
"route53HostedZoneId": "Z1234567890"
|
|
211
|
+
}
|
|
212
|
+
},
|
|
213
|
+
"variants": {
|
|
214
|
+
"website": {
|
|
215
|
+
"languages": {
|
|
216
|
+
"en": {
|
|
217
|
+
"baseUrl": "example.com",
|
|
218
|
+
"cloudFrontAliases": ["example.com", "www.example.com"]
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
`route53HostedZoneId` is optional. Leave it out if you want to manage DNS yourself.
|
|
227
|
+
|
|
228
|
+
</details>
|
|
229
|
+
|
|
230
|
+
<details>
|
|
231
|
+
<summary>6. Run the first local check and deploy</summary>
|
|
232
|
+
|
|
233
|
+
```bash
|
|
234
|
+
npx s3te validate
|
|
235
|
+
npx s3te render --env dev
|
|
236
|
+
npx s3te test
|
|
237
|
+
npx s3te doctor --env dev
|
|
238
|
+
npx s3te deploy --env dev
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
`render` writes the local preview into `offline/S3TELocal/preview/dev/...`.
|
|
242
|
+
|
|
243
|
+
`deploy` creates or updates the persistent environment stack, uses a temporary deploy stack for packaged Lambda artifacts, synchronizes the source project into the code bucket, and removes the temporary stack again when the deploy finishes.
|
|
244
|
+
|
|
245
|
+
If you left `route53HostedZoneId` out of the config, the last DNS step stays manual: point your domain at the created CloudFront distribution after deploy.
|
|
246
|
+
|
|
247
|
+
</details>
|
|
248
|
+
|
|
249
|
+
## Usage
|
|
250
|
+
|
|
251
|
+
Once the project is installed, your everyday loop is deliberately small: edit templates, validate, render locally, then deploy.
|
|
252
|
+
|
|
253
|
+
### Daily Workflow
|
|
254
|
+
|
|
255
|
+
<details>
|
|
256
|
+
<summary>Typical daily loop</summary>
|
|
257
|
+
|
|
258
|
+
1. Edit files in `app/part/` and `app/website/`.
|
|
259
|
+
2. If you use content-driven tags without Webiny, edit `offline/content/en.json` or `offline/content/items.json`.
|
|
260
|
+
3. Validate and render locally.
|
|
261
|
+
4. Run your tests.
|
|
262
|
+
5. Deploy when the result looks right.
|
|
263
|
+
|
|
264
|
+
```bash
|
|
265
|
+
npx s3te validate
|
|
266
|
+
npx s3te render --env dev
|
|
267
|
+
npx s3te test
|
|
268
|
+
npx s3te deploy --env dev
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
</details>
|
|
272
|
+
|
|
273
|
+
### CLI Commands
|
|
274
|
+
|
|
275
|
+
<details>
|
|
276
|
+
<summary>Command overview</summary>
|
|
277
|
+
|
|
278
|
+
| Command | What it does |
|
|
279
|
+
| --- | --- |
|
|
280
|
+
| `s3te init` | Creates the starter project structure and base config. |
|
|
281
|
+
| `s3te validate` | Checks config and template syntax without rendering outputs. |
|
|
282
|
+
| `s3te render --env <name>` | Renders locally into `offline/S3TELocal/preview/<env>/...`. |
|
|
283
|
+
| `s3te test` | Runs the project tests from `offline/tests/`. |
|
|
284
|
+
| `s3te package --env <name>` | Builds the AWS deployment artifacts without deploying them yet. |
|
|
285
|
+
| `s3te doctor --env <name>` | Checks local machine and AWS access before deploy. |
|
|
286
|
+
| `s3te deploy --env <name>` | Deploys or updates the AWS environment and syncs source files. |
|
|
287
|
+
| `s3te migrate` | Updates older project configs and can retrofit Webiny into an existing S3TE project. |
|
|
288
|
+
|
|
289
|
+
</details>
|
|
290
|
+
|
|
291
|
+
### Template Commands
|
|
292
|
+
|
|
293
|
+
These are the core S3TE commands you will use even in a plain HTML-only project.
|
|
294
|
+
|
|
295
|
+
<details>
|
|
296
|
+
<summary><code><part></code> - reuse a partial file</summary>
|
|
297
|
+
|
|
298
|
+
```html
|
|
299
|
+
<part>head.part</part>
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
</details>
|
|
303
|
+
|
|
304
|
+
<details>
|
|
305
|
+
<summary><code><if></code> - render inline HTML only when a condition matches</summary>
|
|
306
|
+
|
|
307
|
+
```html
|
|
308
|
+
<if>{
|
|
309
|
+
"env": "prod",
|
|
310
|
+
"template": "<meta name='robots' content='all'>"
|
|
311
|
+
}</if>
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
</details>
|
|
315
|
+
|
|
316
|
+
<details>
|
|
317
|
+
<summary><code><fileattribute></code> - print metadata of the current output file</summary>
|
|
318
|
+
|
|
319
|
+
```html
|
|
320
|
+
<fileattribute>filename</fileattribute>
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
</details>
|
|
324
|
+
|
|
325
|
+
<details>
|
|
326
|
+
<summary><code><lang></code> - print the current language metadata</summary>
|
|
327
|
+
|
|
328
|
+
```html
|
|
329
|
+
<html lang="<lang>2</lang>">
|
|
330
|
+
<link rel="canonical" href="https://<lang>baseurl</lang>">
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
</details>
|
|
334
|
+
|
|
335
|
+
<details>
|
|
336
|
+
<summary><code><switchlang></code> - choose inline content by language</summary>
|
|
337
|
+
|
|
338
|
+
```html
|
|
339
|
+
<switchlang>
|
|
340
|
+
<de>Willkommen</de>
|
|
341
|
+
<en>Welcome</en>
|
|
342
|
+
</switchlang>
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
</details>
|
|
346
|
+
|
|
347
|
+
If you also want content-driven commands such as `dbmulti` or `dbmultifile`, continue with the optional Webiny section below. The same commands can also read from local `offline/content/*.json` files when you are not using Webiny yet.
|
|
348
|
+
|
|
349
|
+
## Optional: Webiny CMS
|
|
350
|
+
|
|
351
|
+
You do not need Webiny to use S3TE. Start with plain HTML first. Add Webiny only when editors should maintain content in a CMS instead of editing local JSON files under `offline/content/`.
|
|
352
|
+
|
|
353
|
+
The supported target for this optional path is Webiny 6.x on its standard AWS deployment model.
|
|
354
|
+
|
|
355
|
+

|
|
356
|
+
|
|
357
|
+
<details>
|
|
358
|
+
<summary>Install Webiny first by following the official guides</summary>
|
|
359
|
+
|
|
360
|
+
This section assumes that S3TE is already installed and deployed. The S3TE-specific Webiny setup only starts after you already have a running Webiny 6.x installation in AWS.
|
|
361
|
+
|
|
362
|
+
- [Install Webiny](https://www.webiny.com/learn/course/getting-started/installing-webiny)
|
|
363
|
+
|
|
364
|
+
</details>
|
|
365
|
+
|
|
366
|
+
<details>
|
|
367
|
+
<summary>Retrofit Webiny onto an existing S3TE project</summary>
|
|
368
|
+
|
|
369
|
+
1. Install Webiny in AWS and finish the Webiny setup first.
|
|
370
|
+
2. Find the Webiny DynamoDB table that contains the CMS entries you want S3TE to mirror.
|
|
371
|
+
3. Upgrade your existing S3TE config for Webiny:
|
|
372
|
+
|
|
373
|
+
```bash
|
|
374
|
+
npx s3te migrate --enable-webiny --webiny-source-table webiny-1234567 --webiny-tenant root --webiny-model article --write
|
|
375
|
+
```
|
|
376
|
+
|
|
377
|
+
`staticContent` and `staticCodeContent` are kept automatically. Add `--webiny-model` once per custom model you want S3TE to mirror.
|
|
378
|
+
|
|
379
|
+
4. Turn on DynamoDB Streams for the Webiny source table with `NEW_AND_OLD_IMAGES`.
|
|
380
|
+
5. If your S3TE language keys are not identical to your Webiny locales, add `webinyLocale` per language in `s3te.config.json`, for example `"en": { "webinyLocale": "en-US" }`.
|
|
381
|
+
6. If your Webiny installation hosts multiple tenants, keep `integrations.webiny.tenant` set so S3TE only mirrors the intended tenant.
|
|
382
|
+
7. Check the project again:
|
|
383
|
+
|
|
384
|
+
```bash
|
|
385
|
+
npx s3te doctor --env prod
|
|
386
|
+
```
|
|
387
|
+
|
|
388
|
+
8. Redeploy the existing S3TE environment:
|
|
389
|
+
|
|
390
|
+
```bash
|
|
391
|
+
npx s3te deploy --env prod
|
|
392
|
+
```
|
|
393
|
+
|
|
394
|
+
That deploy updates the existing environment stack and adds the Webiny mirror resources to it. You do not need a fresh S3TE installation.
|
|
395
|
+
|
|
396
|
+
</details>
|
|
397
|
+
|
|
398
|
+
<details>
|
|
399
|
+
<summary>What the migration command changes</summary>
|
|
400
|
+
|
|
401
|
+
The migration command writes or updates the `integrations.webiny` block in `s3te.config.json`. A typical result looks like this:
|
|
402
|
+
|
|
403
|
+
Example config block:
|
|
404
|
+
|
|
405
|
+
```json
|
|
406
|
+
"integrations": {
|
|
407
|
+
"webiny": {
|
|
408
|
+
"enabled": true,
|
|
409
|
+
"sourceTableName": "webiny-1234567",
|
|
410
|
+
"mirrorTableName": "{stackPrefix}_s3te_content_{project}",
|
|
411
|
+
"tenant": "root",
|
|
412
|
+
"relevantModels": ["article", "staticContent", "staticCodeContent"]
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
```
|
|
416
|
+
|
|
417
|
+
For localized Webiny projects, the language block can also carry the mapping explicitly:
|
|
418
|
+
|
|
419
|
+
```json
|
|
420
|
+
"languages": {
|
|
421
|
+
"en": {
|
|
422
|
+
"baseUrl": "example.com",
|
|
423
|
+
"cloudFrontAliases": ["example.com"],
|
|
424
|
+
"webinyLocale": "en-US"
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
```
|
|
428
|
+
|
|
429
|
+
</details>
|
|
430
|
+
|
|
431
|
+
<details>
|
|
432
|
+
<summary>Content template commands</summary>
|
|
433
|
+
|
|
434
|
+
These commands are useful both with Webiny and with local JSON content files:
|
|
435
|
+
|
|
436
|
+
- `dbpart`
|
|
437
|
+
- `dbmulti`
|
|
438
|
+
- `dbmultifile`
|
|
439
|
+
- `dbitem`
|
|
440
|
+
- `dbmultifileitem`
|
|
441
|
+
|
|
442
|
+
</details>
|
package/bin/s3te.mjs
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@projectdochelp/s3te",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "CLI, render core, AWS adapter, and testkit for S3TemplateEngine projects",
|
|
5
|
+
"repository": {
|
|
6
|
+
"type": "git",
|
|
7
|
+
"url": "git+https://github.com/ProjectDocHelp/S3TemplateEngine.git"
|
|
8
|
+
},
|
|
9
|
+
"homepage": "https://github.com/ProjectDocHelp/S3TemplateEngine#readme",
|
|
10
|
+
"bugs": {
|
|
11
|
+
"url": "https://github.com/ProjectDocHelp/S3TemplateEngine/issues"
|
|
12
|
+
},
|
|
13
|
+
"license": "MIT",
|
|
14
|
+
"type": "module",
|
|
15
|
+
"keywords": [
|
|
16
|
+
"s3te",
|
|
17
|
+
"s3templateengine",
|
|
18
|
+
"cli",
|
|
19
|
+
"aws",
|
|
20
|
+
"static-site"
|
|
21
|
+
],
|
|
22
|
+
"engines": {
|
|
23
|
+
"node": ">=20"
|
|
24
|
+
},
|
|
25
|
+
"bin": {
|
|
26
|
+
"s3te": "bin/s3te.mjs"
|
|
27
|
+
},
|
|
28
|
+
"exports": {
|
|
29
|
+
".": "./src/index.mjs",
|
|
30
|
+
"./core": "./packages/core/src/index.mjs",
|
|
31
|
+
"./aws-adapter": "./packages/aws-adapter/src/index.mjs",
|
|
32
|
+
"./testkit": "./packages/testkit/src/index.mjs",
|
|
33
|
+
"./package.json": "./package.json"
|
|
34
|
+
},
|
|
35
|
+
"files": [
|
|
36
|
+
"bin/",
|
|
37
|
+
"packages/cli/bin/",
|
|
38
|
+
"packages/cli/src/",
|
|
39
|
+
"packages/core/src/",
|
|
40
|
+
"packages/aws-adapter/src/",
|
|
41
|
+
"packages/testkit/src/",
|
|
42
|
+
"src/",
|
|
43
|
+
"README.md",
|
|
44
|
+
"LICENSE"
|
|
45
|
+
],
|
|
46
|
+
"dependencies": {
|
|
47
|
+
"@aws-sdk/client-cloudfront": "^3.0.0",
|
|
48
|
+
"@aws-sdk/client-dynamodb": "^3.0.0",
|
|
49
|
+
"@aws-sdk/client-lambda": "^3.0.0",
|
|
50
|
+
"@aws-sdk/client-s3": "^3.0.0",
|
|
51
|
+
"@aws-sdk/client-sfn": "^3.0.0",
|
|
52
|
+
"@aws-sdk/client-ssm": "^3.0.0",
|
|
53
|
+
"@aws-sdk/lib-dynamodb": "^3.0.0",
|
|
54
|
+
"@aws-sdk/util-dynamodb": "^3.0.0"
|
|
55
|
+
},
|
|
56
|
+
"publishConfig": {
|
|
57
|
+
"access": "public"
|
|
58
|
+
},
|
|
59
|
+
"scripts": {
|
|
60
|
+
"test": "node ./scripts/run-tests.mjs",
|
|
61
|
+
"cli": "node ./packages/cli/bin/s3te.mjs",
|
|
62
|
+
"pack:publish": "npm pack",
|
|
63
|
+
"pack:check": "npm pack --dry-run",
|
|
64
|
+
"publish:dry-run": "npm publish --access public --dry-run"
|
|
65
|
+
}
|
|
66
|
+
}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { spawn } from "node:child_process";
|
|
2
|
+
|
|
3
|
+
import { S3teError } from "../../core/src/index.mjs";
|
|
4
|
+
|
|
5
|
+
function toCliError(message, details) {
|
|
6
|
+
return new S3teError("AWS_AUTH_ERROR", message, details);
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function runProcess(command, args, options = {}) {
|
|
10
|
+
return new Promise((resolve, reject) => {
|
|
11
|
+
const child = spawn(command, args, {
|
|
12
|
+
cwd: options.cwd,
|
|
13
|
+
env: {
|
|
14
|
+
...process.env,
|
|
15
|
+
AWS_PAGER: "",
|
|
16
|
+
...(options.env ?? {})
|
|
17
|
+
},
|
|
18
|
+
stdio: options.stdio ?? "pipe"
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
let stdout = "";
|
|
22
|
+
let stderr = "";
|
|
23
|
+
|
|
24
|
+
if (child.stdout) {
|
|
25
|
+
child.stdout.on("data", (chunk) => {
|
|
26
|
+
stdout += chunk.toString();
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
if (child.stderr) {
|
|
31
|
+
child.stderr.on("data", (chunk) => {
|
|
32
|
+
stderr += chunk.toString();
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
child.on("error", reject);
|
|
37
|
+
child.on("close", (code) => {
|
|
38
|
+
if (code !== 0) {
|
|
39
|
+
reject(new S3teError(options.errorCode ?? "ADAPTER_ERROR", `${command} ${args.join(" ")} failed.`, {
|
|
40
|
+
command,
|
|
41
|
+
args,
|
|
42
|
+
code,
|
|
43
|
+
stdout,
|
|
44
|
+
stderr
|
|
45
|
+
}));
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
resolve({ code: code ?? 0, stdout, stderr });
|
|
50
|
+
});
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export async function runAwsCli(args, options = {}) {
|
|
55
|
+
const finalArgs = [...args];
|
|
56
|
+
if (options.profile) {
|
|
57
|
+
finalArgs.unshift(options.profile);
|
|
58
|
+
finalArgs.unshift("--profile");
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
if (options.region) {
|
|
62
|
+
finalArgs.unshift(options.region);
|
|
63
|
+
finalArgs.unshift("--region");
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
return runProcess("aws", finalArgs, {
|
|
67
|
+
cwd: options.cwd,
|
|
68
|
+
env: options.env,
|
|
69
|
+
errorCode: options.errorCode ?? "ADAPTER_ERROR",
|
|
70
|
+
stdio: options.stdio
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export async function ensureAwsCliAvailable(options = {}) {
|
|
75
|
+
try {
|
|
76
|
+
await runProcess("aws", ["--version"], {
|
|
77
|
+
cwd: options.cwd,
|
|
78
|
+
errorCode: "AWS_AUTH_ERROR"
|
|
79
|
+
});
|
|
80
|
+
} catch (error) {
|
|
81
|
+
throw toCliError("AWS CLI is not installed or not available in PATH.", { cause: error.message });
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export async function ensureAwsCredentials({ region, profile, cwd }) {
|
|
86
|
+
try {
|
|
87
|
+
const result = await runAwsCli(["sts", "get-caller-identity", "--output", "json"], {
|
|
88
|
+
region,
|
|
89
|
+
profile,
|
|
90
|
+
cwd,
|
|
91
|
+
errorCode: "AWS_AUTH_ERROR"
|
|
92
|
+
});
|
|
93
|
+
return JSON.parse(result.stdout || "{}");
|
|
94
|
+
} catch (error) {
|
|
95
|
+
throw toCliError("AWS credentials are not configured or not valid.", {
|
|
96
|
+
region,
|
|
97
|
+
profile,
|
|
98
|
+
cause: error.message,
|
|
99
|
+
details: error.details
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
}
|