@nilejs/nile 0.0.5 → 0.0.7

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
@@ -1,92 +1,379 @@
1
- # @nilejs/nile
1
+ # 🌊 Nile
2
2
 
3
3
  [![NPM Version](https://img.shields.io/npm/v/@nilejs/nile.svg)](https://www.npmjs.com/package/@nilejs/nile)
4
4
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
5
+ [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](./CONTRIBUTING.md)
5
6
 
6
- The core framework package for Nile, a TypeScript-first, service and actions oriented backend framework.
7
+ ![TypeScript](https://img.shields.io/badge/TypeScript-3178C6?logo=typescript&logoColor=white)
8
+ ![Hono](https://img.shields.io/badge/Hono-E36002?logo=hono&logoColor=white)
9
+ ![Zod](https://img.shields.io/badge/Zod-3E67B1?logo=zod&logoColor=white)
10
+ ![Drizzle](https://img.shields.io/badge/Drizzle-C5F74F?logo=drizzle&logoColor=black)
11
+
12
+ TypeScript-first, service and actions oriented backend framework for building modern, fast, safe and AI-ready backends with simplest developer experience possible.
13
+
14
+ You define actions, group them into services, and get a predictable API with validation, error handling, and schema export, no route definitions, no controllers, no middleware chains and rest api conventions to care about, just your business logic. And it's all AI agent-ready out of the box, progressively discoverable and tool calling ready with validation.
7
15
 
8
16
  ## Install
9
17
 
18
+ > Or View Full Docs -> [nile-js.github.io/nile](https://nile-js.github.io/nile)
19
+
20
+ ### Scaffold a project (recommended)
21
+
22
+ The fastest way to start is with the CLI. It creates a working project with services, database, and dev tooling pre-configured:
23
+
24
+ ```bash
25
+ npx @nilejs/cli new my-app
26
+ ```
27
+
28
+ ```bash
29
+ cd my-app && bun install && bun run dev
30
+ ```
31
+
32
+ The CLI also includes generators for adding services, actions, and extracting Zod schemas with TypeScript types. See [`@nilejs/cli`](https://github.com/nile-js/nile/tree/main/packages/cli) for details.
33
+
34
+ ### Client Library
35
+
36
+ For frontend applications, use the standalone, type-safe client:
37
+
38
+ ```bash
39
+ bun add @nilejs/client
40
+ ```
41
+
42
+ See [`@nilejs/client`](https://github.com/nile-js/nile/tree/main/packages/client) for full usage and type-safe action invocation.
43
+
44
+ ### Manual install
45
+
10
46
  ```bash
11
47
  bun add @nilejs/nile zod slang-ts
12
48
  ```
13
49
 
50
+ ```bash
51
+ npm install @nilejs/nile zod slang-ts
52
+ ```
53
+
14
54
  If using the database layer (`createModel`, `getZodSchema`):
15
55
 
16
56
  ```bash
17
57
  bun add drizzle-orm drizzle-zod
18
58
  ```
19
59
 
20
- ## What's in this package
21
-
22
- This package provides the server runtime, engine, and all core utilities:
23
-
24
- - **`createNileServer`** - Server factory that wires up services, hooks, and REST transport
25
- - **`createService` / `createServices`** - Service definition factories
26
- - **`createAction` / `createActions`** - Action definition factories with Zod validation
27
- - **`createModel`** - Type-safe CRUD model factory for Drizzle tables
28
- - **`getContext`** - Access the shared NileContext (dependency injection, resources, sessions)
29
- - **Engine** - Pipeline execution with before/after hooks, validation, and Result-based flow
30
- - **REST layer** - Single-endpoint `POST /services` transport built on Hono
31
- - **CORS** - Configurable origin control with per-route rules
32
- - **Logging** - Structured log persistence with chunking support
33
- - **Error handling** - `handleError` utility with Result pattern enforcement
60
+ ## Quick Start
34
61
 
35
- ## Quick example
62
+ ### 1. Define an action
36
63
 
37
64
  ```typescript
38
- import { createNileServer, createAction } from "@nilejs/nile";
65
+ // services/tasks/create.ts
39
66
  import { Ok } from "slang-ts";
40
67
  import z from "zod";
68
+ import { createAction, type Action } from "@nilejs/nile";
41
69
 
42
- const greet = createAction({
43
- name: "greet",
44
- description: "Say hello",
45
- validation: z.object({ name: z.string() }),
46
- handler: (data) => Ok({ message: `Hello, ${data.name}!` }),
70
+ const createTaskSchema = z.object({
71
+ title: z.string().min(1, "Title is required"),
72
+ status: z.enum(["pending", "in-progress", "done"]).default("pending"),
47
73
  });
48
74
 
75
+ const createTaskHandler = (data: Record<string, unknown>) => {
76
+ const task = {
77
+ id: crypto.randomUUID(),
78
+ title: data.title as string,
79
+ status: (data.status as string) ?? "pending",
80
+ };
81
+ return Ok({ task });
82
+ };
83
+
84
+ export const createTaskAction: Action = createAction({
85
+ name: "create",
86
+ description: "Create a new task",
87
+ validation: createTaskSchema,
88
+ handler: createTaskHandler,
89
+ });
90
+ ```
91
+
92
+ ### 2. Group actions into a service
93
+
94
+ ```typescript
95
+ // services/config.ts
96
+ import { type Services } from "@nilejs/nile";
97
+ import { createTaskAction } from "./tasks/create";
98
+ import { listTaskAction } from "./tasks/list";
99
+
100
+ export const services: Services = [
101
+ {
102
+ name: "tasks",
103
+ description: "Task management",
104
+ actions: [createTaskAction, listTaskAction],
105
+ },
106
+ ];
107
+ ```
108
+
109
+ ### 3. Start the server
110
+
111
+ ```typescript
112
+ // server.ts
113
+ import { createNileServer } from "@nilejs/nile";
114
+ import { services } from "./services/config";
115
+
49
116
  const server = createNileServer({
50
117
  serverName: "my-app",
51
- services: [{ name: "hello", description: "Greeting service", actions: [greet] }],
52
- rest: { baseUrl: "/api", port: 8000 },
118
+ services,
119
+ rest: {
120
+ baseUrl: "/api",
121
+ port: 8000,
122
+ },
53
123
  });
54
124
 
55
125
  if (server.rest) {
56
- Bun.serve({ fetch: server.rest.app.fetch, port: 8000 });
126
+ const { fetch } = server.rest.app;
127
+ Bun.serve({ fetch, port: 8000 });
128
+ console.log("Server running at http://localhost:8000");
129
+ }
130
+ ```
131
+
132
+ ### 4. Call it
133
+
134
+ ```bash
135
+ curl -X POST http://localhost:8000/api/services \
136
+ -H "Content-Type: application/json" \
137
+ -d '{
138
+ "intent": "execute",
139
+ "service": "tasks",
140
+ "action": "create",
141
+ "payload": { "title": "Ship it", "status": "pending" }
142
+ }'
143
+ ```
144
+
145
+ ```json
146
+ {
147
+ "status": true,
148
+ "message": "Action 'tasks.create' executed",
149
+ "data": {
150
+ "task": {
151
+ "id": "a1b2c3d4-...",
152
+ "title": "Ship it",
153
+ "status": "pending"
154
+ }
155
+ }
156
+ }
157
+ ```
158
+
159
+ ## Why Nile
160
+
161
+ **You write business logic. Nile handles the rest.**
162
+
163
+ Most backend frameworks make you think about HTTP verbs, route trees, middleware ordering, and error serialization before you write a single line of domain logic. Nile removes that ceremony. You define actions, plain functions that take data and return results, and they become callable over a single POST endpoint or other protocols such as web sockets or rpc within your codebase.
164
+
165
+ **Nothing crashes silently.** Every action handler returns `Ok(data)` or `Err(message)` using the Result pattern from [Slang Ts](github.com/Hussseinkizz/slang) Functional programming utilities library. So no unhandled exceptions, no try-catch spaghetti, no mystery 500s. Your control flow is predictable by design and safe.
166
+
167
+ **AI agents can call your API without adapters.** Every action with a Zod validation schema automatically exports its parameters as JSON Schema. An LLM can discover your services, read the schemas, and make tool calls, no custom integration code required.
168
+
169
+ **Your database, your choice.** Nile doesn't own your data layer. When you want structured DB access, nile works with drizzle orm and any databases it supports, postgres, pglite or sqlite and more, but also provides utilities like `createModel` for simplifying type-safe CRUD operations for any Drizzle table with auto-validation, error handling, and pagination built in to reduce boilerplate. You can also use any other database library or raw queries in your action handlers, it's all up to you.
170
+
171
+ **There's more to Nile** than just the core server, you get service and action based architecture, powerful hook system, structured logging and enforced error handling, rate limiting, CORS control, uploads, single context for dependency injection or sharing, and more. And you don't need a Phd to understand how to use any of them.
172
+
173
+ ## Core Concepts
174
+
175
+ Nile uses a single POST endpoint for everything. Instead of mapping HTTP verbs to routes, you send a JSON body with an **intent** that tells the server what you want to do.
176
+
177
+ Every request has the same shape:
178
+
179
+ ```typescript
180
+ {
181
+ intent: "explore" | "execute" | "schema",
182
+ service: string, // service name, or "*" for all
183
+ action: string, // action name, or "*" for all
184
+ payload: object // data for the action (use {} when not needed)
185
+ }
186
+ ```
187
+
188
+ Every response has the same shape:
189
+
190
+ ```typescript
191
+ {
192
+ status: boolean, // true = success, false = error
193
+ message: string, // human-readable description
194
+ data: object // result payload, or {} on error
57
195
  }
58
196
  ```
59
197
 
60
- ## Project structure
198
+ ### Explore, discover what's available
61
199
 
200
+ List all services:
201
+
202
+ ```bash
203
+ curl -X POST http://localhost:8000/api/services \
204
+ -H "Content-Type: application/json" \
205
+ -d '{ "intent": "explore", "service": "*", "action": "*", "payload": {} }'
62
206
  ```
63
- packages/nile/
64
- index.ts # Public API exports
65
- engine/ # Service registry, action pipeline, hook execution
66
- nile/ # Server factory, context management
67
- rest/ # Hono-based REST transport, intent handlers, middleware
68
- cors/ # CORS configuration and resolution
69
- logging/ # Structured log creation and retrieval
70
- utils/ # Error handling, diagnostics, DB model utilities
207
+
208
+ ```json
209
+ {
210
+ "status": true,
211
+ "message": "Available services",
212
+ "data": {
213
+ "result": [
214
+ {
215
+ "name": "tasks",
216
+ "description": "Task management",
217
+ "actions": ["create", "list"]
218
+ }
219
+ ]
220
+ }
221
+ }
71
222
  ```
72
223
 
73
- ## Development
224
+ Drill into a service to see its actions:
74
225
 
75
226
  ```bash
76
- # Run tests
77
- bun run test:run
227
+ curl -X POST http://localhost:8000/api/services \
228
+ -H "Content-Type: application/json" \
229
+ -d '{ "intent": "explore", "service": "tasks", "action": "*", "payload": {} }'
230
+ ```
78
231
 
79
- # Build
80
- bun run build
232
+ ```json
233
+ {
234
+ "status": true,
235
+ "message": "Actions for 'tasks'",
236
+ "data": {
237
+ "result": [
238
+ {
239
+ "name": "create",
240
+ "description": "Create a new task",
241
+ "isProtected": false,
242
+ "validation": true
243
+ }
244
+ ]
245
+ }
246
+ }
247
+ ```
248
+
249
+ ### Execute, call an action
250
+
251
+ This is the same call shown in Quick Start. Send `"intent": "execute"` with the service, action, and payload. The action's Zod schema validates the payload before the handler runs. If validation fails, you get a clear error:
252
+
253
+ ```json
254
+ {
255
+ "status": false,
256
+ "message": "Validation failed: title - Required",
257
+ "data": {}
258
+ }
259
+ ```
81
260
 
82
- # Lint and format
83
- bun run check && bun run fix
261
+ ### Schema, get JSON Schema for actions
262
+
263
+ Fetch the validation schema for any action as JSON Schema. This is what makes Nile AI-ready, an agent can read these schemas to know exactly what parameters an action accepts.
264
+
265
+ ```bash
266
+ curl -X POST http://localhost:8000/api/services \
267
+ -H "Content-Type: application/json" \
268
+ -d '{ "intent": "schema", "service": "tasks", "action": "create", "payload": {} }'
269
+ ```
270
+
271
+ ```json
272
+ {
273
+ "status": true,
274
+ "message": "Schema for 'tasks.create'",
275
+ "data": {
276
+ "create": {
277
+ "type": "object",
278
+ "properties": {
279
+ "title": { "type": "string", "minLength": 1 },
280
+ "status": { "type": "string", "enum": ["pending", "in-progress", "done"], "default": "pending" }
281
+ },
282
+ "required": ["title"]
283
+ }
284
+ }
285
+ }
84
286
  ```
85
287
 
86
- ## Related packages
288
+ Use `"service": "*", "action": "*"` to get schemas for every action across all services in one call.
289
+
290
+ ### Hooks, intercept and transform
291
+
292
+ Hooks let you run logic before or after an action executes. They work at two levels:
293
+
294
+ **Per-action hooks** point to other registered actions. A hook definition is just a reference, `{ service, action, isCritical }`, so any action can serve as a hook for any other action.
295
+
296
+ ```typescript
297
+ export const createTaskAction: Action = createAction({
298
+ name: "create",
299
+ description: "Create a new task",
300
+ validation: createTaskSchema,
301
+ handler: createTaskHandler,
302
+ hooks: {
303
+ before: [
304
+ { service: "audit", action: "logAccess", isCritical: false }
305
+ ],
306
+ after: [
307
+ { service: "notifications", action: "notify", isCritical: false }
308
+ ]
309
+ },
310
+ });
311
+ ```
312
+
313
+ Before hooks run sequentially and chain, each hook's output becomes the next hook's input. After hooks work the same way, receiving the handler's result.
314
+
315
+ When `isCritical` is `true`, a hook failure stops the pipeline. When `false`, failures are logged and skipped.
316
+
317
+ **Global hooks** run on every action. Define them in your server config:
318
+
319
+ ```typescript
320
+ const server = createNileServer({
321
+ serverName: "my-app",
322
+ services,
323
+ onBeforeActionHandler: ({ nileContext, action, payload }) => {
324
+ // runs before every action, auth checks, logging, etc.
325
+ return Ok(payload);
326
+ },
327
+ onAfterActionHandler: ({ nileContext, action, payload, result }) => {
328
+ // runs after every action, transforms, auditing, etc.
329
+ return result;
330
+ },
331
+ });
332
+ ```
333
+
334
+ The full execution pipeline runs in this order:
335
+
336
+ ```txt
337
+ Global Before Hook
338
+ -> Per-Action Before Hooks (sequential)
339
+ -> Validation (Zod)
340
+ -> Handler
341
+ -> Per-Action After Hooks (sequential)
342
+ -> Global After Hook
343
+ -> Response
344
+ ```
345
+
346
+ Any step returning `Err` short-circuits the pipeline.
347
+
348
+ ## Project Structure
349
+
350
+ ```txt
351
+ my-api/
352
+ server.ts
353
+ services/
354
+ config.ts
355
+ tasks/
356
+ create.ts
357
+ list.ts
358
+ get.ts
359
+ db/
360
+ schema.ts
361
+ client.ts
362
+ models/
363
+ tasks.ts
364
+ ```
365
+
366
+ ## Contributing
367
+
368
+ > First developed by Hussein Kizz at [Nile Squad Labz](https://nilesquad.com) to power our own B2B saas products and services, and now open-sourced for the community. Over 1 year in the making, to now powering Agentic backends and open for community contributions.
369
+
370
+ Contributions are welcome.
87
371
 
88
- - [`@nilejs/cli`](https://github.com/nile-js/nile/tree/main/packages/cli) - Project scaffolding and code generation
89
- - [`@nilejs/client`](https://github.com/nile-js/nile/tree/main/packages/client) - Type-safe frontend client
372
+ 1. Fork the repository
373
+ 2. Create your feature branch (`git checkout -b feature/your-feature`)
374
+ 3. Commit your changes (`git commit -m 'Add your feature'`)
375
+ 4. Push to the branch (`git push origin feature/your-feature`)
376
+ 5. Open a Pull Request
90
377
 
91
378
  ## License
92
379