create-nifra 2.1.0 → 2.2.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/dist/auth.js +1 -1
- package/package.json +2 -1
- package/src/agent-files.ts +149 -0
- package/template/package.json +3 -3
- package/template-isr/package.json +6 -6
- package/template-site/package.json +8 -8
- package/template-site-preact/package.json +8 -8
- package/template-site-solid/package.json +8 -8
- package/template-site-svelte/package.json +8 -8
- package/template-site-vue/package.json +8 -8
package/dist/auth.js
CHANGED
|
@@ -33,7 +33,7 @@ export const AUTH_PRESETS = {
|
|
|
33
33
|
label: "better-auth",
|
|
34
34
|
note: "email/password + sessions, mounted at /api/auth/* — add OAuth providers in auth.ts.",
|
|
35
35
|
// @nifrajs/better-auth mounts it; better-auth is the implementation (peer-installed alongside).
|
|
36
|
-
deps: { "@nifrajs/better-auth": "^2.
|
|
36
|
+
deps: { "@nifrajs/better-auth": "^2.2.0", "better-auth": "^1.2.0" },
|
|
37
37
|
},
|
|
38
38
|
};
|
|
39
39
|
/** The better-auth `database` adapter expression + its import line, for the scaffolded DB's ORM. */
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-nifra",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.2.0",
|
|
4
4
|
"description": "Scaffold a new nifra app — `bun create nifra <dir>`.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"bun",
|
|
@@ -29,6 +29,7 @@
|
|
|
29
29
|
},
|
|
30
30
|
"files": [
|
|
31
31
|
"dist",
|
|
32
|
+
"src/agent-files.ts",
|
|
32
33
|
"template",
|
|
33
34
|
"template-site",
|
|
34
35
|
"template-site-vue",
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The canonical generators for the agent-discovery files an app ships so a coding agent auto-discovers
|
|
3
|
+
* the project's nifra MCP server and prefers it over writing nifra from memory:
|
|
4
|
+
*
|
|
5
|
+
* .mcp.json — Claude Code's project MCP registry ({ mcpServers: { nifra: { command, args } } })
|
|
6
|
+
* .cursor/mcp.json — Cursor's MCP registry (same server config)
|
|
7
|
+
* CLAUDE.md — Claude's preamble (use the MCP first; gate on `nifra check`) + `@AGENTS.md` import
|
|
8
|
+
* AGENTS.md "MCP" — a section for non-Claude agents pointing at the same server
|
|
9
|
+
*
|
|
10
|
+
* Single source of truth: both `create-nifra` (scaffold time) and `@nifrajs/cli`'s `nifra init-agents`
|
|
11
|
+
* (retrofit an existing app) import these, so the four files can never drift apart. This module is
|
|
12
|
+
* dependency-free (pure string + object generation) on purpose — `create-nifra` ships with no runtime
|
|
13
|
+
* deps, and `@nifrajs/cli` imports it as a workspace dependency.
|
|
14
|
+
*
|
|
15
|
+
* Why `bunx @nifrajs/cli mcp` (not `bunx nifra mcp`): the `nifra` binary is provided by the
|
|
16
|
+
* `@nifrajs/cli` package. A scaffolded `site` app carries `@nifrajs/cli` as a devDependency, so either
|
|
17
|
+
* spelling would resolve `node_modules/.bin/nifra` locally — BUT the `api`/`isr` templates do NOT carry
|
|
18
|
+
* `@nifrajs/cli`, and the bare npm package literally named `nifra` (this monorepo's `@nifrajs/web` shim)
|
|
19
|
+
* exposes NO `nifra` bin. So `bunx nifra mcp` would fetch the wrong package and fail there. Naming the
|
|
20
|
+
* bin-owning package, `bunx @nifrajs/cli mcp`, resolves the locally-installed bin when present and
|
|
21
|
+
* otherwise fetches the package that actually provides the `nifra` command — robust across every
|
|
22
|
+
* template and for any existing app.
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
import { readFileSync } from "node:fs"
|
|
26
|
+
|
|
27
|
+
/** The MCP launch command, shared by `.mcp.json` and `.cursor/mcp.json`. See the module header for why
|
|
28
|
+
* the package is named explicitly rather than relying on the bare `nifra` bin. */
|
|
29
|
+
export const MCP_SERVER_COMMAND = "bunx" as const
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* The `@nifrajs/cli` version the launch command pins to — DERIVED at load time from this package's own
|
|
33
|
+
* `version`, never hardcoded. `fixed` changeset versioning ([["@nifrajs/*", "create-nifra", "nifra"]] in
|
|
34
|
+
* `.changeset/config.json`) bumps `create-nifra` and `@nifrajs/cli` in lockstep, so `create-nifra@x`
|
|
35
|
+
* always means `@nifrajs/cli@x`. Deriving it here means a release bump has nothing to forget to update —
|
|
36
|
+
* there is no stale literal to drift (the 1.0.0 cut shipped a beta pin exactly this way). `check:publish`
|
|
37
|
+
* still asserts it equals `@nifrajs/cli`'s version as a belt-and-suspenders guard on the `fixed` link.
|
|
38
|
+
*
|
|
39
|
+
* Resolves correctly under BOTH export conditions: the `bun` export runs `src/agent-files.ts`
|
|
40
|
+
* (`../package.json` → the package root) and the tsc `default` export runs `dist/agent-files.js`
|
|
41
|
+
* (`../package.json` → the same root, since `dist/` sits beside the manifest). npm always ships a
|
|
42
|
+
* package's own `package.json`, so the read can't miss at install time.
|
|
43
|
+
*
|
|
44
|
+
* Why pin at all instead of `bunx @nifrajs/cli mcp`: `bunx` keys its cache on the exact version spec.
|
|
45
|
+
* An UNPINNED spec resolves to the `latest` tag once, then `bunx` reuses that cached copy on every
|
|
46
|
+
* later spawn WITHOUT re-checking the registry — so an editor that once launched an older `@nifrajs/cli`
|
|
47
|
+
* keeps respawning the stale binary even after a newer one is published (the MCP server silently runs
|
|
48
|
+
* old code). Pinning the exact version makes the version part of the cache key, so each release fetches
|
|
49
|
+
* fresh and a stale cache can never shadow it. The cost: an already-scaffolded app's `.mcp.json` freezes
|
|
50
|
+
* at its scaffold-time version until `nifra init-agents` is re-run — an acceptable, deterministic trade.
|
|
51
|
+
*/
|
|
52
|
+
export const MCP_CLI_VERSION: string = (
|
|
53
|
+
JSON.parse(readFileSync(new URL("../package.json", import.meta.url), "utf8")) as {
|
|
54
|
+
version: string
|
|
55
|
+
}
|
|
56
|
+
).version
|
|
57
|
+
export const MCP_SERVER_ARGS = [`@nifrajs/cli@${MCP_CLI_VERSION}`, "mcp"] as const
|
|
58
|
+
|
|
59
|
+
/** The server entry registered under the `nifra` key in both Claude Code's and Cursor's MCP config. */
|
|
60
|
+
export interface McpServerConfig {
|
|
61
|
+
readonly command: string
|
|
62
|
+
readonly args: readonly string[]
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/** Claude Code / Cursor MCP config shape: a map of server name → launch config. */
|
|
66
|
+
export interface McpConfig {
|
|
67
|
+
readonly mcpServers: Readonly<Record<string, McpServerConfig>>
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/** The one canonical MCP config object both registries serialize — the anti-drift seam. */
|
|
71
|
+
export const MCP_CONFIG: McpConfig = {
|
|
72
|
+
mcpServers: {
|
|
73
|
+
nifra: { command: MCP_SERVER_COMMAND, args: [...MCP_SERVER_ARGS] },
|
|
74
|
+
},
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/** Serialize the canonical MCP config as the JSON written to `.mcp.json` and `.cursor/mcp.json`.
|
|
78
|
+
* Trailing newline so the file is POSIX-clean and diffs don't flag a missing EOL. */
|
|
79
|
+
export function mcpJson(): string {
|
|
80
|
+
return `${JSON.stringify(MCP_CONFIG, null, 2)}\n`
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* `CLAUDE.md` — Claude Code reads this automatically. It is deliberately NOT a copy of `AGENTS.md`:
|
|
85
|
+
* a short preamble that (1) tells Claude this project ships a nifra MCP, registered in `.mcp.json`, and
|
|
86
|
+
* to PREFER it, and (2) pulls in the full cookbook with Claude Code's `@file` import directive on its
|
|
87
|
+
* own line — `@AGENTS.md` — so the conventions live in exactly one place and can't drift between the
|
|
88
|
+
* two files. Keep this short; the depth is in `AGENTS.md`.
|
|
89
|
+
*/
|
|
90
|
+
export function claudeMd(): string {
|
|
91
|
+
return `# CLAUDE.md
|
|
92
|
+
|
|
93
|
+
This project ships a **nifra MCP server**, registered for Claude Code in \`.mcp.json\` (it launches with
|
|
94
|
+
\`${MCP_SERVER_COMMAND} ${MCP_SERVER_ARGS.join(" ")}\`). **Prefer the MCP tools** over writing nifra from memory — they are
|
|
95
|
+
typechecked against *this* project and this installed version, so they beat training-data recall:
|
|
96
|
+
|
|
97
|
+
- \`nifra_docs\` / \`nifra_example\` — exact signatures + verified, compiling snippets. Reach for these
|
|
98
|
+
before hand-writing a route, a loader, or a client call; a remembered API is often stale or wrong.
|
|
99
|
+
- \`nifra_context\` — this project's route index + conventions, so changes fit the existing surface.
|
|
100
|
+
- \`nifra_types\` — the EXACT TypeScript of any \`@nifrajs/*\` symbol (e.g. \`nifra_types({ name: "RateLimitStore" })\`).
|
|
101
|
+
Call it for a precise type; **never read \`node_modules/@nifrajs/**/*.d.ts\`** — the tool is the authoritative, complete source.
|
|
102
|
+
- **\`nifra_check\` is the done-gate.** Before declaring any change complete, run \`nifra_check\` (or
|
|
103
|
+
\`nifra check --json\` in a terminal). It typechecks the frontend↔backend contract and flags drift
|
|
104
|
+
(hand-rolled \`fetch()\` to this app's own API, server-only imports in \`routes/\`). A failing check
|
|
105
|
+
means the work isn't done — fix it, don't ship around it.
|
|
106
|
+
|
|
107
|
+
The full nifra cookbook for this app — backend rules, the typed never-throwing client, file routing, and
|
|
108
|
+
the gotchas — lives in \`AGENTS.md\`, imported here so it stays the single source of truth:
|
|
109
|
+
|
|
110
|
+
@AGENTS.md
|
|
111
|
+
`
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* The "## MCP server" section appended to a scaffolded (or retrofitted) `AGENTS.md`, so non-Claude
|
|
116
|
+
* agents (Cursor, and anything that reads `AGENTS.md`) also learn the MCP exists and what to prefer.
|
|
117
|
+
* Mirrors the CLAUDE.md preamble's guidance without the Claude-specific `@import`.
|
|
118
|
+
*/
|
|
119
|
+
export function agentsMcpSection(): string {
|
|
120
|
+
return `## MCP server
|
|
121
|
+
|
|
122
|
+
This project ships a **nifra MCP server** — launch it with \`${MCP_SERVER_COMMAND} ${MCP_SERVER_ARGS.join(" ")}\`. It's registered for
|
|
123
|
+
Claude Code in \`.mcp.json\` and for Cursor in \`.cursor/mcp.json\`; other agents can point their MCP client
|
|
124
|
+
at that command. **Prefer its tools** over writing nifra from memory — they're typechecked against this
|
|
125
|
+
project + the installed version, so they beat training-data recall:
|
|
126
|
+
|
|
127
|
+
- \`nifra_docs\` / \`nifra_example\` — exact signatures + verified, compiling snippets.
|
|
128
|
+
- \`nifra_context\` / \`nifra_routes\` — this project's route index + per-route schemas.
|
|
129
|
+
- \`nifra_types\` — the EXACT TypeScript of any \`@nifrajs/*\` symbol (interface/type/function). Call it for a
|
|
130
|
+
precise type; **never read \`@nifrajs\` \`.d.ts\` files** — this is the authoritative, complete source.
|
|
131
|
+
- \`nifra_check\` — the done-gate (typecheck + drift lints). Run it before calling work complete; a
|
|
132
|
+
failing check means it isn't done. (\`nifra check --json\` in a terminal does the same.)`
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/** Identifies a generated agent-discovery file: where it goes (relative to the project root) and how to
|
|
136
|
+
* produce its content. `merge` is for files that augment an existing one (AGENTS.md) rather than own it. */
|
|
137
|
+
export interface AgentFileSpec {
|
|
138
|
+
/** Path relative to the project root (POSIX-style; the caller joins onto the cwd). */
|
|
139
|
+
readonly path: string
|
|
140
|
+
/** A human label for the "wrote/skipped" report. */
|
|
141
|
+
readonly label: string
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/** The standalone files this module fully owns (whole-file generators). AGENTS.md is handled separately
|
|
145
|
+
* because create-nifra builds it from `agents.ts` and the retrofit command appends a section to it. */
|
|
146
|
+
export const MCP_JSON_PATH = ".mcp.json"
|
|
147
|
+
export const CURSOR_MCP_JSON_PATH = ".cursor/mcp.json"
|
|
148
|
+
export const CLAUDE_MD_PATH = "CLAUDE.md"
|
|
149
|
+
export const AGENTS_MD_PATH = "AGENTS.md"
|
package/template/package.json
CHANGED
|
@@ -10,9 +10,9 @@
|
|
|
10
10
|
"typecheck": "tsc --noEmit"
|
|
11
11
|
},
|
|
12
12
|
"dependencies": {
|
|
13
|
-
"@nifrajs/client": "^2.
|
|
14
|
-
"@nifrajs/core": "^2.
|
|
15
|
-
"@nifrajs/schema": "^2.
|
|
13
|
+
"@nifrajs/client": "^2.2.0",
|
|
14
|
+
"@nifrajs/core": "^2.2.0",
|
|
15
|
+
"@nifrajs/schema": "^2.2.0"
|
|
16
16
|
},
|
|
17
17
|
"devDependencies": {
|
|
18
18
|
"@types/bun": "latest",
|
|
@@ -9,16 +9,16 @@
|
|
|
9
9
|
"dev:bun": "bun run server.ts"
|
|
10
10
|
},
|
|
11
11
|
"dependencies": {
|
|
12
|
-
"@nifrajs/client": "^2.
|
|
13
|
-
"@nifrajs/core": "^2.
|
|
14
|
-
"@nifrajs/schema": "^2.
|
|
15
|
-
"@nifrajs/web": "^2.
|
|
16
|
-
"@nifrajs/web-react": "^2.
|
|
12
|
+
"@nifrajs/client": "^2.2.0",
|
|
13
|
+
"@nifrajs/core": "^2.2.0",
|
|
14
|
+
"@nifrajs/schema": "^2.2.0",
|
|
15
|
+
"@nifrajs/web": "^2.2.0",
|
|
16
|
+
"@nifrajs/web-react": "^2.2.0",
|
|
17
17
|
"react": "^19.0.0",
|
|
18
18
|
"react-dom": "^19.0.0"
|
|
19
19
|
},
|
|
20
20
|
"devDependencies": {
|
|
21
|
-
"@nifrajs/cli": "^2.
|
|
21
|
+
"@nifrajs/cli": "^2.2.0",
|
|
22
22
|
"@types/react": "^19.0.0",
|
|
23
23
|
"@types/react-dom": "^19.0.0",
|
|
24
24
|
"typescript": "^6.0.3"
|
|
@@ -17,20 +17,20 @@
|
|
|
17
17
|
"deploy:vercel": "vercel deploy --prebuilt"
|
|
18
18
|
},
|
|
19
19
|
"dependencies": {
|
|
20
|
-
"@nifrajs/client": "^2.
|
|
21
|
-
"@nifrajs/core": "^2.
|
|
22
|
-
"@nifrajs/schema": "^2.
|
|
23
|
-
"@nifrajs/deno": "^2.
|
|
24
|
-
"@nifrajs/node": "^2.
|
|
25
|
-
"@nifrajs/web": "^2.
|
|
26
|
-
"@nifrajs/web-react": "^2.
|
|
20
|
+
"@nifrajs/client": "^2.2.0",
|
|
21
|
+
"@nifrajs/core": "^2.2.0",
|
|
22
|
+
"@nifrajs/schema": "^2.2.0",
|
|
23
|
+
"@nifrajs/deno": "^2.2.0",
|
|
24
|
+
"@nifrajs/node": "^2.2.0",
|
|
25
|
+
"@nifrajs/web": "^2.2.0",
|
|
26
|
+
"@nifrajs/web-react": "^2.2.0",
|
|
27
27
|
"react": "^19.0.0",
|
|
28
28
|
"react-dom": "^19.0.0"
|
|
29
29
|
},
|
|
30
30
|
"devDependencies": {
|
|
31
31
|
"@types/react": "^19.0.0",
|
|
32
32
|
"@types/react-dom": "^19.0.0",
|
|
33
|
-
"@nifrajs/cli": "^2.
|
|
33
|
+
"@nifrajs/cli": "^2.2.0",
|
|
34
34
|
"@vitejs/plugin-react": "^4.3.0",
|
|
35
35
|
"typescript": "^6.0.3",
|
|
36
36
|
"vite": "^8.0.0"
|
|
@@ -17,18 +17,18 @@
|
|
|
17
17
|
"deploy:vercel": "vercel deploy --prebuilt"
|
|
18
18
|
},
|
|
19
19
|
"dependencies": {
|
|
20
|
-
"@nifrajs/client": "^2.
|
|
21
|
-
"@nifrajs/core": "^2.
|
|
22
|
-
"@nifrajs/schema": "^2.
|
|
23
|
-
"@nifrajs/deno": "^2.
|
|
24
|
-
"@nifrajs/node": "^2.
|
|
25
|
-
"@nifrajs/web": "^2.
|
|
26
|
-
"@nifrajs/web-preact": "^2.
|
|
20
|
+
"@nifrajs/client": "^2.2.0",
|
|
21
|
+
"@nifrajs/core": "^2.2.0",
|
|
22
|
+
"@nifrajs/schema": "^2.2.0",
|
|
23
|
+
"@nifrajs/deno": "^2.2.0",
|
|
24
|
+
"@nifrajs/node": "^2.2.0",
|
|
25
|
+
"@nifrajs/web": "^2.2.0",
|
|
26
|
+
"@nifrajs/web-preact": "^2.2.0",
|
|
27
27
|
"preact": "^10.25.0"
|
|
28
28
|
},
|
|
29
29
|
"devDependencies": {
|
|
30
30
|
"@preact/preset-vite": "^2.9.0",
|
|
31
|
-
"@nifrajs/cli": "^2.
|
|
31
|
+
"@nifrajs/cli": "^2.2.0",
|
|
32
32
|
"typescript": "^6.0.3",
|
|
33
33
|
"vite": "^8.0.0"
|
|
34
34
|
}
|
|
@@ -17,17 +17,17 @@
|
|
|
17
17
|
"deploy:vercel": "vercel deploy --prebuilt"
|
|
18
18
|
},
|
|
19
19
|
"dependencies": {
|
|
20
|
-
"@nifrajs/client": "^2.
|
|
21
|
-
"@nifrajs/core": "^2.
|
|
22
|
-
"@nifrajs/schema": "^2.
|
|
23
|
-
"@nifrajs/deno": "^2.
|
|
24
|
-
"@nifrajs/node": "^2.
|
|
25
|
-
"@nifrajs/web": "^2.
|
|
26
|
-
"@nifrajs/web-solid": "^2.
|
|
20
|
+
"@nifrajs/client": "^2.2.0",
|
|
21
|
+
"@nifrajs/core": "^2.2.0",
|
|
22
|
+
"@nifrajs/schema": "^2.2.0",
|
|
23
|
+
"@nifrajs/deno": "^2.2.0",
|
|
24
|
+
"@nifrajs/node": "^2.2.0",
|
|
25
|
+
"@nifrajs/web": "^2.2.0",
|
|
26
|
+
"@nifrajs/web-solid": "^2.2.0",
|
|
27
27
|
"solid-js": "^1.9.0"
|
|
28
28
|
},
|
|
29
29
|
"devDependencies": {
|
|
30
|
-
"@nifrajs/cli": "^2.
|
|
30
|
+
"@nifrajs/cli": "^2.2.0",
|
|
31
31
|
"typescript": "^6.0.3",
|
|
32
32
|
"vite": "^8.0.0",
|
|
33
33
|
"vite-plugin-solid": "^2.10.0"
|
|
@@ -17,18 +17,18 @@
|
|
|
17
17
|
"deploy:vercel": "vercel deploy --prebuilt"
|
|
18
18
|
},
|
|
19
19
|
"dependencies": {
|
|
20
|
-
"@nifrajs/client": "^2.
|
|
21
|
-
"@nifrajs/core": "^2.
|
|
22
|
-
"@nifrajs/schema": "^2.
|
|
23
|
-
"@nifrajs/deno": "^2.
|
|
24
|
-
"@nifrajs/node": "^2.
|
|
25
|
-
"@nifrajs/web": "^2.
|
|
26
|
-
"@nifrajs/web-svelte": "^2.
|
|
20
|
+
"@nifrajs/client": "^2.2.0",
|
|
21
|
+
"@nifrajs/core": "^2.2.0",
|
|
22
|
+
"@nifrajs/schema": "^2.2.0",
|
|
23
|
+
"@nifrajs/deno": "^2.2.0",
|
|
24
|
+
"@nifrajs/node": "^2.2.0",
|
|
25
|
+
"@nifrajs/web": "^2.2.0",
|
|
26
|
+
"@nifrajs/web-svelte": "^2.2.0",
|
|
27
27
|
"svelte": "^5.3.0"
|
|
28
28
|
},
|
|
29
29
|
"devDependencies": {
|
|
30
30
|
"@sveltejs/vite-plugin-svelte": "^5.0.0",
|
|
31
|
-
"@nifrajs/cli": "^2.
|
|
31
|
+
"@nifrajs/cli": "^2.2.0",
|
|
32
32
|
"typescript": "^6.0.3",
|
|
33
33
|
"vite": "^8.0.0"
|
|
34
34
|
}
|
|
@@ -17,17 +17,17 @@
|
|
|
17
17
|
"deploy:vercel": "vercel deploy --prebuilt"
|
|
18
18
|
},
|
|
19
19
|
"dependencies": {
|
|
20
|
-
"@nifrajs/client": "^2.
|
|
21
|
-
"@nifrajs/core": "^2.
|
|
22
|
-
"@nifrajs/schema": "^2.
|
|
23
|
-
"@nifrajs/deno": "^2.
|
|
24
|
-
"@nifrajs/node": "^2.
|
|
25
|
-
"@nifrajs/web": "^2.
|
|
26
|
-
"@nifrajs/web-vue": "^2.
|
|
20
|
+
"@nifrajs/client": "^2.2.0",
|
|
21
|
+
"@nifrajs/core": "^2.2.0",
|
|
22
|
+
"@nifrajs/schema": "^2.2.0",
|
|
23
|
+
"@nifrajs/deno": "^2.2.0",
|
|
24
|
+
"@nifrajs/node": "^2.2.0",
|
|
25
|
+
"@nifrajs/web": "^2.2.0",
|
|
26
|
+
"@nifrajs/web-vue": "^2.2.0",
|
|
27
27
|
"vue": "^3.5.0"
|
|
28
28
|
},
|
|
29
29
|
"devDependencies": {
|
|
30
|
-
"@nifrajs/cli": "^2.
|
|
30
|
+
"@nifrajs/cli": "^2.2.0",
|
|
31
31
|
"@vitejs/plugin-vue": "^5.2.0",
|
|
32
32
|
"@vue/compiler-sfc": "^3.5.0",
|
|
33
33
|
"typescript": "^6.0.3",
|