@nilejs/cli 1.0.2 → 1.1.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 +4 -4
- package/dist/index.js +7 -7
- package/package.json +26 -1
- package/template/README.md +1 -1
- package/template/SKILL.md +12 -13
- package/template/package.json +1 -1
- package/template/src/index.ts +2 -2
- package/template/src/services/tasks/actions/create.ts +7 -7
- package/template/src/services/tasks/actions/delete.ts +6 -6
- package/template/src/services/tasks/actions/get.ts +5 -5
- package/template/src/services/tasks/actions/list.ts +2 -2
- package/template/src/services/tasks/actions/update.ts +8 -8
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 nile-js
|
|
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
CHANGED
|
@@ -72,12 +72,12 @@ const getUserSchema = z.object({
|
|
|
72
72
|
|
|
73
73
|
type GetUserInput = z.infer<typeof getUserSchema>;
|
|
74
74
|
|
|
75
|
-
const getUserHandler = async (
|
|
75
|
+
const getUserHandler = async (data: GetUserInput) => {
|
|
76
76
|
// Implement users.get-user here
|
|
77
|
-
return Ok({ result:
|
|
77
|
+
return Ok({ result: data });
|
|
78
78
|
};
|
|
79
79
|
|
|
80
|
-
export const getUserAction = createAction
|
|
80
|
+
export const getUserAction = createAction({
|
|
81
81
|
name: "get-user",
|
|
82
82
|
description: "GetUser action for users",
|
|
83
83
|
validation: getUserSchema,
|
|
@@ -107,7 +107,7 @@ Every registered action is included in `ServicePayloads`. Actions without a vali
|
|
|
107
107
|
|
|
108
108
|
## Current starter
|
|
109
109
|
|
|
110
|
-
|
|
110
|
+
The starter uses Nile `^1.1.0`, Zod 4, TypeScript 7 and the Drizzle model helpers. The generated layout passes Nile’s strict boot checks. Database setup returns a Result and prevents startup on failure; shutdown drains Nile’s work before closing PGlite. Helpers are available as `utils.createModel`, and Result helpers come from `@nilejs/nile/fp`.
|
|
111
111
|
|
|
112
112
|
Existing apps are not rewritten when the CLI updates. For an older starter, add a service entry point at `src/services/<domain>/index.ts`, register its actions there, and import that service from `services.config.ts`. [Nile’s migration notes](https://github.com/nile-js/nile/blob/main/packages/nile/docs/release-migration.md) describe the current error and startup behavior.
|
|
113
113
|
|
package/dist/index.js
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
import { resolve as resolve6 } from "node:path";
|
|
5
5
|
import { Command } from "commander";
|
|
6
6
|
// package.json
|
|
7
|
-
var version = "1.0.
|
|
7
|
+
var version = "1.0.3";
|
|
8
8
|
|
|
9
9
|
// src/commands/generate-action.ts
|
|
10
10
|
import { resolve } from "node:path";
|
|
@@ -99,12 +99,12 @@ const ${camel}Schema = z.object({
|
|
|
99
99
|
|
|
100
100
|
type ${pascal}Input = z.infer<typeof ${camel}Schema>;
|
|
101
101
|
|
|
102
|
-
const ${camel}Handler = async (
|
|
102
|
+
const ${camel}Handler = async (data: ${pascal}Input) => {
|
|
103
103
|
// Implement ${serviceName}.${actionName} here
|
|
104
|
-
return Ok({ result:
|
|
104
|
+
return Ok({ result: data });
|
|
105
105
|
};
|
|
106
106
|
|
|
107
|
-
export const ${camel}Action = createAction
|
|
107
|
+
export const ${camel}Action = createAction({
|
|
108
108
|
name: "${actionName}",
|
|
109
109
|
description: "${pascal} action for ${serviceName}",
|
|
110
110
|
validation: ${camel}Schema,
|
|
@@ -459,11 +459,11 @@ const sample${pascal}Schema = z.object({
|
|
|
459
459
|
|
|
460
460
|
type Sample${pascal}Input = z.infer<typeof sample${pascal}Schema>;
|
|
461
461
|
|
|
462
|
-
const sample${pascal}Handler = async (
|
|
463
|
-
return Ok({ ${camel}: { name:
|
|
462
|
+
const sample${pascal}Handler = async (data: Sample${pascal}Input) => {
|
|
463
|
+
return Ok({ ${camel}: { name: data.name } });
|
|
464
464
|
};
|
|
465
465
|
|
|
466
|
-
export const sample${pascal}Action = createAction
|
|
466
|
+
export const sample${pascal}Action = createAction({
|
|
467
467
|
name: "sample",
|
|
468
468
|
description: "Sample ${serviceName} action",
|
|
469
469
|
validation: sample${pascal}Schema,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nilejs/cli",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "CLI for scaffolding and generating Nile backend projects",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -10,6 +10,31 @@
|
|
|
10
10
|
"dist",
|
|
11
11
|
"template"
|
|
12
12
|
],
|
|
13
|
+
"homepage": "https://nile-js.github.io/nile/",
|
|
14
|
+
"bugs": {
|
|
15
|
+
"url": "https://github.com/nile-js/nile/issues"
|
|
16
|
+
},
|
|
17
|
+
"repository": {
|
|
18
|
+
"type": "git",
|
|
19
|
+
"url": "git+https://github.com/nile-js/nile.git",
|
|
20
|
+
"directory": "packages/cli"
|
|
21
|
+
},
|
|
22
|
+
"author": "Hussein Kizz",
|
|
23
|
+
"license": "MIT",
|
|
24
|
+
"keywords": [
|
|
25
|
+
"nile",
|
|
26
|
+
"cli",
|
|
27
|
+
"scaffolding",
|
|
28
|
+
"generator",
|
|
29
|
+
"codegen",
|
|
30
|
+
"backend",
|
|
31
|
+
"typescript",
|
|
32
|
+
"bun",
|
|
33
|
+
"zod"
|
|
34
|
+
],
|
|
35
|
+
"publishConfig": {
|
|
36
|
+
"access": "public"
|
|
37
|
+
},
|
|
13
38
|
"dependencies": {
|
|
14
39
|
"commander": "^13.1.0",
|
|
15
40
|
"json-schema-to-zod": "^2.7.0",
|
package/template/README.md
CHANGED
|
@@ -85,7 +85,7 @@ Responses have exactly `status`, `message` and `data`. The default success messa
|
|
|
85
85
|
|
|
86
86
|
## Optional features
|
|
87
87
|
|
|
88
|
-
Keep business logic in actions and ordinary functions. Configure other features when the product needs them: [typed Socket.IO topics](https://nile-js.github.io/nile/guide/features/websockets/), [cron jobs](https://nile-js.github.io/nile/guide/features/cron-jobs/), [rate limits](https://nile-js.github.io/nile/guide/features/rate-limiting/), [queues](https://nile-js.github.io/nile/guide/features/queues-debounce-throttle/) and [telemetry](https://nile-js.github.io/nile/guide/features/telemetry/).
|
|
88
|
+
Keep business logic in actions and ordinary functions. Configure other features when the product needs them: [typed Socket.IO topics](https://nile-js.github.io/nile/guide/features/websockets/), [cron jobs](https://nile-js.github.io/nile/guide/features/cron-jobs/), [rate limits](https://nile-js.github.io/nile/guide/features/rate-limiting/), [queues](https://nile-js.github.io/nile/guide/features/queues-debounce-throttle/) and [telemetry](https://nile-js.github.io/nile/guide/features/telemetry/). On the frontend, `createNileClient` calls actions and sends and receives topics through `nile.socket`.
|
|
89
89
|
|
|
90
90
|
## Adding services
|
|
91
91
|
|
package/template/SKILL.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: nile
|
|
3
|
-
description: Work in a Nile Js backend (@nilejs/nile
|
|
3
|
+
description: Work in a Nile Js backend (@nilejs/nile 2.x). Organize business operations as services and actions with Zod validation, Result returns, hooks, JWT protection and typed clients. Use when adding or changing actions, services, hooks, uploads, topics, schedules or the @nilejs/client calls in a Nile Js project.
|
|
4
4
|
license: MIT
|
|
5
5
|
---
|
|
6
6
|
|
|
@@ -39,7 +39,6 @@ src/
|
|
|
39
39
|
client.ts connection and driver
|
|
40
40
|
models/ persistence operations
|
|
41
41
|
hooks/ shared action policies
|
|
42
|
-
business/ optional reusable domain functions
|
|
43
42
|
generated/ client payload/schema contracts
|
|
44
43
|
```
|
|
45
44
|
|
|
@@ -49,7 +48,7 @@ Structure violations fail startup by default. An application needs `src/index.ts
|
|
|
49
48
|
|
|
50
49
|
## The action pattern
|
|
51
50
|
|
|
52
|
-
|
|
51
|
+
Define a named schema, derive the handler’s data type and pass the named handler to `createAction`. The action type and handler return type are inferred. Use `data` and `context` for the parameters you need; omit unused parameters:
|
|
53
52
|
|
|
54
53
|
```ts
|
|
55
54
|
import { createAction } from "@nilejs/nile";
|
|
@@ -62,15 +61,15 @@ const createProjectSchema = z.object({
|
|
|
62
61
|
|
|
63
62
|
type CreateProjectInput = z.infer<typeof createProjectSchema>;
|
|
64
63
|
|
|
65
|
-
const createProjectHandler = (
|
|
66
|
-
if (
|
|
64
|
+
const createProjectHandler = (data: CreateProjectInput) => {
|
|
65
|
+
if (data.name === "system") {
|
|
67
66
|
return Err("Choose a different project name");
|
|
68
67
|
}
|
|
69
68
|
|
|
70
|
-
return Ok({ project: { name:
|
|
69
|
+
return Ok({ project: { name: data.name } });
|
|
71
70
|
};
|
|
72
71
|
|
|
73
|
-
export const createProjectAction = createAction
|
|
72
|
+
export const createProjectAction = createAction({
|
|
74
73
|
name: "create",
|
|
75
74
|
description: "Create a project",
|
|
76
75
|
validation: createProjectSchema,
|
|
@@ -104,7 +103,7 @@ Action names are unique within a service. Folder names do not create routes; onl
|
|
|
104
103
|
|
|
105
104
|
## Handlers take (data, context)
|
|
106
105
|
|
|
107
|
-
Nile Js calls every handler with two arguments: the validated input and the execution's `NileContext`.
|
|
106
|
+
Nile Js calls every handler with two arguments: the validated input and the execution's `NileContext`. For a named handler, annotate `data` with the schema’s parsed output type and use `context` for its second parameter. Import `NileContext` when you need to annotate it. `createAction` infers its type from the handler; leave off the repeated generic argument and inferred return annotation. Read an optional context with `?.` or explicitly reject its absence before using it.
|
|
108
107
|
|
|
109
108
|
- `context.getSession("rest")` returns the verified JWT identity (`userId`, `organizationId` and other claims) for a protected action.
|
|
110
109
|
- `context.resources` holds what `createNileServer` received (`logger`, `database`).
|
|
@@ -258,7 +257,7 @@ This helper is internal: its failure still needs translation before being return
|
|
|
258
257
|
|
|
259
258
|
- HTTP: `POST /api/services` with `{ "intent": "execute", "service": "projects", "action": "create", "payload": { ... } }`.
|
|
260
259
|
- Client (`@nilejs/client`): `createNileClient<Payloads>({ baseUrl })`, then `await nile.invoke({ service, action, payload })`. Every method returns a Result: `if (result.isErr) { ... return; }`, then read `result.value`. On failure `result.error` is the message and `result.details` holds the server's `data`. `data` is a deprecated alias; do not use it.
|
|
261
|
-
-
|
|
260
|
+
- Topics: define each with `createTopic({ name, data, scope?, canReceive?, canSend? })` and pass `createTopics([...])` to the server `socket` config. A missing `canReceive` or `canSend` denies clients. Connections verify the server `auth` JWT; `user` in the checks is `{ userId, organizationId, claims }` or `undefined`. In actions, `const { socket } = getContext({ topics })`, then `socket.send({ topic, scope?, to?: { userId } | { connectionId }, data })` after the write commits. On the frontend, `nile.socket.receive({ topic, scope, onMessage })` subscribes and returns a Result holding `unsubscribe()`; `nile.socket.send` sends. Sockets do not call actions; use `nile.invoke`.
|
|
262
261
|
- Server code: `await server.invoke({ service, action, payload, credentials? })`. Protected actions need `credentials` with headers.
|
|
263
262
|
- Uploads: `nile.upload({ service, action, files, fields })` for `isSpecial: { contentType: "multipart/form-data" }` actions. A JSON request to such an action returns HTTP 400.
|
|
264
263
|
|
|
@@ -267,7 +266,7 @@ This helper is internal: its failure still needs translation before being return
|
|
|
267
266
|
1. Find the domain in `services.config.ts` and read its `index.ts`. Name the action for the business operation, then define its input schema and named handler.
|
|
268
267
|
2. Keep a short, single-use rule in that handler. Extract ordinary domain functions when a rule is reused, complicated enough to test independently, or coordinates a transaction. Do not create a repository, class or service layer solely because a folder exists.
|
|
269
268
|
3. Put data access in the project’s model convention. `utils.createModel` and `utils.getZodSchema` are optional Drizzle helpers; a handwritten model is also valid. Pass the database or transaction explicitly where transaction ownership matters.
|
|
270
|
-
4. For a growing action, move its private helpers under its action folder’s `modules/`. Put helpers shared by the domain in the service’s `modules/`.
|
|
269
|
+
4. For a growing action, move its private helpers under its action folder’s `modules/`. Put helpers shared by the domain in the service’s `modules/`. A rule another domain also needs stays in the domain that owns it; the other service imports it from there. Do not expose a private helper as an action just to call it.
|
|
271
270
|
5. Register the action in the domain’s `actions` list. An export alone does not make it reachable. Register a new service in the root registry.
|
|
272
271
|
6. Carry validated input into business functions and trusted identity into policy checks. Keep request identity in scoped sessions and execution state, not process-wide context values.
|
|
273
272
|
7. Verify the registered operation through `server.invoke` or a transport when changing validation, permissions or registration. Test a transaction’s rollback and idempotency when those are part of the business guarantee.
|
|
@@ -311,7 +310,7 @@ Read the page for the feature you change before you write code:
|
|
|
311
310
|
- [Cron jobs](https://nile-js.github.io/nile/guide/features/cron-jobs)
|
|
312
311
|
- [Database models](https://nile-js.github.io/nile/guide/features/database-models)
|
|
313
312
|
- [API discovery and schemas](https://nile-js.github.io/nile/guide/features/api-discovery)
|
|
314
|
-
- [HTTP
|
|
313
|
+
- [HTTP and direct calls](https://nile-js.github.io/nile/guide/features/calling-actions)
|
|
315
314
|
- [Retries and utilities](https://nile-js.github.io/nile/guide/features/retries-and-utilities)
|
|
316
315
|
- [Rate limiting](https://nile-js.github.io/nile/guide/features/rate-limiting)
|
|
317
316
|
- [File uploads](https://nile-js.github.io/nile/guide/features/file-uploads)
|
|
@@ -324,7 +323,7 @@ Advanced pages cover handler context, composed hooks, execution options and test
|
|
|
324
323
|
1. Read `services.config.ts`, the target service’s `index.ts` and its actions before you change anything.
|
|
325
324
|
2. Follow the existing pattern in that service. Do not add a second architecture.
|
|
326
325
|
3. Never invent an API. Check the guide, the installed `@nilejs/nile` types in `node_modules`, or the existing code. If it is not there, say so.
|
|
327
|
-
4. Use named schemas
|
|
326
|
+
4. Use named schemas and handlers. Name action parameters `data` and `context`, and hook parameters `hookContext`. Annotate a named handler’s data from the schema; let `createAction` and return types infer the rest. Use braces on every `if`.
|
|
328
327
|
5. Start with business rules in the action’s named handler. Move reusable rules or transaction coordination into ordinary domain functions when that makes them easier to share or test. Keep persistence in models or repositories; keep transaction boundaries explicit.
|
|
329
328
|
6. Typecheck and run the relevant tests after a coherent change. Exercise the registered action through `server.invoke` or a transport when registration, policy or validation changes.
|
|
330
329
|
7. Do not commit, publish or change secrets, `.env` values or deployment settings unless the user asks.
|
|
@@ -337,7 +336,7 @@ Advanced pages cover handler context, composed hooks, execution options and test
|
|
|
337
336
|
- A global before hook's returned value does not replace the payload. Use a local hook to transform input.
|
|
338
337
|
- A local hook does not protect the parent action.
|
|
339
338
|
- `context.set` values are shared by all requests. Never store the current user there.
|
|
340
|
-
- A rate limit or topic
|
|
339
|
+
- A rate limit or topic permission (`canReceive`, `canSend`) that is missing denies or does not apply. Read the feature page for the default.
|
|
341
340
|
- Multiple replicas each keep their own queues, schedules, rate-limit counters and WebSocket subscriptions.
|
|
342
341
|
- JWT failures return fixed messages such as `JWT authentication failed: token expired` or `JWT authentication failed: invalid token`. They never include the token or its claims, so do not add them back in your own logs.
|
|
343
342
|
- Import Results from `@nilejs/nile/fp`, not a separately installed `slang-ts`. Two copies of `slang-ts` produce type errors.
|
package/template/package.json
CHANGED
package/template/src/index.ts
CHANGED
|
@@ -54,12 +54,12 @@ const server = await createNileServer({
|
|
|
54
54
|
onBoot: {
|
|
55
55
|
// The first PGlite start on a slow machine can take longer than the 10 second default.
|
|
56
56
|
maxWaitTime: 30_000,
|
|
57
|
-
fn: async (
|
|
57
|
+
fn: async (context) => {
|
|
58
58
|
const prepared = await pushSchema();
|
|
59
59
|
if (prepared.isErr) {
|
|
60
60
|
return prepared;
|
|
61
61
|
}
|
|
62
|
-
|
|
62
|
+
context.resources?.logger?.info({
|
|
63
63
|
atFunction: "onBoot",
|
|
64
64
|
message: "{{projectName}} booted - PGLite schema ready",
|
|
65
65
|
});
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createAction } from "@nilejs/nile";
|
|
2
|
-
import {
|
|
2
|
+
import { Ok } from "@nilejs/nile/fp";
|
|
3
3
|
import z from "zod";
|
|
4
4
|
import { taskModel } from "@/db/models";
|
|
5
5
|
|
|
@@ -14,23 +14,23 @@ const createTaskSchema = z.object({
|
|
|
14
14
|
|
|
15
15
|
type CreateTaskInput = z.infer<typeof createTaskSchema>;
|
|
16
16
|
|
|
17
|
-
const createTaskHandler = async (
|
|
17
|
+
const createTaskHandler = async (data: CreateTaskInput) => {
|
|
18
18
|
const result = await taskModel.create({
|
|
19
19
|
data: {
|
|
20
|
-
title:
|
|
21
|
-
description:
|
|
22
|
-
status:
|
|
20
|
+
title: data.title,
|
|
21
|
+
description: data.description,
|
|
22
|
+
status: data.status,
|
|
23
23
|
},
|
|
24
24
|
});
|
|
25
25
|
|
|
26
26
|
if (result.isErr) {
|
|
27
|
-
return
|
|
27
|
+
return result;
|
|
28
28
|
}
|
|
29
29
|
|
|
30
30
|
return Ok({ task: result.value });
|
|
31
31
|
};
|
|
32
32
|
|
|
33
|
-
export const createTaskAction = createAction
|
|
33
|
+
export const createTaskAction = createAction({
|
|
34
34
|
name: "create",
|
|
35
35
|
description: "Create a new task",
|
|
36
36
|
validation: createTaskSchema,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createAction } from "@nilejs/nile";
|
|
2
|
-
import {
|
|
2
|
+
import { Ok } from "@nilejs/nile/fp";
|
|
3
3
|
import z from "zod";
|
|
4
4
|
import { taskModel } from "@/db/models";
|
|
5
5
|
|
|
@@ -9,17 +9,17 @@ const deleteTaskSchema = z.object({
|
|
|
9
9
|
|
|
10
10
|
type DeleteTaskInput = z.infer<typeof deleteTaskSchema>;
|
|
11
11
|
|
|
12
|
-
const deleteTaskHandler = async (
|
|
13
|
-
const result = await taskModel.delete(
|
|
12
|
+
const deleteTaskHandler = async (data: DeleteTaskInput) => {
|
|
13
|
+
const result = await taskModel.delete(data.id);
|
|
14
14
|
|
|
15
15
|
if (result.isErr) {
|
|
16
|
-
return
|
|
16
|
+
return result;
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
-
return Ok({ deleted: true, id:
|
|
19
|
+
return Ok({ deleted: true, id: data.id });
|
|
20
20
|
};
|
|
21
21
|
|
|
22
|
-
export const deleteTaskAction = createAction
|
|
22
|
+
export const deleteTaskAction = createAction({
|
|
23
23
|
name: "delete",
|
|
24
24
|
description: "Delete a task by ID",
|
|
25
25
|
validation: deleteTaskSchema,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createAction } from "@nilejs/nile";
|
|
2
|
-
import {
|
|
2
|
+
import { Ok } from "@nilejs/nile/fp";
|
|
3
3
|
import z from "zod";
|
|
4
4
|
import { taskModel } from "@/db/models";
|
|
5
5
|
|
|
@@ -9,17 +9,17 @@ const getTaskSchema = z.object({
|
|
|
9
9
|
|
|
10
10
|
type GetTaskInput = z.infer<typeof getTaskSchema>;
|
|
11
11
|
|
|
12
|
-
const getTaskHandler = async (
|
|
13
|
-
const result = await taskModel.findById(
|
|
12
|
+
const getTaskHandler = async (data: GetTaskInput) => {
|
|
13
|
+
const result = await taskModel.findById(data.id);
|
|
14
14
|
|
|
15
15
|
if (result.isErr) {
|
|
16
|
-
return
|
|
16
|
+
return result;
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
return Ok({ task: result.value });
|
|
20
20
|
};
|
|
21
21
|
|
|
22
|
-
export const getTaskAction = createAction
|
|
22
|
+
export const getTaskAction = createAction({
|
|
23
23
|
name: "get",
|
|
24
24
|
description: "Get a task by ID",
|
|
25
25
|
validation: getTaskSchema,
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { createAction } from "@nilejs/nile";
|
|
2
|
-
import {
|
|
2
|
+
import { Ok } from "@nilejs/nile/fp";
|
|
3
3
|
import { taskModel } from "@/db/models";
|
|
4
4
|
|
|
5
5
|
const listTasksHandler = async () => {
|
|
6
6
|
const result = await taskModel.findAll();
|
|
7
7
|
|
|
8
8
|
if (result.isErr) {
|
|
9
|
-
return
|
|
9
|
+
return result;
|
|
10
10
|
}
|
|
11
11
|
|
|
12
12
|
return Ok({ tasks: result.value });
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createAction } from "@nilejs/nile";
|
|
2
|
-
import {
|
|
2
|
+
import { Ok } from "@nilejs/nile/fp";
|
|
3
3
|
import z from "zod";
|
|
4
4
|
import { taskModel } from "@/db/models";
|
|
5
5
|
|
|
@@ -12,25 +12,25 @@ const updateTaskSchema = z.object({
|
|
|
12
12
|
|
|
13
13
|
type UpdateTaskInput = z.infer<typeof updateTaskSchema>;
|
|
14
14
|
|
|
15
|
-
const updateTaskHandler = async (
|
|
15
|
+
const updateTaskHandler = async (data: UpdateTaskInput) => {
|
|
16
16
|
// Fields left out of the request stay undefined and are not changed.
|
|
17
17
|
const result = await taskModel.update({
|
|
18
|
-
id:
|
|
18
|
+
id: data.id,
|
|
19
19
|
data: {
|
|
20
|
-
title:
|
|
21
|
-
description:
|
|
22
|
-
status:
|
|
20
|
+
title: data.title,
|
|
21
|
+
description: data.description,
|
|
22
|
+
status: data.status,
|
|
23
23
|
},
|
|
24
24
|
});
|
|
25
25
|
|
|
26
26
|
if (result.isErr) {
|
|
27
|
-
return
|
|
27
|
+
return result;
|
|
28
28
|
}
|
|
29
29
|
|
|
30
30
|
return Ok({ task: result.value });
|
|
31
31
|
};
|
|
32
32
|
|
|
33
|
-
export const updateTaskAction = createAction
|
|
33
|
+
export const updateTaskAction = createAction({
|
|
34
34
|
name: "update",
|
|
35
35
|
description: "Update an existing task",
|
|
36
36
|
validation: updateTaskSchema,
|