faf-cli 4.3.0 → 4.3.1
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/cli.d.ts.map +1 -1
- package/dist/cli.js +40 -22
- package/dist/cli.js.map +1 -1
- package/dist/commands/readme.d.ts +11 -6
- package/dist/commands/readme.d.ts.map +1 -1
- package/dist/commands/readme.js +167 -120
- package/dist/commands/readme.js.map +1 -1
- package/dist/commands/show.d.ts.map +1 -1
- package/dist/commands/show.js +22 -7
- package/dist/commands/show.js.map +1 -1
- package/dist/commands/sixws.d.ts +6 -0
- package/dist/commands/sixws.d.ts.map +1 -0
- package/dist/commands/sixws.js +154 -0
- package/dist/commands/sixws.js.map +1 -0
- package/dist/utils/file-utils.d.ts.map +1 -1
- package/dist/utils/file-utils.js +1 -4
- package/dist/utils/file-utils.js.map +1 -1
- package/package.json +5 -2
- package/project.faf +4 -4
- package/scripts/ANTHROPIC-DEMO.sh +203 -0
- package/scripts/boris-ready.sh +169 -0
- package/scripts/bundle-yaml.js +87 -0
- package/scripts/check-version.js +88 -0
- package/scripts/clean-build.js +34 -0
- package/scripts/cleanup-unused.sh +54 -0
- package/scripts/debug-django.txt +9 -0
- package/scripts/debug-mongo.txt +9 -0
- package/scripts/debug-react.txt +9 -0
- package/scripts/debug-rust.txt +9 -0
- package/scripts/debug-whisper.cpp.txt +9 -0
- package/scripts/evaluate-family-member.ts +300 -0
- package/scripts/generate-docs.ts +358 -0
- package/scripts/generate-drift-reports.sh +111 -0
- package/scripts/industry-showcase.json +122 -0
- package/scripts/mcp-ecosystem-research.sh +58 -0
- package/scripts/migrate-yaml-imports.sh +55 -0
- package/scripts/migrate-yaml.ts +132 -0
- package/scripts/performance-validation.ts +460 -0
- package/scripts/postinstall.js +30 -0
- package/scripts/prepare-release.ts +421 -0
- package/scripts/run-industry-showcase.ts +237 -0
- package/scripts/run-test-showcase.ts +244 -0
- package/scripts/setup-github-watch.sh +43 -0
- package/scripts/sync-version.js +35 -0
- package/scripts/test-integration-detection.ts +93 -0
- package/scripts/test-integration-simple.js +93 -0
- package/scripts/test-medal-progression.sh +143 -0
- package/scripts/test-showcase-results.json +109 -0
- package/scripts/test-showcase.json +32 -0
- package/scripts/update-version.js +148 -0
- package/scripts/verify-build.js +343 -0
- package/scripts/version-check.js +78 -0
- package/scripts/watch-discussions.sh +86 -0
|
@@ -0,0 +1,300 @@
|
|
|
1
|
+
#!/usr/bin/env ts-node
|
|
2
|
+
/**
|
|
3
|
+
* FAF Integration Quality Evaluation
|
|
4
|
+
*
|
|
5
|
+
* Evaluates tools for FAF integration based on:
|
|
6
|
+
* - Developer adoption (weekly downloads)
|
|
7
|
+
* - Security & reliability
|
|
8
|
+
* - Active maintenance
|
|
9
|
+
* - MCP server availability
|
|
10
|
+
* - .faf context contribution (slots filled)
|
|
11
|
+
*
|
|
12
|
+
* Championship Standard: 85% minimum quality score required
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import https from 'https';
|
|
16
|
+
import { promisify } from 'util';
|
|
17
|
+
|
|
18
|
+
const get = promisify(https.get);
|
|
19
|
+
|
|
20
|
+
interface IntegrationQuality {
|
|
21
|
+
integration: string;
|
|
22
|
+
weeklyDownloads: number;
|
|
23
|
+
lastPublish: string;
|
|
24
|
+
hasVulnerabilities: boolean;
|
|
25
|
+
qualityScore: number;
|
|
26
|
+
mcpServers: string[];
|
|
27
|
+
contextSlotsFilled: number;
|
|
28
|
+
totalScore: number;
|
|
29
|
+
tier: 'trophy' | 'gold' | 'silver' | 'bronze' | 'yellow' | 'red';
|
|
30
|
+
approved: boolean;
|
|
31
|
+
reasoning: string;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// Minimum quality thresholds for FAF integration approval
|
|
35
|
+
const INTEGRATION_REQUIREMENTS = {
|
|
36
|
+
weeklyDownloads: 100_000, // 100k+ shows real developer adoption
|
|
37
|
+
qualityScore: 85, // Bronze tier minimum (Championship standard)
|
|
38
|
+
maxDaysSincePublish: 90, // Active maintenance within 3 months
|
|
39
|
+
minContextSlots: 2, // Must contribute to 2+ .faf context fields
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
async function fetchJSON(url: string): Promise<any> {
|
|
43
|
+
return new Promise((resolve, reject) => {
|
|
44
|
+
https.get(url, (res) => {
|
|
45
|
+
let data = '';
|
|
46
|
+
res.on('data', (chunk) => data += chunk);
|
|
47
|
+
res.on('end', () => {
|
|
48
|
+
try {
|
|
49
|
+
resolve(JSON.parse(data));
|
|
50
|
+
} catch (e) {
|
|
51
|
+
reject(e);
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
}).on('error', reject);
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
async function getWeeklyDownloads(pkg: string): Promise<number> {
|
|
59
|
+
try {
|
|
60
|
+
const url = `https://api.npmjs.org/downloads/point/last-week/${pkg}`;
|
|
61
|
+
const data = await fetchJSON(url);
|
|
62
|
+
return data.downloads || 0;
|
|
63
|
+
} catch {
|
|
64
|
+
return 0;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
async function getPackageInfo(pkg: string): Promise<any> {
|
|
69
|
+
const url = `https://registry.npmjs.com/${pkg}`;
|
|
70
|
+
return await fetchJSON(url);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function getDaysSincePublish(publishDate: string): number {
|
|
74
|
+
const now = new Date();
|
|
75
|
+
const published = new Date(publishDate);
|
|
76
|
+
const diffTime = Math.abs(now.getTime() - published.getTime());
|
|
77
|
+
const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24));
|
|
78
|
+
return diffDays;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function calculateMaintenanceScore(info: any): number {
|
|
82
|
+
const latestVersion = info['dist-tags']?.latest;
|
|
83
|
+
if (!latestVersion) return 0;
|
|
84
|
+
|
|
85
|
+
const publishDate = info.time?.[latestVersion];
|
|
86
|
+
if (!publishDate) return 0;
|
|
87
|
+
|
|
88
|
+
const daysSince = getDaysSincePublish(publishDate);
|
|
89
|
+
|
|
90
|
+
// Scoring:
|
|
91
|
+
// < 30 days = 100
|
|
92
|
+
// 30-60 days = 90
|
|
93
|
+
// 60-90 days = 85
|
|
94
|
+
// > 90 days = declining score
|
|
95
|
+
if (daysSince < 30) return 100;
|
|
96
|
+
if (daysSince < 60) return 90;
|
|
97
|
+
if (daysSince < 90) return 85;
|
|
98
|
+
return Math.max(0, 85 - (daysSince - 90));
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// MCP servers available for each integration
|
|
102
|
+
const INTEGRATION_MCP_SERVERS: Record<string, string[]> = {
|
|
103
|
+
'react': ['@react-mcp/server', 'react-mcp-tools'],
|
|
104
|
+
'next': ['@vercel/mcp-server', '@nextjs/mcp-tools'],
|
|
105
|
+
'svelte': ['@sveltejs/mcp', 'svelte-kit-mcp'],
|
|
106
|
+
'vue': ['@vue/mcp-server', 'vue-mcp-tools'],
|
|
107
|
+
'vite': ['vite-mcp-server'],
|
|
108
|
+
'typescript': ['typescript-language-server', '@typescript/mcp-tools'],
|
|
109
|
+
'n8n': ['n8n-mcp', 'n8n-nodes-mcp'],
|
|
110
|
+
'@supabase/supabase-js': ['@supabase/mcp-server-supabase'],
|
|
111
|
+
'prisma': ['@prisma/mcp-server'],
|
|
112
|
+
'@vercel/node': ['@vercel/mcp-server'],
|
|
113
|
+
'astro': ['@astro/mcp-server'],
|
|
114
|
+
'zod': ['zod-mcp-validator'],
|
|
115
|
+
'axios': ['http-mcp-tools'],
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
// .faf context slots populated by each integration
|
|
119
|
+
const CONTEXT_CONTRIBUTION: Record<string, string[]> = {
|
|
120
|
+
'react': ['frontend', 'ui_library', 'state_management'],
|
|
121
|
+
'next': ['frontend', 'backend', 'runtime', 'hosting', 'api_type'],
|
|
122
|
+
'svelte': ['frontend', 'ui_library', 'state_management'],
|
|
123
|
+
'vue': ['frontend', 'ui_library', 'state_management'],
|
|
124
|
+
'vite': ['build', 'package_manager'],
|
|
125
|
+
'typescript': ['main_language', 'type_system'],
|
|
126
|
+
'n8n': ['automation_platform', 'workflow_engine', 'integration_layer', 'api_orchestration'],
|
|
127
|
+
'@supabase/supabase-js': ['database', 'backend', 'api_type'],
|
|
128
|
+
'prisma': ['database', 'orm'],
|
|
129
|
+
'@vercel/node': ['runtime', 'hosting'],
|
|
130
|
+
'astro': ['frontend', 'build', 'hosting'],
|
|
131
|
+
'zod': ['validation', 'type_system'],
|
|
132
|
+
'axios': ['http_client', 'api_communication'],
|
|
133
|
+
'dotenv': ['configuration', 'environment'],
|
|
134
|
+
'chalk': ['terminal_ui', 'output_formatting'],
|
|
135
|
+
'yargs': ['cli_framework', 'argument_parsing'],
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
function getTier(score: number): IntegrationQuality['tier'] {
|
|
139
|
+
if (score >= 99) return 'trophy';
|
|
140
|
+
if (score >= 95) return 'gold';
|
|
141
|
+
if (score >= 90) return 'silver';
|
|
142
|
+
if (score >= 85) return 'bronze';
|
|
143
|
+
if (score >= 70) return 'yellow';
|
|
144
|
+
return 'red';
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
function getEmoji(tier: IntegrationQuality['tier']): string {
|
|
148
|
+
const emojis = {
|
|
149
|
+
trophy: '🏆',
|
|
150
|
+
gold: '🥇',
|
|
151
|
+
silver: '🥈',
|
|
152
|
+
bronze: '🥉',
|
|
153
|
+
yellow: '🟡',
|
|
154
|
+
red: '🔴'
|
|
155
|
+
};
|
|
156
|
+
return emojis[tier];
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
async function evaluateIntegration(pkg: string): Promise<IntegrationQuality> {
|
|
160
|
+
console.log(`\n🔗 Evaluating Integration: ${pkg}...`);
|
|
161
|
+
|
|
162
|
+
const weeklyDownloads = await getWeeklyDownloads(pkg);
|
|
163
|
+
const info = await getPackageInfo(pkg);
|
|
164
|
+
const maintainedScore = calculateMaintenanceScore(info);
|
|
165
|
+
const mcpServers = INTEGRATION_MCP_SERVERS[pkg] || [];
|
|
166
|
+
const contextSlotsFilled = CONTEXT_CONTRIBUTION[pkg]?.length || 0;
|
|
167
|
+
|
|
168
|
+
// Calculate total score
|
|
169
|
+
let totalScore = 0;
|
|
170
|
+
const scores = {
|
|
171
|
+
downloads: 0,
|
|
172
|
+
maintenance: 0,
|
|
173
|
+
mcp: 0,
|
|
174
|
+
slots: 0
|
|
175
|
+
};
|
|
176
|
+
|
|
177
|
+
// Downloads (30 points max)
|
|
178
|
+
if (weeklyDownloads >= 50_000_000) scores.downloads = 30; // 50M+
|
|
179
|
+
else if (weeklyDownloads >= 10_000_000) scores.downloads = 28; // 10M+
|
|
180
|
+
else if (weeklyDownloads >= 1_000_000) scores.downloads = 25; // 1M+
|
|
181
|
+
else if (weeklyDownloads >= 100_000) scores.downloads = 20; // 100k+
|
|
182
|
+
else scores.downloads = Math.floor((weeklyDownloads / 100_000) * 20);
|
|
183
|
+
|
|
184
|
+
// Maintenance (30 points max)
|
|
185
|
+
scores.maintenance = Math.floor(maintainedScore * 0.3);
|
|
186
|
+
|
|
187
|
+
// MCP availability (20 points max)
|
|
188
|
+
scores.mcp = mcpServers.length > 0 ? 20 : 0;
|
|
189
|
+
|
|
190
|
+
// Context contribution (20 points max)
|
|
191
|
+
scores.slots = Math.min(20, contextSlotsFilled * 5);
|
|
192
|
+
|
|
193
|
+
totalScore = scores.downloads + scores.maintenance + scores.mcp + scores.slots;
|
|
194
|
+
|
|
195
|
+
const tier = getTier(totalScore);
|
|
196
|
+
const approved = totalScore >= INTEGRATION_REQUIREMENTS.qualityScore;
|
|
197
|
+
|
|
198
|
+
const latestVersion = info['dist-tags']?.latest;
|
|
199
|
+
const publishDate = info.time?.[latestVersion] || 'unknown';
|
|
200
|
+
|
|
201
|
+
const reasoning = [
|
|
202
|
+
`Adoption: ${weeklyDownloads.toLocaleString()} developers/week (${scores.downloads}/30 pts)`,
|
|
203
|
+
`Quality: ${maintainedScore}% maintenance score (${scores.maintenance}/30 pts)`,
|
|
204
|
+
`MCP Integration: ${mcpServers.length} server(s) available (${scores.mcp}/20 pts)`,
|
|
205
|
+
`Context: Fills ${contextSlotsFilled} .faf slots (${scores.slots}/20 pts)`,
|
|
206
|
+
`Updated: ${publishDate.split('T')[0]}`
|
|
207
|
+
].join('\n ');
|
|
208
|
+
|
|
209
|
+
console.log(` ${getEmoji(tier)} Quality Score: ${totalScore}/100 (${tier})`);
|
|
210
|
+
console.log(` ${approved ? '✅ APPROVED' : '❌ NOT APPROVED'}`);
|
|
211
|
+
|
|
212
|
+
return {
|
|
213
|
+
integration: pkg,
|
|
214
|
+
weeklyDownloads,
|
|
215
|
+
lastPublish: publishDate,
|
|
216
|
+
hasVulnerabilities: false, // TODO: Check npm audit
|
|
217
|
+
qualityScore: maintainedScore,
|
|
218
|
+
mcpServers,
|
|
219
|
+
contextSlotsFilled,
|
|
220
|
+
totalScore,
|
|
221
|
+
tier,
|
|
222
|
+
approved,
|
|
223
|
+
reasoning
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
async function main() {
|
|
228
|
+
console.log('🔗 FAF Integration Quality Assessment\n');
|
|
229
|
+
console.log('Championship Standard: 85+ quality score required\n');
|
|
230
|
+
console.log('='.repeat(60));
|
|
231
|
+
|
|
232
|
+
const candidates = [
|
|
233
|
+
// Phase 1: Core tooling
|
|
234
|
+
'zod',
|
|
235
|
+
'axios',
|
|
236
|
+
'dotenv',
|
|
237
|
+
'chalk',
|
|
238
|
+
'yargs',
|
|
239
|
+
|
|
240
|
+
// Phase 2: Top frameworks
|
|
241
|
+
'react',
|
|
242
|
+
'next',
|
|
243
|
+
'svelte',
|
|
244
|
+
'vue',
|
|
245
|
+
'vite',
|
|
246
|
+
|
|
247
|
+
// Phase 3: Full coverage
|
|
248
|
+
'typescript',
|
|
249
|
+
'@supabase/supabase-js',
|
|
250
|
+
'prisma',
|
|
251
|
+
'@vercel/node',
|
|
252
|
+
'astro'
|
|
253
|
+
];
|
|
254
|
+
|
|
255
|
+
const evaluations: IntegrationQuality[] = [];
|
|
256
|
+
|
|
257
|
+
for (const pkg of candidates) {
|
|
258
|
+
try {
|
|
259
|
+
const evaluation = await evaluateIntegration(pkg);
|
|
260
|
+
evaluations.push(evaluation);
|
|
261
|
+
await new Promise(resolve => setTimeout(resolve, 200)); // Rate limit
|
|
262
|
+
} catch (error) {
|
|
263
|
+
console.error(`❌ Failed to evaluate ${pkg}:`, error);
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
console.log('\n' + '='.repeat(60));
|
|
268
|
+
console.log('\n📊 INTEGRATION APPROVAL SUMMARY\n');
|
|
269
|
+
|
|
270
|
+
const approved = evaluations.filter(e => e.approved);
|
|
271
|
+
const needsWork = evaluations.filter(e => !e.approved);
|
|
272
|
+
|
|
273
|
+
console.log(`✅ APPROVED INTEGRATIONS: ${approved.length}/${evaluations.length}`);
|
|
274
|
+
approved.forEach(e => {
|
|
275
|
+
console.log(` ${getEmoji(e.tier)} ${e.integration} - ${e.totalScore}/100 quality score`);
|
|
276
|
+
});
|
|
277
|
+
|
|
278
|
+
console.log(`\n⚠️ NEEDS IMPROVEMENT: ${needsWork.length}/${evaluations.length}`);
|
|
279
|
+
needsWork.forEach(e => {
|
|
280
|
+
console.log(` ${getEmoji(e.tier)} ${e.integration} - ${e.totalScore}/100 (below 85% threshold)`);
|
|
281
|
+
});
|
|
282
|
+
|
|
283
|
+
console.log('\n🔗 RECOMMENDED INTEGRATIONS:\n');
|
|
284
|
+
console.log('Add these to package.json to enable smart detection:\n');
|
|
285
|
+
console.log('"dependencies": {');
|
|
286
|
+
approved.forEach((e, i) => {
|
|
287
|
+
const comma = i < approved.length - 1 ? ',' : '';
|
|
288
|
+
console.log(` "${e.integration}": "latest"${comma} // ${e.contextSlotsFilled} context slots`);
|
|
289
|
+
});
|
|
290
|
+
console.log('}');
|
|
291
|
+
|
|
292
|
+
console.log('\n🏁 Integration assessment complete!');
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
// Run if called directly
|
|
296
|
+
if (require.main === module) {
|
|
297
|
+
main().catch(console.error);
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
export { evaluateIntegration, type IntegrationQuality };
|
|
@@ -0,0 +1,358 @@
|
|
|
1
|
+
#!/usr/bin/env ts-node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* 📚 Documentation Generator - F1-Inspired Championship Docs
|
|
5
|
+
* Auto-generates command reference from FAF_INDEX
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import * as fs from 'fs/promises';
|
|
9
|
+
import * as path from 'path';
|
|
10
|
+
import { FAF_INDEX } from '../src/commands/index';
|
|
11
|
+
import { FAF_COLORS, FAF_ICONS } from '../src/utils/championship-style';
|
|
12
|
+
|
|
13
|
+
const DOCS_DIR = path.join(__dirname, '..', 'docs-site');
|
|
14
|
+
|
|
15
|
+
interface GenerationStats {
|
|
16
|
+
commandPages: number;
|
|
17
|
+
conceptPages: number;
|
|
18
|
+
totalPages: number;
|
|
19
|
+
errors: string[];
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Main documentation generation function
|
|
24
|
+
*/
|
|
25
|
+
async function generateDocs(): Promise<void> {
|
|
26
|
+
console.log(`${FAF_COLORS.fafCyan('🏗️ Generating FAF CLI Documentation...')}`);
|
|
27
|
+
|
|
28
|
+
const stats: GenerationStats = {
|
|
29
|
+
commandPages: 0,
|
|
30
|
+
conceptPages: 0,
|
|
31
|
+
totalPages: 0,
|
|
32
|
+
errors: []
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
try {
|
|
36
|
+
// Ensure docs directory exists
|
|
37
|
+
await ensureDocsDirectory();
|
|
38
|
+
|
|
39
|
+
// Generate command reference pages
|
|
40
|
+
await generateCommandPages(stats);
|
|
41
|
+
|
|
42
|
+
// Generate concept pages
|
|
43
|
+
await generateConceptPages(stats);
|
|
44
|
+
|
|
45
|
+
// Generate index pages
|
|
46
|
+
await generateIndexPages(stats);
|
|
47
|
+
|
|
48
|
+
// Generate navigation config
|
|
49
|
+
await generateNavigation();
|
|
50
|
+
|
|
51
|
+
// Show results
|
|
52
|
+
console.log();
|
|
53
|
+
console.log(`${FAF_COLORS.fafGreen('✅ Documentation Generation Complete!')}`);
|
|
54
|
+
console.log(`${FAF_COLORS.fafCyan('├─')} Command pages: ${stats.commandPages}`);
|
|
55
|
+
console.log(`${FAF_COLORS.fafCyan('├─')} Concept pages: ${stats.conceptPages}`);
|
|
56
|
+
console.log(`${FAF_COLORS.fafCyan('├─')} Total pages: ${stats.totalPages}`);
|
|
57
|
+
|
|
58
|
+
if (stats.errors.length > 0) {
|
|
59
|
+
console.log(`${FAF_COLORS.fafOrange('└─')} Errors: ${stats.errors.length}`);
|
|
60
|
+
stats.errors.forEach(error => {
|
|
61
|
+
console.log(` ${FAF_COLORS.fafOrange('⚠️')} ${error}`);
|
|
62
|
+
});
|
|
63
|
+
} else {
|
|
64
|
+
console.log(`${FAF_COLORS.fafGreen('└─')} No errors! 🏆`);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
} catch (error) {
|
|
68
|
+
console.error(`${FAF_COLORS.fafOrange('❌ Generation failed:')} ${error}`);
|
|
69
|
+
process.exit(1);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Ensure docs directory structure exists
|
|
75
|
+
*/
|
|
76
|
+
async function ensureDocsDirectory(): Promise<void> {
|
|
77
|
+
const dirs = [
|
|
78
|
+
path.join(DOCS_DIR, 'pages'),
|
|
79
|
+
path.join(DOCS_DIR, 'pages', 'commands'),
|
|
80
|
+
path.join(DOCS_DIR, 'pages', 'concepts'),
|
|
81
|
+
path.join(DOCS_DIR, 'pages', 'examples'),
|
|
82
|
+
path.join(DOCS_DIR, 'components'),
|
|
83
|
+
path.join(DOCS_DIR, 'public', 'screenshots'),
|
|
84
|
+
path.join(DOCS_DIR, 'public', 'examples')
|
|
85
|
+
];
|
|
86
|
+
|
|
87
|
+
for (const dir of dirs) {
|
|
88
|
+
await fs.mkdir(dir, { recursive: true });
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Generate command reference pages
|
|
94
|
+
*/
|
|
95
|
+
async function generateCommandPages(stats: GenerationStats): Promise<void> {
|
|
96
|
+
const commands = Object.entries(FAF_INDEX).filter(([_, entry]) => entry.type === 'command');
|
|
97
|
+
|
|
98
|
+
for (const [key, entry] of commands) {
|
|
99
|
+
try {
|
|
100
|
+
const content = generateCommandPageContent(key, entry);
|
|
101
|
+
const filePath = path.join(DOCS_DIR, 'pages', 'commands', `${key}.mdx`);
|
|
102
|
+
await fs.writeFile(filePath, content);
|
|
103
|
+
stats.commandPages++;
|
|
104
|
+
stats.totalPages++;
|
|
105
|
+
} catch (error) {
|
|
106
|
+
stats.errors.push(`Command ${key}: ${error}`);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Generate concept pages
|
|
113
|
+
*/
|
|
114
|
+
async function generateConceptPages(stats: GenerationStats): Promise<void> {
|
|
115
|
+
const concepts = Object.entries(FAF_INDEX).filter(([_, entry]) => entry.type === 'concept');
|
|
116
|
+
|
|
117
|
+
for (const [key, entry] of concepts) {
|
|
118
|
+
try {
|
|
119
|
+
const content = generateConceptPageContent(key, entry);
|
|
120
|
+
const filePath = path.join(DOCS_DIR, 'pages', 'concepts', `${key}.mdx`);
|
|
121
|
+
await fs.writeFile(filePath, content);
|
|
122
|
+
stats.conceptPages++;
|
|
123
|
+
stats.totalPages++;
|
|
124
|
+
} catch (error) {
|
|
125
|
+
stats.errors.push(`Concept ${key}: ${error}`);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Generate index pages
|
|
132
|
+
*/
|
|
133
|
+
async function generateIndexPages(stats: GenerationStats): Promise<void> {
|
|
134
|
+
// Commands index
|
|
135
|
+
const commandsIndex = generateCommandsIndexContent();
|
|
136
|
+
await fs.writeFile(
|
|
137
|
+
path.join(DOCS_DIR, 'pages', 'commands', 'index.mdx'),
|
|
138
|
+
commandsIndex
|
|
139
|
+
);
|
|
140
|
+
|
|
141
|
+
// Concepts index
|
|
142
|
+
const conceptsIndex = generateConceptsIndexContent();
|
|
143
|
+
await fs.writeFile(
|
|
144
|
+
path.join(DOCS_DIR, 'pages', 'concepts', 'index.mdx'),
|
|
145
|
+
conceptsIndex
|
|
146
|
+
);
|
|
147
|
+
|
|
148
|
+
// Main index
|
|
149
|
+
const mainIndex = generateMainIndexContent();
|
|
150
|
+
await fs.writeFile(
|
|
151
|
+
path.join(DOCS_DIR, 'pages', 'index.mdx'),
|
|
152
|
+
mainIndex
|
|
153
|
+
);
|
|
154
|
+
|
|
155
|
+
stats.totalPages += 3;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Generate command page content
|
|
160
|
+
*/
|
|
161
|
+
function generateCommandPageContent(key: string, entry: any): string {
|
|
162
|
+
return `# ${key}
|
|
163
|
+
|
|
164
|
+
${entry.description}
|
|
165
|
+
|
|
166
|
+
## Usage
|
|
167
|
+
|
|
168
|
+
\`\`\`bash
|
|
169
|
+
${entry.usage || `faf ${key}`}
|
|
170
|
+
\`\`\`
|
|
171
|
+
|
|
172
|
+
${entry.examples ? `
|
|
173
|
+
## Examples
|
|
174
|
+
|
|
175
|
+
${entry.examples.map((example: string) => `\`\`\`bash
|
|
176
|
+
${example}
|
|
177
|
+
\`\`\`\n`).join('')}
|
|
178
|
+
` : ''}
|
|
179
|
+
|
|
180
|
+
${entry.related ? `
|
|
181
|
+
## Related Commands
|
|
182
|
+
|
|
183
|
+
${entry.related.map((rel: string) => `- [${rel}](./${rel})`).join('\n')}
|
|
184
|
+
` : ''}
|
|
185
|
+
|
|
186
|
+
## Category
|
|
187
|
+
|
|
188
|
+
**${entry.category}** - ${getCategoryDescription(entry.category)}
|
|
189
|
+
`;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* Generate concept page content
|
|
194
|
+
*/
|
|
195
|
+
function generateConceptPageContent(key: string, entry: any): string {
|
|
196
|
+
return `# ${key}
|
|
197
|
+
|
|
198
|
+
${entry.description}
|
|
199
|
+
|
|
200
|
+
${entry.related ? `
|
|
201
|
+
## Related
|
|
202
|
+
|
|
203
|
+
${entry.related.map((rel: string) => `- [${rel}](../${getRelatedType(rel)}/${rel})`).join('\n')}
|
|
204
|
+
` : ''}
|
|
205
|
+
|
|
206
|
+
## Category
|
|
207
|
+
|
|
208
|
+
**${entry.category}** - ${getCategoryDescription(entry.category)}
|
|
209
|
+
`;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* Generate commands index content
|
|
214
|
+
*/
|
|
215
|
+
function generateCommandsIndexContent(): string {
|
|
216
|
+
const commands = Object.entries(FAF_INDEX).filter(([_, entry]) => entry.type === 'command');
|
|
217
|
+
|
|
218
|
+
return `# Commands Reference
|
|
219
|
+
|
|
220
|
+
Complete reference for all FAF CLI commands.
|
|
221
|
+
|
|
222
|
+
## Core Commands
|
|
223
|
+
|
|
224
|
+
${commands.filter(([_, entry]) => entry.category === 'core').map(([key, entry]) =>
|
|
225
|
+
`### [${key}](./${key})
|
|
226
|
+
${entry.description}
|
|
227
|
+
\`\`\`bash
|
|
228
|
+
${entry.usage || `faf ${key}`}
|
|
229
|
+
\`\`\`
|
|
230
|
+
`).join('\n')}
|
|
231
|
+
|
|
232
|
+
## All Commands
|
|
233
|
+
|
|
234
|
+
${commands.map(([key, entry]) => `- **[${key}](./${key})** - ${entry.description}`).join('\n')}
|
|
235
|
+
`;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
/**
|
|
239
|
+
* Generate concepts index content
|
|
240
|
+
*/
|
|
241
|
+
function generateConceptsIndexContent(): string {
|
|
242
|
+
const concepts = Object.entries(FAF_INDEX).filter(([_, entry]) => entry.type === 'concept');
|
|
243
|
+
|
|
244
|
+
return `# Core Concepts
|
|
245
|
+
|
|
246
|
+
Understanding the fundamentals of FAF CLI and AI context management.
|
|
247
|
+
|
|
248
|
+
${concepts.map(([key, entry]) => `## [${key}](./${key})
|
|
249
|
+
|
|
250
|
+
${entry.description}
|
|
251
|
+
`).join('\n')}
|
|
252
|
+
`;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
/**
|
|
256
|
+
* Generate main index content
|
|
257
|
+
*/
|
|
258
|
+
function generateMainIndexContent(): string {
|
|
259
|
+
return `---
|
|
260
|
+
title: FAF CLI Documentation
|
|
261
|
+
---
|
|
262
|
+
|
|
263
|
+
# 🏎️ FAF CLI Documentation
|
|
264
|
+
|
|
265
|
+
Welcome to the **Championship-grade AI context management** documentation!
|
|
266
|
+
|
|
267
|
+
## Quick Start
|
|
268
|
+
|
|
269
|
+
\`\`\`bash
|
|
270
|
+
# Install FAF CLI
|
|
271
|
+
npm install -g @faf/cli
|
|
272
|
+
|
|
273
|
+
# Initialize your project
|
|
274
|
+
faf init
|
|
275
|
+
|
|
276
|
+
# Check your AI context score
|
|
277
|
+
faf score
|
|
278
|
+
|
|
279
|
+
# Build trust with AI
|
|
280
|
+
faf trust
|
|
281
|
+
\`\`\`
|
|
282
|
+
|
|
283
|
+
## What is FAF?
|
|
284
|
+
|
|
285
|
+
FAF (Foundational AI-Context Format) transforms developer psychology from **hope-driven** to **trust-driven** AI development. In 30 seconds, FAF replaces 20 minutes of questions.
|
|
286
|
+
|
|
287
|
+
## Core Features
|
|
288
|
+
|
|
289
|
+
- 🚀 **Universal AI Context** - Works with Claude, ChatGPT, Gemini
|
|
290
|
+
- ⚡ **F1-Inspired Performance** - Championship speed (<40ms status)
|
|
291
|
+
- 🎯 **Trust-Driven Development** - Eliminate AI anxiety
|
|
292
|
+
- 💎 **Technical Credit System** - Psychology revolution vs debt
|
|
293
|
+
|
|
294
|
+
## Documentation Sections
|
|
295
|
+
|
|
296
|
+
- **[Commands](/commands)** - Complete CLI reference
|
|
297
|
+
- **[Concepts](/concepts)** - Core concepts and principles
|
|
298
|
+
- **[Examples](/examples)** - Real-world usage patterns
|
|
299
|
+
|
|
300
|
+
---
|
|
301
|
+
|
|
302
|
+
**🏁 Making AI development better for everyone!**
|
|
303
|
+
`;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
/**
|
|
307
|
+
* Generate navigation configuration
|
|
308
|
+
*/
|
|
309
|
+
async function generateNavigation(): Promise<void> {
|
|
310
|
+
const navConfig = `export default {
|
|
311
|
+
logo: <span>🏎️ FAF CLI</span>,
|
|
312
|
+
project: {
|
|
313
|
+
link: 'https://github.com/faf-org/cli'
|
|
314
|
+
},
|
|
315
|
+
docsRepositoryBase: 'https://github.com/faf-org/cli/tree/main/docs',
|
|
316
|
+
sidebar: {
|
|
317
|
+
defaultMenuCollapseLevel: 1
|
|
318
|
+
},
|
|
319
|
+
footer: {
|
|
320
|
+
text: '🏁 Making AI development better for everyone!'
|
|
321
|
+
}
|
|
322
|
+
}`;
|
|
323
|
+
|
|
324
|
+
await fs.writeFile(
|
|
325
|
+
path.join(DOCS_DIR, 'theme.config.tsx'),
|
|
326
|
+
navConfig
|
|
327
|
+
);
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
/**
|
|
331
|
+
* Helper functions
|
|
332
|
+
*/
|
|
333
|
+
function getCategoryDescription(category: string): string {
|
|
334
|
+
const descriptions: Record<string, string> = {
|
|
335
|
+
core: 'Essential FAF functionality',
|
|
336
|
+
ai: 'AI integration and compatibility',
|
|
337
|
+
trust: 'Trust and confidence management',
|
|
338
|
+
utilities: 'Helper tools and utilities',
|
|
339
|
+
improvement: 'Context improvement tools',
|
|
340
|
+
psychology: 'Developer psychology enhancement',
|
|
341
|
+
concepts: 'Fundamental concepts',
|
|
342
|
+
discovery: 'Technology discovery and analysis'
|
|
343
|
+
};
|
|
344
|
+
return descriptions[category] || 'FAF functionality';
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
function getRelatedType(key: string): string {
|
|
348
|
+
const entry = FAF_INDEX[key as keyof typeof FAF_INDEX];
|
|
349
|
+
if (!entry) return 'commands';
|
|
350
|
+
return entry.type === 'command' ? 'commands' : 'concepts';
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
// Run the generator
|
|
354
|
+
if (require.main === module) {
|
|
355
|
+
generateDocs().catch(console.error);
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
export { generateDocs };
|