@nilejs/cli 0.0.3 → 0.0.5
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 +10 -10
- package/dist/index.js +28 -3
- package/package.json +6 -6
- package/template/.env.example +1 -1
- package/template/README.md +8 -8
- package/template/package.json +1 -0
- package/template/src/index.ts +22 -19
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
[](https://www.npmjs.com/package/@nilejs/cli)
|
|
4
4
|
|
|
5
|
-
CLI for scaffolding and generating [Nile](https://
|
|
5
|
+
CLI for scaffolding and generating [Nile](https://github.com/nile-js/nile/tree/main/packages/nile) backend projects.
|
|
6
6
|
|
|
7
7
|
## Install
|
|
8
8
|
|
|
@@ -60,12 +60,12 @@ The scaffolded project includes:
|
|
|
60
60
|
|
|
61
61
|
### `nile generate service <name>`
|
|
62
62
|
|
|
63
|
-
Alias: `nile
|
|
63
|
+
Alias: `nile gen service <name>`
|
|
64
64
|
|
|
65
65
|
Generate a new service directory under `src/services/` with a demo action and barrel export. Run this from the project root.
|
|
66
66
|
|
|
67
67
|
```bash
|
|
68
|
-
nile
|
|
68
|
+
nile gen service users
|
|
69
69
|
```
|
|
70
70
|
|
|
71
71
|
Creates:
|
|
@@ -80,12 +80,12 @@ After creating the files, the CLI asks whether to auto-register the service in `
|
|
|
80
80
|
|
|
81
81
|
### `nile generate action <service-name> <action-name>`
|
|
82
82
|
|
|
83
|
-
Alias: `nile
|
|
83
|
+
Alias: `nile gen action <service-name> <action-name>`
|
|
84
84
|
|
|
85
85
|
Generate a new action file in an existing service directory.
|
|
86
86
|
|
|
87
87
|
```bash
|
|
88
|
-
nile
|
|
88
|
+
nile gen action users get-user
|
|
89
89
|
```
|
|
90
90
|
|
|
91
91
|
Creates `src/services/users/get-user.ts` with:
|
|
@@ -116,12 +116,12 @@ Kebab-case names are converted to camelCase for variables and PascalCase for typ
|
|
|
116
116
|
|
|
117
117
|
### `nile generate schema`
|
|
118
118
|
|
|
119
|
-
Alias: `nile
|
|
119
|
+
Alias: `nile gen schema`
|
|
120
120
|
|
|
121
121
|
Extract Zod validation schemas from your action definitions and generate TypeScript files with schema exports and inferred types.
|
|
122
122
|
|
|
123
123
|
```bash
|
|
124
|
-
nile
|
|
124
|
+
nile gen schema
|
|
125
125
|
```
|
|
126
126
|
|
|
127
127
|
The command auto-detects `src/services/services.config.ts`. If the file is not found, it prompts for the path. It spawns a `bun` subprocess to import your services config, extracts JSON Schema from each action's validation field, and converts them back to Zod code strings.
|
|
@@ -147,9 +147,9 @@ Requires [Bun](https://bun.sh) installed for the extraction subprocess.
|
|
|
147
147
|
| Command | Description |
|
|
148
148
|
|---|---|
|
|
149
149
|
| `nile new <name>` | Scaffold a new project |
|
|
150
|
-
| `nile
|
|
151
|
-
| `nile
|
|
152
|
-
| `nile
|
|
150
|
+
| `nile gen service <name>` | Add a service with a demo action |
|
|
151
|
+
| `nile gen action <service> <name>` | Add an action to an existing service |
|
|
152
|
+
| `nile gen schema` | Generate Zod schemas and TypeScript types |
|
|
153
153
|
|
|
154
154
|
## Generated Project Structure
|
|
155
155
|
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
// src/index.ts
|
|
4
|
+
import { resolve as resolve6 } from "node:path";
|
|
4
5
|
import { Command } from "commander";
|
|
5
6
|
|
|
6
7
|
// src/commands/generate-action.ts
|
|
@@ -237,14 +238,30 @@ var generateTypesFile = (extraction) => {
|
|
|
237
238
|
generateHeader(),
|
|
238
239
|
`import type { z } from "zod";`,
|
|
239
240
|
"import type {",
|
|
240
|
-
...schemaImports.map((name
|
|
241
|
-
`} from "./schemas";`,
|
|
241
|
+
...schemaImports.map((name) => ` ${name},`),
|
|
242
|
+
`} from "./schemas.js";`,
|
|
242
243
|
""
|
|
243
244
|
];
|
|
244
245
|
for (const entry of entries) {
|
|
245
246
|
lines.push(`export type ${entry.typeName} = z.infer<typeof ${entry.exportName}>;`);
|
|
246
247
|
}
|
|
247
248
|
lines.push("");
|
|
249
|
+
lines.push("/** Map of all services and their action payloads for @nilejs/client */");
|
|
250
|
+
lines.push("export type ServicePayloads = {");
|
|
251
|
+
const serviceMap = {};
|
|
252
|
+
for (const entry of entries) {
|
|
253
|
+
if (!serviceMap[entry.serviceName]) {
|
|
254
|
+
serviceMap[entry.serviceName] = [];
|
|
255
|
+
}
|
|
256
|
+
serviceMap[entry.serviceName].push(` "${entry.actionName}": ${entry.typeName};`);
|
|
257
|
+
}
|
|
258
|
+
for (const [service, actions] of Object.entries(serviceMap)) {
|
|
259
|
+
lines.push(` "${service}": {`);
|
|
260
|
+
lines.push(...actions);
|
|
261
|
+
lines.push(" };");
|
|
262
|
+
}
|
|
263
|
+
lines.push("};");
|
|
264
|
+
lines.push("");
|
|
248
265
|
return lines.join(`
|
|
249
266
|
`);
|
|
250
267
|
};
|
|
@@ -587,10 +604,18 @@ var newCommand = async (projectName) => {
|
|
|
587
604
|
};
|
|
588
605
|
|
|
589
606
|
// src/index.ts
|
|
607
|
+
var ensureDepsInstalled = () => {
|
|
608
|
+
const nodeModulesPath = resolve6(process.cwd(), "node_modules");
|
|
609
|
+
if (!pathExists(nodeModulesPath)) {
|
|
610
|
+
error("Dependencies not installed.");
|
|
611
|
+
hint("Run 'bun install' first, then try again.");
|
|
612
|
+
process.exit(1);
|
|
613
|
+
}
|
|
614
|
+
};
|
|
590
615
|
var program = new Command;
|
|
591
616
|
program.name("nile").description("CLI for the Nile backend framework").version("0.0.1");
|
|
592
617
|
program.command("new").argument("<project-name>", "Name of the project to create").description("Scaffold a new Nile project").action(newCommand);
|
|
593
|
-
var generate = program.command("generate").alias("
|
|
618
|
+
var generate = program.command("generate").alias("gen").description("Generate services and actions").hook("preAction", ensureDepsInstalled);
|
|
594
619
|
generate.command("service").argument("<name>", "Service name (kebab-case recommended)").description("Generate a new service with a demo action").action(generateServiceCommand);
|
|
595
620
|
generate.command("action").argument("<service-name>", "Name of the existing service").argument("<action-name>", "Name of the action to create").description("Generate a new action in an existing service").action(generateActionCommand);
|
|
596
621
|
generate.command("schema").option("-e, --entry <path>", "Path to services config file").option("-o, --output <path>", "Output directory for generated files").description("Generate Zod schemas and TypeScript types from action validations").action(generateSchemaCommand);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nilejs/cli",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.5",
|
|
4
4
|
"description": "CLI for scaffolding and generating Nile backend projects",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -10,10 +10,6 @@
|
|
|
10
10
|
"dist",
|
|
11
11
|
"template"
|
|
12
12
|
],
|
|
13
|
-
"scripts": {
|
|
14
|
-
"build": "bun run scripts/build.ts",
|
|
15
|
-
"dev": "bun run src/index.ts"
|
|
16
|
-
},
|
|
17
13
|
"dependencies": {
|
|
18
14
|
"commander": "^13.1.0",
|
|
19
15
|
"json-schema-to-zod": "^2.7.0",
|
|
@@ -22,5 +18,9 @@
|
|
|
22
18
|
"devDependencies": {
|
|
23
19
|
"@types/node": "^22.8.1",
|
|
24
20
|
"typescript": "^5"
|
|
21
|
+
},
|
|
22
|
+
"scripts": {
|
|
23
|
+
"build": "bun run scripts/build.ts",
|
|
24
|
+
"dev": "bun run src/index.ts"
|
|
25
25
|
}
|
|
26
|
-
}
|
|
26
|
+
}
|
package/template/.env.example
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
# Add your environment variables here
|
package/template/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# {{projectName}}
|
|
2
2
|
|
|
3
|
-
Built with [Nile](https://
|
|
3
|
+
Built with [Nile](https://github.com/nile-js/nile).
|
|
4
4
|
|
|
5
5
|
## Setup
|
|
6
6
|
|
|
@@ -17,6 +17,9 @@ The server starts at `http://localhost:8000`. PGLite creates an embedded Postgre
|
|
|
17
17
|
| Script | Description |
|
|
18
18
|
|---|---|
|
|
19
19
|
| `bun run dev` | Start the development server |
|
|
20
|
+
| `bun run gen service <name>` | Generate a new service |
|
|
21
|
+
| `bun run gen action <service> <name>` | Generate a new action |
|
|
22
|
+
| `bun run gen schema` | Generate Zod schemas and TypeScript types |
|
|
20
23
|
| `bun run db:generate` | Generate Drizzle migrations from schema changes |
|
|
21
24
|
| `bun run db:push` | Push schema changes directly to the database |
|
|
22
25
|
| `bun run db:studio` | Open Drizzle Studio to browse your data |
|
|
@@ -77,8 +80,7 @@ curl -X POST http://localhost:8000/api/services \
|
|
|
77
80
|
Generate a new service with the CLI:
|
|
78
81
|
|
|
79
82
|
```bash
|
|
80
|
-
|
|
81
|
-
# or: nile g service users
|
|
83
|
+
bun run gen service users
|
|
82
84
|
```
|
|
83
85
|
|
|
84
86
|
Or manually create a directory under `src/services/` with action files and register it in `src/services/services.config.ts`.
|
|
@@ -88,8 +90,7 @@ Or manually create a directory under `src/services/` with action files and regis
|
|
|
88
90
|
Generate a new action in an existing service:
|
|
89
91
|
|
|
90
92
|
```bash
|
|
91
|
-
|
|
92
|
-
# or: nile g action users get-user
|
|
93
|
+
bun run gen action users get-user
|
|
93
94
|
```
|
|
94
95
|
|
|
95
96
|
Each action file exports a single action created with `createAction`, which takes a Zod validation schema and a handler function that returns `Ok(data)` or `Err(message)`.
|
|
@@ -99,8 +100,7 @@ Each action file exports a single action created with `createAction`, which take
|
|
|
99
100
|
Extract Zod validation schemas from your actions and generate TypeScript types:
|
|
100
101
|
|
|
101
102
|
```bash
|
|
102
|
-
|
|
103
|
-
# or: nile g schema
|
|
103
|
+
bun run gen schema
|
|
104
104
|
```
|
|
105
105
|
|
|
106
106
|
This auto-detects `src/services/services.config.ts`, reads validation schemas from all actions, and outputs two files:
|
|
@@ -126,7 +126,7 @@ See the [Drizzle getting started guide](https://orm.drizzle.team/docs/get-starte
|
|
|
126
126
|
## Tech Stack
|
|
127
127
|
|
|
128
128
|
- **Runtime:** [Bun](https://bun.sh)
|
|
129
|
-
- **Framework:** [@nilejs/nile](https://
|
|
129
|
+
- **Framework:** [@nilejs/nile](https://github.com/nile-js/nile/tree/main/packages/nile)
|
|
130
130
|
- **Database:** [PGLite](https://electric-sql.com/product/pglite) (embedded Postgres)
|
|
131
131
|
- **ORM:** [Drizzle](https://orm.drizzle.team)
|
|
132
132
|
- **Validation:** [Zod](https://zod.dev)
|
package/template/package.json
CHANGED
package/template/src/index.ts
CHANGED
|
@@ -4,12 +4,12 @@ import { safeTry } from "slang-ts";
|
|
|
4
4
|
import { db } from "@/db/client";
|
|
5
5
|
import { services } from "@/services/services.config";
|
|
6
6
|
|
|
7
|
-
const logger = createLogger("{{projectName}}", {
|
|
7
|
+
const logger = createLogger("{{projectName}}", {
|
|
8
|
+
mode: "dev",
|
|
9
|
+
chunking: "monthly",
|
|
10
|
+
});
|
|
8
11
|
|
|
9
|
-
/**
|
|
10
|
-
* Push schema to PGLite on boot.
|
|
11
|
-
* Creates the tasks table if it doesn't exist.
|
|
12
|
-
*/
|
|
12
|
+
/** Push schema to PGLite on boot */
|
|
13
13
|
const pushSchema = async () => {
|
|
14
14
|
const result = await safeTry(() =>
|
|
15
15
|
db.execute(sql`
|
|
@@ -39,29 +39,32 @@ const server = createNileServer({
|
|
|
39
39
|
port: 8000,
|
|
40
40
|
allowedOrigins: ["http://localhost:8000"],
|
|
41
41
|
enableStatus: true,
|
|
42
|
+
discovery: { enabled: true },
|
|
42
43
|
},
|
|
43
44
|
onBoot: {
|
|
44
|
-
fn: async () => {
|
|
45
|
+
fn: async (ctx) => {
|
|
45
46
|
await pushSchema();
|
|
46
|
-
logger
|
|
47
|
+
ctx.resources?.logger?.info({
|
|
47
48
|
atFunction: "onBoot",
|
|
48
|
-
message: "{{projectName}} booted
|
|
49
|
+
message: "{{projectName}} booted - PGLite schema ready",
|
|
49
50
|
});
|
|
50
51
|
},
|
|
51
52
|
},
|
|
52
53
|
});
|
|
53
54
|
|
|
55
|
+
// Register custom middleware (runs before all service requests)
|
|
56
|
+
server.rest?.addMiddleware("/api", async (c, next) => {
|
|
57
|
+
const start = performance.now();
|
|
58
|
+
await next();
|
|
59
|
+
const ms = (performance.now() - start).toFixed(1);
|
|
60
|
+
logger.info({
|
|
61
|
+
atFunction: "requestLog",
|
|
62
|
+
message: `${c.req.method} ${c.req.path} - ${ms}ms`,
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
|
|
54
66
|
if (server.rest) {
|
|
55
67
|
const port = server.config.rest?.port ?? 8000;
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
Bun.serve({ port, fetch });
|
|
59
|
-
|
|
60
|
-
console.log(`\n{{projectName}} listening on http://localhost:${port}`);
|
|
61
|
-
console.log("\nTry it:");
|
|
62
|
-
console.log(` curl -X POST http://localhost:${port}/api/services \\`);
|
|
63
|
-
console.log(` -H "Content-Type: application/json" \\`);
|
|
64
|
-
console.log(
|
|
65
|
-
` -d '{"intent":"explore","service":"*","action":"*","payload":{}}'`
|
|
66
|
-
);
|
|
68
|
+
Bun.serve({ port, fetch: server.rest.app.fetch });
|
|
69
|
+
console.log(`\n{{projectName}} listening on http://localhost:${port}\n`);
|
|
67
70
|
}
|