create-fumadocs-app 16.0.3 → 16.0.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/dist/bin.d.ts +1 -0
- package/dist/bin.js +215 -0
- package/dist/chunk-BEZTHMLF.js +51 -0
- package/dist/chunk-JCFTHRDR.js +50 -0
- package/dist/chunk-UXPTMGXV.js +130 -0
- package/dist/{chunk-HLHY7KAF.js → chunk-ZWEHS3HT.js} +29 -19
- package/dist/index.d.ts +63 -1
- package/dist/index.js +6 -208
- package/dist/plugins/biome.base.d.ts +45 -0
- package/dist/plugins/biome.base.js +18 -0
- package/dist/plugins/biome.d.ts +5 -0
- package/dist/plugins/biome.js +43 -0
- package/dist/plugins/biome.next.d.ts +49 -0
- package/dist/plugins/biome.next.js +18 -0
- package/dist/plugins/eslint.d.ts +5 -0
- package/dist/plugins/eslint.js +61 -0
- package/dist/plugins/next-use-src.d.ts +8 -0
- package/dist/plugins/next-use-src.js +39 -0
- package/dist/plugins/orama-cloud.d.ts +5 -0
- package/dist/plugins/orama-cloud.js +359 -0
- package/package.json +17 -7
- package/dist/chunk-3VWJJEHU.js +0 -204
- package/dist/create-app.d.ts +0 -49
- package/dist/create-app.js +0 -7
- package/dist/orama-cloud-VQUOOEZ2.js +0 -313
- package/template/+next+biome/biome.json +0 -34
- package/template/+next+eslint/eslint.config.mjs +0 -26
|
@@ -1,313 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
copy,
|
|
3
|
-
depVersions,
|
|
4
|
-
pick,
|
|
5
|
-
sourceDir,
|
|
6
|
-
writeFile
|
|
7
|
-
} from "./chunk-HLHY7KAF.js";
|
|
8
|
-
|
|
9
|
-
// src/plugins/orama-cloud.ts
|
|
10
|
-
import path from "path";
|
|
11
|
-
import fs2 from "fs/promises";
|
|
12
|
-
|
|
13
|
-
// src/transform/shared.ts
|
|
14
|
-
import { IndentationText, Project, QuoteKind } from "ts-morph";
|
|
15
|
-
import fs from "fs/promises";
|
|
16
|
-
var project = new Project({
|
|
17
|
-
manipulationSettings: {
|
|
18
|
-
indentationText: IndentationText.TwoSpaces,
|
|
19
|
-
quoteKind: QuoteKind.Single
|
|
20
|
-
}
|
|
21
|
-
});
|
|
22
|
-
async function createSourceFile(path2) {
|
|
23
|
-
return project.createSourceFile(path2, (await fs.readFile(path2)).toString(), {
|
|
24
|
-
overwrite: true
|
|
25
|
-
});
|
|
26
|
-
}
|
|
27
|
-
function getCodeValue(v) {
|
|
28
|
-
return new Function(`return ${v}`)();
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
// src/transform/tanstack-start.ts
|
|
32
|
-
import { SyntaxKind } from "ts-morph";
|
|
33
|
-
function addTanstackPrerender(sourceFile, paths) {
|
|
34
|
-
const optionsArg = getTanstackStartCall(sourceFile)?.getArguments()[0]?.asKind(SyntaxKind.ObjectLiteralExpression);
|
|
35
|
-
if (!optionsArg) {
|
|
36
|
-
return;
|
|
37
|
-
}
|
|
38
|
-
const pagesProperty = optionsArg.getProperty("pages")?.asKind(SyntaxKind.PropertyAssignment);
|
|
39
|
-
if (pagesProperty) {
|
|
40
|
-
const initializer = pagesProperty.getInitializerIfKindOrThrow(
|
|
41
|
-
SyntaxKind.ArrayLiteralExpression
|
|
42
|
-
);
|
|
43
|
-
const existingPaths = /* @__PURE__ */ new Set();
|
|
44
|
-
for (const element of initializer.getElements()) {
|
|
45
|
-
const value = element.asKind(SyntaxKind.ObjectLiteralExpression)?.getProperty("path")?.asKind(SyntaxKind.PropertyAssignment)?.getInitializer()?.getText();
|
|
46
|
-
if (value) {
|
|
47
|
-
existingPaths.add(getCodeValue(value));
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
for (const path2 of paths) {
|
|
51
|
-
if (existingPaths.has(path2)) continue;
|
|
52
|
-
initializer.addElement(toItem(path2));
|
|
53
|
-
}
|
|
54
|
-
} else {
|
|
55
|
-
optionsArg.addProperty(
|
|
56
|
-
`pages: [
|
|
57
|
-
${paths.map((path2) => ` ${toItem(path2)}`).join(",\n")}
|
|
58
|
-
]`
|
|
59
|
-
);
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
function toItem(path2) {
|
|
63
|
-
return `{ path: '${path2}' }`;
|
|
64
|
-
}
|
|
65
|
-
function getTanstackStartCall(sourceFile) {
|
|
66
|
-
const pluginsProperty = sourceFile.getDefaultExportSymbol()?.getValueDeclaration()?.getFirstDescendantByKind(SyntaxKind.ObjectLiteralExpression)?.getProperty("plugins")?.getFirstChildByKind(SyntaxKind.ArrayLiteralExpression);
|
|
67
|
-
if (!pluginsProperty) return;
|
|
68
|
-
for (const element of pluginsProperty.getElements()) {
|
|
69
|
-
const expression = element.asKind(SyntaxKind.CallExpression);
|
|
70
|
-
if (expression && expression.getFirstChildByKind(SyntaxKind.Identifier)?.getText() === "tanstackStart") {
|
|
71
|
-
return expression;
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
// src/transform/react-router.ts
|
|
77
|
-
import {
|
|
78
|
-
ts
|
|
79
|
-
} from "ts-morph";
|
|
80
|
-
var SyntaxKind2 = ts.SyntaxKind;
|
|
81
|
-
function removeReactRouterPrerenderExclude(sourceFile, paths) {
|
|
82
|
-
const methodBody = getPrerenderMethod(sourceFile)?.getBody();
|
|
83
|
-
if (!methodBody) return;
|
|
84
|
-
const initializer = methodBody.getDescendantsOfKind(SyntaxKind2.VariableDeclaration).find((item) => item.getName() === "excluded")?.getInitializerIfKind(SyntaxKind2.ArrayLiteralExpression);
|
|
85
|
-
if (!initializer) return;
|
|
86
|
-
for (const element of initializer.getElements()) {
|
|
87
|
-
const value = getCodeValue(element.getText());
|
|
88
|
-
if (paths.includes(value)) {
|
|
89
|
-
initializer.removeElement(element);
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
function addReactRouterRoute(sourceFile, routes) {
|
|
94
|
-
modifyReactRouterRoutes(sourceFile, (arr) => {
|
|
95
|
-
for (const { path: path2, entry } of routes) {
|
|
96
|
-
arr.addElement(`route('${path2}', '${entry}')`);
|
|
97
|
-
}
|
|
98
|
-
});
|
|
99
|
-
}
|
|
100
|
-
function filterReactRouterRoute(sourceFile, filter) {
|
|
101
|
-
modifyReactRouterRoutes(sourceFile, (arr) => {
|
|
102
|
-
for (const element of arr.getElements()) {
|
|
103
|
-
if (!element.isKind(SyntaxKind2.CallExpression) || element.getFirstChildByKind(SyntaxKind2.Identifier)?.getText() !== "route" || filter({
|
|
104
|
-
path: getCodeValue(element.getArguments()[0].getText())
|
|
105
|
-
}))
|
|
106
|
-
continue;
|
|
107
|
-
arr.removeElement(element);
|
|
108
|
-
}
|
|
109
|
-
});
|
|
110
|
-
}
|
|
111
|
-
function modifyReactRouterRoutes(sourceFile, mod) {
|
|
112
|
-
const initializer = sourceFile.getDefaultExportSymbol()?.getValueDeclaration()?.getFirstDescendantByKind(SyntaxKind2.ArrayLiteralExpression);
|
|
113
|
-
if (initializer) mod(initializer);
|
|
114
|
-
}
|
|
115
|
-
function getPrerenderMethod(sourceFile) {
|
|
116
|
-
return sourceFile.getDefaultExportSymbol()?.getValueDeclaration()?.getFirstDescendantByKind(SyntaxKind2.ObjectLiteralExpression)?.getProperty("prerender")?.asKind(SyntaxKind2.MethodDeclaration) ?? null;
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
// src/transform/provider.ts
|
|
120
|
-
import { StructureKind, SyntaxKind as SyntaxKind3 } from "ts-morph";
|
|
121
|
-
function addSearchDialog(sourceFile) {
|
|
122
|
-
const elements = sourceFile.getDescendantsOfKind(SyntaxKind3.JsxElement);
|
|
123
|
-
for (const element of elements) {
|
|
124
|
-
const provider = element.getFirstChildByKind(SyntaxKind3.JsxOpeningElement);
|
|
125
|
-
if (provider?.getTagNameNode().getText() !== "RootProvider") continue;
|
|
126
|
-
if (provider.getAttributes().some(
|
|
127
|
-
(attr) => attr.isKind(SyntaxKind3.JsxAttribute) && attr.getNameNode().getText() === "search"
|
|
128
|
-
))
|
|
129
|
-
continue;
|
|
130
|
-
provider.addAttribute({
|
|
131
|
-
kind: StructureKind.JsxAttribute,
|
|
132
|
-
name: "search",
|
|
133
|
-
initializer: "{{ SearchDialog }}"
|
|
134
|
-
});
|
|
135
|
-
}
|
|
136
|
-
sourceFile.addImportDeclaration({
|
|
137
|
-
moduleSpecifier: "@/components/search",
|
|
138
|
-
defaultImport: "SearchDialog"
|
|
139
|
-
});
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
// src/plugins/orama-cloud.ts
|
|
143
|
-
function oramaCloud() {
|
|
144
|
-
return {
|
|
145
|
-
packageJson(packageJson) {
|
|
146
|
-
return {
|
|
147
|
-
...packageJson,
|
|
148
|
-
scripts: {
|
|
149
|
-
...packageJson.scripts,
|
|
150
|
-
build: `${packageJson.scripts.build} && bun scripts/sync-content.ts`
|
|
151
|
-
},
|
|
152
|
-
dependencies: {
|
|
153
|
-
...packageJson.dependencies,
|
|
154
|
-
...pick(depVersions, ["@orama/core"])
|
|
155
|
-
}
|
|
156
|
-
};
|
|
157
|
-
},
|
|
158
|
-
readme(content) {
|
|
159
|
-
return `${content}
|
|
160
|
-
|
|
161
|
-
## Orama Cloud
|
|
162
|
-
|
|
163
|
-
This project uses Orama Cloud for 3rd party search solution.
|
|
164
|
-
|
|
165
|
-
See https://fumadocs.dev/docs/headless/search/orama-cloud for integrating Orama Cloud to Fumadocs.`;
|
|
166
|
-
},
|
|
167
|
-
async afterWrite() {
|
|
168
|
-
const { dest, template, options } = this;
|
|
169
|
-
const appDir = path.join(dest, options.useSrcDir ? "src" : ".");
|
|
170
|
-
await copy(path.join(sourceDir, "template/+orama-cloud/@root"), dest);
|
|
171
|
-
await copy(path.join(sourceDir, "template/+orama-cloud/@app"), appDir);
|
|
172
|
-
if (template.value === "tanstack-start") {
|
|
173
|
-
await Promise.all([
|
|
174
|
-
fluent(
|
|
175
|
-
createSourceFile(path.join(dest, "vite.config.ts")),
|
|
176
|
-
(file) => addTanstackPrerender(file, ["/static.json"]),
|
|
177
|
-
(file) => file.save()
|
|
178
|
-
),
|
|
179
|
-
fs2.unlink(path.join(dest, "src/routes/api/search.ts")).catch(() => null),
|
|
180
|
-
writeFile(
|
|
181
|
-
path.join(dest, "src/routes/static[.]json.ts"),
|
|
182
|
-
route.tanstack
|
|
183
|
-
),
|
|
184
|
-
updateRootProvider(path.join(dest, "src/routes/__root.tsx"))
|
|
185
|
-
]);
|
|
186
|
-
} else if (template.value.startsWith("react-router")) {
|
|
187
|
-
await Promise.all([
|
|
188
|
-
fluent(
|
|
189
|
-
createSourceFile(path.join(dest, "app/routes.ts")),
|
|
190
|
-
(file) => filterReactRouterRoute(file, ({ path: path2 }) => path2 !== "api/search"),
|
|
191
|
-
(file) => addReactRouterRoute(file, [
|
|
192
|
-
{
|
|
193
|
-
path: "static.json",
|
|
194
|
-
entry: "routes/static.ts"
|
|
195
|
-
}
|
|
196
|
-
]),
|
|
197
|
-
(file) => file.save()
|
|
198
|
-
),
|
|
199
|
-
fluent(
|
|
200
|
-
createSourceFile(path.join(dest, "react-router.config.ts")),
|
|
201
|
-
(file) => removeReactRouterPrerenderExclude(file, ["/api/search"]),
|
|
202
|
-
(file) => file.save()
|
|
203
|
-
),
|
|
204
|
-
fs2.unlink(path.join(dest, "app/docs/search.ts")).catch(() => null),
|
|
205
|
-
writeFile(
|
|
206
|
-
path.join(dest, "app/routes/static.ts"),
|
|
207
|
-
route["react-router"]
|
|
208
|
-
),
|
|
209
|
-
updateRootProvider(path.join(dest, "app/root.tsx"))
|
|
210
|
-
]);
|
|
211
|
-
} else if (template.value.startsWith("+next")) {
|
|
212
|
-
await Promise.all([
|
|
213
|
-
fs2.unlink(path.join(appDir, "app/api/search/route.ts")).catch(() => null),
|
|
214
|
-
writeFile(path.join(appDir, "app/static.json/route.ts"), route.next),
|
|
215
|
-
updateRootProvider(path.join(appDir, "app/layout.tsx"))
|
|
216
|
-
]);
|
|
217
|
-
} else {
|
|
218
|
-
await Promise.all([
|
|
219
|
-
fs2.unlink(path.join(dest, "src/pages/api/search.ts")).catch(() => null),
|
|
220
|
-
writeFile(
|
|
221
|
-
path.join(dest, "src/pages/api/static.json.ts"),
|
|
222
|
-
route.waku
|
|
223
|
-
),
|
|
224
|
-
updateRootProvider(path.join(dest, "src/components/provider.tsx"))
|
|
225
|
-
]);
|
|
226
|
-
}
|
|
227
|
-
const filePath = {
|
|
228
|
-
"+next+fuma-docs-mdx": ".next/server/app/static.json.body",
|
|
229
|
-
"tanstack-start": ".output/public/static.json",
|
|
230
|
-
"react-router": "build/client/static.json",
|
|
231
|
-
"react-router-spa": "build/client/static.json",
|
|
232
|
-
waku: "dist/public/static.json"
|
|
233
|
-
}[template.value];
|
|
234
|
-
await writeFile(
|
|
235
|
-
path.join(dest, "scripts/sync-content.ts"),
|
|
236
|
-
`import { type OramaDocument, sync } from 'fumadocs-core/search/orama-cloud';
|
|
237
|
-
import * as fs from 'node:fs/promises';
|
|
238
|
-
import { OramaCloud } from '@orama/core';
|
|
239
|
-
|
|
240
|
-
// the path of pre-rendered \`static.json\`
|
|
241
|
-
const filePath = '${filePath}';
|
|
242
|
-
|
|
243
|
-
async function main() {
|
|
244
|
-
const orama = new OramaCloud({
|
|
245
|
-
projectId: process.env.NEXT_PUBLIC_ORAMA_PROJECT_ID,
|
|
246
|
-
apiKey: process.env.ORAMA_PRIVATE_API_KEY,
|
|
247
|
-
});
|
|
248
|
-
|
|
249
|
-
const content = await fs.readFile(filePath);
|
|
250
|
-
const records = JSON.parse(content.toString()) as OramaDocument[];
|
|
251
|
-
|
|
252
|
-
await sync(orama, {
|
|
253
|
-
index: process.env.NEXT_PUBLIC_ORAMA_DATASOURCE_ID,
|
|
254
|
-
documents: records,
|
|
255
|
-
});
|
|
256
|
-
|
|
257
|
-
console.log(\`search updated: \${records.length} records\`);
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
void main();`
|
|
261
|
-
);
|
|
262
|
-
}
|
|
263
|
-
};
|
|
264
|
-
}
|
|
265
|
-
async function updateRootProvider(rootPath) {
|
|
266
|
-
await fluent(
|
|
267
|
-
createSourceFile(rootPath),
|
|
268
|
-
(file) => addSearchDialog(file),
|
|
269
|
-
(file) => file.save()
|
|
270
|
-
);
|
|
271
|
-
}
|
|
272
|
-
async function fluent(value, ...actions) {
|
|
273
|
-
for (const action of actions) {
|
|
274
|
-
await action(await value);
|
|
275
|
-
}
|
|
276
|
-
return value;
|
|
277
|
-
}
|
|
278
|
-
var route = {
|
|
279
|
-
next: `import { exportSearchIndexes } from '@/lib/export-search-indexes';
|
|
280
|
-
|
|
281
|
-
export const revalidate = false;
|
|
282
|
-
|
|
283
|
-
export async function GET() {
|
|
284
|
-
return Response.json(await exportSearchIndexes());
|
|
285
|
-
}`,
|
|
286
|
-
"react-router": `import { exportSearchIndexes } from '@/lib/export-search-indexes';
|
|
287
|
-
|
|
288
|
-
export async function loader() {
|
|
289
|
-
return Response.json(await exportSearchIndexes());
|
|
290
|
-
}`,
|
|
291
|
-
tanstack: `import { createFileRoute } from '@tanstack/react-router';
|
|
292
|
-
import { exportSearchIndexes } from '@/lib/export-search-indexes';
|
|
293
|
-
|
|
294
|
-
export const Route = createFileRoute('/static.json')({
|
|
295
|
-
server: {
|
|
296
|
-
handlers: {
|
|
297
|
-
GET: async () => Response.json(await exportSearchIndexes()),
|
|
298
|
-
},
|
|
299
|
-
},
|
|
300
|
-
});`,
|
|
301
|
-
waku: `import { exportSearchIndexes } from '@/lib/export-search-indexes';
|
|
302
|
-
|
|
303
|
-
export async function GET() {
|
|
304
|
-
return Response.json(await exportSearchIndexes());
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
export const getConfig = () => ({
|
|
308
|
-
render: 'static',
|
|
309
|
-
});`
|
|
310
|
-
};
|
|
311
|
-
export {
|
|
312
|
-
oramaCloud
|
|
313
|
-
};
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"$schema": "https://biomejs.dev/schemas/2.2.0/schema.json",
|
|
3
|
-
"vcs": {
|
|
4
|
-
"enabled": true,
|
|
5
|
-
"clientKind": "git",
|
|
6
|
-
"useIgnoreFile": true
|
|
7
|
-
},
|
|
8
|
-
"files": {
|
|
9
|
-
"ignoreUnknown": true,
|
|
10
|
-
"includes": ["**", "!node_modules", "!.next", "!dist", "!build", "!.source"]
|
|
11
|
-
},
|
|
12
|
-
"formatter": {
|
|
13
|
-
"enabled": true,
|
|
14
|
-
"indentStyle": "space",
|
|
15
|
-
"indentWidth": 2
|
|
16
|
-
},
|
|
17
|
-
"linter": {
|
|
18
|
-
"enabled": true,
|
|
19
|
-
"rules": {
|
|
20
|
-
"recommended": true
|
|
21
|
-
},
|
|
22
|
-
"domains": {
|
|
23
|
-
"next": "recommended",
|
|
24
|
-
"react": "recommended"
|
|
25
|
-
}
|
|
26
|
-
},
|
|
27
|
-
"assist": {
|
|
28
|
-
"actions": {
|
|
29
|
-
"source": {
|
|
30
|
-
"organizeImports": "on"
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
}
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import { dirname } from 'path';
|
|
2
|
-
import { fileURLToPath } from 'url';
|
|
3
|
-
import { FlatCompat } from '@eslint/eslintrc';
|
|
4
|
-
|
|
5
|
-
const __filename = fileURLToPath(import.meta.url);
|
|
6
|
-
const __dirname = dirname(__filename);
|
|
7
|
-
|
|
8
|
-
const compat = new FlatCompat({
|
|
9
|
-
baseDirectory: __dirname,
|
|
10
|
-
});
|
|
11
|
-
|
|
12
|
-
const eslintConfig = [
|
|
13
|
-
...compat.extends('next/core-web-vitals', 'next/typescript'),
|
|
14
|
-
{
|
|
15
|
-
ignores: [
|
|
16
|
-
'node_modules/**',
|
|
17
|
-
'.next/**',
|
|
18
|
-
'out/**',
|
|
19
|
-
'build/**',
|
|
20
|
-
'.source/**',
|
|
21
|
-
'next-env.d.ts',
|
|
22
|
-
],
|
|
23
|
-
},
|
|
24
|
-
];
|
|
25
|
-
|
|
26
|
-
export default eslintConfig;
|