@aggiovato/yrest 0.1.1 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +201 -28
- package/dist/cli/index.js +569 -59
- package/dist/cli/index.mjs +569 -59
- package/dist/index.d.mts +124 -3
- package/dist/index.d.ts +124 -3
- package/dist/index.js +494 -44
- package/dist/index.mjs +494 -44
- package/package.json +13 -4
package/README.md
CHANGED
|
@@ -7,23 +7,23 @@ Define your data in a `db.yml` file and get a fully functional CRUD REST API in
|
|
|
7
7
|
## Install
|
|
8
8
|
|
|
9
9
|
```bash
|
|
10
|
-
npm install -D yrest
|
|
10
|
+
npm install -D @aggiovato/yrest
|
|
11
11
|
```
|
|
12
12
|
|
|
13
13
|
Or run directly with npx:
|
|
14
14
|
|
|
15
15
|
```bash
|
|
16
|
-
npx yrest serve db.yml
|
|
16
|
+
npx @aggiovato/yrest serve db.yml
|
|
17
17
|
```
|
|
18
18
|
|
|
19
19
|
## Quick start
|
|
20
20
|
|
|
21
21
|
```bash
|
|
22
22
|
# Create a sample db.yml in the current directory
|
|
23
|
-
npx yrest init
|
|
23
|
+
npx @aggiovato/yrest init
|
|
24
24
|
|
|
25
25
|
# Start the server
|
|
26
|
-
npx yrest serve db.yml
|
|
26
|
+
npx @aggiovato/yrest serve db.yml
|
|
27
27
|
```
|
|
28
28
|
|
|
29
29
|
```txt
|
|
@@ -41,18 +41,19 @@ Resources (base: /):
|
|
|
41
41
|
Creates a sample `db.yml` in the current directory.
|
|
42
42
|
|
|
43
43
|
```bash
|
|
44
|
-
yrest init # basic sample (default)
|
|
45
|
-
yrest init --sample relational # with _rel relations
|
|
46
|
-
yrest init --file api.yml # custom filename
|
|
47
|
-
yrest init --sample relational --file api.yml
|
|
44
|
+
npx @aggiovato/yrest init # basic sample (default)
|
|
45
|
+
npx @aggiovato/yrest init --sample relational # with _rel relations
|
|
46
|
+
npx @aggiovato/yrest init --file api.yml # custom filename
|
|
47
|
+
npx @aggiovato/yrest init --sample relational --file api.yml
|
|
48
48
|
```
|
|
49
49
|
|
|
50
|
-
| Flag
|
|
51
|
-
|
|
52
|
-
| `--file`
|
|
53
|
-
| `--sample` | `basic`
|
|
50
|
+
| Flag | Default | Description |
|
|
51
|
+
| ---------- | -------- | ----------------------------------- |
|
|
52
|
+
| `--file` | `db.yml` | Output filename |
|
|
53
|
+
| `--sample` | `basic` | Sample data (`basic`, `relational`) |
|
|
54
54
|
|
|
55
55
|
**Samples:**
|
|
56
|
+
|
|
56
57
|
- `basic` — two independent collections: `users` and `products`
|
|
57
58
|
- `relational` — three collections with `_rel` relationships: `users`, `posts` and `comments`
|
|
58
59
|
|
|
@@ -61,17 +62,17 @@ yrest init --sample relational --file api.yml
|
|
|
61
62
|
Starts the mock server.
|
|
62
63
|
|
|
63
64
|
```bash
|
|
64
|
-
yrest serve db.yml
|
|
65
|
-
yrest serve db.yml --port 3001
|
|
66
|
-
yrest serve db.yml --host 0.0.0.0
|
|
67
|
-
yrest serve db.yml --base /api
|
|
65
|
+
npx @aggiovato/yrest serve db.yml
|
|
66
|
+
npx @aggiovato/yrest serve db.yml --port 3001
|
|
67
|
+
npx @aggiovato/yrest serve db.yml --host 0.0.0.0
|
|
68
|
+
npx @aggiovato/yrest serve db.yml --base /api
|
|
68
69
|
```
|
|
69
70
|
|
|
70
|
-
| Flag
|
|
71
|
-
|
|
72
|
-
| `--port` | `3070`
|
|
73
|
-
| `--host` | `localhost` | Host to bind
|
|
74
|
-
| `--base` | _(none)_
|
|
71
|
+
| Flag | Default | Description |
|
|
72
|
+
| -------- | ----------- | --------------------- |
|
|
73
|
+
| `--port` | `3070` | Port to listen on |
|
|
74
|
+
| `--host` | `localhost` | Host to bind |
|
|
75
|
+
| `--base` | _(none)_ | Prefix for all routes |
|
|
75
76
|
|
|
76
77
|
## Database format
|
|
77
78
|
|
|
@@ -107,14 +108,82 @@ DELETE /users/:id Delete
|
|
|
107
108
|
|
|
108
109
|
With `--base /api` all routes are prefixed: `/api/users`, `/api/users/:id`, etc.
|
|
109
110
|
|
|
111
|
+
## Query params
|
|
112
|
+
|
|
113
|
+
All query params can be combined freely.
|
|
114
|
+
|
|
115
|
+
### Filtering
|
|
116
|
+
|
|
117
|
+
Return only items that match a field value:
|
|
118
|
+
|
|
119
|
+
```txt
|
|
120
|
+
GET /users?name=Ana
|
|
121
|
+
GET /users?role=admin&active=true
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
Comparison is case-sensitive and converts types to string (`?id=1` matches numeric `id: 1`).
|
|
125
|
+
|
|
126
|
+
### Sorting
|
|
127
|
+
|
|
128
|
+
```txt
|
|
129
|
+
GET /users?_sort=name # ascending (default)
|
|
130
|
+
GET /users?_sort=name&_order=desc # descending
|
|
131
|
+
GET /users?_sort=id&_order=asc
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
String fields are compared case-insensitively. Items missing the sort field are pushed to the end.
|
|
135
|
+
|
|
136
|
+
### Pagination
|
|
137
|
+
|
|
138
|
+
```txt
|
|
139
|
+
GET /users?_page=1&_limit=10 # page 1, 10 items per page
|
|
140
|
+
GET /users?_limit=5 # first 5 items
|
|
141
|
+
GET /users?_page=2&_limit=5 # items 6–10
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
When pagination is active, the response includes an `X-Total-Count` header with the total number of items before pagination (after any active filter).
|
|
145
|
+
|
|
146
|
+
### Combined example
|
|
147
|
+
|
|
148
|
+
```txt
|
|
149
|
+
GET /users?role=admin&_sort=name&_order=asc&_page=1&_limit=5
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
Returns the first 5 admin users sorted alphabetically by name.
|
|
153
|
+
|
|
154
|
+
## Relational data
|
|
155
|
+
|
|
156
|
+
Use `_rel` to declare foreign key relationships between collections:
|
|
157
|
+
|
|
158
|
+
```yaml
|
|
159
|
+
_rel:
|
|
160
|
+
posts:
|
|
161
|
+
userId: users
|
|
162
|
+
|
|
163
|
+
users:
|
|
164
|
+
- id: 1
|
|
165
|
+
name: Ana
|
|
166
|
+
|
|
167
|
+
posts:
|
|
168
|
+
- id: 1
|
|
169
|
+
title: First post
|
|
170
|
+
userId: 1
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
This enables nested routes:
|
|
174
|
+
|
|
175
|
+
```txt
|
|
176
|
+
GET /users/1/posts # all posts where userId === 1
|
|
177
|
+
```
|
|
178
|
+
|
|
110
179
|
## HTTP responses
|
|
111
180
|
|
|
112
|
-
| Status | When
|
|
113
|
-
|
|
114
|
-
| `200`
|
|
115
|
-
| `201`
|
|
116
|
-
| `404`
|
|
117
|
-
| `500`
|
|
181
|
+
| Status | When |
|
|
182
|
+
| ------ | -------------------------------------- |
|
|
183
|
+
| `200` | Successful GET, PUT, PATCH, DELETE |
|
|
184
|
+
| `201` | Successful POST |
|
|
185
|
+
| `404` | Resource or id not found |
|
|
186
|
+
| `500` | Error reading or writing the YAML file |
|
|
118
187
|
|
|
119
188
|
DELETE returns the deleted item (useful for debugging).
|
|
120
189
|
|
|
@@ -134,7 +203,10 @@ CORS is enabled by default, so you can call the API from any frontend running on
|
|
|
134
203
|
|
|
135
204
|
```ts
|
|
136
205
|
// List
|
|
137
|
-
const users = await fetch("http://localhost:3070/users").then(r => r.json());
|
|
206
|
+
const users = await fetch("http://localhost:3070/users").then((r) => r.json());
|
|
207
|
+
|
|
208
|
+
// Filter + sort + paginate
|
|
209
|
+
const res = await fetch("http://localhost:3070/users?role=admin&_sort=name&_page=1&_limit=10");
|
|
138
210
|
|
|
139
211
|
// Create
|
|
140
212
|
await fetch("http://localhost:3070/users", {
|
|
@@ -164,6 +236,107 @@ await fetch("http://localhost:3070/users/1", { method: "DELETE" });
|
|
|
164
236
|
}
|
|
165
237
|
```
|
|
166
238
|
|
|
239
|
+
---
|
|
240
|
+
|
|
241
|
+
## Contributing
|
|
242
|
+
|
|
243
|
+
### Prerequisites
|
|
244
|
+
|
|
245
|
+
- Node.js >= 20
|
|
246
|
+
- [Task](https://taskfile.dev) — task runner (`brew install go-task` / `scoop install task` / [other methods](https://taskfile.dev/installation/))
|
|
247
|
+
|
|
248
|
+
### Task commands
|
|
249
|
+
|
|
250
|
+
Run `task --list` to see all available commands.
|
|
251
|
+
|
|
252
|
+
#### Development
|
|
253
|
+
|
|
254
|
+
| Command | What it does |
|
|
255
|
+
| ----------------- | ------------------------------------------------------------------------------- |
|
|
256
|
+
| `task test` | Runs the full test suite once |
|
|
257
|
+
| `task test:watch` | Runs tests in watch mode — reruns on every file change |
|
|
258
|
+
| `task build` | Compiles TypeScript to `dist/` via tsup |
|
|
259
|
+
| `task dev` | Builds once, then starts watch-build + server from `dist/` in parallel |
|
|
260
|
+
| `task serve:dist` | Builds and starts the server from the local `dist/` |
|
|
261
|
+
| `task serve:npx` | Starts the version currently published on npm (useful to compare against local) |
|
|
262
|
+
|
|
263
|
+
#### Release
|
|
264
|
+
|
|
265
|
+
| Command | What it does |
|
|
266
|
+
| -------------------- | -------------------------------------------------------------- |
|
|
267
|
+
| `task release:patch` | Bumps `x.x.N`, creates a git commit and tag |
|
|
268
|
+
| `task release:minor` | Bumps `x.N.0`, creates a git commit and tag |
|
|
269
|
+
| `task release:major` | Bumps `N.0.0`, creates a git commit and tag |
|
|
270
|
+
| `task publish` | Runs tests + build and publishes to npm (requires `npm login`) |
|
|
271
|
+
|
|
272
|
+
### Development workflow
|
|
273
|
+
|
|
274
|
+
**Day-to-day work:**
|
|
275
|
+
|
|
276
|
+
```bash
|
|
277
|
+
task test:watch # keep this running in one terminal
|
|
278
|
+
task dev # keep this running in another terminal
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
`test:watch` reruns the suite on every save so you catch regressions immediately. `dev` rebuilds and serves so you can call the endpoints manually while you work.
|
|
282
|
+
|
|
283
|
+
**Before committing:**
|
|
284
|
+
|
|
285
|
+
```bash
|
|
286
|
+
task test # confirm everything passes
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
The test suite covers all routes, filters, sorting, pagination and CRUD operations. Do not commit with failing tests.
|
|
290
|
+
|
|
291
|
+
**Good practices:**
|
|
292
|
+
|
|
293
|
+
- Write tests for every new feature or bug fix before opening a PR.
|
|
294
|
+
- Keep `db.yml` in a valid state — it is used as the default file when running local servers.
|
|
295
|
+
- `dist/` is gitignored and generated at build time; never commit it manually.
|
|
296
|
+
- Version bumps are done with `task release:*`, not by editing `package.json` directly — the Task command also creates the git tag that triggers the publish pipeline.
|
|
297
|
+
|
|
298
|
+
### Release workflow
|
|
299
|
+
|
|
300
|
+
Releases are fully automated via GitHub Actions once a version tag is pushed:
|
|
301
|
+
|
|
302
|
+
```bash
|
|
303
|
+
# 1. Make sure all tests pass
|
|
304
|
+
task test
|
|
305
|
+
|
|
306
|
+
# 2. Bump the version (choose one)
|
|
307
|
+
task release:patch # bug fixes
|
|
308
|
+
task release:minor # new features, backwards compatible
|
|
309
|
+
task release:major # breaking changes
|
|
310
|
+
|
|
311
|
+
# 3. Push the commit and the tag
|
|
312
|
+
git push && git push --tags
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
Step 3 triggers two GitHub Actions pipelines automatically (no manual action needed after the push):
|
|
316
|
+
|
|
317
|
+
- **CI** — runs on every push to `main` and on every PR. Executes typecheck + tests on Node 20 and Node 22.
|
|
318
|
+
- **Publish** — runs only when a `v*` tag is pushed. Runs tests + build and publishes to npm using Trusted Publishing (no tokens stored as secrets).
|
|
319
|
+
|
|
320
|
+
### CI/CD pipelines
|
|
321
|
+
|
|
322
|
+
```
|
|
323
|
+
push to main / PR open
|
|
324
|
+
│
|
|
325
|
+
▼
|
|
326
|
+
[CI workflow]
|
|
327
|
+
├── Node 20: typecheck + tests
|
|
328
|
+
└── Node 22: typecheck + tests
|
|
329
|
+
|
|
330
|
+
push tag v*
|
|
331
|
+
│
|
|
332
|
+
▼
|
|
333
|
+
[Publish workflow]
|
|
334
|
+
├── tests + build (via prepublishOnly)
|
|
335
|
+
└── npm publish --provenance (via Trusted Publishing / OIDC)
|
|
336
|
+
```
|
|
337
|
+
|
|
338
|
+
---
|
|
339
|
+
|
|
167
340
|
## License
|
|
168
341
|
|
|
169
342
|
MIT
|