naider 1.20.0 → 1.21.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 +73 -1
- package/bin/naide.js +111 -18
- package/mcp/server.js +1 -1
- package/package.json +1 -1
- package/src/gen.js +979 -50
package/README.md
CHANGED
|
@@ -77,6 +77,9 @@ naide pkg install <name> # Install a NAIDE package
|
|
|
77
77
|
naide pkg publish # Publish package to npm
|
|
78
78
|
naide -w <file> # Watch mode (auto-restart on changes)
|
|
79
79
|
naide -d <file> # Debug mode (Node.js inspector)
|
|
80
|
+
naide ~~ "instruction" # Generate NAIDE code from natural language
|
|
81
|
+
naide gen "instruction" # Same as ~~ (alias)
|
|
82
|
+
naide --expand <file> # Show ~~ directive expansion results
|
|
80
83
|
naide --emit <file> # Print generated JavaScript
|
|
81
84
|
naide -o <out.js> <file> # Write JavaScript to file
|
|
82
85
|
naide --mid <file.nx> # Show intermediate NAIDE v1 (debug X mode)
|
|
@@ -84,11 +87,80 @@ naide --ast <file> # Print AST
|
|
|
84
87
|
naide --tokens <file> # Print token stream
|
|
85
88
|
```
|
|
86
89
|
|
|
90
|
+
### Code Generation (`~~`)
|
|
91
|
+
|
|
92
|
+
Generate valid NAIDE code from natural language instructions — no AI, no network, no dependencies. Pure pattern matching + template composition with self-healing parser validation. Multi-entity support with automatic relationship detection, paginated CRUD, soft delete, batch operations, nested routes, seed data, tests, and full project scaffolding.
|
|
93
|
+
|
|
94
|
+
```bash
|
|
95
|
+
# Single entity
|
|
96
|
+
naide ~~ "REST API for users with auth"
|
|
97
|
+
naide ~~ "todo app with database"
|
|
98
|
+
|
|
99
|
+
# Multi-entity (auto-detects relationships, injects foreign keys)
|
|
100
|
+
naide ~~ "users and products and orders with auth"
|
|
101
|
+
|
|
102
|
+
# Composite presets
|
|
103
|
+
naide ~~ "shop" # User + Product + Order
|
|
104
|
+
naide ~~ "crm" # User + Contact + Deal + Activity
|
|
105
|
+
naide ~~ "sns" # User + Post + Comment + Message + Notification
|
|
106
|
+
naide ~~ "booking" # User + Event + Reservation
|
|
107
|
+
|
|
108
|
+
# Project mode (generates full directory)
|
|
109
|
+
naide ~~ "e-commerce app with auth" --project
|
|
110
|
+
|
|
111
|
+
# File write mode (merge into existing file)
|
|
112
|
+
naide ~~ "REST API for users" --write app.naide
|
|
113
|
+
|
|
114
|
+
# Japanese
|
|
115
|
+
naide ~~ "ECサイト"
|
|
116
|
+
naide ~~ "ユーザー管理APIを認証付きで"
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
Generated routes per entity: paginated list, CRUD, soft delete, restore, batch create/delete, nested routes (from relationships), file upload, webhooks. With auth: register, login, profile, admin stats, audit log.
|
|
120
|
+
|
|
121
|
+
Project mode (`--project`) generates: `app.naide`, `package.json`, `.env`, `Dockerfile`, `README.md`, `openapi.json`, `admin.html`, `client.mjs`.
|
|
122
|
+
|
|
123
|
+
API usage:
|
|
124
|
+
|
|
125
|
+
```javascript
|
|
126
|
+
import { generate, generateProject } from 'naider';
|
|
127
|
+
|
|
128
|
+
const result = generate("users and products with auth");
|
|
129
|
+
console.log(result.entities); // ['User', 'Product']
|
|
130
|
+
console.log(result.relationships); // [{parent:'User', child:'Product', fk:'user_id'}]
|
|
131
|
+
console.log(result.valid); // true
|
|
132
|
+
console.log(result.analysis); // {entities, relationships, plan, ...}
|
|
133
|
+
|
|
134
|
+
const project = generateProject("e-commerce with auth");
|
|
135
|
+
project.files.forEach(f => console.log(f.path));
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
**Self-healing**: Generated code is validated against the actual NAIDE parser. Parse errors are auto-fixed (up to 5 retries) — missing colons, indent issues, reserved keyword conflicts.
|
|
139
|
+
|
|
140
|
+
**Field normalization**: Smart aliases — `e-mail` → `email`, `pwd` → `password`, `tel` → `phone`, `desc` → `description`. Field types are auto-inferred from names (`email` → `str + email`, `age` → `int`, `done` → `bool`).
|
|
141
|
+
|
|
142
|
+
<details>
|
|
143
|
+
<summary>Keyword Cheat Sheet</summary>
|
|
144
|
+
|
|
145
|
+
| Category | Keywords |
|
|
146
|
+
|----------|----------|
|
|
147
|
+
| Intent | `server` `api` `rest` `bot` `cli` `page` `test` `database` `ai` `crud` `auth` `websocket` `mail` `graphql` |
|
|
148
|
+
| Composite | `todo` `blog` `chat` `shop` `fullstack` `board` `crm` `inventory` `booking` `sns` |
|
|
149
|
+
| Platform | `discord` `slack` `telegram` `line` |
|
|
150
|
+
| DB Type | `sqlite` `postgres` |
|
|
151
|
+
| JP Intent | `サーバー` `認証` `ログイン` `会員` `CRUD` `管理` `データベース` `ボット` `テスト` `ページ` `メール` |
|
|
152
|
+
| JP Entity | `ユーザー` `商品` `記事` `タスク` `注文` `コメント` `イベント` `問い合わせ` `通知` `カテゴリ` `掲示板` `決済` `予約` `社員` |
|
|
153
|
+
| JP Composite | `管理システム` `やることリスト` `ブログ` `チャットアプリ` `ECサイト` `掲示板` |
|
|
154
|
+
| NL Phrases | `"users can comment"` `"admin manage"` `"upload"` `"search"` `"notification"` `"deploy"` `"seed"` |
|
|
155
|
+
| Fields | `"with name email age"` — auto-inferred types & validators |
|
|
156
|
+
|
|
157
|
+
</details>
|
|
158
|
+
|
|
87
159
|
### REPL
|
|
88
160
|
|
|
89
161
|
```
|
|
90
162
|
$ naide
|
|
91
|
-
NAIDE REPL v1.
|
|
163
|
+
NAIDE REPL v1.21.0 — type NAIDE code, see JavaScript output
|
|
92
164
|
Type .exit to quit, .eval to toggle eval mode
|
|
93
165
|
|
|
94
166
|
>>> str name = "hello"
|
package/bin/naide.js
CHANGED
|
@@ -8,7 +8,7 @@ import { spawn } from 'child_process';
|
|
|
8
8
|
import { createRequire } from 'module';
|
|
9
9
|
const _require = createRequire(import.meta.url);
|
|
10
10
|
|
|
11
|
-
const NAIDE_VERSION = '1.
|
|
11
|
+
const NAIDE_VERSION = '1.21.0';
|
|
12
12
|
|
|
13
13
|
function crashReport(err, context = {}) {
|
|
14
14
|
const info = [
|
|
@@ -114,6 +114,9 @@ const flags = {
|
|
|
114
114
|
check: false,
|
|
115
115
|
target: 'node',
|
|
116
116
|
expand: false,
|
|
117
|
+
project: false,
|
|
118
|
+
write: null,
|
|
119
|
+
replace: false,
|
|
117
120
|
};
|
|
118
121
|
|
|
119
122
|
const files = [];
|
|
@@ -133,6 +136,9 @@ for (let i = 0; i < args.length; i++) {
|
|
|
133
136
|
case '--check': flags.check = true; flags.run = false; break;
|
|
134
137
|
case '--target': case '-t': flags.target = args[++i]; break;
|
|
135
138
|
case '--expand': flags.expand = true; flags.run = false; break;
|
|
139
|
+
case '--project': case '-p': flags.project = true; break;
|
|
140
|
+
case '--write': flags.write = args[++i]; break;
|
|
141
|
+
case '--replace': flags.replace = true; break;
|
|
136
142
|
default: files.push(arg);
|
|
137
143
|
}
|
|
138
144
|
}
|
|
@@ -142,25 +148,35 @@ if (files[0] === 'gen' || files[0] === '~~') {
|
|
|
142
148
|
const instruction = files.slice(1).join(' ');
|
|
143
149
|
if (!instruction) {
|
|
144
150
|
console.log(`
|
|
145
|
-
NAIDE
|
|
151
|
+
NAIDE Agent Coder (~~)
|
|
146
152
|
|
|
147
153
|
Usage:
|
|
148
154
|
naide ~~ "REST API for users with auth"
|
|
149
155
|
naide gen "todo app with database"
|
|
150
|
-
naide gen "
|
|
156
|
+
naide gen "users and products and orders with auth"
|
|
157
|
+
naide ~~ "ECサイト" --project
|
|
151
158
|
|
|
152
|
-
|
|
153
|
-
|
|
159
|
+
Autonomous code generator with analysis, multi-entity support,
|
|
160
|
+
relationship detection, and full auth routes. No AI, no network.
|
|
154
161
|
|
|
155
162
|
Examples:
|
|
156
163
|
naide ~~ "REST API for products with name price stock"
|
|
157
|
-
naide ~~ "
|
|
164
|
+
naide ~~ "users and products with auth" # multi-entity
|
|
165
|
+
naide ~~ "SNS app" # User+Post+Comment
|
|
166
|
+
naide ~~ "ECサイト" # User+Product+Order
|
|
167
|
+
naide ~~ "予約システム" # User+Reservation
|
|
158
168
|
naide ~~ "Discord bot with hello and help commands"
|
|
159
|
-
naide ~~ "
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
naide ~~ "
|
|
163
|
-
naide
|
|
169
|
+
naide ~~ "ユーザーと商品と注文の管理APIを認証付きで" # JP multi-entity
|
|
170
|
+
|
|
171
|
+
Project Mode (--project):
|
|
172
|
+
naide ~~ "e-commerce app with auth" --project
|
|
173
|
+
# Creates: app.naide, package.json, .env, .gitignore,
|
|
174
|
+
# Dockerfile, .dockerignore, README.md
|
|
175
|
+
|
|
176
|
+
File Write Mode:
|
|
177
|
+
naide ~~ "add auth" app.naide # merge into existing file
|
|
178
|
+
naide ~~ "add websocket" --write app.naide # explicit --write
|
|
179
|
+
naide ~~ "REST API" --write app.naide --replace # overwrite file
|
|
164
180
|
|
|
165
181
|
In .naide files:
|
|
166
182
|
~~ "REST API for users with auth"
|
|
@@ -170,15 +186,18 @@ if (files[0] === 'gen' || files[0] === '~~') {
|
|
|
170
186
|
naide --expand app.naide Show ~~ expansion results
|
|
171
187
|
|
|
172
188
|
API:
|
|
173
|
-
import { generate } from 'naider';
|
|
174
|
-
const result = generate("
|
|
175
|
-
console.log(result.
|
|
189
|
+
import { generate, generateProject, writeToFile } from 'naider';
|
|
190
|
+
const result = generate("users and products with auth");
|
|
191
|
+
console.log(result.analysis); // agent analysis
|
|
192
|
+
console.log(result.entities); // ['User', 'Product']
|
|
193
|
+
writeToFile("app.naide", "add auth"); // merge into file
|
|
176
194
|
|
|
177
195
|
── Keyword Cheat Sheet ──────────────────────────────────────
|
|
178
196
|
|
|
179
197
|
Intent server, api, rest, bot, cli, page, test, database,
|
|
180
198
|
ai, crud, auth, websocket, mail, graphql
|
|
181
|
-
Composite todo, blog, chat, shop, fullstack, board
|
|
199
|
+
Composite todo, blog, chat, shop, fullstack, board,
|
|
200
|
+
crm, inventory, booking, sns
|
|
182
201
|
Platform discord, slack, telegram, line
|
|
183
202
|
DB Type sqlite, postgres
|
|
184
203
|
JP Intent サーバー, 認証, ログイン, 会員, CRUD, 管理, データベース,
|
|
@@ -187,25 +206,99 @@ if (files[0] === 'gen' || files[0] === '~~') {
|
|
|
187
206
|
問い合わせ, 通知, カテゴリ, プロジェクト, 掲示板, 決済
|
|
188
207
|
Fields "with name email age" — auto-inferred types & validators
|
|
189
208
|
Field Alias e-mail→email, pwd→password, tel→phone, desc→description
|
|
209
|
+
Relations Auto-detected: User→Post, User→Order, Product→Order, etc.
|
|
190
210
|
|
|
191
211
|
────────────────────────────────────────────────────────────
|
|
192
212
|
`);
|
|
193
213
|
process.exit(0);
|
|
194
214
|
}
|
|
195
215
|
|
|
196
|
-
const { generate } = await import('../src/gen.js');
|
|
216
|
+
const { generate, generateProject, writeToFile } = await import('../src/gen.js');
|
|
217
|
+
|
|
218
|
+
// Write mode: inject into existing .naide/.nx file
|
|
219
|
+
const targetFile = instruction.match(/\S+\.(?:naide|nx)$/)?.[0];
|
|
220
|
+
if (targetFile || flags.write) {
|
|
221
|
+
const file = flags.write || targetFile;
|
|
222
|
+
const cleanInstruction = targetFile ? instruction.replace(/\s+\S+\.(?:naide|nx)$/, '') : instruction;
|
|
223
|
+
const mode = flags.replace ? 'replace' : 'append';
|
|
224
|
+
const result = writeToFile(resolve(file), cleanInstruction, { mode });
|
|
225
|
+
const a = result.analysis;
|
|
226
|
+
process.stderr.write('\n ── NAIDE Agent ──────────────────────────────────────────\n');
|
|
227
|
+
process.stderr.write(` Input: "${a.instruction}"\n`);
|
|
228
|
+
process.stderr.write(` Action: ${result.action} → ${file}\n`);
|
|
229
|
+
if (a.entities.length > 0) {
|
|
230
|
+
process.stderr.write(` Entities: ${a.entities.map(e => `${e.name} (${e.fieldCount} fields)`).join(', ')}\n`);
|
|
231
|
+
}
|
|
232
|
+
process.stderr.write(' ────────────────────────────────────────────────────────\n\n');
|
|
233
|
+
console.log(result.code);
|
|
234
|
+
process.stderr.write(` ── ${result.action}: ${file} (valid: ${result.valid}) ──\n`);
|
|
235
|
+
process.exit(0);
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
// Project mode: generate full project directory
|
|
239
|
+
if (flags.project) {
|
|
240
|
+
const result = generateProject(instruction);
|
|
241
|
+
const primaryName = (result.entities[0] || 'app').toLowerCase().replace(/[^a-z0-9]/g, '');
|
|
242
|
+
const dir = flags.output || (primaryName + '-app');
|
|
243
|
+
const outDir = resolve(dir);
|
|
244
|
+
if (!existsSync(outDir)) mkdirSync(outDir, { recursive: true });
|
|
245
|
+
for (const f of result.files) {
|
|
246
|
+
const fp = resolve(outDir, f.path);
|
|
247
|
+
writeFileSync(fp, f.content, 'utf-8');
|
|
248
|
+
}
|
|
249
|
+
const a = result.analysis;
|
|
250
|
+
process.stderr.write('\n ── NAIDE Agent ──────────────────────────────────────────\n');
|
|
251
|
+
process.stderr.write(` Input: "${a.instruction}"\n`);
|
|
252
|
+
if (a.entities.length > 0) {
|
|
253
|
+
process.stderr.write(` Entities: ${a.entities.map(e => `${e.name} (${e.fieldCount} fields)`).join(', ')}\n`);
|
|
254
|
+
}
|
|
255
|
+
if (a.relationships.length > 0) {
|
|
256
|
+
for (const r of a.relationships) process.stderr.write(` Relation: ${r.parent} 1→N ${r.child} (${r.fk})\n`);
|
|
257
|
+
}
|
|
258
|
+
process.stderr.write(` Plan:\n`);
|
|
259
|
+
for (const step of a.plan) process.stderr.write(` + ${step}\n`);
|
|
260
|
+
process.stderr.write(' ────────────────────────────────────────────────────────\n\n');
|
|
261
|
+
console.log(` Project created: ${dir}/`);
|
|
262
|
+
for (const f of result.files) console.log(` ${f.path}`);
|
|
263
|
+
console.log(`\n cd ${dir} && npm install && npm run dev\n`);
|
|
264
|
+
process.exit(0);
|
|
265
|
+
}
|
|
266
|
+
|
|
197
267
|
const result = generate(instruction);
|
|
198
268
|
|
|
199
269
|
if (flags.output) {
|
|
200
270
|
writeFileSync(flags.output, result.code, 'utf-8');
|
|
201
271
|
console.log(` Generated: ${flags.output} (${result.intents.join(' + ')})`);
|
|
202
272
|
} else {
|
|
273
|
+
// Agent-style analysis header
|
|
274
|
+
const a = result.analysis;
|
|
275
|
+
process.stderr.write('\n ── NAIDE Agent ──────────────────────────────────────────\n');
|
|
276
|
+
process.stderr.write(` Input: "${a.instruction}"\n`);
|
|
277
|
+
if (a.entities.length > 0) {
|
|
278
|
+
process.stderr.write(` Entities: ${a.entities.map(e => `${e.name} (${e.fieldCount} fields)`).join(', ')}\n`);
|
|
279
|
+
}
|
|
280
|
+
if (a.relationships.length > 0) {
|
|
281
|
+
for (const r of a.relationships) {
|
|
282
|
+
process.stderr.write(` Relation: ${r.parent} 1→N ${r.child} (${r.fk})\n`);
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
process.stderr.write(` Plan:\n`);
|
|
286
|
+
for (const step of a.plan) {
|
|
287
|
+
process.stderr.write(` + ${step}\n`);
|
|
288
|
+
}
|
|
289
|
+
process.stderr.write(' ────────────────────────────────────────────────────────\n\n');
|
|
290
|
+
|
|
203
291
|
console.log(result.code);
|
|
292
|
+
|
|
204
293
|
const meta = [`[${result.intents.join(' + ')}]`];
|
|
205
|
-
if (result.
|
|
294
|
+
if (result.entities && result.entities.length > 1) {
|
|
295
|
+
meta.push(`→ ${result.entities.join(', ')}`);
|
|
296
|
+
} else if (result.schema) {
|
|
297
|
+
meta.push(`→ ${result.schema}`);
|
|
298
|
+
}
|
|
206
299
|
meta.push(`valid: ${result.valid}`);
|
|
207
300
|
if (result.fixed) meta.push('(auto-fixed)');
|
|
208
|
-
process.stderr.write(
|
|
301
|
+
process.stderr.write(` ── gen ~~ ${meta.join(' ')} ──\n`);
|
|
209
302
|
if (result.repairs.length > 0) {
|
|
210
303
|
process.stderr.write(' Repairs:\n');
|
|
211
304
|
for (const r of result.repairs) process.stderr.write(` - ${r}\n`);
|
package/mcp/server.js
CHANGED
|
@@ -192,7 +192,7 @@ async function handleMessage(msg) {
|
|
|
192
192
|
respond(msg.id, {
|
|
193
193
|
protocolVersion: '2024-11-05',
|
|
194
194
|
capabilities: { tools: {} },
|
|
195
|
-
serverInfo: { name: 'naide-mcp', version: '1.
|
|
195
|
+
serverInfo: { name: 'naide-mcp', version: '1.21.0' }
|
|
196
196
|
});
|
|
197
197
|
break;
|
|
198
198
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "naider",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.21.0",
|
|
4
4
|
"description": "NAIDE - Simpler than Python, compiles to 15 targets. AI-specialized language with 35+ built-in functions, syntax sugar (unless/until/repeat/swap/is/isnt), and 47 features. Targets: Node.js, Python, TypeScript, C, C++, Java, Go, Rust, PHP, Ruby, Kotlin, Swift, Dart, C#, Bun.",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"exports": {
|