naider 1.10.1 → 1.11.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
@@ -1,1021 +1,1052 @@
1
- # NAIDE
2
-
3
- **Node AI Development Environment** — A programming language designed for AI-speed code generation that transpiles to Node.js.
4
-
5
- NAIDE is built on three principles: one way to write everything (zero ambiguity), keyword-driven intent (the first token decides meaning), and minimal token count (fewer tokens = faster AI generation). It includes built-in declarations for servers, databases, authentication, file uploads, WebSockets, job queues, testing, and more — all with zero external dependencies.
6
-
7
- Two syntax modes:
8
-
9
- - **NAIDE** (`.naide`) — Human-readable, ~40% fewer tokens than JavaScript
10
- - **NAIDE-X** (`.nx`) — AI-only readability, ~80% fewer tokens than JavaScript
11
-
12
- ## Install
13
-
14
- ```bash
15
- npm install -g naider
16
- ```
17
-
18
- ## Quick Start
19
-
20
- ```bash
21
- # Create a new project
22
- naide init my-app
23
- cd my-app
24
- npm install
25
- npm run dev
26
- ```
27
-
28
- Or write a file directly:
29
-
30
- ```python
31
- # app.naide
32
- server app port 3000:
33
- get "/":
34
- ret {message: "Hello from NAIDE"}
35
- ```
36
-
37
- ```bash
38
- naide app.naide
39
- ```
40
-
41
- ## CLI
42
-
43
- ```bash
44
- naide <file> # Run a .naide or .nx file
45
- naide # Start interactive REPL
46
- naide repl # Start interactive REPL
47
- naide init [dir] # Scaffold a new project
48
- naide build [dir] [outdir] # Transpile all files to JavaScript
49
- naide check <files...> # Type-check without running
50
- naide fmt <files...> # Format NAIDE files
51
- naide lsp # Start Language Server (LSP)
52
- naide vscode # Install VS Code extension
53
- naide deploy [dir] # Generate Dockerfile for deployment
54
- naide convert <files...> # Convert .nx ↔ .naide (bidirectional)
55
- naide pkg init # Create naide.pkg.json manifest
56
- naide pkg install <name> # Install a NAIDE package
57
- naide pkg publish # Publish package to npm
58
- naide -w <file> # Watch mode (auto-restart on changes)
59
- naide -d <file> # Debug mode (Node.js inspector)
60
- naide --emit <file> # Print generated JavaScript
61
- naide -o <out.js> <file> # Write JavaScript to file
62
- naide --mid <file.nx> # Show intermediate NAIDE v1 (debug X mode)
63
- naide --ast <file> # Print AST
64
- naide --tokens <file> # Print token stream
65
- ```
66
-
67
- ### REPL
68
-
69
- ```
70
- $ naide
71
- NAIDE REPL v1.9.0 — type NAIDE code, see JavaScript output
72
- Type .exit to quit, .eval to toggle eval mode
73
-
74
- >>> str name = "hello"
75
- const name = "hello";
76
-
77
- >>> fn add(int a, int b) -> int:
78
- ... ret a + b
79
- ...
80
- function add(a, b) {
81
- return a + b;
82
- }
83
- ```
84
-
85
- Type `.eval` to switch to evaluation mode (runs the code instead of showing JS).
86
-
87
- ### Playground
88
-
89
- Open `playground/index.html` in a browser (via a local server) for a live in-browser transpiler with examples and token count comparison.
90
-
91
- ### Benchmark
92
-
93
- ```bash
94
- node benchmark/compare.js
95
- ```
96
-
97
- ```
98
- Language Tokens Chars Lines Savings
99
- JavaScript 330 2590 78 —
100
- NAIDE 66 517 19 -80%
101
- NAIDE-X 39 435 19 -88%
102
- ```
103
-
104
- ## Language Reference
105
-
106
- ### Variables
107
-
108
- ```python
109
- str name = "hello" # immutable (const)
110
- int count = 42
111
- num price = 9.99
112
- bool active = true
113
- list items = [1, 2, 3]
114
- map config = {host: "localhost"}
115
- any data = null
116
-
117
- mut int counter = 0 # mutable (let)
118
- mut str label = "init"
119
- ```
120
-
121
- Types: `str`, `int`, `num`, `bool`, `list`, `map`, `any`, `json`, `void`
122
-
123
- ### String Interpolation
124
-
125
- ```python
126
- str greeting = "Hello {name}, you have {count} items"
127
- ```
128
-
129
- Double-quoted strings with `{expr}` are auto-interpolated.
130
-
131
- ### Functions
132
-
133
- ```python
134
- fn add(int a, int b) -> int:
135
- ret a + b
136
-
137
- fn greet(str name, str prefix = "Hello"):
138
- log "{prefix}, {name}!"
139
-
140
- fn sum(...int nums) -> int:
141
- mut int total = 0
142
- each n in nums:
143
- total += n
144
- ret total
145
-
146
- fn.async fetchUser(str id) -> map:
147
- any res = await fetch("/api/users/{id}")
148
- ret await res.json()
149
- ```
150
-
151
- ### Control Flow
152
-
153
- ```python
154
- if count > 10:
155
- log "many"
156
- elif count > 5:
157
- log "some"
158
- else:
159
- log "few"
160
-
161
- str size = if count > 10 then "big" else "small"
162
- ```
163
-
164
- ### Loops
165
-
166
- ```python
167
- each item in items:
168
- log item
169
-
170
- each key, val in config:
171
- log "{key}: {val}"
172
-
173
- for i in 0..10:
174
- log i
175
-
176
- while active:
177
- log "running"
178
- active = false
179
- ```
180
-
181
- ### Pattern Matching
182
-
183
- ```python
184
- match status:
185
- "ok": log "success"
186
- "error": log "failed"
187
- _: log "unknown"
188
- ```
189
-
190
- ### Error Handling
191
-
192
- ```python
193
- try:
194
- data = await fetchData(url)
195
- fail e:
196
- log.error e.message
197
- ensure:
198
- log "request completed"
199
- ```
200
-
201
- `ensure:` is NAIDE's `finally` — the block always runs, whether the `try` succeeds or fails. `fail` is optional:
202
-
203
- ```python
204
- try:
205
- conn = await openConnection()
206
- ret await conn.query("SELECT 1")
207
- ensure:
208
- conn.close()
209
- ```
210
-
211
- ### Type Checking
212
-
213
- ```python
214
- if typeof data == "string":
215
- log "is string"
216
-
217
- if err instanceof TypeError:
218
- log "type error"
219
- ```
220
-
221
- `typeof` returns the type as a string. `instanceof` checks if a value is an instance of a class/constructor.
222
-
223
- ### Classes
224
-
225
- ```python
226
- model User:
227
- str name
228
- str email
229
- int age = 0
230
-
231
- fn greet() -> str:
232
- ret "Hi, I'm {self.name}"
233
-
234
- model Admin extends User:
235
- str role = "admin"
236
- fn permissions() -> list:
237
- ret ["read", "write", "delete"]
238
- ```
239
-
240
- ### Pipe Operator
241
-
242
- ```python
243
- list result = data
244
- |> filter((x) => x.active)
245
- |> map((x) => x.name)
246
- |> sort()
247
- ```
248
-
249
- ### Imports / Exports
250
-
251
- ```python
252
- use express
253
- use {readFile, writeFile} from "fs/promises"
254
- use axios from "axios"
255
-
256
- pub fn helper() -> str:
257
- ret "exported"
258
- pub str VERSION = "1.0.0"
259
- ```
260
-
261
- ## Server & API Features
262
-
263
- All features below are zero-dependency — the runtime is bundled with the package.
264
-
265
- ### server — Express App
266
-
267
- ```python
268
- server app port 3000:
269
- get "/":
270
- ret {message: "hello"}
271
- post "/api/data" (req, res):
272
- ret req.body
273
- put "/api/data/:id" (req, res):
274
- ret {updated: true}
275
- del "/api/data/:id":
276
- ret {deleted: true}
277
- patch "/api/data/:id" (req, res):
278
- ret {patched: true}
279
- ```
280
-
281
- ### schema — Data Models
282
-
283
- ```python
284
- schema User:
285
- id auto
286
- name str required min(2) max(50)
287
- email str required email unique
288
- age int optional min(0) max(150)
289
- role enum("admin", "user") default("user")
290
- joined timestamp auto
291
- ```
292
-
293
- Types: `str`, `int`, `num`, `bool`, `auto` (UUID), `timestamp`, `enum(...)`
294
- Modifiers: `required`, `optional`, `min(n)`, `max(n)`, `email`, `url`, `unique`, `auto`, `default(val)`
295
-
296
- ### db — Persistent Storage
297
-
298
- ```python
299
- db "data/"
300
- ```
301
-
302
- Schemas auto-persist to JSON files (`data/User.json`, etc.). Without `db`, data is in-memory only.
303
-
304
- ### crud — Auto-generated REST Endpoints
305
-
306
- ```python
307
- server app port 3000:
308
- crud "/api/users" User
309
- ```
310
-
311
- Generates GET (list + by-ID), POST, PUT, DELETE with validation. Built-in pagination, search, and sort:
312
-
313
- ```
314
- GET /api/users?page=2&limit=10&q=john&sort=name&order=asc
315
- ```
316
-
317
- Response: `{ data: [...], total, page, limit, pages }`
318
-
319
- ### validate — Request Validation
320
-
321
- ```python
322
- server app port 3000:
323
- validate "/api/users" User
324
- post "/api/users" (req, res):
325
- user = UserStore.create(req.body) # body is pre-validated
326
- ret user
327
- ```
328
-
329
- Auto-validates POST/PUT/PATCH bodies against the schema. Returns `400` with error details if invalid. Validated data replaces `req.body`.
330
-
331
- ### auth — JWT Authentication
332
-
333
- ```python
334
- server app port 3000:
335
- auth JWT_SECRET:
336
- protect "/api/*"
337
- public "/api/auth/*"
338
-
339
- post "/api/auth/login" (req, res):
340
- token = auth.sign({id: user.id})
341
- ret {token}
342
- ```
343
-
344
- ### cors / limit / cookie / session
345
-
346
- ```python
347
- server app port 3000:
348
- cors "*" # CORS middleware
349
- limit "/api/*" 100 "1m" # rate limiting (100 req/min)
350
- cookie # cookie parser → req.cookies
351
- session "my-secret" # cookie sessions → req.session
352
- ```
353
-
354
- ### upload — File Uploads
355
-
356
- ```python
357
- server app port 3000:
358
- upload "/api/upload" "avatar" (req, res):
359
- ret {filename: req.file.filename, size: req.file.size}
360
- ```
361
-
362
- Zero-dependency multipart parser. `req.file` = `{filename, contentType, data, size}`.
363
-
364
- ### view — Template Rendering
365
-
366
- ```python
367
- server app port 3000:
368
- view "./views"
369
- get "/":
370
- ret.render "home" {title: "Welcome", items: ["a", "b"]}
371
- ```
372
-
373
- Reads `.html` files with `{{variable}}`, `{{if key}}...{{/if}}`, `{{each item in list}}...{{/each}}`.
374
-
375
- ### sse — Server-Sent Events
376
-
377
- ```python
378
- server app port 3000:
379
- sse "/events"
380
- post "/api/notify" (req, res):
381
- sse.broadcast req.body
382
- ret {ok: true}
383
- ```
384
-
385
- `sse.send(data)`, `sse.broadcast(data)`, `sse.count`.
386
-
387
- ### cache — Response Caching
388
-
389
- ```python
390
- server app port 3000:
391
- cache "/api/*" "5m"
392
- ```
393
-
394
- Caches GET responses in memory with TTL. Sets `X-Cache: HIT/MISS`.
395
-
396
- ### ws — WebSocket
397
-
398
- ```python
399
- server app port 3000:
400
- ws "/chat":
401
- on "connect":
402
- send({type: "welcome"})
403
- on "message" (data):
404
- broadcast(data)
405
- on "close":
406
- log "client left"
407
- ```
408
-
409
- Built-in `send(data)` and `broadcast(data)`. Requires `npm install ws`.
410
-
411
- ### group — Route Groups
412
-
413
- ```python
414
- server app port 3000:
415
- group "/api/v1":
416
- get "/users":
417
- ret users
418
- post "/users" (req, res):
419
- ret req.body
420
- ```
421
-
422
- ### mid — Named Middleware
423
-
424
- ```python
425
- fn logger(req, res, next):
426
- log req.method, req.url
427
- next()
428
-
429
- server app port 3000:
430
- mid logger # apply globally
431
- mid logger "/api" # apply to path only
432
- ```
433
-
434
- ### Route-Level Middleware
435
-
436
- Apply middleware to specific routes with bracket syntax:
437
-
438
- ```python
439
- server app port 3000:
440
- get "/admin" [authCheck] (req, res):
441
- ret {admin: true}
442
-
443
- post "/api/data" [auth, logger, validator] (req, res):
444
- ret req.body
445
- ```
446
-
447
- Compiles to `app.get("/admin", authCheck, (req, res) => { ... })`.
448
-
449
- ### static — Serve Files
450
-
451
- ```python
452
- server app port 3000:
453
- static "/public"
454
- ```
455
-
456
- ### error — Error Handler
457
-
458
- ```python
459
- server app port 3000:
460
- error (err, req, res):
461
- log.error err.message
462
- ret.status 500 {error: "Internal error"}
463
- ```
464
-
465
- ### openapi — Auto-Generated API Docs
466
-
467
- ```python
468
- server app port 3000:
469
- openapi "/docs"
470
- ```
471
-
472
- Generates an OpenAPI 3.1 JSON spec from your schemas, served at the specified path.
473
-
474
- ### Response Helpers
475
-
476
- ```python
477
- ret {data: items} # JSON (default)
478
- ret.status 404 {error: "nope"} # status code
479
- ret.redirect "/login" # redirect
480
- ret.redirect 301 "/new-url" # redirect with status
481
- ret.html "<h1>Hello</h1>" # HTML
482
- ret.text "pong" # plain text
483
- ret.file "/path/to/file" # send file
484
- ret.download "/path/to/file.zip" # file download
485
- ret.download "/file.zip" "custom.zip" # download with filename
486
- ret.render "template" {data} # render template (requires view)
487
- ```
488
-
489
- ## Testing
490
-
491
- Built-in test syntax using Node.js test runner:
492
-
493
- ```python
494
- test "user creation":
495
- user = UserStore.create({name: "Alice", email: "alice@test.com"})
496
- assert user.name == "Alice"
497
- assert user.email == "alice@test.com"
498
-
499
- test "math":
500
- assert 1 + 1 == 2
501
- assert 10 > 5
502
- ```
503
-
504
- `assert a == b` generates `assert.strictEqual` for better error messages. Run with `node --test`.
505
-
506
- ### Mock / Spy (Test Utilities)
507
-
508
- ```python
509
- fn.async main():
510
- # Create a mock function
511
- any mock = createMock()
512
- mock(1, 2)
513
- mock("hello")
514
- log mock.callCount() # 2
515
- log mock.calledWith(1, 2) # true
516
-
517
- # Mock with return value
518
- mock.returns(42)
519
- log mock() # 42
520
-
521
- # Spy on an existing method
522
- any spy = createSpy(obj, "method")
523
- obj.method("arg")
524
- log spy.callCount() # 1
525
- spy.restore() # restores original method
526
- ```
527
-
528
- `createMock(fn?)` — create a mock function with `.calls`, `.callCount()`, `.calledWith(...)`, `.returns(val)`, `.impl(fn)`, `.reset()`.
529
- `createSpy(obj, method)` — wraps an existing method with a mock. `.restore()` reverts it.
530
-
531
- ## Job Queue
532
-
533
- In-memory async job queue for background processing:
534
-
535
- ```python
536
- queue jobs:
537
- job "sendEmail" (data):
538
- log "sending to {data.to}"
539
- job "resize" (data):
540
- log "resizing {data.path}"
541
-
542
- server app port 3000:
543
- post "/api/notify" (req, res):
544
- jobs.add("sendEmail", {to: req.body.email})
545
- ret {queued: true}
546
- ```
547
-
548
- ## Scheduled Tasks & Events
549
-
550
- ```python
551
- every "5m":
552
- log "cleanup running"
553
-
554
- watch User.create (event):
555
- log "new user: {event.data.name}"
556
- ```
557
-
558
- Intervals: `"30s"`, `"5m"`, `"1h"`, `"1d"`.
559
- `watch` connects to `crud` events automatically.
560
-
561
- ## Environment Variables
562
-
563
- ```python
564
- env:
565
- PORT int default(3000)
566
- JWT_SECRET str required
567
- DB_URL str default("data/")
568
- ```
569
-
570
- Variables become constants. Missing `required` vars exit with an error.
571
-
572
- ## Built-in Functions
573
-
574
- ```python
575
- str id = uuid() # UUID
576
- str hashed = hash("password") # scrypt hash
577
- bool ok = verify("password", hashed) # timing-safe verify
578
- str token = sign({id: 1}) # JWT (uses auth secret)
579
- str token = sign({id: 1}, "my-secret") # JWT (explicit secret)
580
- ```
581
-
582
- Auto-imported from the runtime when used.
583
-
584
- ## HTTP Client
585
-
586
- ```python
587
- fn.async getUsers() -> any:
588
- any users = await api.get("https://api.example.com/users")
589
- ret users
590
-
591
- fn.async createUser(map data) -> any:
592
- any result = await api.post("https://api.example.com/users", data)
593
- ret result
594
- ```
595
-
596
- Methods: `api.get(url)`, `api.post(url, body)`, `api.put(url, body)`, `api.del(url)`, `api.raw(url, opts)`.
597
-
598
- ## AI / LLM Integration
599
-
600
- Built-in AI client — zero dependencies, auto-detects provider from API key:
601
-
602
- ```python
603
- fn.async main():
604
- # Simple prompt
605
- str answer = await ai.ask("Explain NAIDE in one sentence")
606
-
607
- # Structured JSON output
608
- map result = await ai.json("List 3 colors", {colors: ["string"]})
609
-
610
- # Multi-turn chat
611
- list msgs = [{role: "user", content: "Hi"}, {role: "assistant", content: "Hello!"}, {role: "user", content: "What is 2+2?"}]
612
- str reply = await ai.chat(msgs)
613
-
614
- # With options
615
- str answer2 = await ai.ask("hello", {model: "gpt-4o", maxTokens: 100})
616
- ```
617
-
618
- Set `AI_KEY`, `OPENAI_API_KEY`, or `ANTHROPIC_API_KEY` env var. Provider auto-detected: `sk-ant-*` → Anthropic, otherwise OpenAI-compatible.
619
-
620
- ### AI Streaming
621
-
622
- ```python
623
- fn.async main():
624
- each chunk in await ai.stream("Write a poem"):
625
- log chunk
626
- ```
627
-
628
- Returns an async iterator of text chunks — works with SSE for real-time chat UIs.
629
-
630
- ### Embeddings & Vector Search (RAG)
631
-
632
- ```python
633
- fn.async main():
634
- # Generate embeddings
635
- list vec = await ai.embed("hello world")
636
- list vecs = await ai.embed(["hello", "world"])
637
-
638
- # Cosine similarity
639
- num score = ai.similarity(vec1, vec2)
640
- ```
641
-
642
- Built-in vector store for RAG:
643
-
644
- ```python
645
- fn.async search(str query):
646
- list qVec = await ai.embed(query)
647
- list results = vectors.search(qVec, 5)
648
- ret results
649
- ```
650
-
651
- `createVectorStore()` — in-memory vector store with `add(id, embedding, metadata)`, `search(queryEmbedding, topK)`, `remove(id)`, `clear()`.
652
-
653
- ### Prompt Templates
654
-
655
- Reusable prompt declarations with default variables:
656
-
657
- ```python
658
- prompt summarize {lang: "en"}:
659
- "Summarize the following text in {lang}:"
660
- "{text}"
661
-
662
- fn.async main():
663
- str p = summarize({text: "hello world"})
664
- str answer = await ai.ask(p)
665
- ```
666
-
667
- Multi-line templates are joined with newlines. Variables use `{name}` syntax.
668
-
669
- ### AI in Server Routes
670
-
671
- ```python
672
- server app port 3000:
673
- post "/api/ask" (req, res):
674
- str answer = await ai.ask(req.body.prompt)
675
- ret {answer}
676
- ```
677
-
678
- ## SQL Database
679
-
680
- SQLite and PostgreSQL support with the same store API:
681
-
682
- ```python
683
- db.sql "sqlite" "app.db"
684
-
685
- schema User:
686
- id auto
687
- name str required
688
- email str required email
689
-
690
- server app port 3000:
691
- crud "/api/users" User
692
- ```
693
-
694
- Schemas with `db.sql` auto-use SQL storage instead of JSON files. Same API: `getAll`, `getById`, `create`, `update`, `delete`, `where`, `count`, `clear`.
695
-
696
- Schema migration is automatic — when you add new fields to a schema, `ALTER TABLE ADD COLUMN` runs at startup. No manual migration needed.
697
-
698
- PostgreSQL:
699
-
700
- ```python
701
- db.sql "postgres" "postgresql://localhost/mydb"
702
- ```
703
-
704
- ## Language Server (LSP)
705
-
706
- Built-in LSP for editor integration — diagnostics, completions, and hover docs:
707
-
708
- ```bash
709
- naide lsp
710
- ```
711
-
712
- ### VS Code
713
-
714
- ```bash
715
- naide vscode
716
- ```
717
-
718
- One command installs the extension — syntax highlighting, LSP diagnostics, autocomplete, and hover docs for `.naide` and `.nx` files. Restart VS Code after install.
719
-
720
- ## Deploy
721
-
722
- Generate deployment files with one command:
723
-
724
- ```bash
725
- naide deploy
726
- ```
727
-
728
- Creates `Dockerfile` and `.dockerignore`. Then:
729
-
730
- ```bash
731
- docker build -t naide-app .
732
- docker run -p 3000:3000 naide-app
733
- ```
734
-
735
- ## Multi-File Projects
736
-
737
- Import between NAIDE files — extensions are auto-rewritten to `.mjs` in output:
738
-
739
- ```python
740
- # routes.naide
741
- pub fn.async handleUser(req, res):
742
- ret {user: req.params.id}
743
- ```
744
-
745
- ```python
746
- # app.naide
747
- use {handleUser} from "./routes.naide"
748
-
749
- server app port 3000:
750
- get "/user/:id" [handleUser] (req, res):
751
- ret {ok: true}
752
- ```
753
-
754
- Build all files with `naide build`, which compiles every `.naide`/`.nx` file to `.mjs`.
755
-
756
- ## Full Example
757
-
758
- ```python
759
- db.sql "sqlite" "app.db"
760
-
761
- env:
762
- PORT int default(3000)
763
- JWT_SECRET str required
764
-
765
- schema User:
766
- id auto
767
- name str required min(2) max(50)
768
- email str required email
769
- password str required
770
-
771
- queue jobs:
772
- job "welcome" (data):
773
- log "Welcome email to {data.email}"
774
-
775
- server app port PORT:
776
- cors "*"
777
- cookie
778
- session JWT_SECRET
779
- auth JWT_SECRET:
780
- protect "/api/*"
781
- public "/api/auth/*"
782
- limit "/api/*" 100 "1m"
783
- static "/public"
784
- cache "/api/users" "1m"
785
- validate "/api/users" User
786
- crud "/api/users" User
787
- openapi "/docs"
788
-
789
- post "/api/auth/register" (req, res):
790
- try:
791
- str hashed = hash(req.body.password)
792
- user = UserStore.create({...req.body, password: hashed})
793
- token = auth.sign({id: user.id})
794
- jobs.add("welcome", {email: user.email})
795
- ret {token, user}
796
- fail e:
797
- ret.status 500 {error: e.message}
798
- ensure:
799
- log.info "register attempt handled"
800
-
801
- post "/api/auth/login" (req, res):
802
- user = UserStore.where({email: req.body.email})[0]
803
- if not user:
804
- ret.status 401 {error: "Invalid credentials"}
805
- if not verify(req.body.password, user.password):
806
- ret.status 401 {error: "Invalid credentials"}
807
- token = auth.sign({id: user.id})
808
- ret {token}
809
-
810
- post "/api/ask" (req, res):
811
- str answer = await ai.ask(req.body.prompt)
812
- ret {answer}
813
-
814
- get "/admin" [authCheck] (req, res):
815
- if typeof req.user == "undefined":
816
- ret.status 401 {error: "not authenticated"}
817
- ret {admin: true}
818
-
819
- get "/old-page":
820
- ret.redirect 301 "/new-page"
821
-
822
- get "/download":
823
- ret.download "/files/report.pdf" "report.pdf"
824
-
825
- ws "/chat":
826
- on "message" (data):
827
- broadcast(data)
828
-
829
- sse "/events"
830
-
831
- get "/":
832
- ret.html "<h1>Welcome</h1>"
833
-
834
- error (err, req, res):
835
- log.error err.message
836
- ret.status 500 {error: "Something went wrong"}
837
-
838
- watch User.create (event):
839
- log "new user: {event.data.name}"
840
-
841
- every "30m":
842
- log "cleanup"
843
- ```
844
-
845
- This generates a complete production API — SQLite database, AI/LLM integration, auth, password hashing, CORS, sessions, rate limiting, CRUD with pagination/search, WebSocket, SSE, file caching, request validation, background jobs, auto-generated API docs, route middleware, file downloads, redirects with status codes, type checking, error handling with ensure/finally, and event-driven hooks — from ~75 lines.
846
-
847
- ## NAIDE-X Syntax (.nx)
848
-
849
- Every keyword is a single character. Line-start symbol = intent.
850
-
851
- ```
852
- s:name="World" -- str name = "World"
853
- i:count=42 -- int count = 42
854
- ~i:counter=0 -- mut int counter = 0
855
-
856
- f greet(s:who)s -- fn greet(str who) -> str:
857
- >"Hello, {who}!" -- ret "Hello, {who}!"
858
-
859
- ~f fetchData(s:url)a -- fn.async fetchData(str url) -> any:
860
- >~fetch(url) -- ret await fetch(url)
861
-
862
- ?count>5 -- if count > 5:
863
- log"many" -- log "many"
864
- |count>2 -- elif count > 2:
865
- log"some" -- log "some"
866
- : -- else:
867
- log"few" -- log "few"
868
-
869
- @item<items -- each item in items:
870
- @i<0..10 -- for i in 0..10:
871
- *active -- while active:
872
-
873
- $app:3000 -- server app port 3000:
874
- G"/users" -- get "/users":
875
- >users -- ret users
876
- P"/users"(req,res) -- post "/users" (req, res):
877
- >req.body -- ret req.body
878
- ```
879
-
880
- ### NAIDE-X Cheat Sheet
881
-
882
- | Symbol | Meaning | Symbol | Meaning |
883
- |--------|---------|--------|---------|
884
- | `>` | return | `?` | if |
885
- | `\|` | elif | `:` | else |
886
- | `@` | loop | `*` | while |
887
- | `!` | try | `!!` | catch |
888
- | `!!!` | ensure/finally | `>.d` | ret.download |
889
- | `$` | server | `^` | model |
890
- | `<` | import | `%` | match |
891
- | `f` | function | `~f` | async function |
892
- | `+` | export | `~` | await |
893
- | `G` | GET | `P` | POST |
894
- | `U` | PUT | `D` | DELETE |
895
- | `X` | PATCH | `>.s` | ret.status |
896
- | `>.r` | ret.redirect | `>.h` | ret.html |
897
- | `>.t` | ret.text | `>.v` | ret.render |
898
-
899
- Types: `s`=str `i`=int `n`=num `b`=bool `l`=list `m`=map `a`=any
900
-
901
- High-level keywords work in both modes: `schema`, `crud`, `auth`, `cors`, `limit`, `env`, `every`, `watch`, `static`, `ws`, `db`, `db.sql`, `group`, `cookie`, `error`, `session`, `upload`, `view`, `sse`, `cache`, `patch`, `validate`, `test`, `assert`, `queue`, `openapi`, `typeof`, `instanceof`, `ensure`, `ai`, `prompt`.
902
-
903
- NAIDE-X log shorthands: `log.e` = error, `log.w` = warn, `log.i` = info, `log.d` = debug.
904
-
905
- ## Plugin System
906
-
907
- Register and use plugins for extensibility:
908
-
909
- ```python
910
- registerPlugin("logger", (opts) =>
911
- ret {log: (msg) => log "[{opts.prefix}] {msg}"}
912
- )
913
-
914
- any logger = usePlugin("logger", {prefix: "APP"})
915
- logger.log("started")
916
-
917
- list names = listPlugins()
918
- ```
919
-
920
- `registerPlugin(name, setup)` — registers a plugin factory. `usePlugin(name, opts?)` — initializes on first call, returns cached exports. `listPlugins()` — returns registered plugin names.
921
-
922
- ## Convert (NX ↔ NAIDE)
923
-
924
- Bidirectional conversion between `.nx` and `.naide`:
925
-
926
- ```bash
927
- naide convert file.nx # → file.naide (expand to readable syntax)
928
- naide convert file.naide # → file.nx (compress to NX syntax)
929
- ```
930
-
931
- ## Source Maps & Error Remapping
932
-
933
- Runtime errors are automatically remapped to source file line numbers:
934
-
935
- ```
936
- Error in app.naide:12
937
- 10 | user = UserStore.getById(id)
938
- 11 | if not user:
939
- >>12 | throw "not found"
940
- ```
941
-
942
- The CLI tracks source-to-output line mappings and shows context from your `.naide`/`.nx` file, not the generated JavaScript.
943
-
944
- ## Native Dependency Detection
945
-
946
- When you run a `.naide` file, the CLI scans generated JavaScript for missing dependencies (`express`, `better-sqlite3`, `pg`, `ws`) and prints install hints:
947
-
948
- ```
949
- [NAIDE] Missing: express — run: npm install express
950
- ```
951
-
952
- ## Type Checker
953
-
954
- Compile-time type checking without running the code:
955
-
956
- ```bash
957
- naide check app.naide
958
- ```
959
-
960
- Catches type mismatches at compile time:
961
-
962
- ```
963
- app.naide:3 ERROR: Type mismatch: cannot assign str to int
964
- app.naide:7 WARN: Type warning: reassigning int variable 'count' with str
965
- ```
966
-
967
- The type checker understands NAIDE's type annotations (`str`, `int`, `num`, `bool`, `list`, `map`), infers types from expressions and function return values, and checks assignments for compatibility. `num` accepts `int` values. `any` and `json` accept all types.
968
-
969
- Also available as a flag: `naide --check app.naide` or programmatically via `compile(source, { typeCheck: true })`.
970
-
971
- ## Async Error Handling
972
-
973
- Async route handlers are automatically wrapped with try/catch to prevent unhandled rejections:
974
-
975
- ```python
976
- server app port 3000:
977
- post "/api/data" (req, res):
978
- any data = await fetchData() # if this throws...
979
- ret data # ...a 500 JSON error is returned automatically
980
- ```
981
-
982
- Generated code includes `try { ... } catch (__err) { res.status(500).json({ error: __err.message }) }` around async handlers. Routes with explicit `try/fail` blocks are left as-is.
983
-
984
- A global `process.on('unhandledRejection')` handler is also added to server code to catch any remaining async errors.
985
-
986
- ## Debugger
987
-
988
- Debug NAIDE programs with the Node.js inspector:
989
-
990
- ```bash
991
- naide -d app.naide # starts with --inspect-brk
992
- ```
993
-
994
- Then open `chrome://inspect` in Chrome to connect. The program pauses at the first line so you can set breakpoints before execution.
995
-
996
- ## Package Ecosystem
997
-
998
- Manage NAIDE packages via npm:
999
-
1000
- ```bash
1001
- naide pkg init # create naide.pkg.json manifest
1002
- naide pkg install my-plugin # install from npm + add to manifest
1003
- naide pkg publish # publish to npm with naide-plugin keyword
1004
- naide pkg list # list installed NAIDE packages
1005
- ```
1006
-
1007
- The `naide.pkg.json` manifest tracks NAIDE-specific metadata (main entry, exports, dependencies) while using npm as the underlying registry.
1008
-
1009
- ## Why NAIDE?
1010
-
1011
- AI code generation speed depends on:
1012
-
1013
- 1. **Token count** — fewer output tokens = faster generation
1014
- 2. **Predictability** — one way to write everything = better next-token prediction
1015
- 3. **Context window** — shorter code = more room for complex projects
1016
-
1017
- NAIDE-X is designed as an **AI-internal representation** — the AI thinks in NAIDE-X, users receive standard JavaScript.
1018
-
1019
- ## License
1020
-
1021
- MIT
1
+ # NAIDE
2
+
3
+ **Node AI Development Environment** — A programming language designed for AI-speed code generation that transpiles to Node.js.
4
+
5
+ NAIDE is built on three principles: one way to write everything (zero ambiguity), keyword-driven intent (the first token decides meaning), and minimal token count (fewer tokens = faster AI generation). It includes built-in declarations for servers, databases, authentication, file uploads, WebSockets, Discord bots, job queues, testing, and more — all with zero external dependencies.
6
+
7
+ Two syntax modes:
8
+
9
+ - **NAIDE** (`.naide`) — Human-readable, ~40% fewer tokens than JavaScript
10
+ - **NAIDE-X** (`.nx`) — AI-only readability, ~80% fewer tokens than JavaScript
11
+
12
+ ## Install
13
+
14
+ ```bash
15
+ npm install -g naider
16
+ ```
17
+
18
+ ## Quick Start
19
+
20
+ ```bash
21
+ # Create a new project
22
+ naide init my-app
23
+ cd my-app
24
+ npm install
25
+ npm run dev
26
+ ```
27
+
28
+ Or write a file directly:
29
+
30
+ ```python
31
+ # app.naide
32
+ server app port 3000:
33
+ get "/":
34
+ ret {message: "Hello from NAIDE"}
35
+ ```
36
+
37
+ ```bash
38
+ naide app.naide
39
+ ```
40
+
41
+ ## CLI
42
+
43
+ ```bash
44
+ naide <file> # Run a .naide or .nx file
45
+ naide # Start interactive REPL
46
+ naide repl # Start interactive REPL
47
+ naide init [dir] # Scaffold a new project
48
+ naide build [dir] [outdir] # Transpile all files to JavaScript
49
+ naide check <files...> # Type-check without running
50
+ naide fmt <files...> # Format NAIDE files
51
+ naide lsp # Start Language Server (LSP)
52
+ naide vscode # Install VS Code extension
53
+ naide deploy [dir] # Generate Dockerfile for deployment
54
+ naide convert <files...> # Convert .nx ↔ .naide (bidirectional)
55
+ naide pkg init # Create naide.pkg.json manifest
56
+ naide pkg install <name> # Install a NAIDE package
57
+ naide pkg publish # Publish package to npm
58
+ naide -w <file> # Watch mode (auto-restart on changes)
59
+ naide -d <file> # Debug mode (Node.js inspector)
60
+ naide --emit <file> # Print generated JavaScript
61
+ naide -o <out.js> <file> # Write JavaScript to file
62
+ naide --mid <file.nx> # Show intermediate NAIDE v1 (debug X mode)
63
+ naide --ast <file> # Print AST
64
+ naide --tokens <file> # Print token stream
65
+ ```
66
+
67
+ ### REPL
68
+
69
+ ```
70
+ $ naide
71
+ NAIDE REPL v1.11.0 — type NAIDE code, see JavaScript output
72
+ Type .exit to quit, .eval to toggle eval mode
73
+
74
+ >>> str name = "hello"
75
+ const name = "hello";
76
+
77
+ >>> fn add(int a, int b) -> int:
78
+ ... ret a + b
79
+ ...
80
+ function add(a, b) {
81
+ return a + b;
82
+ }
83
+ ```
84
+
85
+ Type `.eval` to switch to evaluation mode (runs the code instead of showing JS).
86
+
87
+ ### Playground
88
+
89
+ Open `playground/index.html` in a browser (via a local server) for a live in-browser transpiler with examples and token count comparison.
90
+
91
+ ### Benchmark
92
+
93
+ ```bash
94
+ node benchmark/compare.js
95
+ ```
96
+
97
+ ```
98
+ Language Tokens Chars Lines Savings
99
+ JavaScript 330 2590 78 —
100
+ NAIDE 66 517 19 -80%
101
+ NAIDE-X 39 435 19 -88%
102
+ ```
103
+
104
+ ## Language Reference
105
+
106
+ ### Variables
107
+
108
+ ```python
109
+ str name = "hello" # immutable (const)
110
+ int count = 42
111
+ num price = 9.99
112
+ bool active = true
113
+ list items = [1, 2, 3]
114
+ map config = {host: "localhost"}
115
+ any data = null
116
+
117
+ mut int counter = 0 # mutable (let)
118
+ mut str label = "init"
119
+ ```
120
+
121
+ Types: `str`, `int`, `num`, `bool`, `list`, `map`, `any`, `json`, `void`
122
+
123
+ ### String Interpolation
124
+
125
+ ```python
126
+ str greeting = "Hello {name}, you have {count} items"
127
+ ```
128
+
129
+ Double-quoted strings with `{expr}` are auto-interpolated.
130
+
131
+ ### Functions
132
+
133
+ ```python
134
+ fn add(int a, int b) -> int:
135
+ ret a + b
136
+
137
+ fn greet(str name, str prefix = "Hello"):
138
+ log "{prefix}, {name}!"
139
+
140
+ fn sum(...int nums) -> int:
141
+ mut int total = 0
142
+ each n in nums:
143
+ total += n
144
+ ret total
145
+
146
+ fn.async fetchUser(str id) -> map:
147
+ any res = await fetch("/api/users/{id}")
148
+ ret await res.json()
149
+ ```
150
+
151
+ ### Control Flow
152
+
153
+ ```python
154
+ if count > 10:
155
+ log "many"
156
+ elif count > 5:
157
+ log "some"
158
+ else:
159
+ log "few"
160
+
161
+ str size = if count > 10 then "big" else "small"
162
+ ```
163
+
164
+ ### Loops
165
+
166
+ ```python
167
+ each item in items:
168
+ log item
169
+
170
+ each key, val in config:
171
+ log "{key}: {val}"
172
+
173
+ for i in 0..10:
174
+ log i
175
+
176
+ while active:
177
+ log "running"
178
+ active = false
179
+ ```
180
+
181
+ ### Pattern Matching
182
+
183
+ ```python
184
+ match status:
185
+ "ok": log "success"
186
+ "error": log "failed"
187
+ _: log "unknown"
188
+ ```
189
+
190
+ ### Error Handling
191
+
192
+ ```python
193
+ try:
194
+ data = await fetchData(url)
195
+ fail e:
196
+ log.error e.message
197
+ ensure:
198
+ log "request completed"
199
+ ```
200
+
201
+ `ensure:` is NAIDE's `finally` — the block always runs, whether the `try` succeeds or fails. `fail` is optional:
202
+
203
+ ```python
204
+ try:
205
+ conn = await openConnection()
206
+ ret await conn.query("SELECT 1")
207
+ ensure:
208
+ conn.close()
209
+ ```
210
+
211
+ ### Type Checking
212
+
213
+ ```python
214
+ if typeof data == "string":
215
+ log "is string"
216
+
217
+ if err instanceof TypeError:
218
+ log "type error"
219
+ ```
220
+
221
+ `typeof` returns the type as a string. `instanceof` checks if a value is an instance of a class/constructor.
222
+
223
+ ### Classes
224
+
225
+ ```python
226
+ model User:
227
+ str name
228
+ str email
229
+ int age = 0
230
+
231
+ fn greet() -> str:
232
+ ret "Hi, I'm {self.name}"
233
+
234
+ model Admin extends User:
235
+ str role = "admin"
236
+ fn permissions() -> list:
237
+ ret ["read", "write", "delete"]
238
+ ```
239
+
240
+ ### Pipe Operator
241
+
242
+ ```python
243
+ list result = data
244
+ |> filter((x) => x.active)
245
+ |> map((x) => x.name)
246
+ |> sort()
247
+ ```
248
+
249
+ ### Imports / Exports
250
+
251
+ ```python
252
+ use express
253
+ use {readFile, writeFile} from "fs/promises"
254
+ use axios from "axios"
255
+
256
+ pub fn helper() -> str:
257
+ ret "exported"
258
+ pub str VERSION = "1.0.0"
259
+ ```
260
+
261
+ ## Server & API Features
262
+
263
+ All features below are zero-dependency — the runtime is bundled with the package.
264
+
265
+ ### server — Express App
266
+
267
+ ```python
268
+ server app port 3000:
269
+ get "/":
270
+ ret {message: "hello"}
271
+ post "/api/data" (req, res):
272
+ ret req.body
273
+ put "/api/data/:id" (req, res):
274
+ ret {updated: true}
275
+ del "/api/data/:id":
276
+ ret {deleted: true}
277
+ patch "/api/data/:id" (req, res):
278
+ ret {patched: true}
279
+ ```
280
+
281
+ ### schema — Data Models
282
+
283
+ ```python
284
+ schema User:
285
+ id auto
286
+ name str required min(2) max(50)
287
+ email str required email unique
288
+ age int optional min(0) max(150)
289
+ role enum("admin", "user") default("user")
290
+ joined timestamp auto
291
+ ```
292
+
293
+ Types: `str`, `int`, `num`, `bool`, `auto` (UUID), `timestamp`, `enum(...)`
294
+ Modifiers: `required`, `optional`, `min(n)`, `max(n)`, `email`, `url`, `unique`, `auto`, `default(val)`
295
+
296
+ ### db — Persistent Storage
297
+
298
+ ```python
299
+ db "data/"
300
+ ```
301
+
302
+ Schemas auto-persist to JSON files (`data/User.json`, etc.). Without `db`, data is in-memory only.
303
+
304
+ ### crud — Auto-generated REST Endpoints
305
+
306
+ ```python
307
+ server app port 3000:
308
+ crud "/api/users" User
309
+ ```
310
+
311
+ Generates GET (list + by-ID), POST, PUT, DELETE with validation. Built-in pagination, search, and sort:
312
+
313
+ ```
314
+ GET /api/users?page=2&limit=10&q=john&sort=name&order=asc
315
+ ```
316
+
317
+ Response: `{ data: [...], total, page, limit, pages }`
318
+
319
+ ### validate — Request Validation
320
+
321
+ ```python
322
+ server app port 3000:
323
+ validate "/api/users" User
324
+ post "/api/users" (req, res):
325
+ user = UserStore.create(req.body) # body is pre-validated
326
+ ret user
327
+ ```
328
+
329
+ Auto-validates POST/PUT/PATCH bodies against the schema. Returns `400` with error details if invalid. Validated data replaces `req.body`.
330
+
331
+ ### auth — JWT Authentication
332
+
333
+ ```python
334
+ server app port 3000:
335
+ auth JWT_SECRET:
336
+ protect "/api/*"
337
+ public "/api/auth/*"
338
+
339
+ post "/api/auth/login" (req, res):
340
+ token = auth.sign({id: user.id})
341
+ ret {token}
342
+ ```
343
+
344
+ ### cors / limit / cookie / session
345
+
346
+ ```python
347
+ server app port 3000:
348
+ cors "*" # CORS middleware
349
+ limit "/api/*" 100 "1m" # rate limiting (100 req/min)
350
+ cookie # cookie parser → req.cookies
351
+ session "my-secret" # cookie sessions → req.session
352
+ ```
353
+
354
+ ### upload — File Uploads
355
+
356
+ ```python
357
+ server app port 3000:
358
+ upload "/api/upload" "avatar" (req, res):
359
+ ret {filename: req.file.filename, size: req.file.size}
360
+ ```
361
+
362
+ Zero-dependency multipart parser. `req.file` = `{filename, contentType, data, size}`.
363
+
364
+ ### view — Template Rendering
365
+
366
+ ```python
367
+ server app port 3000:
368
+ view "./views"
369
+ get "/":
370
+ ret.render "home" {title: "Welcome", items: ["a", "b"]}
371
+ ```
372
+
373
+ Reads `.html` files with `{{variable}}`, `{{if key}}...{{/if}}`, `{{each item in list}}...{{/each}}`.
374
+
375
+ ### sse — Server-Sent Events
376
+
377
+ ```python
378
+ server app port 3000:
379
+ sse "/events"
380
+ post "/api/notify" (req, res):
381
+ sse.broadcast req.body
382
+ ret {ok: true}
383
+ ```
384
+
385
+ `sse.send(data)`, `sse.broadcast(data)`, `sse.count`.
386
+
387
+ ### cache — Response Caching
388
+
389
+ ```python
390
+ server app port 3000:
391
+ cache "/api/*" "5m"
392
+ ```
393
+
394
+ Caches GET responses in memory with TTL. Sets `X-Cache: HIT/MISS`.
395
+
396
+ ### ws — WebSocket
397
+
398
+ ```python
399
+ server app port 3000:
400
+ ws "/chat":
401
+ on "connect":
402
+ send({type: "welcome"})
403
+ on "message" (data):
404
+ broadcast(data)
405
+ on "close":
406
+ log "client left"
407
+ ```
408
+
409
+ Built-in `send(data)` and `broadcast(data)`. Requires `npm install ws`.
410
+
411
+ ### group — Route Groups
412
+
413
+ ```python
414
+ server app port 3000:
415
+ group "/api/v1":
416
+ get "/users":
417
+ ret users
418
+ post "/users" (req, res):
419
+ ret req.body
420
+ ```
421
+
422
+ ### mid — Named Middleware
423
+
424
+ ```python
425
+ fn logger(req, res, next):
426
+ log req.method, req.url
427
+ next()
428
+
429
+ server app port 3000:
430
+ mid logger # apply globally
431
+ mid logger "/api" # apply to path only
432
+ ```
433
+
434
+ ### Route-Level Middleware
435
+
436
+ Apply middleware to specific routes with bracket syntax:
437
+
438
+ ```python
439
+ server app port 3000:
440
+ get "/admin" [authCheck] (req, res):
441
+ ret {admin: true}
442
+
443
+ post "/api/data" [auth, logger, validator] (req, res):
444
+ ret req.body
445
+ ```
446
+
447
+ Compiles to `app.get("/admin", authCheck, (req, res) => { ... })`.
448
+
449
+ ### static — Serve Files
450
+
451
+ ```python
452
+ server app port 3000:
453
+ static "/public"
454
+ ```
455
+
456
+ ### error — Error Handler
457
+
458
+ ```python
459
+ server app port 3000:
460
+ error (err, req, res):
461
+ log.error err.message
462
+ ret.status 500 {error: "Internal error"}
463
+ ```
464
+
465
+ ### openapi — Auto-Generated API Docs
466
+
467
+ ```python
468
+ server app port 3000:
469
+ openapi "/docs"
470
+ ```
471
+
472
+ Generates an OpenAPI 3.1 JSON spec from your schemas, served at the specified path.
473
+
474
+ ### Response Helpers
475
+
476
+ ```python
477
+ ret {data: items} # JSON (default)
478
+ ret.status 404 {error: "nope"} # status code
479
+ ret.redirect "/login" # redirect
480
+ ret.redirect 301 "/new-url" # redirect with status
481
+ ret.html "<h1>Hello</h1>" # HTML
482
+ ret.text "pong" # plain text
483
+ ret.file "/path/to/file" # send file
484
+ ret.download "/path/to/file.zip" # file download
485
+ ret.download "/file.zip" "custom.zip" # download with filename
486
+ ret.render "template" {data} # render template (requires view)
487
+ ```
488
+
489
+ ## Testing
490
+
491
+ Built-in test syntax using Node.js test runner:
492
+
493
+ ```python
494
+ test "user creation":
495
+ user = UserStore.create({name: "Alice", email: "alice@test.com"})
496
+ assert user.name == "Alice"
497
+ assert user.email == "alice@test.com"
498
+
499
+ test "math":
500
+ assert 1 + 1 == 2
501
+ assert 10 > 5
502
+ ```
503
+
504
+ `assert a == b` generates `assert.strictEqual` for better error messages. Run with `node --test`.
505
+
506
+ ### Mock / Spy (Test Utilities)
507
+
508
+ ```python
509
+ fn.async main():
510
+ # Create a mock function
511
+ any mock = createMock()
512
+ mock(1, 2)
513
+ mock("hello")
514
+ log mock.callCount() # 2
515
+ log mock.calledWith(1, 2) # true
516
+
517
+ # Mock with return value
518
+ mock.returns(42)
519
+ log mock() # 42
520
+
521
+ # Spy on an existing method
522
+ any spy = createSpy(obj, "method")
523
+ obj.method("arg")
524
+ log spy.callCount() # 1
525
+ spy.restore() # restores original method
526
+ ```
527
+
528
+ `createMock(fn?)` — create a mock function with `.calls`, `.callCount()`, `.calledWith(...)`, `.returns(val)`, `.impl(fn)`, `.reset()`.
529
+ `createSpy(obj, method)` — wraps an existing method with a mock. `.restore()` reverts it.
530
+
531
+ ## Job Queue
532
+
533
+ In-memory async job queue for background processing:
534
+
535
+ ```python
536
+ queue jobs:
537
+ job "sendEmail" (data):
538
+ log "sending to {data.to}"
539
+ job "resize" (data):
540
+ log "resizing {data.path}"
541
+
542
+ server app port 3000:
543
+ post "/api/notify" (req, res):
544
+ jobs.add("sendEmail", {to: req.body.email})
545
+ ret {queued: true}
546
+ ```
547
+
548
+ ## Discord Bot
549
+
550
+ Built-in `bot` syntax for Discord bots — events, message handling, and slash commands with zero boilerplate:
551
+
552
+ ```python
553
+ bot myBot token DISCORD_TOKEN:
554
+ on "ready":
555
+ log "Bot is online!"
556
+
557
+ on "message" (msg):
558
+ if msg.content == "!ping":
559
+ msg.reply("Pong!")
560
+
561
+ slash "hello" "Says hello":
562
+ interaction.reply("Hello!")
563
+
564
+ slash "ask" "Ask the AI":
565
+ str answer = await ai.ask(interaction.options.getString("question"))
566
+ interaction.reply(answer)
567
+ ```
568
+
569
+ Compiles to **discord.js** (Node.js/Bun) or **discord.py** (Python). Multi-target:
570
+
571
+ ```bash
572
+ naide bot.naide # Node.js (discord.js)
573
+ naide bot.naide --target bun # Bun (discord.js)
574
+ naide bot.naide --target python # Python (discord.py)
575
+ ```
576
+
577
+ The `on "message"` event maps to `messageCreate` (discord.js) / `on_message` (discord.py). Slash commands are auto-registered on bot startup.
578
+
579
+ ## Scheduled Tasks & Events
580
+
581
+ ```python
582
+ every "5m":
583
+ log "cleanup running"
584
+
585
+ watch User.create (event):
586
+ log "new user: {event.data.name}"
587
+ ```
588
+
589
+ Intervals: `"30s"`, `"5m"`, `"1h"`, `"1d"`.
590
+ `watch` connects to `crud` events automatically.
591
+
592
+ ## Environment Variables
593
+
594
+ ```python
595
+ env:
596
+ PORT int default(3000)
597
+ JWT_SECRET str required
598
+ DB_URL str default("data/")
599
+ ```
600
+
601
+ Variables become constants. Missing `required` vars exit with an error.
602
+
603
+ ## Built-in Functions
604
+
605
+ ```python
606
+ str id = uuid() # UUID
607
+ str hashed = hash("password") # scrypt hash
608
+ bool ok = verify("password", hashed) # timing-safe verify
609
+ str token = sign({id: 1}) # JWT (uses auth secret)
610
+ str token = sign({id: 1}, "my-secret") # JWT (explicit secret)
611
+ ```
612
+
613
+ Auto-imported from the runtime when used.
614
+
615
+ ## HTTP Client
616
+
617
+ ```python
618
+ fn.async getUsers() -> any:
619
+ any users = await api.get("https://api.example.com/users")
620
+ ret users
621
+
622
+ fn.async createUser(map data) -> any:
623
+ any result = await api.post("https://api.example.com/users", data)
624
+ ret result
625
+ ```
626
+
627
+ Methods: `api.get(url)`, `api.post(url, body)`, `api.put(url, body)`, `api.del(url)`, `api.raw(url, opts)`.
628
+
629
+ ## AI / LLM Integration
630
+
631
+ Built-in AI client — zero dependencies, auto-detects provider from API key:
632
+
633
+ ```python
634
+ fn.async main():
635
+ # Simple prompt
636
+ str answer = await ai.ask("Explain NAIDE in one sentence")
637
+
638
+ # Structured JSON output
639
+ map result = await ai.json("List 3 colors", {colors: ["string"]})
640
+
641
+ # Multi-turn chat
642
+ list msgs = [{role: "user", content: "Hi"}, {role: "assistant", content: "Hello!"}, {role: "user", content: "What is 2+2?"}]
643
+ str reply = await ai.chat(msgs)
644
+
645
+ # With options
646
+ str answer2 = await ai.ask("hello", {model: "gpt-4o", maxTokens: 100})
647
+ ```
648
+
649
+ Set `AI_KEY`, `OPENAI_API_KEY`, or `ANTHROPIC_API_KEY` env var. Provider auto-detected: `sk-ant-*` → Anthropic, otherwise OpenAI-compatible.
650
+
651
+ ### AI Streaming
652
+
653
+ ```python
654
+ fn.async main():
655
+ each chunk in await ai.stream("Write a poem"):
656
+ log chunk
657
+ ```
658
+
659
+ Returns an async iterator of text chunks — works with SSE for real-time chat UIs.
660
+
661
+ ### Embeddings & Vector Search (RAG)
662
+
663
+ ```python
664
+ fn.async main():
665
+ # Generate embeddings
666
+ list vec = await ai.embed("hello world")
667
+ list vecs = await ai.embed(["hello", "world"])
668
+
669
+ # Cosine similarity
670
+ num score = ai.similarity(vec1, vec2)
671
+ ```
672
+
673
+ Built-in vector store for RAG:
674
+
675
+ ```python
676
+ fn.async search(str query):
677
+ list qVec = await ai.embed(query)
678
+ list results = vectors.search(qVec, 5)
679
+ ret results
680
+ ```
681
+
682
+ `createVectorStore()` — in-memory vector store with `add(id, embedding, metadata)`, `search(queryEmbedding, topK)`, `remove(id)`, `clear()`.
683
+
684
+ ### Prompt Templates
685
+
686
+ Reusable prompt declarations with default variables:
687
+
688
+ ```python
689
+ prompt summarize {lang: "en"}:
690
+ "Summarize the following text in {lang}:"
691
+ "{text}"
692
+
693
+ fn.async main():
694
+ str p = summarize({text: "hello world"})
695
+ str answer = await ai.ask(p)
696
+ ```
697
+
698
+ Multi-line templates are joined with newlines. Variables use `{name}` syntax.
699
+
700
+ ### AI in Server Routes
701
+
702
+ ```python
703
+ server app port 3000:
704
+ post "/api/ask" (req, res):
705
+ str answer = await ai.ask(req.body.prompt)
706
+ ret {answer}
707
+ ```
708
+
709
+ ## SQL Database
710
+
711
+ SQLite and PostgreSQL support with the same store API:
712
+
713
+ ```python
714
+ db.sql "sqlite" "app.db"
715
+
716
+ schema User:
717
+ id auto
718
+ name str required
719
+ email str required email
720
+
721
+ server app port 3000:
722
+ crud "/api/users" User
723
+ ```
724
+
725
+ Schemas with `db.sql` auto-use SQL storage instead of JSON files. Same API: `getAll`, `getById`, `create`, `update`, `delete`, `where`, `count`, `clear`.
726
+
727
+ Schema migration is automatic — when you add new fields to a schema, `ALTER TABLE ADD COLUMN` runs at startup. No manual migration needed.
728
+
729
+ PostgreSQL:
730
+
731
+ ```python
732
+ db.sql "postgres" "postgresql://localhost/mydb"
733
+ ```
734
+
735
+ ## Language Server (LSP)
736
+
737
+ Built-in LSP for editor integration — diagnostics, completions, and hover docs:
738
+
739
+ ```bash
740
+ naide lsp
741
+ ```
742
+
743
+ ### VS Code
744
+
745
+ ```bash
746
+ naide vscode
747
+ ```
748
+
749
+ One command installs the extension — syntax highlighting, LSP diagnostics, autocomplete, and hover docs for `.naide` and `.nx` files. Restart VS Code after install.
750
+
751
+ ## Deploy
752
+
753
+ Generate deployment files with one command:
754
+
755
+ ```bash
756
+ naide deploy
757
+ ```
758
+
759
+ Creates `Dockerfile` and `.dockerignore`. Then:
760
+
761
+ ```bash
762
+ docker build -t naide-app .
763
+ docker run -p 3000:3000 naide-app
764
+ ```
765
+
766
+ ## Multi-File Projects
767
+
768
+ Import between NAIDE files — extensions are auto-rewritten to `.mjs` in output:
769
+
770
+ ```python
771
+ # routes.naide
772
+ pub fn.async handleUser(req, res):
773
+ ret {user: req.params.id}
774
+ ```
775
+
776
+ ```python
777
+ # app.naide
778
+ use {handleUser} from "./routes.naide"
779
+
780
+ server app port 3000:
781
+ get "/user/:id" [handleUser] (req, res):
782
+ ret {ok: true}
783
+ ```
784
+
785
+ Build all files with `naide build`, which compiles every `.naide`/`.nx` file to `.mjs`.
786
+
787
+ ## Full Example
788
+
789
+ ```python
790
+ db.sql "sqlite" "app.db"
791
+
792
+ env:
793
+ PORT int default(3000)
794
+ JWT_SECRET str required
795
+
796
+ schema User:
797
+ id auto
798
+ name str required min(2) max(50)
799
+ email str required email
800
+ password str required
801
+
802
+ queue jobs:
803
+ job "welcome" (data):
804
+ log "Welcome email to {data.email}"
805
+
806
+ server app port PORT:
807
+ cors "*"
808
+ cookie
809
+ session JWT_SECRET
810
+ auth JWT_SECRET:
811
+ protect "/api/*"
812
+ public "/api/auth/*"
813
+ limit "/api/*" 100 "1m"
814
+ static "/public"
815
+ cache "/api/users" "1m"
816
+ validate "/api/users" User
817
+ crud "/api/users" User
818
+ openapi "/docs"
819
+
820
+ post "/api/auth/register" (req, res):
821
+ try:
822
+ str hashed = hash(req.body.password)
823
+ user = UserStore.create({...req.body, password: hashed})
824
+ token = auth.sign({id: user.id})
825
+ jobs.add("welcome", {email: user.email})
826
+ ret {token, user}
827
+ fail e:
828
+ ret.status 500 {error: e.message}
829
+ ensure:
830
+ log.info "register attempt handled"
831
+
832
+ post "/api/auth/login" (req, res):
833
+ user = UserStore.where({email: req.body.email})[0]
834
+ if not user:
835
+ ret.status 401 {error: "Invalid credentials"}
836
+ if not verify(req.body.password, user.password):
837
+ ret.status 401 {error: "Invalid credentials"}
838
+ token = auth.sign({id: user.id})
839
+ ret {token}
840
+
841
+ post "/api/ask" (req, res):
842
+ str answer = await ai.ask(req.body.prompt)
843
+ ret {answer}
844
+
845
+ get "/admin" [authCheck] (req, res):
846
+ if typeof req.user == "undefined":
847
+ ret.status 401 {error: "not authenticated"}
848
+ ret {admin: true}
849
+
850
+ get "/old-page":
851
+ ret.redirect 301 "/new-page"
852
+
853
+ get "/download":
854
+ ret.download "/files/report.pdf" "report.pdf"
855
+
856
+ ws "/chat":
857
+ on "message" (data):
858
+ broadcast(data)
859
+
860
+ sse "/events"
861
+
862
+ get "/":
863
+ ret.html "<h1>Welcome</h1>"
864
+
865
+ error (err, req, res):
866
+ log.error err.message
867
+ ret.status 500 {error: "Something went wrong"}
868
+
869
+ watch User.create (event):
870
+ log "new user: {event.data.name}"
871
+
872
+ every "30m":
873
+ log "cleanup"
874
+ ```
875
+
876
+ This generates a complete production API — SQLite database, AI/LLM integration, auth, password hashing, CORS, sessions, rate limiting, CRUD with pagination/search, WebSocket, SSE, file caching, request validation, background jobs, auto-generated API docs, route middleware, file downloads, redirects with status codes, type checking, error handling with ensure/finally, and event-driven hooks — from ~75 lines.
877
+
878
+ ## NAIDE-X Syntax (.nx)
879
+
880
+ Every keyword is a single character. Line-start symbol = intent.
881
+
882
+ ```
883
+ s:name="World" -- str name = "World"
884
+ i:count=42 -- int count = 42
885
+ ~i:counter=0 -- mut int counter = 0
886
+
887
+ f greet(s:who)s -- fn greet(str who) -> str:
888
+ >"Hello, {who}!" -- ret "Hello, {who}!"
889
+
890
+ ~f fetchData(s:url)a -- fn.async fetchData(str url) -> any:
891
+ >~fetch(url) -- ret await fetch(url)
892
+
893
+ ?count>5 -- if count > 5:
894
+ log"many" -- log "many"
895
+ |count>2 -- elif count > 2:
896
+ log"some" -- log "some"
897
+ : -- else:
898
+ log"few" -- log "few"
899
+
900
+ @item<items -- each item in items:
901
+ @i<0..10 -- for i in 0..10:
902
+ *active -- while active:
903
+
904
+ $app:3000 -- server app port 3000:
905
+ G"/users" -- get "/users":
906
+ >users -- ret users
907
+ P"/users"(req,res) -- post "/users" (req, res):
908
+ >req.body -- ret req.body
909
+ ```
910
+
911
+ ### NAIDE-X Cheat Sheet
912
+
913
+ | Symbol | Meaning | Symbol | Meaning |
914
+ |--------|---------|--------|---------|
915
+ | `>` | return | `?` | if |
916
+ | `\|` | elif | `:` | else |
917
+ | `@` | loop | `*` | while |
918
+ | `!` | try | `!!` | catch |
919
+ | `!!!` | ensure/finally | `>.d` | ret.download |
920
+ | `$` | server | `^` | model |
921
+ | `<` | import | `%` | match |
922
+ | `f` | function | `~f` | async function |
923
+ | `+` | export | `~` | await |
924
+ | `G` | GET | `P` | POST |
925
+ | `U` | PUT | `D` | DELETE |
926
+ | `X` | PATCH | `>.s` | ret.status |
927
+ | `>.r` | ret.redirect | `>.h` | ret.html |
928
+ | `>.t` | ret.text | `>.v` | ret.render |
929
+
930
+ Types: `s`=str `i`=int `n`=num `b`=bool `l`=list `m`=map `a`=any
931
+
932
+ High-level keywords work in both modes: `schema`, `crud`, `auth`, `cors`, `limit`, `env`, `every`, `watch`, `static`, `ws`, `db`, `db.sql`, `group`, `cookie`, `error`, `session`, `upload`, `view`, `sse`, `cache`, `patch`, `validate`, `test`, `assert`, `queue`, `openapi`, `typeof`, `instanceof`, `ensure`, `ai`, `prompt`, `bot`, `slash`.
933
+
934
+ NAIDE-X log shorthands: `log.e` = error, `log.w` = warn, `log.i` = info, `log.d` = debug.
935
+
936
+ ## Plugin System
937
+
938
+ Register and use plugins for extensibility:
939
+
940
+ ```python
941
+ registerPlugin("logger", (opts) =>
942
+ ret {log: (msg) => log "[{opts.prefix}] {msg}"}
943
+ )
944
+
945
+ any logger = usePlugin("logger", {prefix: "APP"})
946
+ logger.log("started")
947
+
948
+ list names = listPlugins()
949
+ ```
950
+
951
+ `registerPlugin(name, setup)` — registers a plugin factory. `usePlugin(name, opts?)` — initializes on first call, returns cached exports. `listPlugins()` — returns registered plugin names.
952
+
953
+ ## Convert (NX ↔ NAIDE)
954
+
955
+ Bidirectional conversion between `.nx` and `.naide`:
956
+
957
+ ```bash
958
+ naide convert file.nx # → file.naide (expand to readable syntax)
959
+ naide convert file.naide # → file.nx (compress to NX syntax)
960
+ ```
961
+
962
+ ## Source Maps & Error Remapping
963
+
964
+ Runtime errors are automatically remapped to source file line numbers:
965
+
966
+ ```
967
+ Error in app.naide:12
968
+ 10 | user = UserStore.getById(id)
969
+ 11 | if not user:
970
+ >>12 | throw "not found"
971
+ ```
972
+
973
+ The CLI tracks source-to-output line mappings and shows context from your `.naide`/`.nx` file, not the generated JavaScript.
974
+
975
+ ## Native Dependency Detection
976
+
977
+ When you run a `.naide` file, the CLI scans generated JavaScript for missing dependencies (`express`, `better-sqlite3`, `pg`, `ws`) and prints install hints:
978
+
979
+ ```
980
+ [NAIDE] Missing: express — run: npm install express
981
+ ```
982
+
983
+ ## Type Checker
984
+
985
+ Compile-time type checking without running the code:
986
+
987
+ ```bash
988
+ naide check app.naide
989
+ ```
990
+
991
+ Catches type mismatches at compile time:
992
+
993
+ ```
994
+ app.naide:3 ERROR: Type mismatch: cannot assign str to int
995
+ app.naide:7 WARN: Type warning: reassigning int variable 'count' with str
996
+ ```
997
+
998
+ The type checker understands NAIDE's type annotations (`str`, `int`, `num`, `bool`, `list`, `map`), infers types from expressions and function return values, and checks assignments for compatibility. `num` accepts `int` values. `any` and `json` accept all types.
999
+
1000
+ Also available as a flag: `naide --check app.naide` or programmatically via `compile(source, { typeCheck: true })`.
1001
+
1002
+ ## Async Error Handling
1003
+
1004
+ Async route handlers are automatically wrapped with try/catch to prevent unhandled rejections:
1005
+
1006
+ ```python
1007
+ server app port 3000:
1008
+ post "/api/data" (req, res):
1009
+ any data = await fetchData() # if this throws...
1010
+ ret data # ...a 500 JSON error is returned automatically
1011
+ ```
1012
+
1013
+ Generated code includes `try { ... } catch (__err) { res.status(500).json({ error: __err.message }) }` around async handlers. Routes with explicit `try/fail` blocks are left as-is.
1014
+
1015
+ A global `process.on('unhandledRejection')` handler is also added to server code to catch any remaining async errors.
1016
+
1017
+ ## Debugger
1018
+
1019
+ Debug NAIDE programs with the Node.js inspector:
1020
+
1021
+ ```bash
1022
+ naide -d app.naide # starts with --inspect-brk
1023
+ ```
1024
+
1025
+ Then open `chrome://inspect` in Chrome to connect. The program pauses at the first line so you can set breakpoints before execution.
1026
+
1027
+ ## Package Ecosystem
1028
+
1029
+ Manage NAIDE packages via npm:
1030
+
1031
+ ```bash
1032
+ naide pkg init # create naide.pkg.json manifest
1033
+ naide pkg install my-plugin # install from npm + add to manifest
1034
+ naide pkg publish # publish to npm with naide-plugin keyword
1035
+ naide pkg list # list installed NAIDE packages
1036
+ ```
1037
+
1038
+ The `naide.pkg.json` manifest tracks NAIDE-specific metadata (main entry, exports, dependencies) while using npm as the underlying registry.
1039
+
1040
+ ## Why NAIDE?
1041
+
1042
+ AI code generation speed depends on:
1043
+
1044
+ 1. **Token count** — fewer output tokens = faster generation
1045
+ 2. **Predictability** — one way to write everything = better next-token prediction
1046
+ 3. **Context window** — shorter code = more room for complex projects
1047
+
1048
+ NAIDE-X is designed as an **AI-internal representation** — the AI thinks in NAIDE-X, users receive standard JavaScript.
1049
+
1050
+ ## License
1051
+
1052
+ MIT