@aggiovato/yrest 0.1.0 → 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 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 | Default | Description |
51
- |------|---------|-------------|
52
- | `--file` | `db.yml` | Output filename |
53
- | `--sample` | `basic` | Sample data (`basic`, `relational`) |
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 | Default | Description |
71
- |------|---------|-------------|
72
- | `--port` | `3070` | Port to listen on |
73
- | `--host` | `localhost` | Host to bind |
74
- | `--base` | _(none)_ | Prefix for all routes |
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` | Successful GET, PUT, PATCH, DELETE |
115
- | `201` | Successful POST |
116
- | `404` | Resource or id not found |
117
- | `500` | Error reading or writing the YAML file |
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