@fiyuu/core 0.1.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/LICENSE +674 -0
- package/README.md +194 -0
- package/package.json +17 -0
- package/src/artifacts.d.ts +20 -0
- package/src/artifacts.js +274 -0
- package/src/client.d.ts +8 -0
- package/src/client.js +8 -0
- package/src/config.d.ts +179 -0
- package/src/config.js +58 -0
- package/src/contracts.d.ts +176 -0
- package/src/contracts.js +45 -0
- package/src/generator.d.ts +2 -0
- package/src/generator.js +124 -0
- package/src/index.d.ts +11 -0
- package/src/index.js +11 -0
- package/src/media.d.ts +44 -0
- package/src/media.js +87 -0
- package/src/reactive.d.ts +53 -0
- package/src/reactive.js +160 -0
- package/src/responsive-wrapper.d.ts +18 -0
- package/src/responsive-wrapper.js +285 -0
- package/src/responsive.d.ts +15 -0
- package/src/responsive.js +48 -0
- package/src/scanner.d.ts +65 -0
- package/src/scanner.js +200 -0
- package/src/state.d.ts +1 -0
- package/src/state.js +1 -0
- package/src/template.d.ts +48 -0
- package/src/template.js +98 -0
- package/src/virtual.d.ts +14 -0
- package/src/virtual.js +21 -0
package/README.md
ADDED
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
# Fiyuu
|
|
2
|
+
|
|
3
|
+
Fiyuu is an **AI-native fullstack framework** built on GEA.
|
|
4
|
+
It makes app structure deterministic and exports machine-readable artifacts so both developers and AI tools can work with the same reliable context.
|
|
5
|
+
|
|
6
|
+
## What problem does Fiyuu solve?
|
|
7
|
+
|
|
8
|
+
Routing and rendering are already solved by strong frameworks.
|
|
9
|
+
Fiyuu focuses on a different bottleneck: **AI and humans often misread intent in large, fast-changing codebases**.
|
|
10
|
+
|
|
11
|
+
Fiyuu enforces fixed route contracts (`page.tsx`, `query.ts`, `action.ts`, `schema.ts`, `meta.ts`) and generates `.fiyuu/graph.json` plus AI docs (`PROJECT.md`, `PATHS.md`, `EXECUTION.md`, and more). This reduces guesswork in generation, refactors, and review flows.
|
|
12
|
+
|
|
13
|
+
## Why Fiyuu?
|
|
14
|
+
|
|
15
|
+
- **AI-native project context** — `fiyuu sync` exports graph + AI docs from real app structure
|
|
16
|
+
- **Deterministic fullstack contracts** — fixed file conventions reduce hidden behavior and drift
|
|
17
|
+
- **GEA-first runtime** — app route code stays React-free at the framework layer
|
|
18
|
+
- **Built-in diagnostics** — `fiyuu doctor` validates structure and common anti-patterns
|
|
19
|
+
- **AI assistant bridge** — `fiyuu ai "<prompt>"` prints route-aware context for external LLM workflows
|
|
20
|
+
|
|
21
|
+
## Measurable differentiation
|
|
22
|
+
|
|
23
|
+
Fiyuu tracks performance and DX scorecards by release.
|
|
24
|
+
|
|
25
|
+
| Metric | How to measure | Current (v0.1.x) | Target (v0.2) |
|
|
26
|
+
| --- | --- | --- | --- |
|
|
27
|
+
| Cold build time | `time npm run build` | Baseline pending | >= 20% better on reference app profile |
|
|
28
|
+
| SSR latency (avg/p95) | `npm run benchmark:gea` | Baseline pending | >= 15% lower p95 on reference profile |
|
|
29
|
+
| Client JS bundle size | `npm run benchmark:gea` (bundle output) | Baseline pending | >= 20% smaller on reference profile |
|
|
30
|
+
| AI context readiness time | `time fiyuu sync` | Baseline pending | <= 1s for 100-route reference app |
|
|
31
|
+
|
|
32
|
+
Until public scorecards are published, treat Fiyuu as an early-stage framework.
|
|
33
|
+
|
|
34
|
+
## Performance and benchmark tooling
|
|
35
|
+
|
|
36
|
+
Fiyuu uses Node.js native HTTP server (no Express). Client assets are bundled with esbuild. SSG routes are cached in memory with optional `meta.revalidate` (ISR-style TTL). Query results support TTL caching with in-flight de-duplication. Navigation responses and HTML support ETag/304, and client navigation prefetches links on hover/focus/viewport.
|
|
37
|
+
|
|
38
|
+
For app-layer UI performance, `fiyuu/client` also provides `optimizedImage`, `optimizedVideo`, and responsive helpers (`responsiveStyle`, `mediaUp`, `fluid`, etc.) so teams can ship faster pages without adding heavy UI runtime dependencies.
|
|
39
|
+
|
|
40
|
+
## Built-in Database (FiyuuDB)
|
|
41
|
+
|
|
42
|
+
Fiyuu includes a lightweight, always-in-memory database with SQL-like query support:
|
|
43
|
+
|
|
44
|
+
```typescript
|
|
45
|
+
// In query.ts or action.ts
|
|
46
|
+
import { db } from "@fiyuu/db";
|
|
47
|
+
|
|
48
|
+
// SQL-like queries
|
|
49
|
+
const users = await db.query("SELECT * FROM users WHERE age > ? AND status = ?", [18, "active"]);
|
|
50
|
+
await db.query("INSERT INTO users (name, email) VALUES (?, ?)", ["Ali", "ali@test.com"]);
|
|
51
|
+
await db.query("UPDATE users SET status = ? WHERE id = ?", ["inactive", "u_123"]);
|
|
52
|
+
|
|
53
|
+
// Table API
|
|
54
|
+
const table = db.table("users");
|
|
55
|
+
const admins = table.find({ role: "admin" });
|
|
56
|
+
const one = table.findOne({ email: "a@b.com" });
|
|
57
|
+
table.insert({ name: "Ahmet", email: "ahmet@test.com" });
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## Real-time Channels
|
|
61
|
+
|
|
62
|
+
Fiyuu provides built-in real-time communication via WebSocket and NATS:
|
|
63
|
+
|
|
64
|
+
```typescript
|
|
65
|
+
// Server-side (app/services/realtime-sync.ts)
|
|
66
|
+
import { defineService } from "@fiyuu/runtime";
|
|
67
|
+
import { realtime } from "@fiyuu/realtime";
|
|
68
|
+
|
|
69
|
+
export default defineService({
|
|
70
|
+
name: "realtime-sync",
|
|
71
|
+
start({ realtime, db }) {
|
|
72
|
+
const chat = realtime.channel("chat");
|
|
73
|
+
chat.on("message", async (data, socket) => {
|
|
74
|
+
chat.broadcast("new-message", { text: data.text, user: socket.userId });
|
|
75
|
+
await db.query("INSERT INTO messages (text, user) VALUES (?, ?)", [data.text, socket.userId]);
|
|
76
|
+
});
|
|
77
|
+
},
|
|
78
|
+
});
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
```html
|
|
82
|
+
<!-- Client-side -->
|
|
83
|
+
<script>
|
|
84
|
+
const chat = fiyuu.channel("chat");
|
|
85
|
+
chat.on("new-message", (data) => console.log(data));
|
|
86
|
+
chat.emit("message", { text: "Hello!" });
|
|
87
|
+
</script>
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
## Service-based Lifecycle (Always-Alive App)
|
|
91
|
+
|
|
92
|
+
Unlike Next.js (request-driven), Fiyuu apps stay alive continuously with background services:
|
|
93
|
+
|
|
94
|
+
```typescript
|
|
95
|
+
// app/services/data-sync.ts
|
|
96
|
+
import { defineService } from "@fiyuu/runtime";
|
|
97
|
+
|
|
98
|
+
export default defineService({
|
|
99
|
+
name: "data-sync",
|
|
100
|
+
async start({ db, realtime, config, log }) {
|
|
101
|
+
// Runs on boot, continuously in background
|
|
102
|
+
setInterval(async () => {
|
|
103
|
+
const stats = await db.query("SELECT COUNT(*) as c FROM users WHERE active = 1");
|
|
104
|
+
realtime.channel("stats").emit("update", stats[0]);
|
|
105
|
+
}, 30000);
|
|
106
|
+
},
|
|
107
|
+
async stop({ log }) {
|
|
108
|
+
// Cleanup on shutdown
|
|
109
|
+
},
|
|
110
|
+
});
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
Run benchmark:
|
|
114
|
+
|
|
115
|
+
```bash
|
|
116
|
+
npm run benchmark:gea
|
|
117
|
+
npm run benchmark:scorecard
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
This reports per-route latency (`avg`, `p50`, `p95`, `min`, `max`) and total client bundle size.
|
|
121
|
+
The scorecard command also records build/sync/doctor outputs into `docs/benchmarks/latest-scorecard.md`.
|
|
122
|
+
|
|
123
|
+
## Current scope (v2 direction)
|
|
124
|
+
|
|
125
|
+
- Primary: **AI-first routing framework** with deterministic contracts
|
|
126
|
+
- Shipping priority: graph tooling, diagnostics, and SSR + cache primitives
|
|
127
|
+
- Secondary: broader adapters, plugin ecosystem depth, CSR/SSG parity
|
|
128
|
+
|
|
129
|
+
## Competitive snapshot
|
|
130
|
+
|
|
131
|
+
Fiyuu is not positioned as a full replacement for Next.js, Nuxt, or Astro today.
|
|
132
|
+
It is positioned as an AI-native framework workflow where deterministic graph context is a first-class feature.
|
|
133
|
+
|
|
134
|
+
- Ecosystem breadth: behind mature frameworks (current reality)
|
|
135
|
+
- AI-readable architecture context: core investment area
|
|
136
|
+
- Public benchmark scorecards: in progress (`docs/benchmark-matrix.md`)
|
|
137
|
+
|
|
138
|
+
## Use cases
|
|
139
|
+
|
|
140
|
+
- **AI-assisted teams** using Copilot, Cursor, or local LLM pipelines
|
|
141
|
+
- **React-free app layer** teams that prefer explicit route contracts
|
|
142
|
+
- **Internal tools and dashboards** where deterministic structure matters more than maximal abstraction
|
|
143
|
+
|
|
144
|
+
## Quick Start
|
|
145
|
+
|
|
146
|
+
```bash
|
|
147
|
+
npm create fiyuu-app@latest my-app
|
|
148
|
+
cd my-app
|
|
149
|
+
npm install
|
|
150
|
+
npm run dev
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
## Useful commands
|
|
154
|
+
|
|
155
|
+
```bash
|
|
156
|
+
fiyuu dev
|
|
157
|
+
fiyuu build
|
|
158
|
+
fiyuu start
|
|
159
|
+
fiyuu deploy
|
|
160
|
+
fiyuu cloud help
|
|
161
|
+
fiyuu cloud login <token> --endpoint https://api.fiyuu.work
|
|
162
|
+
fiyuu cloud project create mysite
|
|
163
|
+
fiyuu cloud deploy mysite
|
|
164
|
+
fiyuu sync
|
|
165
|
+
fiyuu doctor
|
|
166
|
+
fiyuu doctor --fix
|
|
167
|
+
fiyuu graph stats
|
|
168
|
+
fiyuu graph export --format markdown --out docs/graph.md
|
|
169
|
+
fiyuu ai "explain route dependencies for /requests"
|
|
170
|
+
fiyuu skill list
|
|
171
|
+
fiyuu skill run seo-baseline
|
|
172
|
+
fiyuu feat list
|
|
173
|
+
fiyuu feat socket on
|
|
174
|
+
fiyuu feat socket off
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
## Default starter
|
|
178
|
+
|
|
179
|
+
- One-page home layout
|
|
180
|
+
- Optional feature selection during setup (interactive multi-select)
|
|
181
|
+
- Optional light/dark theme toggle with localStorage persistence
|
|
182
|
+
- Built-in `app/not-found.tsx` and `app/error.tsx`
|
|
183
|
+
|
|
184
|
+
## Documentation
|
|
185
|
+
|
|
186
|
+
- English: `docs/en.md`
|
|
187
|
+
- Turkish: `docs/tr.md`
|
|
188
|
+
- Skills (EN): `docs/skills.md`
|
|
189
|
+
- Skills (TR): `docs/skills.tr.md`
|
|
190
|
+
- v2 Product Spec (TR): `docs/v2-product-spec.tr.md`
|
|
191
|
+
- Benchmark Matrix: `docs/benchmark-matrix.md`
|
|
192
|
+
- Benchmarks Folder: `docs/benchmarks/README.md`
|
|
193
|
+
- AI Demo Walkthrough: `docs/ai-demo.md`
|
|
194
|
+
- AI-for-Framework Guide: `docs/ai-for-framework.md`
|
package/package.json
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@fiyuu/core",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"main": "./src/index.js",
|
|
6
|
+
"types": "./src/index.d.ts",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": "./src/index.js",
|
|
9
|
+
"./client": "./src/client.js"
|
|
10
|
+
},
|
|
11
|
+
"dependencies": {
|
|
12
|
+
"zod": "^3.24.2"
|
|
13
|
+
},
|
|
14
|
+
"peerDependencies": {
|
|
15
|
+
"react": "^19.1.0"
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { type ProjectGraph } from "./scanner.js";
|
|
2
|
+
export declare function syncProjectArtifacts(rootDirectory: string, appDirectory: string): Promise<ProjectGraph>;
|
|
3
|
+
interface SkillSummary {
|
|
4
|
+
name: string;
|
|
5
|
+
description: string;
|
|
6
|
+
tags: string[];
|
|
7
|
+
filePath: string;
|
|
8
|
+
}
|
|
9
|
+
export declare function createAiDocs(graph: ProjectGraph, rootDirectory: string, skills?: SkillSummary[]): {
|
|
10
|
+
project: string;
|
|
11
|
+
paths: string;
|
|
12
|
+
states: string;
|
|
13
|
+
features: string;
|
|
14
|
+
warnings: string;
|
|
15
|
+
skills: string;
|
|
16
|
+
execution: string;
|
|
17
|
+
interventions: string;
|
|
18
|
+
doctor: string;
|
|
19
|
+
};
|
|
20
|
+
export {};
|
package/src/artifacts.js
ADDED
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
import { existsSync, promises as fs } from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { createProjectGraph } from "./scanner.js";
|
|
4
|
+
export async function syncProjectArtifacts(rootDirectory, appDirectory) {
|
|
5
|
+
const graph = await createProjectGraph(appDirectory);
|
|
6
|
+
const outputDirectory = path.join(rootDirectory, ".fiyuu");
|
|
7
|
+
await fs.mkdir(outputDirectory, { recursive: true });
|
|
8
|
+
await fs.writeFile(path.join(outputDirectory, "graph.json"), `${JSON.stringify(graph, null, 2)}\n`);
|
|
9
|
+
const skills = await loadSkillSummaries(rootDirectory);
|
|
10
|
+
const docs = createAiDocs(graph, rootDirectory, skills);
|
|
11
|
+
await Promise.all([
|
|
12
|
+
fs.writeFile(path.join(outputDirectory, "PROJECT.md"), docs.project),
|
|
13
|
+
fs.writeFile(path.join(outputDirectory, "PATHS.md"), docs.paths),
|
|
14
|
+
fs.writeFile(path.join(outputDirectory, "STATES.md"), docs.states),
|
|
15
|
+
fs.writeFile(path.join(outputDirectory, "FEATURES.md"), docs.features),
|
|
16
|
+
fs.writeFile(path.join(outputDirectory, "WARNINGS.md"), docs.warnings),
|
|
17
|
+
fs.writeFile(path.join(outputDirectory, "SKILLS.md"), docs.skills),
|
|
18
|
+
fs.writeFile(path.join(outputDirectory, "EXECUTION.md"), docs.execution),
|
|
19
|
+
fs.writeFile(path.join(outputDirectory, "INTERVENTIONS.md"), docs.interventions),
|
|
20
|
+
fs.writeFile(path.join(outputDirectory, "DOCTOR.md"), docs.doctor),
|
|
21
|
+
]);
|
|
22
|
+
return graph;
|
|
23
|
+
}
|
|
24
|
+
async function loadSkillSummaries(rootDirectory) {
|
|
25
|
+
const skillsDir = path.join(rootDirectory, "skills");
|
|
26
|
+
if (!existsSync(skillsDir))
|
|
27
|
+
return [];
|
|
28
|
+
const entries = await fs.readdir(skillsDir, { withFileTypes: true });
|
|
29
|
+
const skillFiles = entries.filter((entry) => entry.isFile() && entry.name.endsWith(".ts"));
|
|
30
|
+
return Promise.all(skillFiles.map(async (entry) => {
|
|
31
|
+
const filePath = path.join(skillsDir, entry.name);
|
|
32
|
+
const source = await fs.readFile(filePath, "utf8");
|
|
33
|
+
const nameMatch = source.match(/name\s*:\s*["'`]([^"'`]+)["'`]/);
|
|
34
|
+
const descMatch = source.match(/description\s*:\s*["'`]([^"'`]+)["'`]/);
|
|
35
|
+
const tagsMatch = source.match(/tags\s*:\s*\[([^\]]*)\]/);
|
|
36
|
+
const tags = tagsMatch
|
|
37
|
+
? tagsMatch[1].match(/["'`]([^"'`]+)["'`]/g)?.map((t) => t.replace(/["'`]/g, "")) ?? []
|
|
38
|
+
: [];
|
|
39
|
+
return {
|
|
40
|
+
name: nameMatch?.[1] ?? entry.name.replace(/\.ts$/, ""),
|
|
41
|
+
description: descMatch?.[1] ?? "no description",
|
|
42
|
+
tags,
|
|
43
|
+
filePath: `skills/${entry.name}`,
|
|
44
|
+
};
|
|
45
|
+
}));
|
|
46
|
+
}
|
|
47
|
+
export function createAiDocs(graph, rootDirectory, skills = []) {
|
|
48
|
+
const project = `# Fiyuu Project Context
|
|
49
|
+
|
|
50
|
+
This file is auto-generated for AI systems reading the project.
|
|
51
|
+
Do not edit manually — run \`fiyuu sync\` to regenerate.
|
|
52
|
+
|
|
53
|
+
## Summary
|
|
54
|
+
|
|
55
|
+
- root: ${rootDirectory}
|
|
56
|
+
- routes: ${graph.routes.length}
|
|
57
|
+
- features: ${graph.features.length}
|
|
58
|
+
- actions: ${graph.actions.length}
|
|
59
|
+
- queries: ${graph.queries.length}
|
|
60
|
+
- skills: ${skills.length}
|
|
61
|
+
|
|
62
|
+
## Architecture
|
|
63
|
+
|
|
64
|
+
Fiyuu is a file-based fullstack framework built on GEA (@geajs/core).
|
|
65
|
+
Each route is a feature directory under \`app/\` with these fixed files:
|
|
66
|
+
- \`meta.ts\` — intent, title, render mode, SEO (required)
|
|
67
|
+
- \`schema.ts\` — Zod input/output contracts (required)
|
|
68
|
+
- \`page.tsx\` — GEA component for UI (optional)
|
|
69
|
+
- \`query.ts\` — data fetching with \`execute()\` (optional)
|
|
70
|
+
- \`action.ts\` — server mutations with \`execute()\` (optional)
|
|
71
|
+
- \`layout.tsx\` — route-scoped layout wrapper (optional)
|
|
72
|
+
- \`middleware.ts\` — request middleware (optional)
|
|
73
|
+
- \`route.ts\` — raw API route (optional, for \`/api/*\`)
|
|
74
|
+
|
|
75
|
+
## Route Overview
|
|
76
|
+
|
|
77
|
+
${graph.features
|
|
78
|
+
.map((feature) => `- route: ${feature.route}\n intent: ${feature.intent ?? "missing"}\n render: ${feature.render}\n missing: ${feature.missingRequiredFiles.join(", ") || "none"}`)
|
|
79
|
+
.join("\n")}
|
|
80
|
+
`;
|
|
81
|
+
const paths = `# Fiyuu Paths
|
|
82
|
+
|
|
83
|
+
Maps route folders to their fixed files.
|
|
84
|
+
Auto-generated — run \`fiyuu sync\` to update.
|
|
85
|
+
|
|
86
|
+
${graph.features
|
|
87
|
+
.map((feature) => {
|
|
88
|
+
const entries = Object.entries(feature.files)
|
|
89
|
+
.filter(([, value]) => Boolean(value))
|
|
90
|
+
.map(([name, value]) => ` - ${name}: ${value}`)
|
|
91
|
+
.join("\n");
|
|
92
|
+
return `## ${feature.route}\n- directory: ${feature.directory}\n${entries}`;
|
|
93
|
+
})
|
|
94
|
+
.join("\n\n")}
|
|
95
|
+
`;
|
|
96
|
+
const states = `# Fiyuu States
|
|
97
|
+
|
|
98
|
+
Current structural state snapshot for AI review.
|
|
99
|
+
Auto-generated — run \`fiyuu sync\` to update.
|
|
100
|
+
|
|
101
|
+
## Render Modes
|
|
102
|
+
|
|
103
|
+
${graph.features.map((feature) => `- ${feature.route}: ${feature.render}`).join("\n")}
|
|
104
|
+
|
|
105
|
+
## Intent State
|
|
106
|
+
|
|
107
|
+
${graph.features.map((feature) => `- ${feature.route}: ${feature.intent ?? "MISSING"}`).join("\n")}
|
|
108
|
+
|
|
109
|
+
## Schema Descriptions
|
|
110
|
+
|
|
111
|
+
${graph.features.map((feature) => `- ${feature.route}: ${feature.descriptions.join(" | ") || "MISSING"}`).join("\n")}
|
|
112
|
+
`;
|
|
113
|
+
const warnings = `# Fiyuu Warnings
|
|
114
|
+
|
|
115
|
+
Auto-generated — run \`fiyuu sync\` to update.
|
|
116
|
+
|
|
117
|
+
${graph.features.some((feature) => feature.warnings.length > 0)
|
|
118
|
+
? graph.features
|
|
119
|
+
.filter((feature) => feature.warnings.length > 0)
|
|
120
|
+
.map((feature) => `## ${feature.route}\n${feature.warnings.map((w) => `- ${w}`).join("\n")}`)
|
|
121
|
+
.join("\n\n")
|
|
122
|
+
: "No structural warnings detected.\n"}`;
|
|
123
|
+
const features = `# Fiyuu Features
|
|
124
|
+
|
|
125
|
+
## Runtime Capabilities
|
|
126
|
+
|
|
127
|
+
- route count: ${graph.routes.length}
|
|
128
|
+
- action count: ${graph.actions.length}
|
|
129
|
+
- query count: ${graph.queries.length}
|
|
130
|
+
|
|
131
|
+
## Per-Route Capabilities
|
|
132
|
+
|
|
133
|
+
${graph.features
|
|
134
|
+
.map((feature) => `- ${feature.route}:\n render=${feature.render}, page=${Boolean(feature.files["page.tsx"])}, action=${Boolean(feature.files["action.ts"])}, query=${Boolean(feature.files["query.ts"])}`)
|
|
135
|
+
.join("\n")}
|
|
136
|
+
`;
|
|
137
|
+
const skillsDoc = skills.length === 0
|
|
138
|
+
? `# Fiyuu Skills
|
|
139
|
+
|
|
140
|
+
No skills found. Create one with \`fiyuu skill new <name>\`.
|
|
141
|
+
|
|
142
|
+
Skills are project-aware scripts in the \`skills/\` directory.
|
|
143
|
+
AI assistants can read and run them for automated project tasks.
|
|
144
|
+
`
|
|
145
|
+
: `# Fiyuu Skills
|
|
146
|
+
|
|
147
|
+
Skills are project-aware scripts AI assistants can read and execute.
|
|
148
|
+
Run a skill: \`fiyuu skill run <name>\`
|
|
149
|
+
|
|
150
|
+
## Available Skills
|
|
151
|
+
|
|
152
|
+
${skills
|
|
153
|
+
.map((skill) => `### ${skill.name}\n- file: ${skill.filePath}\n- description: ${skill.description}\n- tags: ${skill.tags.join(", ") || "none"}`)
|
|
154
|
+
.join("\n\n")}
|
|
155
|
+
`;
|
|
156
|
+
const execution = buildExecutionDoc(graph);
|
|
157
|
+
const interventions = buildInterventionsDoc();
|
|
158
|
+
const doctor = buildDoctorDoc();
|
|
159
|
+
return {
|
|
160
|
+
project: `${project.trim()}\n`,
|
|
161
|
+
paths: `${paths.trim()}\n`,
|
|
162
|
+
states: `${states.trim()}\n`,
|
|
163
|
+
features: `${features.trim()}\n`,
|
|
164
|
+
warnings: `${warnings.trim()}\n`,
|
|
165
|
+
skills: skillsDoc,
|
|
166
|
+
execution,
|
|
167
|
+
interventions,
|
|
168
|
+
doctor,
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
function buildExecutionDoc(graph) {
|
|
172
|
+
const header = `# Fiyuu Execution Graph
|
|
173
|
+
|
|
174
|
+
Shows the server-side execution chain for every route.
|
|
175
|
+
Auto-generated — run \`fiyuu sync\` to update.
|
|
176
|
+
|
|
177
|
+
Each request follows this deterministic order:
|
|
178
|
+
1. Middleware (if middleware.ts exists)
|
|
179
|
+
2. Query (if query.ts exists) → fetches data, optional cache
|
|
180
|
+
3. Layout (if layout.tsx exists) → wraps page content
|
|
181
|
+
4. Page (page.tsx) → renders HTML
|
|
182
|
+
5. Document → injects meta, client runtime, scripts
|
|
183
|
+
6. Response → sent to browser
|
|
184
|
+
|
|
185
|
+
`;
|
|
186
|
+
const routeSections = graph.features
|
|
187
|
+
.map((feature) => {
|
|
188
|
+
const steps = [];
|
|
189
|
+
const hasMiddleware = Boolean(feature.files["middleware.ts"]);
|
|
190
|
+
const hasQuery = Boolean(feature.files["query.ts"]);
|
|
191
|
+
const hasLayout = Boolean(feature.files["layout.tsx"]);
|
|
192
|
+
const hasPage = Boolean(feature.files["page.tsx"]);
|
|
193
|
+
if (hasMiddleware)
|
|
194
|
+
steps.push(` → middleware.ts intercept / auth / headers`);
|
|
195
|
+
if (hasQuery)
|
|
196
|
+
steps.push(` → query.ts::execute() fetch data → injected as page props`);
|
|
197
|
+
if (hasLayout)
|
|
198
|
+
steps.push(` → layout.tsx::template() wrap content`);
|
|
199
|
+
if (hasPage)
|
|
200
|
+
steps.push(` → page.tsx::Page() render HTML [${feature.render.toUpperCase()}]`);
|
|
201
|
+
steps.push(` → renderDocument() inject meta, runtime, scripts`);
|
|
202
|
+
steps.push(` → HTTP 200 text/html`);
|
|
203
|
+
const flags = [];
|
|
204
|
+
if (feature.render === "ssg")
|
|
205
|
+
flags.push("cached after first render");
|
|
206
|
+
if (feature.render === "csr")
|
|
207
|
+
flags.push("body empty — client bundle renders");
|
|
208
|
+
return [
|
|
209
|
+
`## ${feature.route}`,
|
|
210
|
+
`- render: ${feature.render}`,
|
|
211
|
+
`- intent: ${feature.intent ?? "missing"}`,
|
|
212
|
+
flags.length > 0 ? `- notes: ${flags.join(", ")}` : null,
|
|
213
|
+
``,
|
|
214
|
+
`\`\`\``,
|
|
215
|
+
`Request GET ${feature.route}`,
|
|
216
|
+
...steps,
|
|
217
|
+
`\`\`\``,
|
|
218
|
+
]
|
|
219
|
+
.filter(Boolean)
|
|
220
|
+
.join("\n");
|
|
221
|
+
})
|
|
222
|
+
.join("\n\n");
|
|
223
|
+
return `${header}${routeSections}\n`;
|
|
224
|
+
}
|
|
225
|
+
function buildInterventionsDoc() {
|
|
226
|
+
return `# Fiyuu Interventions
|
|
227
|
+
|
|
228
|
+
Safe framework interventions that can be applied automatically.
|
|
229
|
+
|
|
230
|
+
## Supported via \`fiyuu doctor --fix\`
|
|
231
|
+
|
|
232
|
+
- Replace \`className=\` with \`class=\` in route source files.
|
|
233
|
+
- Add missing \`export async function execute()\` in \`action.ts\` and \`query.ts\`.
|
|
234
|
+
- Create missing \`app/not-found.tsx\` and \`app/error.tsx\` fallback pages.
|
|
235
|
+
- Add missing \`seo.title\` and \`seo.description\` fields in route \`meta.ts\`.
|
|
236
|
+
|
|
237
|
+
## Not auto-fixed (manual review required)
|
|
238
|
+
|
|
239
|
+
- \`dangerouslySetInnerHTML\` usage.
|
|
240
|
+
- React imports or hook usage in GEA routes.
|
|
241
|
+
- noJs violations where \`meta.ts\` sets \`noJs: true\` and page uses \`<script>\`.
|
|
242
|
+
|
|
243
|
+
## SEO baseline
|
|
244
|
+
|
|
245
|
+
- Use route-specific \`seo.title\`.
|
|
246
|
+
- Keep \`seo.description\` around 12-28 words.
|
|
247
|
+
`;
|
|
248
|
+
}
|
|
249
|
+
function buildDoctorDoc() {
|
|
250
|
+
return `# Fiyuu Doctor
|
|
251
|
+
|
|
252
|
+
Command reference for deterministic checks and safe fixes.
|
|
253
|
+
|
|
254
|
+
## Check only
|
|
255
|
+
|
|
256
|
+
\`fiyuu doctor\`
|
|
257
|
+
|
|
258
|
+
- Reports structure violations and quality warnings.
|
|
259
|
+
|
|
260
|
+
## Check + safe fixes
|
|
261
|
+
|
|
262
|
+
\`fiyuu doctor --fix\`
|
|
263
|
+
|
|
264
|
+
- Applies only deterministic, low-risk fixes.
|
|
265
|
+
- Prints each fixed item with \`(fixed)\` marker.
|
|
266
|
+
|
|
267
|
+
## Typical workflow
|
|
268
|
+
|
|
269
|
+
1. \`fiyuu sync\`
|
|
270
|
+
2. \`fiyuu doctor --fix\`
|
|
271
|
+
3. \`fiyuu doctor\`
|
|
272
|
+
4. \`fiyuu build\`
|
|
273
|
+
`;
|
|
274
|
+
}
|
package/src/client.d.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export * from "./contracts.js";
|
|
2
|
+
export * from "./state.js";
|
|
3
|
+
export * from "./virtual.js";
|
|
4
|
+
export * from "./template.js";
|
|
5
|
+
export * from "./media.js";
|
|
6
|
+
export * from "./responsive.js";
|
|
7
|
+
export * from "./responsive-wrapper.js";
|
|
8
|
+
export * from "./reactive.js";
|
package/src/client.js
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export * from "./contracts.js";
|
|
2
|
+
export * from "./state.js";
|
|
3
|
+
export * from "./virtual.js";
|
|
4
|
+
export * from "./template.js";
|
|
5
|
+
export * from "./media.js";
|
|
6
|
+
export * from "./responsive.js";
|
|
7
|
+
export * from "./responsive-wrapper.js";
|
|
8
|
+
export * from "./reactive.js";
|