niral 0.1.2 → 0.1.4

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 ADDED
@@ -0,0 +1,109 @@
1
+ # Niral CLI
2
+
3
+ Zero-dependency launcher for the Niral full-stack framework. Requires Node.js 22+.
4
+
5
+ ## Use
6
+
7
+ ```sh
8
+ npx niral create myapp
9
+ cd myapp
10
+ npx niral dev
11
+ ```
12
+
13
+ Or install one global launcher:
14
+
15
+ ```sh
16
+ npm install -g niral
17
+ niral create myapp --template blog
18
+ niral dev myapp
19
+ ```
20
+
21
+ Both `niral` and `create-niral` packages provide the same two executable names.
22
+ Install only one globally to avoid bin conflicts. Templates: `minimal` (default),
23
+ `blog`, `dashboard`. Create refuses to overwrite a nonempty project directory.
24
+
25
+ The first project command downloads the framework from the official
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.
29
+
30
+ ## Commands
31
+
32
+ ```sh
33
+ npx niral --help
34
+ 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
+ ```
41
+
42
+ All framework commands and arguments are forwarded, with the framework's exit
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
+
51
+ ```sh
52
+ npx niral@latest update
53
+ ```
54
+
55
+ This explicitly updates `NIRAL_HOME/framework`, even when the cached framework
56
+ has no `update` command. The default is the repository's `main` branch. Updating
57
+ also refreshes an existing generated shell shim so its updater remains independent
58
+ of older pinned framework code. Updating the npm launcher alone does not refresh
59
+ the framework; update a globally installed launcher separately with
60
+ `npm install -g niral@latest`.
61
+
62
+ Set `APPROVED_FRAMEWORK_SHA` to a reviewed full 40-character lowercase commit SHA:
63
+
64
+ ```sh
65
+ NIRAL_REF="$APPROVED_FRAMEWORK_SHA" npx niral@latest update
66
+ niral update
67
+ NIRAL_REF=main npx niral@latest update
68
+ ```
69
+
70
+ The selection is saved in `NIRAL_HOME/.framework-ref`; plain updates retain it.
71
+ Existing `v`-prefixed version tags are also accepted, but tags can move: use a
72
+ full commit SHA for reproducibility. `NIRAL_REF=main` explicitly removes the pin.
73
+ Fresh installations accept the same variable; switching a cached install requires
74
+ an explicit update. npm versions and framework revisions are independent.
75
+
76
+ Git installs must be clean, on `main` or a managed detached pin, and use the
77
+ official HTTPS origin. `main` updates
78
+ are fast-forward only; a Git failure never replaces the checkout with an archive.
79
+ Pin changes and non-Git replacements are staged and syntax-checked first; the complete previous
80
+ directory is retained at the printed `framework-backup-*/framework` path. Local
81
+ files in that backup are not merged into the new framework. No backups are pruned.
82
+
83
+ Stop active development/build commands before updating. Concurrent installers are
84
+ refused. If interrupted, inspect other installer processes before manually removing
85
+ a stale `NIRAL_HOME/.framework-install-lock` directory. Symlinked installs and
86
+ updates invoked from unmanaged source checkouts are refused; maintain those with
87
+ Git. An update does not migrate apps, publish packages or deploy/restart servers.
88
+
89
+ ## Developer Intelligence
90
+
91
+ ```sh
92
+ npx niral di setup
93
+ npx niral di status
94
+ npx niral di ask "Explain this project" --root ./myapp --read-only
95
+ npx niral di chat --root ./myapp
96
+ npx niral di new myblog "Customize the home page" --template blog
97
+ ```
98
+
99
+ `npx niral di setup` offers OpenAI, Claude (Anthropic), Azure OpenAI or Custom.
100
+ Named providers set protocol/auth automatically; Custom keeps manual choices.
101
+ Enter your exact model/deployment and credential variable name. Azure also asks
102
+ for its resource URL or `/openai/v1` base. Bedrock is not yet supported.
103
+ Use `npx niral di setup --help` for noninteractive flags.
104
+ Credentials stay in a named environment variable, not config or project files.
105
+ File reads/edits require a terminal and per-tool approval; writes retain backups
106
+ and reject stale hashes. `ask <prompt> --no-tools` permits prompt-only automation.
107
+ No unrestricted shell, automatic tests, transcript persistence or Niral Cloud
108
+ requirement. See the [DI commands and safeguards](https://niral.site/docs/cli).
109
+ Existing cached frameworks need `npx niral@latest update` to acquire DI commands.
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
- // npx create-niral my-app — the beginner's one command.
3
- import { ensureFramework, installLauncher, runNiral } from "../index.js";
2
+ // npx create-niral my-app [--template blog|dashboard] — the beginner's one command.
3
+ import { ensureFramework, installLauncher, runNiral, runLauncher } from "../index.js";
4
4
 
5
5
  const usage = "usage: npx create-niral <app-name|.> [--template minimal|blog|dashboard]";
6
6
 
@@ -9,8 +9,10 @@ async function main(argv = process.argv.slice(2)) {
9
9
  console.log(usage);
10
10
  return 0;
11
11
  }
12
+ if (argv.length === 1 && ["--version", "-v"].includes(argv[0])) return runLauncher(["--version"]);
12
13
  const name = argv[0];
13
14
  if (!name || (name.startsWith("-") && name !== ".")) throw new Error(usage);
15
+ if (argv.length !== 1 && !(argv.length === 3 && argv[1] === "--template" && ["minimal", "blog", "dashboard"].includes(argv[2]))) throw new Error(usage);
14
16
 
15
17
  await ensureFramework();
16
18
  const code = runNiral(["create", name, ...argv.slice(1)]);
@@ -19,6 +21,7 @@ async function main(argv = process.argv.slice(2)) {
19
21
  const { profile, added } = installLauncher();
20
22
  console.log("");
21
23
  if (added) console.log(`✓ \`niral\` command installed — PATH updated in ${profile} (open a new terminal)`);
24
+ if (!profile) console.log("Use npx niral <command>, or add NIRAL_HOME/bin to your PATH.");
22
25
  const cd = name === "." ? "" : ` cd ${name}\n`;
23
26
  console.log(`Next:\n${cd} niral dev # or: npx niral dev\n`);
24
27
  return 0;
package/bin/niral.js CHANGED
@@ -1,11 +1,10 @@
1
1
  #!/usr/bin/env node
2
2
  // niral <command> — forwards to the framework at ~/.niral/framework.
3
3
  // Available globally after `npm i -g create-niral`, or per-call via `npx niral dev`.
4
- import { ensureFramework, runNiral } from "../index.js";
4
+ import { runLauncher } from "../index.js";
5
5
 
6
6
  async function main() {
7
- await ensureFramework();
8
- return runNiral(process.argv.slice(2));
7
+ return runLauncher(process.argv.slice(2));
9
8
  }
10
9
 
11
10
  main().then((code) => {
package/index.js CHANGED
@@ -6,29 +6,45 @@
6
6
  * forwards commands to it. The framework itself never touches npm.
7
7
  */
8
8
 
9
- import { existsSync, mkdirSync, rmSync, writeFileSync, chmodSync, appendFileSync, readFileSync } from "node:fs";
9
+ import { existsSync, mkdirSync, mkdtempSync, renameSync, lstatSync, realpathSync, rmSync, writeFileSync, chmodSync, appendFileSync, readFileSync } from "node:fs";
10
10
  import { spawnSync } from "node:child_process";
11
- import { join } from "node:path";
11
+ import { join, resolve } from "node:path";
12
12
  import { homedir } from "node:os";
13
13
  import { get } from "node:https";
14
14
 
15
- export const NIRAL_HOME = process.env.NIRAL_HOME || join(homedir(), ".niral");
15
+ export const NIRAL_HOME = resolve(process.env.NIRAL_HOME || join(homedir(), ".niral"));
16
16
  const FRAMEWORK = join(NIRAL_HOME, "framework");
17
- const TARBALL = "https://codeload.github.com/Zyora-Dev/niral/tar.gz/refs/heads/main";
18
17
  const REPO = "https://github.com/Zyora-Dev/niral.git";
19
18
 
20
19
  function download(url, dest) {
21
20
  return new Promise((resolve, reject) => {
22
- get(url, (res) => {
23
- if (res.statusCode !== 200) return reject(new Error(`download failed: HTTP ${res.statusCode}`));
21
+ const request = get(url, (res) => {
22
+ if (res.statusCode !== 200) {
23
+ res.resume();
24
+ return reject(new Error(`download failed: HTTP ${res.statusCode}`));
25
+ }
24
26
  const chunks = [];
25
- res.on("data", (c) => chunks.push(c));
27
+ let bytes = 0;
28
+ res.on("data", (chunk) => {
29
+ bytes += chunk.length;
30
+ if (bytes > 64 * 1024 * 1024) {
31
+ request.destroy(new Error("framework download exceeds 64 MiB"));
32
+ return;
33
+ }
34
+ chunks.push(chunk);
35
+ });
26
36
  res.on("end", () => {
27
- writeFileSync(dest, Buffer.concat(chunks));
28
- resolve();
37
+ try {
38
+ writeFileSync(dest, Buffer.concat(chunks));
39
+ resolve();
40
+ } catch (error) {
41
+ reject(error);
42
+ }
29
43
  });
30
44
  res.on("error", reject);
31
45
  }).on("error", reject);
46
+ const deadline = setTimeout(() => request.destroy(new Error("framework download timed out")), 60000);
47
+ request.on("close", () => clearTimeout(deadline));
32
48
  });
33
49
  }
34
50
 
@@ -42,51 +58,174 @@ function commandError(label, result) {
42
58
  return new Error(`${label} failed: ${detail}`);
43
59
  }
44
60
 
45
- async function installFromTarball() {
46
- const tgz = join(NIRAL_HOME, "niral.tgz");
47
- await download(TARBALL, tgz);
48
- rmSync(FRAMEWORK, { recursive: true, force: true });
49
- mkdirSync(FRAMEWORK, { recursive: true });
50
- const extracted = spawnSync("tar", ["-xzf", tgz, "-C", FRAMEWORK, "--strip-components=1"], { encoding: "utf8" });
61
+ async function installFromTarball(stage, ref) {
62
+ const tgz = join(stage, "niral.tgz");
63
+ await download(`https://codeload.github.com/Zyora-Dev/niral/tar.gz/${ref === "main" ? "refs/heads/main" : encodeURIComponent(ref)}`, tgz);
64
+ const target = join(stage, "framework");
65
+ mkdirSync(target);
66
+ const extracted = spawnSync("tar", ["-xzf", tgz, "-C", target, "--strip-components=1"], { encoding: "utf8", timeout: 120000 });
51
67
  rmSync(tgz, { force: true });
52
68
  if (extracted.error || extracted.status !== 0) throw commandError("framework extraction", extracted);
53
69
  }
54
70
 
55
71
  /** Download the framework to ~/.niral/framework (git if available, tarball otherwise). */
56
72
  export async function ensureFramework({ update = false } = {}) {
57
- if (existsSync(join(FRAMEWORK, "bin", "niral.js")) && !update) return FRAMEWORK;
58
- console.log("niral · downloading the framework (one time, ~1 MB — it has zero dependencies)…");
73
+ if (Number(process.versions.node.split(".")[0]) < 22) throw new Error("Niral requires Node.js 22 or newer");
74
+ const pinFile = join(NIRAL_HOME, ".framework-ref");
75
+ const previousRef = existsSync(pinFile) ? readFileSync(pinFile, "utf8").trim() : "main";
76
+ const ref = process.env.NIRAL_REF ?? previousRef;
77
+ if (!/^(?:main|[a-f0-9]{40}|v\d+\.\d+\.\d+(?:[-.][A-Za-z0-9.-]+)?)$/.test(ref)) throw new Error("NIRAL_REF must be main, a full lowercase commit SHA, or a v-prefixed version tag");
78
+ if (existsSync(join(FRAMEWORK, "bin", "niral.js")) && !update) {
79
+ if (ref !== previousRef) throw new Error("framework pin differs from the installed version; run niral update with NIRAL_REF set");
80
+ return FRAMEWORK;
81
+ }
59
82
  mkdirSync(NIRAL_HOME, { recursive: true });
60
- let installed = false;
61
- if (hasGit()) {
62
- const gitResult = existsSync(join(FRAMEWORK, ".git"))
63
- ? spawnSync("git", ["pull", "--ff-only", "-q"], { cwd: FRAMEWORK, encoding: "utf8" })
64
- : (() => {
65
- rmSync(FRAMEWORK, { recursive: true, force: true });
66
- return spawnSync("git", ["clone", "-q", "--depth", "1", REPO, FRAMEWORK], { encoding: "utf8" });
67
- })();
68
- if (!gitResult.error && gitResult.status === 0) {
69
- installed = true;
70
- } else {
71
- const reason = gitResult.error?.message || gitResult.stderr?.trim() || `exit ${gitResult.status ?? "unknown"}`;
72
- console.warn(`niral · Git download unavailable (${reason}); trying the release tarball…`);
83
+ const lock = join(NIRAL_HOME, ".framework-install-lock");
84
+ try {
85
+ mkdirSync(lock);
86
+ } catch (error) {
87
+ if (error.code === "EEXIST") throw new Error(`framework installation is locked: ${lock}. Check for another installer before removing a stale lock.`);
88
+ throw error;
89
+ }
90
+ let stage;
91
+ try {
92
+ if (existsSync(join(FRAMEWORK, "bin", "niral.js")) && !update) return FRAMEWORK;
93
+ const entry = lstatSync(FRAMEWORK, { throwIfNoEntry: false });
94
+ if (entry && (!entry.isDirectory() || entry.isSymbolicLink())) throw new Error("framework path must be a real directory; installation left unchanged");
95
+ console.log(update ? "niral: updating the installed framework..." : "niral: downloading the framework...");
96
+ if (existsSync(join(FRAMEWORK, ".git"))) {
97
+ if (!hasGit()) throw new Error("Git is required to update this checkout; installation left unchanged");
98
+ const git = (args) => {
99
+ const result = spawnSync("git", args, { cwd: FRAMEWORK, encoding: "utf8", timeout: 120000, env: { ...process.env, GIT_TERMINAL_PROMPT: "0" } });
100
+ if (result.error || result.status !== 0) throw commandError("Git update (no archive fallback)", result);
101
+ return result.stdout.trim();
102
+ };
103
+ if (git(["status", "--porcelain", "--untracked-files=all"])) throw new Error("framework checkout has local changes; preserve them before updating");
104
+ const branch = git(["branch", "--show-current"]);
105
+ if (branch !== "main" && !(previousRef !== "main" && branch === "")) throw new Error("framework checkout is not on main or a managed pin; update it manually with Git");
106
+ if (![REPO, REPO.replace(/\.git$/, "")].includes(git(["remote", "get-url", "origin"]))) throw new Error("framework origin differs from the official repository; update it manually with Git");
107
+ if (ref === "main" && previousRef === "main") {
108
+ const previous = git(["rev-parse", "HEAD"]);
109
+ git(["pull", "--ff-only", "origin", "main"]);
110
+ console.log(`niral: framework ${git(["rev-parse", "--short", "HEAD"])} (previous ${previous})`);
111
+ return FRAMEWORK;
112
+ }
113
+ }
114
+ stage = mkdtempSync(join(NIRAL_HOME, ".framework-stage-"));
115
+ const target = join(stage, "framework");
116
+ let installed = false;
117
+ if (hasGit()) {
118
+ const args = ref === "main" ? ["clone", "-q", "--depth", "1", "--branch", "main", REPO, target] : ["clone", "-q", "--no-checkout", REPO, target];
119
+ const cloned = spawnSync("git", args, {
120
+ encoding: "utf8", timeout: 120000, env: { ...process.env, GIT_TERMINAL_PROMPT: "0" },
121
+ });
122
+ installed = !cloned.error && cloned.status === 0;
123
+ if (installed && ref !== "main") {
124
+ const checkedOut = spawnSync("git", ["checkout", "--detach", ref], { cwd: target, encoding: "utf8", timeout: 120000, env: { ...process.env, GIT_TERMINAL_PROMPT: "0" } });
125
+ if (checkedOut.error || checkedOut.status !== 0) throw commandError("pinned framework checkout", checkedOut);
126
+ if (/^[a-f0-9]{40}$/.test(ref)) {
127
+ const revision = spawnSync("git", ["rev-parse", "HEAD"], { cwd: target, encoding: "utf8", timeout: 10000 });
128
+ if (revision.status !== 0 || revision.stdout.trim() !== ref) throw new Error("pinned framework revision did not match the requested commit");
129
+ }
130
+ }
131
+ if (!installed) {
132
+ rmSync(target, { recursive: true, force: true });
133
+ console.warn("niral: Git download unavailable; trying the framework archive...");
134
+ }
73
135
  }
136
+ if (!installed) await installFromTarball(stage, ref);
137
+ const manifest = JSON.parse(readFileSync(join(target, "package.json"), "utf8"));
138
+ if (manifest.name !== "niral" || !existsSync(join(target, "src", "index.js"))) throw new Error("download is not a Niral framework");
139
+ const checked = spawnSync(process.execPath, ["--check", join(target, "bin", "niral.js")], { encoding: "utf8", timeout: 10000 });
140
+ if (checked.error || checked.status !== 0) throw commandError("downloaded CLI validation", checked);
141
+ const stagedPin = join(stage, "ref");
142
+ if (ref !== "main") writeFileSync(stagedPin, ref + "\n");
143
+ let backup;
144
+ if (entry) {
145
+ backup = join(mkdtempSync(join(NIRAL_HOME, "framework-backup-")), "framework");
146
+ renameSync(FRAMEWORK, backup);
147
+ }
148
+ try {
149
+ renameSync(target, FRAMEWORK);
150
+ if (ref === "main") rmSync(pinFile, { force: true });
151
+ else renameSync(stagedPin, pinFile);
152
+ } catch (error) {
153
+ if (existsSync(FRAMEWORK)) renameSync(FRAMEWORK, target);
154
+ if (backup) renameSync(backup, FRAMEWORK);
155
+ throw error;
156
+ }
157
+ if (backup) console.log(`niral: previous framework preserved at ${backup}`);
158
+ console.log(`niral: framework ${manifest.version} ready (${ref})`);
159
+ return FRAMEWORK;
160
+ } finally {
161
+ if (stage) rmSync(stage, { recursive: true, force: true });
162
+ rmSync(lock, { recursive: true, force: true });
163
+ }
164
+ }
165
+
166
+ export async function updateFramework({ sourceRoot } = {}) {
167
+ if (sourceRoot && (!existsSync(FRAMEWORK) || realpathSync(sourceRoot) !== realpathSync(FRAMEWORK))) {
168
+ throw new Error("niral update only updates the managed NIRAL_HOME/framework installation. Update source checkouts with Git; deploy servers separately.");
74
169
  }
75
- if (!installed) await installFromTarball();
76
- if (!existsSync(join(FRAMEWORK, "bin", "niral.js"))) throw new Error("framework download failed — try again or clone github.com/Zyora-Dev/niral manually");
77
- return FRAMEWORK;
170
+ await ensureFramework({ update: true });
171
+ }
172
+
173
+ export async function runLauncher(args) {
174
+ if (args[0] === "update") {
175
+ if (args.length === 2 && ["--help", "-h"].includes(args[1])) {
176
+ console.log("usage: niral update\nUpdates NIRAL_HOME/framework using its saved NIRAL_REF (default main); does not update npm packages or deploy apps.");
177
+ return 0;
178
+ }
179
+ if (args.length !== 1) throw new Error("usage: niral update");
180
+ await updateFramework();
181
+ if (existsSync(join(NIRAL_HOME, "bin", process.platform === "win32" ? "niral.cmd" : "niral"))) installLauncher();
182
+ return 0;
183
+ }
184
+ if (!args.length || ["help", "--help", "-h"].includes(args[0])) {
185
+ if (existsSync(join(FRAMEWORK, "bin", "niral.js"))) return runNiral(args);
186
+ console.log("niral <command> [options]\nCommands: create, dev, build, start, check, test, add, doctor, di, update.\nThe first framework command downloads the framework.\nniral di --help: Developer Intelligence setup, status, ask, chat, new.\nniral update: explicitly refresh the installed framework.\nRun niral --help after installation for the full framework command list.");
187
+ return 0;
188
+ }
189
+ if (["--version", "-v", "version"].includes(args[0])) {
190
+ const manifest = JSON.parse(readFileSync(new URL("./package.json", import.meta.url), "utf8"));
191
+ console.log(`${manifest.name} launcher ${manifest.version}`);
192
+ if (existsSync(join(FRAMEWORK, "package.json"))) {
193
+ const framework = JSON.parse(readFileSync(join(FRAMEWORK, "package.json"), "utf8"));
194
+ console.log(`niral framework ${framework.version}`);
195
+ }
196
+ return 0;
197
+ }
198
+ await ensureFramework();
199
+ return runNiral(args);
78
200
  }
79
201
 
80
202
  /** Put a `niral` launcher on the PATH so every later command is just `niral dev`. */
81
203
  export function installLauncher() {
82
204
  const binDir = join(NIRAL_HOME, "bin");
83
205
  mkdirSync(binDir, { recursive: true });
84
- const frameworkCli = join(FRAMEWORK, "bin", "niral.js");
206
+ const launcherDir = join(NIRAL_HOME, "launcher");
207
+ mkdirSync(launcherDir, { recursive: true });
208
+ writeFileSync(join(launcherDir, "index.mjs"), readFileSync(new URL(import.meta.url)));
209
+ const frameworkCli = join(launcherDir, "run.mjs");
210
+ writeFileSync(frameworkCli, `import { ensureFramework, runLauncher, runNiral } from "./index.mjs";
211
+ try {
212
+ const args = process.argv.slice(2);
213
+ if (args[0] === "update") process.exitCode = await runLauncher(args);
214
+ else {
215
+ await ensureFramework();
216
+ process.exitCode = runNiral(args);
217
+ }
218
+ } catch (error) {
219
+ console.error(error.message);
220
+ process.exitCode = 1;
221
+ }
222
+ `);
85
223
  const shim = join(binDir, process.platform === "win32" ? "niral.cmd" : "niral");
86
224
  if (process.platform === "win32") {
87
- writeFileSync(shim, `@echo off\r\n"${process.execPath}" "${frameworkCli}" %*\r\n`);
225
+ writeFileSync(shim, `@echo off\r\nset "NIRAL_HOME=${NIRAL_HOME.replaceAll("%", "%%")}"\r\n"${process.execPath.replaceAll("%", "%%")}" "${frameworkCli.replaceAll("%", "%%")}" %*\r\n`);
88
226
  } else {
89
- writeFileSync(shim, `#!/usr/bin/env sh\nexec "${process.execPath}" "${frameworkCli}" "$@"\n`);
227
+ const quote = (value) => `'${value.replaceAll("'", "'\\''")}'`;
228
+ writeFileSync(shim, `#!/usr/bin/env sh\nexport NIRAL_HOME=${quote(NIRAL_HOME)}\nexec ${quote(process.execPath)} ${quote(frameworkCli)} "$@"\n`);
90
229
  chmodSync(shim, 0o755);
91
230
  }
92
231
 
@@ -95,9 +234,11 @@ export function installLauncher() {
95
234
  : (process.env.SHELL ?? "").endsWith("/bash") ? join(homedir(), ".bashrc")
96
235
  : null;
97
236
  if (profile) {
98
- const line = `export PATH="$HOME/.niral/bin:$PATH"`;
237
+ const line = NIRAL_HOME === join(homedir(), ".niral")
238
+ ? `export PATH="$HOME/.niral/bin:$PATH"`
239
+ : `export PATH='${binDir.replaceAll("'", "'\\''")}':"$PATH"`;
99
240
  const current = existsSync(profile) ? readFileSync(profile, "utf8") : "";
100
- if (!current.includes(".niral/bin")) {
241
+ if (!current.split(/\r?\n/).includes(line)) {
101
242
  appendFileSync(profile, `\n# niral\n${line}\n`);
102
243
  return { shim, profile, added: true };
103
244
  }
package/package.json CHANGED
@@ -1,15 +1,16 @@
1
1
  {
2
2
  "name": "niral",
3
- "version": "0.1.2",
3
+ "version": "0.1.4",
4
4
  "description": "Niral — the zero-dependency full-stack framework by ZyoraLabs. This package is a tiny launcher; the framework itself lives at github.com/Zyora-Dev/niral and has zero dependencies.",
5
5
  "bin": {
6
6
  "niral": "bin/niral.js",
7
7
  "create-niral": "bin/create-niral.js"
8
8
  },
9
9
  "type": "module",
10
+ "files": ["bin/", "index.js", "README.md"],
10
11
  "engines": { "node": ">=22" },
11
12
  "keywords": ["niral", "framework", "fullstack", "zero-dependencies", "ssr", "zyoralabs"],
12
- "homepage": "https://niral.zyora.club",
13
+ "homepage": "https://niral.site",
13
14
  "repository": { "type": "git", "url": "git+https://github.com/Zyora-Dev/niral.git" },
14
15
  "license": "MIT",
15
16
  "dependencies": {}