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 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.11.0 — type NAIDE code, see JavaScript output
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.20.0';
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 Code Generator (~~)
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 "Discord bot with hello command"
156
+ naide gen "users and products and orders with auth"
157
+ naide ~~ "ECサイト" --project
151
158
 
152
- Generates valid NAIDE code from natural language instructions.
153
- No AI, no network — pure pattern matching with self-healing validation.
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 ~~ "blog app with auth and database"
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 ~~ "CLI tool"
160
- naide ~~ "chat app with websocket"
161
- naide ~~ "user management fullstack app"
162
- naide ~~ "ユーザー管理APIを認証付きで"
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("REST API for users");
175
- console.log(result.code);
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.schema) meta.push(`→ ${result.schema}`);
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(`\n ── gen ~~ ${meta.join(' ')} ──\n`);
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.20.0' }
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.20.0",
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": {