nural 0.3.8 → 0.3.10
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/dist/index.cjs +124 -114
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +128 -129
- package/dist/index.d.ts +128 -129
- package/dist/index.js +123 -114
- package/dist/index.js.map +1 -1
- package/package.json +10 -18
- package/README.md +0 -446
- package/dist/cli/index.cjs +0 -221
- package/dist/cli/index.cjs.map +0 -1
- package/dist/cli/index.d.cts +0 -2
- package/dist/cli/index.d.ts +0 -2
- package/dist/cli/index.js +0 -212
- package/dist/cli/index.js.map +0 -1
package/README.md
DELETED
|
@@ -1,446 +0,0 @@
|
|
|
1
|
-
<p align="center">
|
|
2
|
-
<picture>
|
|
3
|
-
<source media="(prefers-color-scheme: dark)" srcset="assets/logo-dark-mode.png">
|
|
4
|
-
<source media="(prefers-color-scheme: light)" srcset="assets/logo-light-mode.png">
|
|
5
|
-
<img alt="Nural Logo" src="assets/logo-light-mode.png" width="300">
|
|
6
|
-
</picture>
|
|
7
|
-
</p>
|
|
8
|
-
|
|
9
|
-
# Nural
|
|
10
|
-
|
|
11
|
-
<p align="center">
|
|
12
|
-
<strong>The intelligent, schema-first REST framework for Node.js</strong>
|
|
13
|
-
</p>
|
|
14
|
-
|
|
15
|
-
<p align="center">
|
|
16
|
-
<a href="https://www.npmjs.com/package/ "><img src="https://img.shields.io/npm/v/nural.svg" alt="npm version"></a>
|
|
17
|
-
<a href="https://github.com/ErrorX407/nural/actions/workflows/ci.yml"><img src="https://github.com/ErrorX407/nural/actions/workflows/ci.yml/badge.svg" alt="Build Status"></a>
|
|
18
|
-
<img src="https://img.shields.io/npm/l/nural.svg" alt="license">
|
|
19
|
-
<a href="https://www.npmjs.com/package/nural"><img src="https://img.shields.io/npm/dm/nural.svg" alt="Downloads"></a>
|
|
20
|
-
</p>
|
|
21
|
-
|
|
22
|
-
---
|
|
23
|
-
|
|
24
|
-
## Features
|
|
25
|
-
|
|
26
|
-
- ⚡ **Type-Safe** – End-to-end TypeScript inference
|
|
27
|
-
- 📝 **Auto Documentation** – OpenAPI spec & Scalar UI out-of-the-box
|
|
28
|
-
- 🛡️ **Validation** – Zod-powered input/output validation
|
|
29
|
-
- 🔄 **Response Mapping** – Auto-strip unlisted fields (no data leaks!)
|
|
30
|
-
- 🔌 **Multi-Framework** – Works with Express & Fastify
|
|
31
|
-
- 🎯 **Middleware Context** – Type-safe context injection
|
|
32
|
-
- 🔒 **Built-in Security** – CORS & Helmet with zero dependencies
|
|
33
|
-
|
|
34
|
-
---
|
|
35
|
-
|
|
36
|
-
## Installation
|
|
37
|
-
|
|
38
|
-
```bash
|
|
39
|
-
npm install nural express
|
|
40
|
-
# or
|
|
41
|
-
npm install nural fastify
|
|
42
|
-
```
|
|
43
|
-
|
|
44
|
-
---
|
|
45
|
-
|
|
46
|
-
## 🛠️ CLI
|
|
47
|
-
|
|
48
|
-
Nural comes with a built-in CLI to help you scaffold projects and generate resources.
|
|
49
|
-
|
|
50
|
-
```bash
|
|
51
|
-
# Create a new project
|
|
52
|
-
npx nural new my-api
|
|
53
|
-
|
|
54
|
-
# Generate resources
|
|
55
|
-
npx nural generate route users
|
|
56
|
-
npx nural generate middleware auth
|
|
57
|
-
npx nural generate service user
|
|
58
|
-
```
|
|
59
|
-
|
|
60
|
-
---
|
|
61
|
-
|
|
62
|
-
## Quick Start
|
|
63
|
-
|
|
64
|
-
```typescript
|
|
65
|
-
import { Nural, createRoute, z } from "nural";
|
|
66
|
-
|
|
67
|
-
// Create app
|
|
68
|
-
const app = new Nural({ framework: "express", docs: true });
|
|
69
|
-
|
|
70
|
-
// Define a route
|
|
71
|
-
const helloRoute = createRoute({
|
|
72
|
-
method: "GET",
|
|
73
|
-
path: "/hello",
|
|
74
|
-
summary: "Health check",
|
|
75
|
-
responses: {
|
|
76
|
-
200: z.object({ message: z.string() }),
|
|
77
|
-
},
|
|
78
|
-
handler: async () => {
|
|
79
|
-
return { message: "Hello from Nural!", secret: "HIDDEN" };
|
|
80
|
-
// ↑ 'secret' is auto-stripped from response!
|
|
81
|
-
},
|
|
82
|
-
});
|
|
83
|
-
|
|
84
|
-
// Register and start
|
|
85
|
-
app.register([helloRoute]);
|
|
86
|
-
app.start(3000);
|
|
87
|
-
// 🚀 Server: http://localhost:3000
|
|
88
|
-
// 📚 Docs: http://localhost:3000/docs
|
|
89
|
-
```
|
|
90
|
-
|
|
91
|
-
---
|
|
92
|
-
|
|
93
|
-
## Validation
|
|
94
|
-
|
|
95
|
-
```typescript
|
|
96
|
-
const userRoute = createRoute({
|
|
97
|
-
method: "POST",
|
|
98
|
-
path: "/users",
|
|
99
|
-
request: {
|
|
100
|
-
body: z.object({
|
|
101
|
-
name: z.string().min(2),
|
|
102
|
-
email: z.string().email(),
|
|
103
|
-
}),
|
|
104
|
-
},
|
|
105
|
-
responses: {
|
|
106
|
-
201: z.object({ id: z.string(), name: z.string() }),
|
|
107
|
-
},
|
|
108
|
-
handler: async ({ body }) => {
|
|
109
|
-
// body is typed as { name: string, email: string }
|
|
110
|
-
return { id: "uuid", name: body.name };
|
|
111
|
-
},
|
|
112
|
-
});
|
|
113
|
-
```
|
|
114
|
-
|
|
115
|
-
---
|
|
116
|
-
|
|
117
|
-
## Middleware
|
|
118
|
-
|
|
119
|
-
```typescript
|
|
120
|
-
import { defineMiddleware } from "nural";
|
|
121
|
-
|
|
122
|
-
const authMiddleware = defineMiddleware(async (req) => {
|
|
123
|
-
const token = req.headers.authorization;
|
|
124
|
-
if (!token) throw new Error("Unauthorized");
|
|
125
|
-
return { user: { id: "123", role: "admin" } };
|
|
126
|
-
});
|
|
127
|
-
|
|
128
|
-
const meRoute = createRoute({
|
|
129
|
-
method: "GET",
|
|
130
|
-
path: "/me",
|
|
131
|
-
middleware: [authMiddleware],
|
|
132
|
-
responses: { 200: z.object({ id: z.string(), role: z.string() }) },
|
|
133
|
-
handler: async ({ user }) => {
|
|
134
|
-
// ↑ 'user' is inferred from middleware!
|
|
135
|
-
return user;
|
|
136
|
-
},
|
|
137
|
-
});
|
|
138
|
-
```
|
|
139
|
-
|
|
140
|
-
---
|
|
141
|
-
|
|
142
|
-
## CORS & Helmet (Built-in Security)
|
|
143
|
-
|
|
144
|
-
```typescript
|
|
145
|
-
// Enable with defaults
|
|
146
|
-
const app = new Nural({
|
|
147
|
-
cors: true,
|
|
148
|
-
helmet: true,
|
|
149
|
-
});
|
|
150
|
-
|
|
151
|
-
// Or with full configuration
|
|
152
|
-
const app = new Nural({
|
|
153
|
-
cors: {
|
|
154
|
-
origin: "https://example.com",
|
|
155
|
-
methods: ["GET", "POST"],
|
|
156
|
-
credentials: true,
|
|
157
|
-
},
|
|
158
|
-
helmet: {
|
|
159
|
-
contentSecurityPolicy: false,
|
|
160
|
-
hsts: { maxAge: 31536000, includeSubDomains: true },
|
|
161
|
-
},
|
|
162
|
-
});
|
|
163
|
-
},
|
|
164
|
-
});
|
|
165
|
-
```
|
|
166
|
-
|
|
167
|
-
---
|
|
168
|
-
|
|
169
|
-
## Unified Exception System
|
|
170
|
-
|
|
171
|
-
Throw standard exceptions anywhere in your code, and Nural automatically formats them into standard JSON error responses.
|
|
172
|
-
|
|
173
|
-
```typescript
|
|
174
|
-
import { NotFoundException, UnauthorizedException } from "nural";
|
|
175
|
-
|
|
176
|
-
// In your service or handler
|
|
177
|
-
if (!user) {
|
|
178
|
-
throw new NotFoundException("User not found");
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
if (!token) {
|
|
182
|
-
throw new UnauthorizedException("Missing token");
|
|
183
|
-
}
|
|
184
|
-
```
|
|
185
|
-
|
|
186
|
-
**Result:**
|
|
187
|
-
|
|
188
|
-
```json
|
|
189
|
-
{
|
|
190
|
-
"statusCode": 404,
|
|
191
|
-
"message": "User not found",
|
|
192
|
-
"error": "Not Found",
|
|
193
|
-
"timestamp": "2026-02-08T12:00:00.000Z"
|
|
194
|
-
}
|
|
195
|
-
```
|
|
196
|
-
|
|
197
|
-
---
|
|
198
|
-
|
|
199
|
-
## Global Error Handler
|
|
200
|
-
|
|
201
|
-
```typescript
|
|
202
|
-
// Enable with defaults (smart error mapping)
|
|
203
|
-
const app = new Nural({ errorHandler: true });
|
|
204
|
-
|
|
205
|
-
// Custom error handler (e.g., Sentry integration)
|
|
206
|
-
const app = new Nural({
|
|
207
|
-
errorHandler: (ctx) => {
|
|
208
|
-
Sentry.captureException(ctx.error);
|
|
209
|
-
return {
|
|
210
|
-
status: 500,
|
|
211
|
-
body: { error: "Something went wrong" },
|
|
212
|
-
};
|
|
213
|
-
},
|
|
214
|
-
});
|
|
215
|
-
|
|
216
|
-
// Full configuration
|
|
217
|
-
const app = new Nural({
|
|
218
|
-
errorHandler: {
|
|
219
|
-
handler: customHandler,
|
|
220
|
-
includeStack: process.env.NODE_ENV !== "production",
|
|
221
|
-
logErrors: true,
|
|
222
|
-
logger: (err, ctx) => winston.error(err.message, { path: ctx.path }),
|
|
223
|
-
},
|
|
224
|
-
});
|
|
225
|
-
```
|
|
226
|
-
|
|
227
|
-
**Smart defaults:** Automatically maps `"unauthorized"` → 401, `"not found"` → 404, Zod errors → 400.
|
|
228
|
-
|
|
229
|
-
### Available Exceptions
|
|
230
|
-
|
|
231
|
-
| Exception | Status Code |
|
|
232
|
-
| :------------------------------ | :---------- |
|
|
233
|
-
| `BadRequestException` | 400 |
|
|
234
|
-
| `UnauthorizedException` | 401 |
|
|
235
|
-
| `ForbiddenException` | 403 |
|
|
236
|
-
| `NotFoundException` | 404 |
|
|
237
|
-
| `ConflictException` | 409 |
|
|
238
|
-
| `GoneException` | 410 |
|
|
239
|
-
| `PayloadTooLargeException` | 413 |
|
|
240
|
-
| `UnsupportedMediaTypeException` | 415 |
|
|
241
|
-
| `UnprocessableEntityException` | 422 |
|
|
242
|
-
| `InternalServerErrorException` | 500 |
|
|
243
|
-
| `NotImplementedException` | 501 |
|
|
244
|
-
| `BadGatewayException` | 502 |
|
|
245
|
-
| `ServiceUnavailableException` | 503 |
|
|
246
|
-
| `GatewayTimeoutException` | 504 |
|
|
247
|
-
|
|
248
|
-
---
|
|
249
|
-
|
|
250
|
-
## Logger
|
|
251
|
-
|
|
252
|
-
Nural comes with a built-in, zero-dependency logger that is lightweight and colorful.
|
|
253
|
-
|
|
254
|
-
```typescript
|
|
255
|
-
import { Logger } from "nural";
|
|
256
|
-
|
|
257
|
-
const logger = new Logger("MyService");
|
|
258
|
-
|
|
259
|
-
logger.log("This is a log message");
|
|
260
|
-
logger.warn("Be careful!");
|
|
261
|
-
logger.error("Something went wrong");
|
|
262
|
-
// Output: [Nural] 1234 - 2026-02-08... [MyService] This is a log message
|
|
263
|
-
```
|
|
264
|
-
|
|
265
|
-
### HTTP Logger
|
|
266
|
-
|
|
267
|
-
The HTTP logger middleware is enabled by default and logs all incoming requests with their status and duration.
|
|
268
|
-
|
|
269
|
-
```typescript
|
|
270
|
-
const app = new Nural({
|
|
271
|
-
logger: {
|
|
272
|
-
enabled: true,
|
|
273
|
-
showUserAgent: true, // Log User-Agent header
|
|
274
|
-
showTime: true, // Log request duration (default: true)
|
|
275
|
-
},
|
|
276
|
-
});
|
|
277
|
-
```
|
|
278
|
-
|
|
279
|
-
---
|
|
280
|
-
|
|
281
|
-
## Configuration
|
|
282
|
-
|
|
283
|
-
```typescript
|
|
284
|
-
const app = new Nural({
|
|
285
|
-
framework: "fastify", // or 'express'
|
|
286
|
-
cors: true, // Enable CORS with defaults
|
|
287
|
-
helmet: true, // Enable security headers with defaults
|
|
288
|
-
|
|
289
|
-
// Documentation
|
|
290
|
-
docs: {
|
|
291
|
-
enabled: true,
|
|
292
|
-
path: "/api-docs",
|
|
293
|
-
ui: "scalar", // 'scalar' (default) or 'swagger'
|
|
294
|
-
|
|
295
|
-
// Full OpenAPI Customization
|
|
296
|
-
openApi: {
|
|
297
|
-
info: {
|
|
298
|
-
title: "My API",
|
|
299
|
-
version: "2.0.0",
|
|
300
|
-
description: "My awesome API",
|
|
301
|
-
},
|
|
302
|
-
servers: [{ url: "https://api.example.com" }],
|
|
303
|
-
// Add Security Schemes (e.g., API Key, Bearer Token)
|
|
304
|
-
components: {
|
|
305
|
-
securitySchemes: {
|
|
306
|
-
bearerAuth: {
|
|
307
|
-
type: "http",
|
|
308
|
-
scheme: "bearer",
|
|
309
|
-
bearerFormat: "JWT",
|
|
310
|
-
},
|
|
311
|
-
},
|
|
312
|
-
},
|
|
313
|
-
// Apply Global Security
|
|
314
|
-
security: [{ bearerAuth: [] }],
|
|
315
|
-
},
|
|
316
|
-
|
|
317
|
-
// Scalar UI Options (fully typed)
|
|
318
|
-
scalar: {
|
|
319
|
-
theme: "moon", // 'alternate', 'default', 'moon', 'purple', 'solarized', etc.
|
|
320
|
-
layout: "modern",
|
|
321
|
-
showSidebar: true,
|
|
322
|
-
hideModels: true,
|
|
323
|
-
darkMode: true,
|
|
324
|
-
// Custom Metadata
|
|
325
|
-
metaData: { title: "API Docs" },
|
|
326
|
-
// Authentication Pre-fill
|
|
327
|
-
authentication: {
|
|
328
|
-
preferredSecurityScheme: "bearerAuth",
|
|
329
|
-
securitySchemes: {
|
|
330
|
-
bearerAuth: { token: "EXAMPLE_TOKEN" },
|
|
331
|
-
},
|
|
332
|
-
},
|
|
333
|
-
},
|
|
334
|
-
|
|
335
|
-
// Swagger UI Options (fully typed)
|
|
336
|
-
swagger: {
|
|
337
|
-
theme: "outline", // 'outline', 'classic', or 'no-theme'
|
|
338
|
-
options: {
|
|
339
|
-
persistAuthorization: true,
|
|
340
|
-
docExpansion: "list",
|
|
341
|
-
defaultModelsExpandDepth: -1,
|
|
342
|
-
filter: true,
|
|
343
|
-
syntaxHighlight: { theme: "monokai" },
|
|
344
|
-
},
|
|
345
|
-
},
|
|
346
|
-
},
|
|
347
|
-
|
|
348
|
-
// Logger
|
|
349
|
-
logger: {
|
|
350
|
-
enabled: true,
|
|
351
|
-
showUserAgent: false,
|
|
352
|
-
showTime: true,
|
|
353
|
-
},
|
|
354
|
-
|
|
355
|
-
// Error Handling
|
|
356
|
-
errorHandler: {
|
|
357
|
-
handler: customHandler, // Optional custom handler
|
|
358
|
-
includeStack: false, // Hide stack traces in production
|
|
359
|
-
logErrors: true, // Log errors to console
|
|
360
|
-
},
|
|
361
|
-
});
|
|
362
|
-
```
|
|
363
|
-
|
|
364
|
-
---
|
|
365
|
-
|
|
366
|
-
## API Reference
|
|
367
|
-
|
|
368
|
-
### `createRoute(config)`
|
|
369
|
-
|
|
370
|
-
| Property | Type | Description |
|
|
371
|
-
| ---------------- | --------------------------- | ---------------------------------------------- |
|
|
372
|
-
| `method` | `HttpMethod` | GET, POST, PUT, PATCH, DELETE |
|
|
373
|
-
| `path` | `string` | Route path (supports `:param`) |
|
|
374
|
-
| `summary` | `string?` | Short description for docs |
|
|
375
|
-
| `description` | `string?` | Detailed description |
|
|
376
|
-
| `tags` | `string[]?` | Grouping for docs |
|
|
377
|
-
| `middleware` | `array?` | Middleware functions |
|
|
378
|
-
| `request.params` | `ZodSchema?` | Path params validation |
|
|
379
|
-
| `request.query` | `ZodSchema?` | Query params validation |
|
|
380
|
-
| `request.body` | `ZodSchema?` | Body validation |
|
|
381
|
-
| `responses` | `Record<number, ZodSchema>` | Response schemas |
|
|
382
|
-
| `security` | `array?` | OpenAPI security (e.g. `[{ bearerAuth: [] }]`) |
|
|
383
|
-
| `openapi` | `object?` | OpenAPI operation overrides |
|
|
384
|
-
| `handler` | `function` | Route handler |
|
|
385
|
-
|
|
386
|
-
### Per-Route Configuration (Security & Headers)
|
|
387
|
-
|
|
388
|
-
You can define security requirements or override OpenAPI properties directly on the route:
|
|
389
|
-
|
|
390
|
-
```typescript
|
|
391
|
-
const protectedRoute = createRoute({
|
|
392
|
-
method: "GET",
|
|
393
|
-
path: "/protected",
|
|
394
|
-
// Define security requirements
|
|
395
|
-
security: [{ bearerAuth: [] }],
|
|
396
|
-
// Override OpenAPI operation (e.g., custom headers)
|
|
397
|
-
openapi: {
|
|
398
|
-
parameters: [
|
|
399
|
-
{
|
|
400
|
-
in: "header",
|
|
401
|
-
name: "X-Custom-Header",
|
|
402
|
-
schema: { type: "string" },
|
|
403
|
-
required: true,
|
|
404
|
-
},
|
|
405
|
-
],
|
|
406
|
-
},
|
|
407
|
-
handler: async () => {
|
|
408
|
-
return { secret: "data" };
|
|
409
|
-
},
|
|
410
|
-
});
|
|
411
|
-
```
|
|
412
|
-
|
|
413
|
-
### Route Context (`ctx`)
|
|
414
|
-
|
|
415
|
-
The `handler` receives a `ctx` object containing:
|
|
416
|
-
|
|
417
|
-
```typescript
|
|
418
|
-
{
|
|
419
|
-
params: { id: "123" }, // Validated path params
|
|
420
|
-
query: { page: 1 }, // Validated query params
|
|
421
|
-
body: { name: "John" }, // Validated body
|
|
422
|
-
req: Request, // Native request object
|
|
423
|
-
res: Response, // Native response object
|
|
424
|
-
...middlewareProps // Properties injected by middleware
|
|
425
|
-
}
|
|
426
|
-
```
|
|
427
|
-
|
|
428
|
-
### `defineMiddleware(fn)`
|
|
429
|
-
|
|
430
|
-
Creates a type-safe middleware that injects context into handlers.
|
|
431
|
-
|
|
432
|
-
### `new Nural(config)`
|
|
433
|
-
|
|
434
|
-
| Property | Type | Default | Description |
|
|
435
|
-
| -------------- | ------------------------------ | ----------- | ------------------------ |
|
|
436
|
-
| `framework` | `'express' \| 'fastify'` | `'express'` | Server framework |
|
|
437
|
-
| `docs` | `boolean \| DocsConfig` | `true` | Documentation settings |
|
|
438
|
-
| `cors` | `boolean \| CorsConfig` | `false` | CORS middleware settings |
|
|
439
|
-
| `helmet` | `boolean \| HelmetConfig` | `false` | Security headers |
|
|
440
|
-
| `errorHandler` | `boolean \| fn \| ErrorConfig` | `true` | Global error handling |
|
|
441
|
-
|
|
442
|
-
---
|
|
443
|
-
|
|
444
|
-
## License
|
|
445
|
-
|
|
446
|
-
MIT © [Chetan Joshi](https://github.com/ErrorX407)
|
package/dist/cli/index.cjs
DELETED
|
@@ -1,221 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
'use strict';
|
|
3
|
-
|
|
4
|
-
var commander = require('commander');
|
|
5
|
-
var inquirer = require('inquirer');
|
|
6
|
-
var chalk = require('chalk');
|
|
7
|
-
var fs = require('fs-extra');
|
|
8
|
-
var path = require('path');
|
|
9
|
-
|
|
10
|
-
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
11
|
-
|
|
12
|
-
var inquirer__default = /*#__PURE__*/_interopDefault(inquirer);
|
|
13
|
-
var chalk__default = /*#__PURE__*/_interopDefault(chalk);
|
|
14
|
-
var fs__default = /*#__PURE__*/_interopDefault(fs);
|
|
15
|
-
var path__default = /*#__PURE__*/_interopDefault(path);
|
|
16
|
-
|
|
17
|
-
var program = new commander.Command();
|
|
18
|
-
program.name("nural").description("Nural Framework CLI").version("0.3.8");
|
|
19
|
-
program.command("new <project-name>").description("Create a new Nural project").action(async (projectName) => {
|
|
20
|
-
const projectPath = path__default.default.join(process.cwd(), projectName);
|
|
21
|
-
if (fs__default.default.existsSync(projectPath)) {
|
|
22
|
-
console.error(
|
|
23
|
-
chalk__default.default.red(`Error: Directory ${projectName} already exists.`)
|
|
24
|
-
);
|
|
25
|
-
process.exit(1);
|
|
26
|
-
}
|
|
27
|
-
const { framework } = await inquirer__default.default.prompt([
|
|
28
|
-
{
|
|
29
|
-
type: "list",
|
|
30
|
-
name: "framework",
|
|
31
|
-
message: "Select a framework (express/fastify):",
|
|
32
|
-
choices: [
|
|
33
|
-
{
|
|
34
|
-
name: "express",
|
|
35
|
-
value: "express",
|
|
36
|
-
description: "Fast, unopinionated, minimalist web framework"
|
|
37
|
-
},
|
|
38
|
-
{
|
|
39
|
-
name: "fastify",
|
|
40
|
-
value: "fastify",
|
|
41
|
-
description: "Fast and low overhead web framework"
|
|
42
|
-
}
|
|
43
|
-
],
|
|
44
|
-
default: "express"
|
|
45
|
-
}
|
|
46
|
-
]);
|
|
47
|
-
console.log(
|
|
48
|
-
chalk__default.default.blue(`
|
|
49
|
-
Initializing new Nural project in ${projectName}...`)
|
|
50
|
-
);
|
|
51
|
-
fs__default.default.ensureDirSync(path__default.default.join(projectPath, "src/config"));
|
|
52
|
-
fs__default.default.ensureDirSync(path__default.default.join(projectPath, "src/routes"));
|
|
53
|
-
fs__default.default.ensureDirSync(path__default.default.join(projectPath, "src/middleware"));
|
|
54
|
-
fs__default.default.ensureDirSync(path__default.default.join(projectPath, "src/services"));
|
|
55
|
-
const packageJson = {
|
|
56
|
-
name: projectName,
|
|
57
|
-
version: "1.0.0",
|
|
58
|
-
main: "dist/index.js",
|
|
59
|
-
scripts: {
|
|
60
|
-
dev: "nodemon --exec tsx src/index.ts",
|
|
61
|
-
build: "tsup src/index.ts --format cjs,esm --dts",
|
|
62
|
-
start: "node dist/index.js"
|
|
63
|
-
},
|
|
64
|
-
dependencies: {
|
|
65
|
-
nural: "^0.3.8",
|
|
66
|
-
[framework]: framework === "express" ? "^5.0.0" : "^5.0.0",
|
|
67
|
-
// Using explicit versions for peer deps
|
|
68
|
-
zod: "^3.22.4"
|
|
69
|
-
},
|
|
70
|
-
devDependencies: {
|
|
71
|
-
tsx: "^4.7.1",
|
|
72
|
-
tsup: "^8.0.2",
|
|
73
|
-
typescript: "^5.3.3",
|
|
74
|
-
nodemon: "^3.1.11",
|
|
75
|
-
"@types/node": "^20.11.24",
|
|
76
|
-
...framework === "express" ? { "@types/express": "^5.0.0" } : {}
|
|
77
|
-
}
|
|
78
|
-
};
|
|
79
|
-
fs__default.default.writeJsonSync(path__default.default.join(projectPath, "package.json"), packageJson, {
|
|
80
|
-
spaces: 2
|
|
81
|
-
});
|
|
82
|
-
const tsconfig = {
|
|
83
|
-
compilerOptions: {
|
|
84
|
-
target: "ES2020",
|
|
85
|
-
module: "CommonJS",
|
|
86
|
-
moduleResolution: "node",
|
|
87
|
-
strict: true,
|
|
88
|
-
esModuleInterop: true,
|
|
89
|
-
skipLibCheck: true,
|
|
90
|
-
forceConsistentCasingInFileNames: true,
|
|
91
|
-
outDir: "./dist"
|
|
92
|
-
},
|
|
93
|
-
include: ["src/**/*"],
|
|
94
|
-
exclude: ["node_modules"]
|
|
95
|
-
};
|
|
96
|
-
fs__default.default.writeJsonSync(path__default.default.join(projectPath, "tsconfig.json"), tsconfig, {
|
|
97
|
-
spaces: 2
|
|
98
|
-
});
|
|
99
|
-
const indexContent = `import { Nural } from "nural";
|
|
100
|
-
import { appConfig } from "./config/app.config";
|
|
101
|
-
|
|
102
|
-
const app = new Nural(appConfig);
|
|
103
|
-
|
|
104
|
-
app.start(3000)
|
|
105
|
-
`;
|
|
106
|
-
fs__default.default.writeFileSync(path__default.default.join(projectPath, "src/index.ts"), indexContent);
|
|
107
|
-
const configContent = `import { NuralConfig } from "nural";
|
|
108
|
-
|
|
109
|
-
export const appConfig: NuralConfig = {
|
|
110
|
-
framework: "${framework}",
|
|
111
|
-
docs: true,
|
|
112
|
-
logger: {
|
|
113
|
-
enabled: true,
|
|
114
|
-
},
|
|
115
|
-
};
|
|
116
|
-
`;
|
|
117
|
-
fs__default.default.writeFileSync(
|
|
118
|
-
path__default.default.join(projectPath, "src/config/app.config.ts"),
|
|
119
|
-
configContent
|
|
120
|
-
);
|
|
121
|
-
console.log(
|
|
122
|
-
chalk__default.default.green(`
|
|
123
|
-
\u2714 Project ${projectName} created successfully!`)
|
|
124
|
-
);
|
|
125
|
-
console.log(chalk__default.default.white(`
|
|
126
|
-
Next steps:`));
|
|
127
|
-
console.log(chalk__default.default.cyan(` cd ${projectName}`));
|
|
128
|
-
console.log(chalk__default.default.cyan(` npm install`));
|
|
129
|
-
console.log(chalk__default.default.cyan(` npm run dev`));
|
|
130
|
-
});
|
|
131
|
-
program.command("generate <type> <name>").alias("g").description("Generate a resource (route, middleware, service)").action((typeArg, nameArg) => {
|
|
132
|
-
const type = typeArg.toLowerCase();
|
|
133
|
-
const name = nameArg.toLowerCase();
|
|
134
|
-
const srcDir = path__default.default.join(process.cwd(), "src");
|
|
135
|
-
if (!fs__default.default.existsSync(srcDir)) {
|
|
136
|
-
console.error(
|
|
137
|
-
chalk__default.default.red(
|
|
138
|
-
"Error: src directory not found. Are you in a Nural project root?"
|
|
139
|
-
)
|
|
140
|
-
);
|
|
141
|
-
process.exit(1);
|
|
142
|
-
}
|
|
143
|
-
const capitalize = (s) => s.charAt(0).toUpperCase() + s.slice(1);
|
|
144
|
-
switch (type) {
|
|
145
|
-
case "route": {
|
|
146
|
-
const routeContent = `import { createRoute, z } from "nural";
|
|
147
|
-
|
|
148
|
-
export const ${name}Route = createRoute({
|
|
149
|
-
method: "GET",
|
|
150
|
-
path: "/${name}",
|
|
151
|
-
summary: "${capitalize(name)} route",
|
|
152
|
-
responses: {
|
|
153
|
-
200: z.object({ message: z.string() }),
|
|
154
|
-
},
|
|
155
|
-
handler: async () => {
|
|
156
|
-
return { message: "Hello from ${name}" };
|
|
157
|
-
},
|
|
158
|
-
|
|
159
|
-
export const ${name}Routes = [${name}Route]
|
|
160
|
-
});
|
|
161
|
-
`;
|
|
162
|
-
const routesDir = path__default.default.join(srcDir, "routes");
|
|
163
|
-
fs__default.default.ensureDirSync(routesDir);
|
|
164
|
-
fs__default.default.writeFileSync(
|
|
165
|
-
path__default.default.join(routesDir, `${name}.routes.ts`),
|
|
166
|
-
routeContent
|
|
167
|
-
);
|
|
168
|
-
console.log(chalk__default.default.green(`Created src/routes/${name}.routes.ts`));
|
|
169
|
-
break;
|
|
170
|
-
}
|
|
171
|
-
case "middleware": {
|
|
172
|
-
const middlewareContent = `import { defineMiddleware } from "nural";
|
|
173
|
-
|
|
174
|
-
export const ${name}Middleware = defineMiddleware(async (req, res) => {
|
|
175
|
-
// TODO: Implement middleware logic
|
|
176
|
-
return { ${name}: true };
|
|
177
|
-
});
|
|
178
|
-
`;
|
|
179
|
-
const middlewareDir = path__default.default.join(srcDir, "middleware");
|
|
180
|
-
fs__default.default.ensureDirSync(middlewareDir);
|
|
181
|
-
fs__default.default.writeFileSync(
|
|
182
|
-
path__default.default.join(middlewareDir, `${name}.middleware.ts`),
|
|
183
|
-
middlewareContent
|
|
184
|
-
);
|
|
185
|
-
console.log(
|
|
186
|
-
chalk__default.default.green(`Created src/middleware/${name}.middleware.ts`)
|
|
187
|
-
);
|
|
188
|
-
break;
|
|
189
|
-
}
|
|
190
|
-
case "service": {
|
|
191
|
-
const serviceContent = `export class ${capitalize(name)}Service {
|
|
192
|
-
constructor() {}
|
|
193
|
-
|
|
194
|
-
async findAll() {
|
|
195
|
-
return [];
|
|
196
|
-
}
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
export const ${name}Service = new ${capitalize(name)}Service();
|
|
200
|
-
`;
|
|
201
|
-
const servicesDir = path__default.default.join(srcDir, "services");
|
|
202
|
-
fs__default.default.ensureDirSync(servicesDir);
|
|
203
|
-
fs__default.default.writeFileSync(
|
|
204
|
-
path__default.default.join(servicesDir, `${name}.service.ts`),
|
|
205
|
-
serviceContent
|
|
206
|
-
);
|
|
207
|
-
console.log(chalk__default.default.green(`Created src/services/${name}.service.ts`));
|
|
208
|
-
break;
|
|
209
|
-
}
|
|
210
|
-
default:
|
|
211
|
-
console.error(
|
|
212
|
-
chalk__default.default.red(
|
|
213
|
-
`Unknown type: ${type}. Supported: route, middleware, service`
|
|
214
|
-
)
|
|
215
|
-
);
|
|
216
|
-
process.exit(1);
|
|
217
|
-
}
|
|
218
|
-
});
|
|
219
|
-
program.parse(process.argv);
|
|
220
|
-
//# sourceMappingURL=index.cjs.map
|
|
221
|
-
//# sourceMappingURL=index.cjs.map
|
package/dist/cli/index.cjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/cli/index.ts"],"names":["Command","path","fs","chalk","inquirer"],"mappings":"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","file":"index.cjs","sourcesContent":["import { Command } from \"commander\";\nimport inquirer from \"inquirer\";\nimport chalk from \"chalk\";\nimport fs from \"fs-extra\";\nimport path from \"path\";\n\nconst program = new Command();\n\nprogram.name(\"nural\").description(\"Nural Framework CLI\").version(\"0.3.8\");\n\nprogram\n .command(\"new <project-name>\")\n .description(\"Create a new Nural project\")\n .action(async (projectName) => {\n const projectPath = path.join(process.cwd(), projectName);\n\n if (fs.existsSync(projectPath)) {\n console.error(\n chalk.red(`Error: Directory ${projectName} already exists.`),\n );\n process.exit(1);\n }\n\n const { framework } = await inquirer.prompt([\n {\n type: \"list\",\n name: \"framework\",\n message: \"Select a framework (express/fastify):\",\n choices: [\n {\n name: \"express\",\n value: \"express\",\n description: \"Fast, unopinionated, minimalist web framework\",\n },\n {\n name: \"fastify\",\n value: \"fastify\",\n description: \"Fast and low overhead web framework\",\n },\n ],\n default: \"express\",\n },\n ]);\n\n console.log(\n chalk.blue(`\\nInitializing new Nural project in ${projectName}...`),\n );\n\n // Create directories\n fs.ensureDirSync(path.join(projectPath, \"src/config\"));\n fs.ensureDirSync(path.join(projectPath, \"src/routes\"));\n fs.ensureDirSync(path.join(projectPath, \"src/middleware\"));\n fs.ensureDirSync(path.join(projectPath, \"src/services\"));\n\n // Create package.json\n const packageJson = {\n name: projectName,\n version: \"1.0.0\",\n main: \"dist/index.js\",\n scripts: {\n dev: \"nodemon --exec tsx src/index.ts\",\n build: \"tsup src/index.ts --format cjs,esm --dts\",\n start: \"node dist/index.js\",\n },\n dependencies: {\n nural: \"^0.3.8\",\n [framework]: framework === \"express\" ? \"^5.0.0\" : \"^5.0.0\", // Using explicit versions for peer deps\n zod: \"^3.22.4\",\n },\n devDependencies: {\n tsx: \"^4.7.1\",\n tsup: \"^8.0.2\",\n typescript: \"^5.3.3\",\n nodemon: \"^3.1.11\",\n \"@types/node\": \"^20.11.24\",\n ...(framework === \"express\" ? { \"@types/express\": \"^5.0.0\" } : {}),\n },\n };\n\n fs.writeJsonSync(path.join(projectPath, \"package.json\"), packageJson, {\n spaces: 2,\n });\n\n // Create tsconfig.json\n const tsconfig = {\n compilerOptions: {\n target: \"ES2020\",\n module: \"CommonJS\",\n moduleResolution: \"node\",\n strict: true,\n esModuleInterop: true,\n skipLibCheck: true,\n forceConsistentCasingInFileNames: true,\n outDir: \"./dist\",\n },\n include: [\"src/**/*\"],\n exclude: [\"node_modules\"],\n };\n\n fs.writeJsonSync(path.join(projectPath, \"tsconfig.json\"), tsconfig, {\n spaces: 2,\n });\n\n // Create src/index.ts\n const indexContent = `import { Nural } from \"nural\";\nimport { appConfig } from \"./config/app.config\";\n\nconst app = new Nural(appConfig);\n\napp.start(3000)\n`;\n fs.writeFileSync(path.join(projectPath, \"src/index.ts\"), indexContent);\n\n // Create src/config/app.config.ts\n const configContent = `import { NuralConfig } from \"nural\";\n\nexport const appConfig: NuralConfig = {\n framework: \"${framework}\",\n docs: true,\n logger: {\n enabled: true,\n },\n};\n`;\n fs.writeFileSync(\n path.join(projectPath, \"src/config/app.config.ts\"),\n configContent,\n );\n\n console.log(\n chalk.green(`\\n✔ Project ${projectName} created successfully!`),\n );\n console.log(chalk.white(`\\nNext steps:`));\n console.log(chalk.cyan(` cd ${projectName}`));\n console.log(chalk.cyan(` npm install`));\n console.log(chalk.cyan(` npm run dev`));\n });\n\nprogram\n .command(\"generate <type> <name>\")\n .alias(\"g\")\n .description(\"Generate a resource (route, middleware, service)\")\n .action((typeArg, nameArg) => {\n const type = typeArg.toLowerCase();\n const name = nameArg.toLowerCase();\n const srcDir = path.join(process.cwd(), \"src\");\n\n if (!fs.existsSync(srcDir)) {\n console.error(\n chalk.red(\n \"Error: src directory not found. Are you in a Nural project root?\",\n ),\n );\n process.exit(1);\n }\n\n const capitalize = (s: string) => s.charAt(0).toUpperCase() + s.slice(1);\n\n switch (type) {\n case \"route\": {\n const routeContent = `import { createRoute, z } from \"nural\";\n\nexport const ${name}Route = createRoute({\n method: \"GET\",\n path: \"/${name}\",\n summary: \"${capitalize(name)} route\",\n responses: {\n 200: z.object({ message: z.string() }),\n },\n handler: async () => {\n return { message: \"Hello from ${name}\" };\n },\n\n export const ${name}Routes = [${name}Route]\n});\n`;\n const routesDir = path.join(srcDir, \"routes\");\n fs.ensureDirSync(routesDir);\n fs.writeFileSync(\n path.join(routesDir, `${name}.routes.ts`),\n routeContent,\n );\n console.log(chalk.green(`Created src/routes/${name}.routes.ts`));\n break;\n }\n case \"middleware\": {\n const middlewareContent = `import { defineMiddleware } from \"nural\";\n\nexport const ${name}Middleware = defineMiddleware(async (req, res) => {\n // TODO: Implement middleware logic\n return { ${name}: true };\n});\n`;\n const middlewareDir = path.join(srcDir, \"middleware\");\n fs.ensureDirSync(middlewareDir);\n fs.writeFileSync(\n path.join(middlewareDir, `${name}.middleware.ts`),\n middlewareContent,\n );\n console.log(\n chalk.green(`Created src/middleware/${name}.middleware.ts`),\n );\n break;\n }\n case \"service\": {\n const serviceContent = `export class ${capitalize(name)}Service {\n constructor() {}\n\n async findAll() {\n return [];\n }\n}\n\nexport const ${name}Service = new ${capitalize(name)}Service();\n`;\n const servicesDir = path.join(srcDir, \"services\");\n fs.ensureDirSync(servicesDir);\n fs.writeFileSync(\n path.join(servicesDir, `${name}.service.ts`),\n serviceContent,\n );\n console.log(chalk.green(`Created src/services/${name}.service.ts`));\n break;\n }\n default:\n console.error(\n chalk.red(\n `Unknown type: ${type}. Supported: route, middleware, service`,\n ),\n );\n process.exit(1);\n }\n });\n\nprogram.parse(process.argv);\n"]}
|
package/dist/cli/index.d.cts
DELETED
package/dist/cli/index.d.ts
DELETED