niral 0.1.4 → 0.1.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/LICENSE +28 -0
- package/README.md +494 -75
- package/assets/niral-logo.svg +1 -0
- package/bin/niral.js +437 -11
- package/niralscript/LICENSE +223 -0
- package/niralscript/README.md +269 -0
- package/niralscript/analysis.js +962 -0
- package/niralscript/check.js +10 -0
- package/niralscript/cli.js +147 -0
- package/niralscript/compile.js +354 -0
- package/niralscript/contracts.js +48 -0
- package/niralscript/errors.js +30 -0
- package/niralscript/expressions.js +652 -0
- package/niralscript/modules.js +58 -0
- package/niralscript/package.json +18 -0
- package/niralscript/parser.js +661 -0
- package/niralscript/scanner.js +150 -0
- package/niralscript/types.js +1067 -0
- package/package.json +19 -11
- package/src/add/api.js +26 -0
- package/src/add/auth.js +451 -0
- package/src/add/chat.js +96 -0
- package/src/add/fonts.js +75 -0
- package/src/add/image.js +61 -0
- package/src/add/imagetools.js +159 -0
- package/src/add/llm.js +127 -0
- package/src/add/sqlite.js +107 -0
- package/src/add/tailwind.js +123 -0
- package/src/add/typescript.js +73 -0
- package/src/build/build.js +345 -0
- package/src/build/bundle-runtime.js +139 -0
- package/src/build/export.js +71 -0
- package/src/check/check.js +425 -0
- package/src/compiler/ast.js +70 -0
- package/src/compiler/codegen.js +845 -0
- package/src/compiler/errors.js +72 -0
- package/src/compiler/jsx.js +460 -0
- package/src/compiler/niralscript.js +263 -0
- package/src/compiler/parser.js +490 -0
- package/src/compiler/rewrite.js +420 -0
- package/src/compiler/scanner.js +198 -0
- package/src/compiler/style.js +193 -0
- package/src/compiler/typescript.js +258 -0
- package/src/create.js +329 -0
- package/src/deploy.js +346 -0
- package/src/dev/client.js +205 -0
- package/src/dev/devtools-client.js +305 -0
- package/src/dev/devtools-errors.js +96 -0
- package/src/dev/devtools.js +119 -0
- package/src/dev/server.js +812 -0
- package/src/dev/websocket.js +145 -0
- package/src/di/README.md +191 -0
- package/src/di/agent.js +100 -0
- package/src/di/cli.js +243 -0
- package/src/di/provider.js +211 -0
- package/src/di/workspace.js +110 -0
- package/src/doctor.js +163 -0
- package/src/index.js +36 -0
- package/src/langs/go/runner.go +176 -0
- package/src/langs/python/runner.py +111 -0
- package/src/langs/ruby/runner.rb +105 -0
- package/src/lsp/analysis.js +226 -0
- package/src/lsp/niralscript.js +187 -0
- package/src/lsp/server.js +227 -0
- package/src/runtime/dom.js +760 -0
- package/src/runtime/forms.js +97 -0
- package/src/runtime/i18n.js +31 -0
- package/src/runtime/index.js +12 -0
- package/src/runtime/live.js +82 -0
- package/src/runtime/navigation.js +15 -0
- package/src/runtime/refresh.js +41 -0
- package/src/runtime/router.js +260 -0
- package/src/runtime/rpc.js +71 -0
- package/src/runtime/signals.js +339 -0
- package/src/runtime/ssr.js +164 -0
- package/src/server/ai.js +107 -0
- package/src/server/auth.js +152 -0
- package/src/server/backplane.js +91 -0
- package/src/server/context.js +48 -0
- package/src/server/dom-shim.js +149 -0
- package/src/server/endpoint-modules.js +77 -0
- package/src/server/endpoints.js +109 -0
- package/src/server/forms.js +67 -0
- package/src/server/hooks.js +112 -0
- package/src/server/i18n.js +75 -0
- package/src/server/integrity.js +73 -0
- package/src/server/jobs.js +342 -0
- package/src/server/live.js +194 -0
- package/src/server/mail.js +179 -0
- package/src/server/migrate.js +88 -0
- package/src/server/oauth.js +144 -0
- package/src/server/observe.js +87 -0
- package/src/server/page.js +135 -0
- package/src/server/polyglot.js +107 -0
- package/src/server/postgres.js +359 -0
- package/src/server/prod.js +779 -0
- package/src/server/rag.js +131 -0
- package/src/server/ratelimit.js +25 -0
- package/src/server/recover.js +183 -0
- package/src/server/remote-snapshot.js +231 -0
- package/src/server/render.js +177 -0
- package/src/server/router.js +132 -0
- package/src/server/rpc.js +264 -0
- package/src/server/security.js +78 -0
- package/src/server/session.js +135 -0
- package/src/server/shield.js +278 -0
- package/src/server/stream.js +121 -0
- package/src/server/uploads.js +96 -0
- package/src/server/watchdog.js +144 -0
- package/src/server/webauthn.js +245 -0
- package/src/server/workers.js +143 -0
- package/src/shared/validate.js +131 -0
- package/src/templates.js +254 -0
- package/src/test-runner.js +88 -0
- package/src/testing.js +41 -0
- package/bin/create-niral.js +0 -35
- package/index.js +0 -257
package/LICENSE
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 ZyoraLabs
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
EXCEPTION: The `niralscript/` directory contains the NiralScript compiler,
|
|
26
|
+
which is licensed separately under the Apache License, Version 2.0, with a
|
|
27
|
+
Runtime Library Exception. See `niralscript/LICENSE` for its terms. The MIT
|
|
28
|
+
license above does not apply to any file in that directory.
|
package/README.md
CHANGED
|
@@ -1,109 +1,528 @@
|
|
|
1
|
-
|
|
1
|
+
<div align="center">
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
# Niral
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
**The full-stack framework with zero dependencies.**
|
|
6
|
+
|
|
7
|
+
Compiler-first components · fine-grained reactivity · SSR at Svelte speed —
|
|
8
|
+
served 7.5× faster than Next.js. Auth, jobs, realtime, AI and deploys built in.
|
|
9
|
+
`node_modules` not required.
|
|
10
|
+
|
|
11
|
+
[Docs](https://niral.site) · [Benchmarks](https://niral.site/docs/benchmarks) · [CLI reference](https://niral.site/docs/cli) · [VS Code extension](https://marketplace.visualstudio.com/items?itemName=zyoralabs.niral-vscode)
|
|
12
|
+
|
|
13
|
+
</div>
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## Quick start
|
|
6
18
|
|
|
7
19
|
```sh
|
|
8
|
-
npx niral
|
|
9
|
-
cd
|
|
10
|
-
npx niral dev
|
|
20
|
+
npx create-niral my-app
|
|
21
|
+
cd my-app
|
|
22
|
+
npx niral dev # → http://localhost:5199
|
|
11
23
|
```
|
|
12
24
|
|
|
13
|
-
|
|
25
|
+
No npm? `curl -fsSL https://niral.site/install.sh | bash` — or go direct:
|
|
14
26
|
|
|
15
27
|
```sh
|
|
16
|
-
|
|
17
|
-
niral create
|
|
18
|
-
niral dev myapp
|
|
28
|
+
git clone https://github.com/Zyora-Dev/niral.git
|
|
29
|
+
node niral/bin/niral.js create my-app
|
|
19
30
|
```
|
|
20
31
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
32
|
+
There is nothing to install. The framework is Node 22+ stdlib, end to end:
|
|
33
|
+
parser, compiler, reactivity, SSR, WebSockets, sessions, crypto, SQLite.
|
|
34
|
+
No account, no cloud, no telemetry — everything runs on your machine.
|
|
24
35
|
|
|
25
|
-
|
|
26
|
-
[repository](https://github.com/Zyora-Dev/niral) into `~/.niral/framework`.
|
|
27
|
-
Set `NIRAL_HOME` to choose another install directory. Normal commands reuse the
|
|
28
|
-
cached framework without checking the network. Keep projects outside that directory.
|
|
36
|
+
## CLI Installation And Updates
|
|
29
37
|
|
|
30
|
-
|
|
38
|
+
Use `npx niral <command>` in the current terminal, or open a new terminal after
|
|
39
|
+
scaffolding to use the generated `niral` command. For a global npm install, choose
|
|
40
|
+
either `npm install -g niral` or `npm install -g create-niral`; both provide the
|
|
41
|
+
same executable names. The framework is cached in `~/.niral/framework`, or under
|
|
42
|
+
`NIRAL_HOME` when configured. Keep apps outside the framework installation.
|
|
31
43
|
|
|
32
44
|
```sh
|
|
45
|
+
npx create-niral myblog --template blog
|
|
33
46
|
npx niral --help
|
|
34
47
|
npx niral --version
|
|
35
|
-
npx niral check myapp
|
|
36
|
-
npx niral test myapp
|
|
37
|
-
npx niral build myapp
|
|
38
|
-
npx niral start myapp
|
|
39
|
-
npx niral add api myapp
|
|
40
48
|
```
|
|
41
49
|
|
|
42
|
-
|
|
43
|
-
status preserved. See the [complete CLI reference](https://niral.site/docs/cli).
|
|
44
|
-
`--version` reports this launcher and, when installed, the framework version.
|
|
45
|
-
The generated direct `niral` shim reports the framework version only.
|
|
46
|
-
|
|
47
|
-
## Update
|
|
48
|
-
|
|
49
|
-
Launcher 0.1.4 supports explicit framework updates and persisted revision pins:
|
|
50
|
+
Launcher 0.1.4 provides **explicit framework updates and revision pins**:
|
|
50
51
|
|
|
51
52
|
```sh
|
|
52
53
|
npx niral@latest update
|
|
54
|
+
niral update
|
|
53
55
|
```
|
|
54
56
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
`
|
|
57
|
+
The first form can upgrade an older cached framework without an update command.
|
|
58
|
+
Normal commands reuse the cache; fetching the latest npm launcher alone does not refresh it.
|
|
59
|
+
Updates follow the official repository's `main` branch by default. Set `NIRAL_REF`
|
|
60
|
+
to a reviewed full lowercase 40-character commit SHA or existing `v`-prefixed tag
|
|
61
|
+
for an explicit installation/update. The selection persists across plain updates;
|
|
62
|
+
use `NIRAL_REF=main npx niral@latest update` to remove it. Tags can move, so use
|
|
63
|
+
full SHAs for reproducibility. Framework pins are independent of npm versions.
|
|
64
|
+
They do not modify app projects, deploy servers or update global npm packages.
|
|
65
|
+
|
|
66
|
+
Stop development/build commands before updating. Dirty/unmanaged-branch/custom-origin Git
|
|
67
|
+
checkouts are refused; failed Git updates never trigger destructive replacement.
|
|
68
|
+
Pin changes and archive replacements are staged, and the previous framework is retained as a backup,
|
|
69
|
+
including any local additions (not merged into the new copy). Source checkouts
|
|
70
|
+
outside the managed installation should be updated with Git.
|
|
71
|
+
|
|
72
|
+
See the [launcher release checklist](installer/README.md) and
|
|
73
|
+
[package usage](installer/niral/README.md).
|
|
74
|
+
|
|
75
|
+
## Release Validation
|
|
76
|
+
|
|
77
|
+
`npm run test:release` runs the framework/compiler, installer recovery, immutable
|
|
78
|
+
build, Devtools, docs, Chromium hydration and form/navigation suites, then verifies
|
|
79
|
+
both npm packages contain exactly their five allowed files. It requires isolated
|
|
80
|
+
TypeScript and Playwright/Chromium tooling; setup is in the
|
|
81
|
+
[release checklist](installer/README.md). CI runs Node 22 and 24 with disposable
|
|
82
|
+
Postgres and image-transcoding gates. The command never publishes or deploys.
|
|
83
|
+
|
|
84
|
+
Builds finish in staging before activation. Release identity includes framework
|
|
85
|
+
source and generated output; identical releases are verified and reused without
|
|
86
|
+
rewriting published files. Failed staging leaves the active release untouched.
|
|
87
|
+
|
|
88
|
+
## Local Devtools
|
|
89
|
+
|
|
90
|
+
Run `niral dev` and open the app directly on `localhost`, `127.0.0.1`, or `::1`.
|
|
91
|
+
The bottom-right Niral launcher opens a development-only inspector showing route
|
|
92
|
+
patterns, layout/module paths, loader timings, RPC dispatch/total durations, HTTP
|
|
93
|
+
statuses and failure categories. Filter requests, select details, pause updates,
|
|
94
|
+
refresh manually or clear the visible list. Escape closes the focused panel.
|
|
95
|
+
|
|
96
|
+
The **Errors** tab captures browser errors, unhandled promise rejections,
|
|
97
|
+
contained Niral runtime failures and failed RPCs (including caught calls,
|
|
98
|
+
network failures and streamed errors). Groups show a safe error class, source,
|
|
99
|
+
count and timestamps. Each tab retains up to 100 groups with the latest 20
|
|
100
|
+
occurrences per group; grouping uses category, class, source and action type,
|
|
101
|
+
not message text. Browser error history is never uploaded to the server.
|
|
102
|
+
|
|
103
|
+
RPC failures link to their exact server trace using an opaque response ID,
|
|
104
|
+
including overlapping requests. Calls started during a click, submit, change
|
|
105
|
+
or keydown handler retain that event's type and local sequence number, never
|
|
106
|
+
its target, text, key or input values. Calls after an async boundary are marked
|
|
107
|
+
unattributed rather than assigned to the most recent interaction. Transport
|
|
108
|
+
failures without a response have no server link; expired traces are unavailable.
|
|
109
|
+
|
|
110
|
+
Verified `.niral` client script lines link to VS Code. Mapping is conservative:
|
|
111
|
+
only unique, unchanged script lines are mapped; transformed or duplicate lines,
|
|
112
|
+
templates, JSX/TSX and unknown frames may show an unresolved line or source.
|
|
113
|
+
This is not a complete source map or a server exception stack. At most 512
|
|
114
|
+
loaded component maps are retained. Editor links include the local project file
|
|
115
|
+
path; server block source is never sent to the browser.
|
|
116
|
+
|
|
117
|
+
The server keeps the latest 100 completed traces in memory (up to 32 loader spans
|
|
118
|
+
per trace), shared across local tabs. Clear hides request history in the current
|
|
119
|
+
panel or empties that tab's browser error buffer, depending on the selected view.
|
|
120
|
+
An explicit error-to-request link can reveal a previously cleared request.
|
|
121
|
+
Pause stops display updates, not collection. Automatic polling runs only while
|
|
122
|
+
the panel is open, visible and unpaused. Numeric request IDs are local to the
|
|
123
|
+
server process; opaque correlation IDs also distinguish server restarts.
|
|
124
|
+
|
|
125
|
+
Only metadata is recorded: no raw request URLs, dynamic parameter values, queries,
|
|
126
|
+
headers, cookies, arguments, results, error messages or stacks. The read-only
|
|
127
|
+
endpoint requires a loopback connection, matching local Host/port, same-origin
|
|
128
|
+
request metadata and an inspector header; forwarded requests are rejected.
|
|
129
|
+
Access through LAN addresses or reverse proxies is unsupported. Do not expose a
|
|
130
|
+
development server publicly. Production builds do not load the inspector or
|
|
131
|
+
provide its endpoints. Icons use the same pinned Lucide CDN as the dev overlays.
|
|
132
|
+
|
|
133
|
+
Reactive-state inspection and dedicated form-action spans are not included.
|
|
134
|
+
Run `node --test tests/devtools.js` for collector, mapping and HTTP security tests;
|
|
135
|
+
see [browser tests](tests/browser/README.md) for UI coverage.
|
|
136
|
+
|
|
137
|
+
## NiralScript Experiment
|
|
138
|
+
|
|
139
|
+
NiralScript is an opt-in, local compiler prototype, not a stable language release.
|
|
140
|
+
Its independent language extension is `.nrs`; `.niral` remains Niral's component
|
|
141
|
+
format. Niral is the first target; official `@niral/react`, `@niral/vite` and
|
|
142
|
+
`@niral/next` adapters now carry the same compiled `.nrs` modules into other
|
|
143
|
+
ecosystems. The
|
|
144
|
+
[v0.1 design draft](NIRALSCRIPT.md) distinguishes implemented and proposed features.
|
|
145
|
+
Use it inside an existing `.niral` component:
|
|
146
|
+
|
|
147
|
+
```html
|
|
148
|
+
<script lang="niralscript">
|
|
149
|
+
state count = 0
|
|
150
|
+
derive doubled = count * 2
|
|
151
|
+
function increment() {
|
|
152
|
+
count += 1
|
|
153
|
+
}
|
|
154
|
+
</script>
|
|
155
|
+
|
|
156
|
+
<button on:click={increment}>Increase</button>
|
|
157
|
+
<p>{count} doubled is {doubled}</p>
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
`state` lowers to the existing `$state` declaration and `derive` to `$derived`.
|
|
161
|
+
Separate declarations with a newline or semicolon; group multiline expressions
|
|
162
|
+
with parentheses, brackets or braces. Existing HTML, CSS, events and bindings
|
|
163
|
+
stay unchanged. Both declarations use Niral's existing DOM and SSR codegen.
|
|
164
|
+
JavaScript, TypeScript and JSX/TSX support is unchanged.
|
|
165
|
+
|
|
166
|
+
The compiler separates a source-spanned statement AST and lexical analysis from Niral emission.
|
|
167
|
+
Initializers are parsed into expression trees with explicit operator precedence,
|
|
168
|
+
collections, calls, members, conditionals and template interpolation. Validated
|
|
169
|
+
source is retained for compatible emission; unsupported syntax is rejected.
|
|
170
|
+
|
|
171
|
+
The independent core lives in the root-level `niralscript/` directory:
|
|
172
|
+
[parser](niralscript/parser.js), [expressions](niralscript/expressions.js),
|
|
173
|
+
[scope analysis](niralscript/analysis.js), [module linker](niralscript/modules.js), [scanner](niralscript/scanner.js) and
|
|
174
|
+
[diagnostics](niralscript/errors.js). It is a private, zero-dependency ES module
|
|
175
|
+
package with no imports from the framework. The
|
|
176
|
+
[Niral adapter](src/compiler/niralscript.js) emits runtime signal calls directly
|
|
177
|
+
from analyzed bindings and translates
|
|
178
|
+
language diagnostics into existing Niral errors. Tests remain in the repository's
|
|
179
|
+
existing test harness. Niral also loads external `.nrs` instance scripts:
|
|
180
|
+
|
|
181
|
+
```html
|
|
182
|
+
<script lang="niralscript" src="./counter.nrs"></script>
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
Paths must be explicit relative `.nrs` files inside the project, without private
|
|
186
|
+
paths or symlinks. Do not mix inline code with `src`. Dev reloads external edits;
|
|
187
|
+
SSR caches and production hashes include their contents. Raw sources stay private.
|
|
188
|
+
|
|
189
|
+
Named imports and aliases (`import { twice as scale } from "./math.nrs"`) can use
|
|
190
|
+
library `export const` and `export function` declarations, and modules can
|
|
191
|
+
re-export members of another module (`export { twice as scale } from "./math.nrs"`).
|
|
192
|
+
Modules keep separate scopes and initialize once per component execution, not as
|
|
193
|
+
process singletons. Transitive dependencies and re-export chains participate in
|
|
194
|
+
semantic checks, SSR invalidation, dev reloads and build hashes. Libraries cannot
|
|
195
|
+
declare top-level input/state/derive/let; default/namespace imports and cycles are
|
|
196
|
+
not supported. Private paths, including `.server.nrs`, are rejected throughout the graph.
|
|
197
|
+
|
|
198
|
+
Read-only external inputs use `input name` in inline or external instance scripts:
|
|
199
|
+
|
|
200
|
+
```html
|
|
201
|
+
<server>
|
|
202
|
+
export function load() { return { title: "Server title" }; }
|
|
203
|
+
</server>
|
|
204
|
+
<script lang="niralscript">
|
|
205
|
+
input title
|
|
206
|
+
state draft = title
|
|
207
|
+
derive label = title + "!"
|
|
208
|
+
</script>
|
|
209
|
+
<h1>{label}</h1>
|
|
210
|
+
<input bind:value={draft} />
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
The Niral adapter supplies same-named props, including route parameters and
|
|
214
|
+
explicit `load()` results. Parent updates flow to inputs and derived values
|
|
215
|
+
without remounting; local state initializers run once per instance. Missing
|
|
216
|
+
inputs are `undefined`, not a default value; explicit `null` is preserved.
|
|
217
|
+
Declare inputs before eager reads. Inputs and tracked aliases cannot be mutated;
|
|
218
|
+
bind editable controls to local state. Defaults, destructuring and input types
|
|
219
|
+
are not supported. Only return browser-safe values from loaders. These are
|
|
220
|
+
adapter rules; the independent language core has no Niral server or props imports.
|
|
221
|
+
|
|
222
|
+
The script supports top-level `input`/`state`/`derive`, ordinary `let`/`const`, named
|
|
223
|
+
functions, named/anonymous `function` expressions and concise/block arrows (including
|
|
224
|
+
`async`), lexical blocks, braced
|
|
225
|
+
`if`/`else`, `for...of`, `for...in`, conventional `for`/`while`, `break`/`continue`,
|
|
226
|
+
`try`/`catch`/`finally`, `throw`, calls, assignments and
|
|
227
|
+
`return`. `await` is supported inside async bodies, not at top level. Native promise
|
|
228
|
+
completion is preserved; async calls and explicit throws are rejected during
|
|
229
|
+
derived evaluation. Initialization remains conservative across await; known
|
|
230
|
+
awaited aliases and explicitly thrown values retain readonly checks in catches.
|
|
231
|
+
Catch sources are conservatively merged across explicit throws in the linked program;
|
|
232
|
+
unknown host returns/rejections are not a general readonly guarantee.
|
|
233
|
+
Nested object/array patterns work in
|
|
234
|
+
ordinary declarations, parameters and loops; arrays/objects support shallow spread.
|
|
235
|
+
Niral checks array callbacks (`map`, `filter`, `find`, `findIndex`, `some`, `every`,
|
|
236
|
+
`forEach`, `reduce`) and helper callback parameters resolving to one known function.
|
|
237
|
+
Patterns support nested defaults, array holes and final identifier rest bindings;
|
|
238
|
+
functions support default/rest parameters and call spread. Prefix/postfix updates
|
|
239
|
+
are statement-only. Destructuring assignment to existing bindings is supported with
|
|
240
|
+
array, object, renamed, nested, member and rest targets; object patterns must be
|
|
241
|
+
parenthesised and reactive `state` cannot be a destructuring target. Labels and
|
|
242
|
+
async iteration remain unsupported.
|
|
243
|
+
Scope checks reject duplicates, unresolved names, direct use before initialization
|
|
244
|
+
and immutable-binding writes. Resolved bindings drive signal reads/writes and
|
|
245
|
+
nested renames without intermediate rune discovery or script token rewriting.
|
|
246
|
+
The rune-emitting lowering API remains available for compatibility; template
|
|
247
|
+
expressions still use the existing compiler. Static checks reject detected derived effects,
|
|
248
|
+
cycles, readonly-alias writes and eager captured reads. Approved intrinsics are
|
|
249
|
+
target-specific; this is not a general purity proof for arbitrary host values.
|
|
250
|
+
External errors retain file/range links in component diagnostics. Gradual type
|
|
251
|
+
annotations, optional chaining, nullish coalescing, `typeof` and independent ESM
|
|
252
|
+
compilation with source maps are implemented locally. The proposed `view` syntax
|
|
253
|
+
is not implemented. Dedicated `.nrs` source-extension support includes compiler
|
|
254
|
+
diagnostics, signature/type-alias hover, completion and definition navigation. Template
|
|
255
|
+
handlers remain ordinary Niral/JavaScript. The subset is not a full
|
|
256
|
+
JavaScript grammar (regex literals and assignment expressions are rejected). It does
|
|
257
|
+
not establish support for arbitrary frontend languages or frameworks.
|
|
258
|
+
|
|
259
|
+
Explicit `contract<Type>(value)` expressions generate runtime data checks from
|
|
260
|
+
the same aliases used by the type checker. They return typed, copied data without
|
|
261
|
+
coercion or throw NRS081 with a field path. Ordinary annotations remain erased.
|
|
262
|
+
Standalone and Niral emitters support the same finite-data subset; Niral RPC
|
|
263
|
+
maps server-side contract failures to HTTP 400. See
|
|
264
|
+
[runtime contracts and limits](NIRALSCRIPT.md#compiler-generated-runtime-contracts).
|
|
61
265
|
|
|
62
|
-
|
|
266
|
+
Run `node --test tests/niralscript.js` for compiler/SSR checks and
|
|
267
|
+
`NIRAL_BROWSER_FILTER=NiralScript node tests/browser/run.js` for dev/production
|
|
268
|
+
Chromium checks using the existing browser tooling. The reusable
|
|
269
|
+
[fixture](tests/fixtures/niralscript.niral) exercises named handlers, shadowing,
|
|
270
|
+
state, derived values, server-loaded inputs, local input binding, keyed lists and
|
|
271
|
+
RPC. Browser checks also cover parent/child updates and route parameters. These checks are
|
|
272
|
+
included in the release gate.
|
|
273
|
+
|
|
274
|
+
Standalone checking and compilation work from this checkout, without Niral components:
|
|
63
275
|
|
|
64
276
|
```sh
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
277
|
+
node niralscript/cli.js --help
|
|
278
|
+
node niralscript/cli.js check counter.nrs --root /path/to/project --json
|
|
279
|
+
node niralscript/cli.js compile counter.nrs --root /path/to/project --out counter.mjs
|
|
68
280
|
```
|
|
69
281
|
|
|
70
|
-
The
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
282
|
+
The `check` command validates entry files and relative module graphs without
|
|
283
|
+
executing source or emitting JavaScript. `compile` emits a self-contained ESM
|
|
284
|
+
`createInstance(inputs, globals, runtime)` factory and a `.mjs.map` file. Output
|
|
285
|
+
parents must exist inside the selected root; existing files are never overwritten.
|
|
286
|
+
The default runtime provides isolated state and pull-based cached derived reads;
|
|
287
|
+
hosts can inject signal/derived primitives. It does not mount a UI or subscribe.
|
|
288
|
+
Both commands report original file/line
|
|
289
|
+
diagnostics and exits 0 on success, 1 on source/file errors, or 2 on invalid usage.
|
|
290
|
+
It has no implicit host globals; repeat `--global name` to declare them without
|
|
291
|
+
asserting purity. Primitive/literal, union, array, structural record, `Promise<T>`
|
|
292
|
+
and function signatures check known initializers, assignments, arguments and returns.
|
|
293
|
+
Reusable aliases/type-only imports, generic named functions/aliases, contextual
|
|
294
|
+
callbacks and branch narrowing are supported. Unknown host values remain permissive
|
|
295
|
+
by default; opt into stricter unknown/null checks with `--strict`, the API's
|
|
296
|
+
`strictTypes: true`, or VS Code's `niral.niralscriptStrictTypes` (reload required).
|
|
297
|
+
Generic constraints, recursive aliases and generic arrows are supported; recursive
|
|
298
|
+
types cannot become runtime contracts.
|
|
299
|
+
Named classes support constructors, typed/generic fields and methods, inheritance,
|
|
300
|
+
private members, accessors, static blocks and `instanceof`. They emit native classes
|
|
301
|
+
in standalone and component output, with readonly/effect/initialization safeguards.
|
|
302
|
+
Class fields are ordinary properties, not automatic signals. Decorators work on
|
|
303
|
+
class declarations, methods, accessors and static fields. Class expressions,
|
|
304
|
+
dynamic computed names and TypeScript class modifiers are not supported;
|
|
305
|
+
see [class contracts and limitations](NIRALSCRIPT.md#classes-and-constructors).
|
|
306
|
+
This is not runtime validation, a fully
|
|
307
|
+
sound type system or Niral client/server security validation. The private package
|
|
308
|
+
exports `niralscript/check` and `niralscript/compile`; neither requires Niral.
|
|
309
|
+
See [standalone checking](NIRALSCRIPT.md#standalone-checking) and
|
|
310
|
+
[compilation](NIRALSCRIPT.md#standalone-compilation) for API/runtime contracts.
|
|
311
|
+
|
|
312
|
+
Run `node bench/niralscript.js` for warm compiler/string-SSR timings and generated
|
|
313
|
+
raw/gzip sizes for equivalent NiralScript, JavaScript and annotated TypeScript
|
|
314
|
+
components, all using Niral. It asserts language and DOM/string SSR parity, warms
|
|
315
|
+
each variant and rotates three-way batches evenly across 12 rounds. TypeScript
|
|
316
|
+
compilation here means Niral's type stripping, not `tsc` or type checking.
|
|
317
|
+
A separate paired script-backend
|
|
318
|
+
measurement compares direct AST emission with lowering through the JavaScript
|
|
319
|
+
rewriter, including parsing and analysis in both, excluding component/template
|
|
320
|
+
compilation.
|
|
321
|
+
|
|
322
|
+
- `node bench/niralscript.js browser`: uses the existing Playwright installation
|
|
323
|
+
under tests/browser to measure warm hydration and synchronous click-to-DOM
|
|
324
|
+
updates in headless Chromium. Asserts SSR element reuse, output and cleanup.
|
|
325
|
+
Creates a loopback server on an assigned free port and closes it afterwards;
|
|
326
|
+
no app files or existing preview servers are changed. Module loading, HTML
|
|
327
|
+
parsing, paint and automation transport are outside the timed regions.
|
|
328
|
+
- `node bench/niralscript.js types`: uses the existing TypeScript compiler resolved
|
|
329
|
+
by `niral check`, separately measuring fresh strict/noEmit programs with
|
|
330
|
+
skipLibCheck, including standard library reads/parsing. No incremental reuse or
|
|
331
|
+
process startup. Also asserts nine diagnostic probes covering annotated values,
|
|
332
|
+
records, arguments, async returns, optional/nullish access, names and effects.
|
|
333
|
+
Wrong-type insertion into an annotated array is rejected by both NiralScript
|
|
334
|
+
and strict TypeScript; unannotated NiralScript values remain dynamic.
|
|
335
|
+
- `node bench/niralscript.js language`: direct JavaScript vs TypeScript vs
|
|
336
|
+
NiralScript with identical function bodies for numeric aggregation, record
|
|
337
|
+
processing, strings and async/await. No components or reactive operations.
|
|
338
|
+
Asserts main/edge/empty outputs and input nonmutation; strict-checks each actual
|
|
339
|
+
TS source. Reports warmed function execution, separate source-transform times
|
|
340
|
+
and complete output sizes. Imports/factory setup/strict checks excluded from
|
|
341
|
+
runtime timings. All execute as JavaScript on the same V8 engine; compiler
|
|
342
|
+
timings differ in checking work, and NRS output includes unused runtime glue.
|
|
343
|
+
- GitHub Actions: the `compare-languages` job in Release Checks configures separate
|
|
344
|
+
Ubuntu24.04 jobs on Node22/24 with TypeScript5.7.3 and three sequential `language`
|
|
345
|
+
runs per job. Artifacts contain logs and commit/runtime/hardware metadata for
|
|
346
|
+
30 days. Correctness failures fail CI; timings are informational because hosted
|
|
347
|
+
runners vary. The workflow and all compiler changes must be committed/pushed
|
|
348
|
+
before a GitHub run can test them.
|
|
349
|
+
- `node bench/niralscript.js standalone`: independently compiles typed `.nrs` to
|
|
350
|
+
ESM and TypeScript via `transpileModule`, alongside an untransformed JS reference.
|
|
351
|
+
Asserts counter/collection outputs, instance isolation, input updates/reset and
|
|
352
|
+
async success/catch. Reports complete module/map sizes, warm transform times and
|
|
353
|
+
balanced runtime batches (100 writes+reads or 1000 unchanged reads), including
|
|
354
|
+
fresh instance creation. NRS bundles its pull/cached runtime; JS/TS implement
|
|
355
|
+
only the measured interface with direct variables/recomputed reads. Array copies
|
|
356
|
+
and mapping are identical; the standalone host explicitly approves native array
|
|
357
|
+
`map` on literal arrays. Only valid supplied input values are compared. TS
|
|
358
|
+
transpilation is not strict checking; maps and runtime strategies differ, so
|
|
359
|
+
transform/size numbers are not equivalent compiler-work or feature comparisons.
|
|
360
|
+
|
|
361
|
+
These are local microbenchmarks, not cross-framework or end-user latency rankings.
|
|
362
|
+
Recorded results, versions and limitations are in [PROGRESS.md](PROGRESS.md).
|
|
88
363
|
|
|
89
364
|
## Developer Intelligence
|
|
90
365
|
|
|
366
|
+
Niral DI runs through the existing CLI, with your exact provider and model:
|
|
367
|
+
|
|
91
368
|
```sh
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
369
|
+
niral di setup
|
|
370
|
+
niral di status
|
|
371
|
+
niral di ask "Explain the routes" --read-only
|
|
372
|
+
niral di chat
|
|
373
|
+
niral di new myblog "Customize the home page" --template blog
|
|
374
|
+
```
|
|
375
|
+
|
|
376
|
+
Setup offers OpenAI, Claude (Anthropic), Azure OpenAI or Custom. Named providers
|
|
377
|
+
set protocol/auth automatically; Custom keeps manual choices. You supply the exact
|
|
378
|
+
model and credential variable name, not the key. Bedrock is not yet supported.
|
|
379
|
+
Explicit flags remain available through `niral di setup --help`.
|
|
380
|
+
Set the named credential variable privately in your terminal. Setup stores no
|
|
381
|
+
key; every workspace tool needs interactive approval. Writes check the current
|
|
382
|
+
file hash and retain external backups. Use `--no-tools` with `ask` for prompt-only
|
|
383
|
+
automation. No shell execution, automatic testing or cloud account requirement.
|
|
384
|
+
Read the [DI command and safety guide](src/di/README.md) before granting file access.
|
|
385
|
+
|
|
386
|
+
## One file, whole feature
|
|
387
|
+
|
|
388
|
+
```html
|
|
389
|
+
<server>
|
|
390
|
+
export async function load() {
|
|
391
|
+
return { items: await db.all() } // SSR data — never ships
|
|
392
|
+
}
|
|
393
|
+
export async function add(text) {
|
|
394
|
+
publish("todos", { text }) // realtime to every tab
|
|
395
|
+
}
|
|
396
|
+
</server>
|
|
397
|
+
|
|
398
|
+
<script>
|
|
399
|
+
let { items } = $props
|
|
400
|
+
let list = $state(items)
|
|
401
|
+
live("todos", (t) => list = [...list, t])
|
|
402
|
+
</script>
|
|
403
|
+
|
|
404
|
+
{#for t of list key t.id}
|
|
405
|
+
<li transition:fade>{t.text}</li>
|
|
406
|
+
{/for}
|
|
97
407
|
```
|
|
98
408
|
|
|
99
|
-
`
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
409
|
+
`load()` runs on the server per request. `add()` becomes a type-safe RPC —
|
|
410
|
+
the compiler splits server and client code, so secrets structurally cannot
|
|
411
|
+
reach the browser (reading `process.env` in client code is a **compile error**).
|
|
412
|
+
|
|
413
|
+
## Measured, not marketed
|
|
414
|
+
|
|
415
|
+
End-to-end — each framework's own production server, dynamic SSR on every
|
|
416
|
+
request, the same 1000-row page, 100 connections × 10 s
|
|
417
|
+
([methodology + run it yourself](bench/e2e/)):
|
|
418
|
+
|
|
419
|
+
| framework | req/s | p50 | p99 | build |
|
|
420
|
+
|-----------|------:|----:|----:|------:|
|
|
421
|
+
| **niral** | **~2,200** | **40 ms** | ~150 ms | **0.2 s** |
|
|
422
|
+
| sveltekit 2 (svelte 5) | ~580 | 128 ms | ~1.6 s | 2.3–3.7 s |
|
|
423
|
+
| next 16 (react 19) | ~290 | 310 ms | 2.3–3.2 s | 3.3–5.5 s |
|
|
424
|
+
|
|
425
|
+
Hydration ties Svelte (6.6 ms / 1000 rows) at 29.7 KB of JS — [bench/hydration/](bench/hydration/).
|
|
426
|
+
|
|
427
|
+
**Streaming SSR — time to first byte** with a 300 ms slow data source
|
|
428
|
+
([run it yourself](bench/streaming/)). Streaming flushes the shell before the
|
|
429
|
+
slow value; `total` stays ~300 ms, but the page paints in single-digit ms:
|
|
430
|
+
|
|
431
|
+
| framework | blocking TTFB | streaming TTFB | streamed data |
|
|
432
|
+
|-----------|--------------:|---------------:|---------------|
|
|
433
|
+
| **niral** | 304 ms | **2 ms** | server-rendered HTML |
|
|
434
|
+
| next 16 | 307 ms | 6 ms | server-rendered HTML |
|
|
435
|
+
| sveltekit 2 | 305 ms | 3 ms | client-resolved payload |
|
|
436
|
+
|
|
437
|
+
## What's in the box
|
|
438
|
+
|
|
439
|
+
- **Components** — `.niral` single-file components, runes (`$state`, `$props`), keyed lists, transitions, context, slots
|
|
440
|
+
- **SSR + hydration** — dual codegen: DOM builder for the client, string renderer for the server, byte-identical output
|
|
441
|
+
- **Streaming SSR** — `<script stream>` flushes the shell first, then streams each `{#await}` branch out of order as its promise settles (server-rendered HTML, revealed with zero framework JS). ~2 ms first byte vs ~300 ms blocking — [bench/streaming/](bench/streaming/)
|
|
442
|
+
- **Server functions** — `<server>` blocks become RPC with compile-time stubs, streaming (async generators → NDJSON), form actions that work without JS
|
|
443
|
+
- **Polyglot** — server blocks in Python, Ruby or Go; same sessions, same RPC
|
|
444
|
+
- **Auth** — passkeys, passwords, TOTP 2FA, OAuth, route guards (`niral add auth` — scaffolded code you own)
|
|
445
|
+
- **Realtime** — live channels on framework-owned WebSockets, session-aware guards
|
|
446
|
+
- **Jobs & cron** — durable SQLite queue that survives deploys; retries, backoff, dead-letters
|
|
447
|
+
- **AI-native** — `ai.chat` / `ai.stream` / `ai.embed` against any OpenAI-compatible endpoint, RAG included, fully-local option (`niral add llm`)
|
|
448
|
+
- **Data** — SQL migrations that auto-apply at boot; `node:sqlite` everywhere
|
|
449
|
+
- **Quality** — `niral test` (boots your real app), `niral check` (the actual TypeScript compiler), `niral doctor`
|
|
450
|
+
- **Ship** — content-hashed atomic releases, one-symlink rollback, graceful drains, generated systemd + nginx + Dockerfile deploy kit, CSP nonces and security headers by default
|
|
451
|
+
- **Recover off-box** — gzip + scrypt + AES-256-GCM snapshots to any S3-compatible store, native SigV4, remote retention and authenticated restore
|
|
452
|
+
- **More** — i18n, SMTP mail, image pipeline, structured logging with request IDs, LSP + VS Code extension
|
|
453
|
+
|
|
454
|
+
## Editor & AI support
|
|
455
|
+
|
|
456
|
+
- **VS Code** — install the [Niral extension](https://marketplace.visualstudio.com/items?itemName=zyoralabs.niral-vscode) (`zyoralabs.niral-vscode`) for `.niral` syntax highlighting, diagnostics, completions and hover docs, backed by the built-in language server (`niral lsp`).
|
|
457
|
+
|
|
458
|
+
```sh
|
|
459
|
+
code --install-extension zyoralabs.niral-vscode
|
|
460
|
+
```
|
|
461
|
+
- **AI agents** — every project scaffolds an `AGENTS.md`, so Copilot / Claude / Cursor understand Niral's conventions natively instead of guessing “Svelte-ish.” New apps also drop a `.vscode/extensions.json` that recommends the extension the moment the folder opens. Agents can run `niral check` / `niral test` to verify their own edits against the real compiler.
|
|
462
|
+
|
|
463
|
+
## Secrets can't escape
|
|
464
|
+
|
|
465
|
+
1. `process.env` in client code → **compile error**
|
|
466
|
+
2. Env files never enter a build
|
|
467
|
+
3. Dev and prod servers refuse to serve them
|
|
468
|
+
4. Scaffolded `.gitignore` keeps them out of git
|
|
469
|
+
5. The deploy script never syncs them — production secrets live only on the server
|
|
470
|
+
|
|
471
|
+
### Security Boundaries
|
|
472
|
+
|
|
473
|
+
Use a currently supported, security-patched Node.js release. The
|
|
474
|
+
[October 21, 2026 Node advisory](https://nodejs.org/en/blog/vulnerability/october-2026-security-releases)
|
|
475
|
+
lists fixes in 22.23.4, 24.22.1 and 26.12.1; use those or a newer patched release
|
|
476
|
+
in a supported line. Framework checks cannot patch Node's DNS, TLS, HTTP or
|
|
477
|
+
decompression internals. PHP is not a Niral runtime.
|
|
478
|
+
|
|
479
|
+
- Private directory/file exclusions are case-insensitive, including nested
|
|
480
|
+
`data/`, dotfiles, environment files and server modules. Public symlinks and
|
|
481
|
+
Windows junctions are not served or traversed by the static build walker.
|
|
482
|
+
Use regular copies for intentionally public assets.
|
|
483
|
+
- Raw `.niral`, `.jsx` and `.tsx` component sources are never copied into static
|
|
484
|
+
build output. Dev requests with noncanonical component-extension case are
|
|
485
|
+
rejected instead of returning uncompiled source.
|
|
486
|
+
- Decoded paths containing backslashes, colons, control characters, dot segments,
|
|
487
|
+
or segments ending in a dot or space return 400, including dynamic route paths.
|
|
488
|
+
- RPC still requires `x-niral-rpc: 1` and now shares form-origin validation.
|
|
489
|
+
Configure `NIRAL_ORIGIN` to the exact public origin (scheme, hostname and port)
|
|
490
|
+
for strict origin matching behind a TLS-terminating proxy. Without that setting,
|
|
491
|
+
unencrypted connections retain host-and-port matching for proxy compatibility.
|
|
492
|
+
Requests without Origin remain allowed unless Fetch Metadata says cross-site;
|
|
493
|
+
this is not authentication or authorization for an application's functions.
|
|
494
|
+
|
|
495
|
+
Rebuild applications after upgrading: previously generated static files may
|
|
496
|
+
already contain copied private data or raw components. Keep development servers
|
|
497
|
+
private, enforce application authorization, and protect release directories from
|
|
498
|
+
untrusted writes. These checks do not sandbox server code or protect against
|
|
499
|
+
malicious local filesystem races/hard links, runtime CVEs or volumetric DDoS.
|
|
500
|
+
|
|
501
|
+
## Repository layout
|
|
502
|
+
|
|
503
|
+
```
|
|
504
|
+
bin/niral.js the CLI — create · dev · check · test · migrate · build · start · deploy · doctor · snapshot/restore
|
|
505
|
+
src/compiler/ parser, codegen (DOM + string-SSR), rewriter
|
|
506
|
+
src/runtime/ signals, DOM ops, hydration, router, i18n, rpc client
|
|
507
|
+
src/server/ dev + prod servers, sessions, auth, jobs, live, ai, rag, migrate
|
|
508
|
+
src/add/ recipes: tailwind · sqlite · fonts · image · auth · typescript · chat · llm
|
|
509
|
+
apps/docs/ the documentation site — a niral app (dogfood)
|
|
510
|
+
apps/quickpoll/ realtime polling app (dogfood)
|
|
511
|
+
bench/ reproducible benchmarks — e2e throughput + streaming TTFB, vs Next.js, SvelteKit, SolidStart, Astro
|
|
512
|
+
tests/ 161 tests — npm test
|
|
513
|
+
editors/vscode/ syntax highlighting + LSP client
|
|
514
|
+
```
|
|
515
|
+
|
|
516
|
+
## Philosophy
|
|
517
|
+
|
|
518
|
+
- **Compiler, not runtime.** The work happens once, at build time.
|
|
519
|
+
- **Zero dependencies, forever.** No supply chain, no audits, no upstream breakage. Every line that runs is a line you can read.
|
|
520
|
+
- **Honest measurement.** Every benchmark in this repo is reproducible. We'd rather you check.
|
|
521
|
+
|
|
522
|
+
---
|
|
523
|
+
|
|
524
|
+
<div align="center">
|
|
525
|
+
|
|
526
|
+
நிரல் — "program" in Tamil · Built in India · Powered by [ZyoraLabs](https://zyoralabs.com)
|
|
527
|
+
|
|
528
|
+
</div>
|