@raystack/chronicle 0.1.0-canary.111b55a → 0.1.0-canary.1e5fdae
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/index.js +212 -833
- package/package.json +13 -9
- package/src/cli/commands/build.ts +30 -70
- package/src/cli/commands/dev.ts +24 -13
- package/src/cli/commands/init.ts +38 -123
- package/src/cli/commands/serve.ts +35 -50
- package/src/cli/commands/start.ts +20 -16
- package/src/cli/index.ts +14 -14
- package/src/cli/utils/config.ts +25 -26
- package/src/cli/utils/index.ts +3 -2
- package/src/cli/utils/resolve.ts +7 -3
- package/src/cli/utils/scaffold.ts +14 -16
- package/src/components/mdx/details.module.css +0 -2
- package/src/components/mdx/image.tsx +5 -20
- package/src/components/mdx/index.tsx +18 -4
- package/src/components/mdx/link.tsx +24 -20
- package/src/components/ui/breadcrumbs.tsx +8 -42
- package/src/components/ui/footer.tsx +2 -3
- package/src/components/ui/search.tsx +116 -71
- package/src/lib/api-routes.ts +6 -8
- package/src/lib/config.ts +31 -29
- package/src/lib/get-llm-text.ts +10 -0
- package/src/lib/head.tsx +26 -22
- package/src/lib/openapi.ts +8 -8
- package/src/lib/page-context.tsx +74 -58
- package/src/lib/source.ts +136 -114
- package/src/pages/ApiLayout.tsx +22 -18
- package/src/pages/ApiPage.tsx +32 -27
- package/src/pages/DocsLayout.tsx +7 -7
- package/src/pages/DocsPage.tsx +11 -11
- package/src/pages/NotFound.tsx +11 -4
- package/src/server/App.tsx +35 -27
- package/src/server/api/apis-proxy.ts +69 -0
- package/src/server/api/health.ts +5 -0
- package/src/server/api/page/[...slug].ts +17 -0
- package/src/server/api/search.ts +170 -0
- package/src/server/api/specs.ts +9 -0
- package/src/server/build-search-index.ts +78 -68
- package/src/server/entry-client.tsx +67 -55
- package/src/server/entry-server.tsx +100 -35
- package/src/server/routes/llms.txt.ts +61 -0
- package/src/server/routes/og.tsx +75 -0
- package/src/server/routes/robots.txt.ts +11 -0
- package/src/server/routes/sitemap.xml.ts +40 -0
- package/src/server/utils/safe-path.ts +17 -0
- package/src/server/vite-config.ts +87 -47
- package/src/themes/default/Layout.tsx +78 -47
- package/src/themes/default/Page.module.css +0 -16
- package/src/themes/default/Page.tsx +9 -11
- package/src/themes/default/Toc.tsx +25 -39
- package/src/themes/default/index.ts +7 -9
- package/src/themes/paper/ChapterNav.tsx +63 -43
- package/src/themes/paper/Layout.module.css +1 -1
- package/src/themes/paper/Layout.tsx +24 -12
- package/src/themes/paper/Page.module.css +16 -4
- package/src/themes/paper/Page.tsx +56 -62
- package/src/themes/paper/ReadingProgress.tsx +160 -139
- package/src/themes/paper/index.ts +5 -5
- package/src/themes/registry.ts +7 -7
- package/src/types/content.ts +5 -21
- package/src/types/globals.d.ts +3 -0
- package/src/types/theme.ts +4 -3
- package/src/cli/__tests__/config.test.ts +0 -25
- package/src/cli/__tests__/scaffold.test.ts +0 -10
- package/src/pages/__tests__/head.test.tsx +0 -57
- package/src/server/__tests__/entry-server.test.tsx +0 -35
- package/src/server/__tests__/handlers.test.ts +0 -77
- package/src/server/__tests__/og.test.ts +0 -23
- package/src/server/__tests__/router.test.ts +0 -72
- package/src/server/__tests__/vite-config.test.ts +0 -25
- package/src/server/adapters/vercel.ts +0 -133
- package/src/server/dev.ts +0 -156
- package/src/server/entry-prod.ts +0 -97
- package/src/server/entry-vercel.ts +0 -28
- package/src/server/handlers/apis-proxy.ts +0 -52
- package/src/server/handlers/health.ts +0 -3
- package/src/server/handlers/llms.ts +0 -58
- package/src/server/handlers/og.ts +0 -87
- package/src/server/handlers/robots.ts +0 -11
- package/src/server/handlers/search.ts +0 -172
- package/src/server/handlers/sitemap.ts +0 -39
- package/src/server/handlers/specs.ts +0 -9
- package/src/server/index.html +0 -12
- package/src/server/prod.ts +0 -18
- package/src/server/request-handler.ts +0 -63
- package/src/server/router.ts +0 -42
- package/src/themes/default/font.ts +0 -4
package/dist/cli/index.js
CHANGED
|
@@ -16,55 +16,109 @@ var __export = (target, all) => {
|
|
|
16
16
|
var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
|
|
17
17
|
var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
18
18
|
|
|
19
|
+
// src/lib/remark-unused-directives.ts
|
|
20
|
+
import { visit } from "unist-util-visit";
|
|
21
|
+
var remarkUnusedDirectives = () => {
|
|
22
|
+
return (tree) => {
|
|
23
|
+
visit(tree, ["textDirective"], (node) => {
|
|
24
|
+
const directive = node;
|
|
25
|
+
if (!directive.data) {
|
|
26
|
+
const hasAttributes = directive.attributes && Object.keys(directive.attributes).length > 0;
|
|
27
|
+
const hasChildren = directive.children && directive.children.length > 0;
|
|
28
|
+
if (!hasAttributes && !hasChildren) {
|
|
29
|
+
const name = directive.name;
|
|
30
|
+
if (!name)
|
|
31
|
+
return;
|
|
32
|
+
Object.keys(directive).forEach((key) => delete directive[key]);
|
|
33
|
+
directive.type = "text";
|
|
34
|
+
directive.value = `:${name}`;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
};
|
|
39
|
+
}, remark_unused_directives_default;
|
|
40
|
+
var init_remark_unused_directives = __esm(() => {
|
|
41
|
+
remark_unused_directives_default = remarkUnusedDirectives;
|
|
42
|
+
});
|
|
43
|
+
|
|
19
44
|
// src/server/vite-config.ts
|
|
20
45
|
var exports_vite_config = {};
|
|
21
46
|
__export(exports_vite_config, {
|
|
22
47
|
createViteConfig: () => createViteConfig
|
|
23
48
|
});
|
|
24
|
-
import path5 from "path";
|
|
25
49
|
import react from "@vitejs/plugin-react";
|
|
26
|
-
import
|
|
50
|
+
import { remarkDirectiveAdmonition, remarkMdxMermaid } from "fumadocs-core/mdx-plugins";
|
|
51
|
+
import { defineConfig as defineFumadocsConfig } from "fumadocs-mdx/config";
|
|
52
|
+
import mdx from "fumadocs-mdx/vite";
|
|
53
|
+
import { nitro } from "nitro/vite";
|
|
54
|
+
import path4 from "node:path";
|
|
27
55
|
import remarkDirective from "remark-directive";
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
56
|
+
function resolveOutputDir(projectRoot, preset) {
|
|
57
|
+
if (preset === "vercel" || preset === "vercel-static")
|
|
58
|
+
return path4.resolve(projectRoot, ".vercel/output");
|
|
59
|
+
return path4.resolve(projectRoot, ".output");
|
|
60
|
+
}
|
|
32
61
|
async function createViteConfig(options) {
|
|
33
|
-
const {
|
|
62
|
+
const { packageRoot, projectRoot, contentDir, preset } = options;
|
|
34
63
|
return {
|
|
35
|
-
root,
|
|
64
|
+
root: packageRoot,
|
|
36
65
|
configFile: false,
|
|
66
|
+
plugins: [
|
|
67
|
+
nitro({
|
|
68
|
+
serverDir: path4.resolve(packageRoot, "src/server"),
|
|
69
|
+
...preset && { preset }
|
|
70
|
+
}),
|
|
71
|
+
mdx({
|
|
72
|
+
default: defineFumadocsConfig({
|
|
73
|
+
mdxOptions: {
|
|
74
|
+
remarkPlugins: [
|
|
75
|
+
remarkDirective,
|
|
76
|
+
[remarkDirectiveAdmonition, {
|
|
77
|
+
tags: {
|
|
78
|
+
CalloutContainer: "Callout",
|
|
79
|
+
CalloutTitle: "CalloutTitle",
|
|
80
|
+
CalloutDescription: "CalloutDescription"
|
|
81
|
+
},
|
|
82
|
+
types: {
|
|
83
|
+
note: "accent",
|
|
84
|
+
tip: "accent",
|
|
85
|
+
info: "accent",
|
|
86
|
+
warn: "attention",
|
|
87
|
+
warning: "attention",
|
|
88
|
+
danger: "alert",
|
|
89
|
+
caution: "alert",
|
|
90
|
+
success: "success"
|
|
91
|
+
}
|
|
92
|
+
}],
|
|
93
|
+
remark_unused_directives_default,
|
|
94
|
+
remarkMdxMermaid
|
|
95
|
+
]
|
|
96
|
+
}
|
|
97
|
+
})
|
|
98
|
+
}, { index: false }),
|
|
99
|
+
react()
|
|
100
|
+
],
|
|
37
101
|
resolve: {
|
|
38
102
|
alias: {
|
|
39
|
-
"@":
|
|
40
|
-
"@content": contentDir
|
|
103
|
+
"@": path4.resolve(packageRoot, "src")
|
|
41
104
|
},
|
|
42
|
-
|
|
105
|
+
conditions: ["module-sync", "import", "node"],
|
|
106
|
+
dedupe: [
|
|
107
|
+
"react",
|
|
108
|
+
"react-dom",
|
|
109
|
+
"react/jsx-runtime",
|
|
110
|
+
"react/jsx-dev-runtime",
|
|
111
|
+
"react-router"
|
|
112
|
+
]
|
|
43
113
|
},
|
|
44
114
|
server: {
|
|
45
115
|
fs: {
|
|
46
|
-
allow: [
|
|
116
|
+
allow: [packageRoot, projectRoot, contentDir]
|
|
47
117
|
}
|
|
48
118
|
},
|
|
49
|
-
plugins: [
|
|
50
|
-
mdx({
|
|
51
|
-
remarkPlugins: [
|
|
52
|
-
remarkFrontmatter,
|
|
53
|
-
remarkMdxFrontmatter,
|
|
54
|
-
remarkGfm,
|
|
55
|
-
remarkDirective
|
|
56
|
-
],
|
|
57
|
-
rehypePlugins: [
|
|
58
|
-
[rehypeShiki, { themes: { light: "github-light", dark: "github-dark" }, defaultColor: false }]
|
|
59
|
-
],
|
|
60
|
-
mdExtensions: [".md"],
|
|
61
|
-
mdxExtensions: [".mdx"]
|
|
62
|
-
}),
|
|
63
|
-
react()
|
|
64
|
-
],
|
|
65
119
|
define: {
|
|
66
|
-
|
|
67
|
-
|
|
120
|
+
__CHRONICLE_CONTENT_DIR__: JSON.stringify(contentDir),
|
|
121
|
+
__CHRONICLE_PROJECT_ROOT__: JSON.stringify(projectRoot)
|
|
68
122
|
},
|
|
69
123
|
css: {
|
|
70
124
|
modules: {
|
|
@@ -72,648 +126,114 @@ async function createViteConfig(options) {
|
|
|
72
126
|
}
|
|
73
127
|
},
|
|
74
128
|
ssr: {
|
|
75
|
-
noExternal: ["@raystack/apsara"]
|
|
129
|
+
noExternal: ["@raystack/apsara", "dayjs", "fumadocs-core"]
|
|
76
130
|
},
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
};
|
|
85
|
-
}
|
|
86
|
-
var init_vite_config = () => {};
|
|
87
|
-
|
|
88
|
-
// src/server/dev.ts
|
|
89
|
-
var exports_dev = {};
|
|
90
|
-
__export(exports_dev, {
|
|
91
|
-
startDevServer: () => startDevServer
|
|
92
|
-
});
|
|
93
|
-
import { createServer as createViteServer } from "vite";
|
|
94
|
-
import { createServer } from "http";
|
|
95
|
-
import fsPromises from "fs/promises";
|
|
96
|
-
import { createReadStream } from "fs";
|
|
97
|
-
import path6 from "path";
|
|
98
|
-
import chalk3 from "chalk";
|
|
99
|
-
async function startDevServer(options) {
|
|
100
|
-
const { port, root, contentDir } = options;
|
|
101
|
-
const viteConfig = await createViteConfig({ root, contentDir, isDev: true });
|
|
102
|
-
const vite = await createViteServer({
|
|
103
|
-
...viteConfig,
|
|
104
|
-
server: { middlewareMode: true },
|
|
105
|
-
appType: "custom"
|
|
106
|
-
});
|
|
107
|
-
const templatePath = path6.resolve(root, "src/server/index.html");
|
|
108
|
-
const server = createServer(async (req, res) => {
|
|
109
|
-
const url = req.url || "/";
|
|
110
|
-
try {
|
|
111
|
-
if (url.startsWith("/@") || url.startsWith("/__vite") || url.startsWith("/node_modules/")) {
|
|
112
|
-
vite.middlewares(req, res, () => {
|
|
113
|
-
res.statusCode = 404;
|
|
114
|
-
res.end();
|
|
115
|
-
});
|
|
116
|
-
return;
|
|
117
|
-
}
|
|
118
|
-
const contentFile = path6.join(contentDir, decodeURIComponent(url.split("?")[0]));
|
|
119
|
-
if (!url.endsWith(".md") && !url.endsWith(".mdx")) {
|
|
120
|
-
try {
|
|
121
|
-
const stat = await fsPromises.stat(contentFile);
|
|
122
|
-
if (stat.isFile()) {
|
|
123
|
-
const ext = path6.extname(contentFile).toLowerCase();
|
|
124
|
-
const mimeTypes = {
|
|
125
|
-
".png": "image/png",
|
|
126
|
-
".jpg": "image/jpeg",
|
|
127
|
-
".jpeg": "image/jpeg",
|
|
128
|
-
".gif": "image/gif",
|
|
129
|
-
".svg": "image/svg+xml",
|
|
130
|
-
".webp": "image/webp",
|
|
131
|
-
".ico": "image/x-icon",
|
|
132
|
-
".pdf": "application/pdf",
|
|
133
|
-
".json": "application/json",
|
|
134
|
-
".yaml": "text/yaml",
|
|
135
|
-
".yml": "text/yaml",
|
|
136
|
-
".txt": "text/plain"
|
|
137
|
-
};
|
|
138
|
-
res.setHeader("Content-Type", mimeTypes[ext] || "application/octet-stream");
|
|
139
|
-
createReadStream(contentFile).pipe(res);
|
|
140
|
-
return;
|
|
131
|
+
environments: {
|
|
132
|
+
client: {
|
|
133
|
+
build: {
|
|
134
|
+
rollupOptions: {
|
|
135
|
+
input: path4.resolve(packageRoot, "src/server/entry-client.tsx")
|
|
141
136
|
}
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
if (/\.(js|ts|tsx|css|map)(\?|$)/.test(url)) {
|
|
145
|
-
vite.middlewares(req, res, () => {
|
|
146
|
-
res.statusCode = 404;
|
|
147
|
-
res.end();
|
|
148
|
-
});
|
|
149
|
-
return;
|
|
150
|
-
}
|
|
151
|
-
const { matchRoute } = await vite.ssrLoadModule(path6.resolve(root, "src/server/router.ts"));
|
|
152
|
-
const routeHandler = matchRoute(new URL(url, `http://localhost:${port}`).href);
|
|
153
|
-
if (routeHandler) {
|
|
154
|
-
const request = new Request(new URL(url, `http://localhost:${port}`));
|
|
155
|
-
const response = await routeHandler(request);
|
|
156
|
-
res.statusCode = response.status;
|
|
157
|
-
response.headers.forEach((value, key) => res.setHeader(key, value));
|
|
158
|
-
const body = await response.text();
|
|
159
|
-
res.end(body);
|
|
160
|
-
return;
|
|
161
|
-
}
|
|
162
|
-
const pathname = new URL(url, `http://localhost:${port}`).pathname;
|
|
163
|
-
const slug = pathname === "/" ? [] : pathname.slice(1).split("/").filter(Boolean);
|
|
164
|
-
const source = await vite.ssrLoadModule(path6.resolve(root, "src/lib/source.ts"));
|
|
165
|
-
const { mdxComponents } = await vite.ssrLoadModule(path6.resolve(root, "src/components/mdx/index.tsx"));
|
|
166
|
-
const { loadConfig } = await vite.ssrLoadModule(path6.resolve(root, "src/lib/config.ts"));
|
|
167
|
-
const config = loadConfig();
|
|
168
|
-
const { loadApiSpecs } = await vite.ssrLoadModule(path6.resolve(root, "src/lib/openapi.ts"));
|
|
169
|
-
const apiSpecs = config.api?.length ? loadApiSpecs(config.api) : [];
|
|
170
|
-
const [tree, sourcePage] = await Promise.all([
|
|
171
|
-
source.buildPageTree(),
|
|
172
|
-
source.getPage(slug)
|
|
173
|
-
]);
|
|
174
|
-
let pageData = null;
|
|
175
|
-
let embeddedData = { config, tree, slug, frontmatter: null, filePath: null };
|
|
176
|
-
if (sourcePage) {
|
|
177
|
-
const component = await source.loadPageComponent(sourcePage);
|
|
178
|
-
const React = await import("react");
|
|
179
|
-
const MDXBody = component;
|
|
180
|
-
pageData = {
|
|
181
|
-
slug,
|
|
182
|
-
frontmatter: sourcePage.frontmatter,
|
|
183
|
-
content: MDXBody ? React.createElement(MDXBody, { components: mdxComponents }) : null
|
|
184
|
-
};
|
|
185
|
-
embeddedData.frontmatter = sourcePage.frontmatter;
|
|
186
|
-
embeddedData.filePath = sourcePage.filePath;
|
|
137
|
+
}
|
|
187
138
|
}
|
|
188
|
-
let template = await fsPromises.readFile(templatePath, "utf-8");
|
|
189
|
-
template = await vite.transformIndexHtml(url, template);
|
|
190
|
-
const dataScript = `<script>window.__PAGE_DATA__ = ${JSON.stringify(embeddedData)}</script>`;
|
|
191
|
-
template = template.replace("<!--head-outlet-->", `<!--head-outlet-->${dataScript}`);
|
|
192
|
-
const { render } = await vite.ssrLoadModule(path6.resolve(root, "src/server/entry-server.tsx"));
|
|
193
|
-
const html = render(url, { config, tree, page: pageData, apiSpecs });
|
|
194
|
-
const finalHtml = template.replace("<!--ssr-outlet-->", html);
|
|
195
|
-
res.setHeader("Content-Type", "text/html");
|
|
196
|
-
res.statusCode = 200;
|
|
197
|
-
res.end(finalHtml);
|
|
198
|
-
} catch (e) {
|
|
199
|
-
vite.ssrFixStacktrace(e);
|
|
200
|
-
console.error(e);
|
|
201
|
-
res.statusCode = 500;
|
|
202
|
-
res.end(e.message);
|
|
203
|
-
}
|
|
204
|
-
});
|
|
205
|
-
server.listen(port, () => {
|
|
206
|
-
console.log(chalk3.cyan(`
|
|
207
|
-
Chronicle dev server running at:`));
|
|
208
|
-
console.log(chalk3.green(` http://localhost:${port}
|
|
209
|
-
`));
|
|
210
|
-
});
|
|
211
|
-
const shutdown = () => {
|
|
212
|
-
vite.close();
|
|
213
|
-
server.close();
|
|
214
|
-
process.exit(0);
|
|
215
|
-
};
|
|
216
|
-
process.on("SIGINT", shutdown);
|
|
217
|
-
process.on("SIGTERM", shutdown);
|
|
218
|
-
return { server, vite };
|
|
219
|
-
}
|
|
220
|
-
var init_dev = __esm(() => {
|
|
221
|
-
init_vite_config();
|
|
222
|
-
});
|
|
223
|
-
|
|
224
|
-
// src/lib/config.ts
|
|
225
|
-
import fs3 from "fs";
|
|
226
|
-
import path7 from "path";
|
|
227
|
-
import { parse as parse2 } from "yaml";
|
|
228
|
-
function resolveConfigPath() {
|
|
229
|
-
const projectRoot = process.env.CHRONICLE_PROJECT_ROOT;
|
|
230
|
-
if (projectRoot) {
|
|
231
|
-
const rootPath = path7.join(projectRoot, CONFIG_FILE);
|
|
232
|
-
if (fs3.existsSync(rootPath))
|
|
233
|
-
return rootPath;
|
|
234
|
-
}
|
|
235
|
-
const cwdPath = path7.join(process.cwd(), CONFIG_FILE);
|
|
236
|
-
if (fs3.existsSync(cwdPath))
|
|
237
|
-
return cwdPath;
|
|
238
|
-
const contentDir = process.env.CHRONICLE_CONTENT_DIR;
|
|
239
|
-
if (contentDir) {
|
|
240
|
-
const contentPath = path7.join(contentDir, CONFIG_FILE);
|
|
241
|
-
if (fs3.existsSync(contentPath))
|
|
242
|
-
return contentPath;
|
|
243
|
-
}
|
|
244
|
-
return null;
|
|
245
|
-
}
|
|
246
|
-
function loadConfig() {
|
|
247
|
-
const configPath = resolveConfigPath();
|
|
248
|
-
if (!configPath) {
|
|
249
|
-
return defaultConfig;
|
|
250
|
-
}
|
|
251
|
-
const raw = fs3.readFileSync(configPath, "utf-8");
|
|
252
|
-
const userConfig = parse2(raw);
|
|
253
|
-
return {
|
|
254
|
-
...defaultConfig,
|
|
255
|
-
...userConfig,
|
|
256
|
-
theme: {
|
|
257
|
-
name: userConfig.theme?.name ?? defaultConfig.theme.name,
|
|
258
|
-
colors: { ...defaultConfig.theme?.colors, ...userConfig.theme?.colors }
|
|
259
139
|
},
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
llms: { enabled: false, ...userConfig.llms },
|
|
264
|
-
analytics: { enabled: false, ...userConfig.analytics }
|
|
265
|
-
};
|
|
266
|
-
}
|
|
267
|
-
var CONFIG_FILE = "chronicle.yaml", defaultConfig;
|
|
268
|
-
var init_config = __esm(() => {
|
|
269
|
-
defaultConfig = {
|
|
270
|
-
title: "Documentation",
|
|
271
|
-
theme: { name: "default" },
|
|
272
|
-
search: { enabled: true, placeholder: "Search..." }
|
|
273
|
-
};
|
|
274
|
-
});
|
|
275
|
-
// src/lib/openapi.ts
|
|
276
|
-
import fs4 from "fs";
|
|
277
|
-
import path8 from "path";
|
|
278
|
-
import { parse as parseYaml } from "yaml";
|
|
279
|
-
function loadApiSpecs(apiConfigs) {
|
|
280
|
-
const contentDir = process.env.CHRONICLE_CONTENT_DIR ?? process.cwd();
|
|
281
|
-
return apiConfigs.map((config) => loadApiSpec(config, contentDir));
|
|
282
|
-
}
|
|
283
|
-
function loadApiSpec(config, contentDir) {
|
|
284
|
-
const specPath = path8.resolve(contentDir, config.spec);
|
|
285
|
-
const raw = fs4.readFileSync(specPath, "utf-8");
|
|
286
|
-
const isYaml = specPath.endsWith(".yaml") || specPath.endsWith(".yml");
|
|
287
|
-
const doc = isYaml ? parseYaml(raw) : JSON.parse(raw);
|
|
288
|
-
let v3Doc;
|
|
289
|
-
if ("swagger" in doc && doc.swagger === "2.0") {
|
|
290
|
-
v3Doc = convertV2toV3(doc);
|
|
291
|
-
} else if ("openapi" in doc && doc.openapi.startsWith("3.")) {
|
|
292
|
-
v3Doc = resolveDocument(doc);
|
|
293
|
-
} else {
|
|
294
|
-
throw new Error(`Unsupported spec version in ${config.spec}`);
|
|
295
|
-
}
|
|
296
|
-
return {
|
|
297
|
-
name: config.name,
|
|
298
|
-
basePath: config.basePath,
|
|
299
|
-
server: config.server,
|
|
300
|
-
auth: config.auth,
|
|
301
|
-
document: v3Doc
|
|
302
|
-
};
|
|
303
|
-
}
|
|
304
|
-
function resolveRef(ref, root) {
|
|
305
|
-
const parts = ref.replace(/^#\//, "").split("/");
|
|
306
|
-
let current = root;
|
|
307
|
-
for (const part of parts) {
|
|
308
|
-
if (current && typeof current === "object" && !Array.isArray(current)) {
|
|
309
|
-
current = current[part];
|
|
310
|
-
} else {
|
|
311
|
-
throw new Error(`Cannot resolve $ref: ${ref}`);
|
|
312
|
-
}
|
|
313
|
-
}
|
|
314
|
-
return current;
|
|
315
|
-
}
|
|
316
|
-
function deepResolveRefs(obj, root, stack = new Set, cache = new Map) {
|
|
317
|
-
if (obj === null || obj === undefined || typeof obj !== "object")
|
|
318
|
-
return obj;
|
|
319
|
-
if (Array.isArray(obj)) {
|
|
320
|
-
return obj.map((item) => deepResolveRefs(item, root, stack, cache));
|
|
321
|
-
}
|
|
322
|
-
const record = obj;
|
|
323
|
-
if (typeof record.$ref === "string") {
|
|
324
|
-
const ref = record.$ref;
|
|
325
|
-
if (cache.has(ref))
|
|
326
|
-
return cache.get(ref);
|
|
327
|
-
if (stack.has(ref))
|
|
328
|
-
return { type: "object", description: "[circular]" };
|
|
329
|
-
stack.add(ref);
|
|
330
|
-
const resolved = deepResolveRefs(resolveRef(ref, root), root, stack, cache);
|
|
331
|
-
stack.delete(ref);
|
|
332
|
-
cache.set(ref, resolved);
|
|
333
|
-
return resolved;
|
|
334
|
-
}
|
|
335
|
-
const result = {};
|
|
336
|
-
for (const [key, value] of Object.entries(record)) {
|
|
337
|
-
result[key] = deepResolveRefs(value, root, stack, cache);
|
|
338
|
-
}
|
|
339
|
-
return result;
|
|
340
|
-
}
|
|
341
|
-
function resolveDocument(doc) {
|
|
342
|
-
const root = doc;
|
|
343
|
-
return deepResolveRefs(doc, root);
|
|
344
|
-
}
|
|
345
|
-
function convertV2toV3(doc) {
|
|
346
|
-
const root = doc;
|
|
347
|
-
const resolved = deepResolveRefs(doc, root);
|
|
348
|
-
const v3Paths = {};
|
|
349
|
-
for (const [pathStr, pathItem] of Object.entries(resolved.paths ?? {})) {
|
|
350
|
-
if (!pathItem)
|
|
351
|
-
continue;
|
|
352
|
-
const v3PathItem = {};
|
|
353
|
-
for (const method of ["get", "post", "put", "delete", "patch"]) {
|
|
354
|
-
const op = pathItem[method];
|
|
355
|
-
if (!op)
|
|
356
|
-
continue;
|
|
357
|
-
v3PathItem[method] = convertV2Operation(op);
|
|
358
|
-
}
|
|
359
|
-
v3Paths[pathStr] = v3PathItem;
|
|
360
|
-
}
|
|
361
|
-
return {
|
|
362
|
-
openapi: "3.0.0",
|
|
363
|
-
info: resolved.info,
|
|
364
|
-
paths: v3Paths,
|
|
365
|
-
tags: resolved.tags ?? []
|
|
366
|
-
};
|
|
367
|
-
}
|
|
368
|
-
function convertV2Operation(op) {
|
|
369
|
-
const params = op.parameters ?? [];
|
|
370
|
-
const v3Params = params.filter((p) => p.in !== "body").map((p) => ({
|
|
371
|
-
name: p.name,
|
|
372
|
-
in: p.in,
|
|
373
|
-
required: p.required ?? false,
|
|
374
|
-
description: p.description,
|
|
375
|
-
schema: { type: p.type ?? "string", format: p.format }
|
|
376
|
-
}));
|
|
377
|
-
const bodyParam = params.find((p) => p.in === "body");
|
|
378
|
-
let requestBody;
|
|
379
|
-
if (bodyParam?.schema) {
|
|
380
|
-
requestBody = {
|
|
381
|
-
required: bodyParam.required ?? false,
|
|
382
|
-
content: {
|
|
383
|
-
"application/json": {
|
|
384
|
-
schema: bodyParam.schema
|
|
385
|
-
}
|
|
140
|
+
nitro: {
|
|
141
|
+
output: {
|
|
142
|
+
dir: resolveOutputDir(projectRoot, preset)
|
|
386
143
|
}
|
|
387
|
-
};
|
|
388
|
-
}
|
|
389
|
-
const v3Responses = {};
|
|
390
|
-
for (const [status, resp] of Object.entries(op.responses ?? {})) {
|
|
391
|
-
const v2Resp = resp;
|
|
392
|
-
const v3Resp = {
|
|
393
|
-
description: v2Resp.description ?? ""
|
|
394
|
-
};
|
|
395
|
-
if (v2Resp.schema) {
|
|
396
|
-
v3Resp.content = {
|
|
397
|
-
"application/json": {
|
|
398
|
-
schema: v2Resp.schema
|
|
399
|
-
}
|
|
400
|
-
};
|
|
401
144
|
}
|
|
402
|
-
v3Responses[status] = v3Resp;
|
|
403
|
-
}
|
|
404
|
-
const result = {
|
|
405
|
-
operationId: op.operationId,
|
|
406
|
-
summary: op.summary,
|
|
407
|
-
description: op.description,
|
|
408
|
-
tags: op.tags,
|
|
409
|
-
parameters: v3Params,
|
|
410
|
-
responses: v3Responses
|
|
411
145
|
};
|
|
412
|
-
if (requestBody) {
|
|
413
|
-
result.requestBody = requestBody;
|
|
414
|
-
}
|
|
415
|
-
return result;
|
|
416
146
|
}
|
|
417
|
-
var
|
|
418
|
-
|
|
419
|
-
// src/lib/api-routes.ts
|
|
420
|
-
import slugify from "slugify";
|
|
421
|
-
function getSpecSlug(spec) {
|
|
422
|
-
return slugify(spec.name, { lower: true, strict: true });
|
|
423
|
-
}
|
|
424
|
-
var init_api_routes = () => {};
|
|
425
|
-
|
|
426
|
-
// src/server/build-search-index.ts
|
|
427
|
-
var exports_build_search_index = {};
|
|
428
|
-
__export(exports_build_search_index, {
|
|
429
|
-
generateSearchIndex: () => generateSearchIndex
|
|
430
|
-
});
|
|
431
|
-
import fs5 from "fs/promises";
|
|
432
|
-
import path9 from "path";
|
|
433
|
-
import matter from "gray-matter";
|
|
434
|
-
function extractHeadings(markdown) {
|
|
435
|
-
const headingRegex = /^#{1,6}\s+(.+)$/gm;
|
|
436
|
-
const headings = [];
|
|
437
|
-
let match;
|
|
438
|
-
while ((match = headingRegex.exec(markdown)) !== null) {
|
|
439
|
-
headings.push(match[1].trim());
|
|
440
|
-
}
|
|
441
|
-
return headings.join(" ");
|
|
442
|
-
}
|
|
443
|
-
async function scanContent(contentDir) {
|
|
444
|
-
const docs = [];
|
|
445
|
-
async function scan(dir, prefix = []) {
|
|
446
|
-
let entries;
|
|
447
|
-
try {
|
|
448
|
-
entries = await fs5.readdir(dir, { withFileTypes: true });
|
|
449
|
-
} catch {
|
|
450
|
-
return;
|
|
451
|
-
}
|
|
452
|
-
for (const entry of entries) {
|
|
453
|
-
if (entry.name.startsWith(".") || entry.name === "node_modules")
|
|
454
|
-
continue;
|
|
455
|
-
const fullPath = path9.join(dir, entry.name);
|
|
456
|
-
if (entry.isDirectory()) {
|
|
457
|
-
await scan(fullPath, [...prefix, entry.name]);
|
|
458
|
-
continue;
|
|
459
|
-
}
|
|
460
|
-
if (!entry.name.endsWith(".mdx") && !entry.name.endsWith(".md"))
|
|
461
|
-
continue;
|
|
462
|
-
const raw = await fs5.readFile(fullPath, "utf-8");
|
|
463
|
-
const { data: fm, content } = matter(raw);
|
|
464
|
-
const baseName = entry.name.replace(/\.(mdx|md)$/, "");
|
|
465
|
-
const slugs = baseName === "index" ? prefix : [...prefix, baseName];
|
|
466
|
-
const url = slugs.length === 0 ? "/" : "/" + slugs.join("/");
|
|
467
|
-
docs.push({
|
|
468
|
-
id: url,
|
|
469
|
-
url,
|
|
470
|
-
title: fm.title ?? baseName,
|
|
471
|
-
content: extractHeadings(content),
|
|
472
|
-
type: "page"
|
|
473
|
-
});
|
|
474
|
-
}
|
|
475
|
-
}
|
|
476
|
-
await scan(contentDir);
|
|
477
|
-
return docs;
|
|
478
|
-
}
|
|
479
|
-
function buildApiDocs() {
|
|
480
|
-
const config = loadConfig();
|
|
481
|
-
if (!config.api?.length)
|
|
482
|
-
return [];
|
|
483
|
-
const docs = [];
|
|
484
|
-
const specs = loadApiSpecs(config.api);
|
|
485
|
-
for (const spec of specs) {
|
|
486
|
-
const specSlug = getSpecSlug(spec);
|
|
487
|
-
const paths = spec.document.paths ?? {};
|
|
488
|
-
for (const [, pathItem] of Object.entries(paths)) {
|
|
489
|
-
if (!pathItem)
|
|
490
|
-
continue;
|
|
491
|
-
for (const method of ["get", "post", "put", "delete", "patch"]) {
|
|
492
|
-
const op = pathItem[method];
|
|
493
|
-
if (!op?.operationId)
|
|
494
|
-
continue;
|
|
495
|
-
const url = `/apis/${specSlug}/${encodeURIComponent(op.operationId)}`;
|
|
496
|
-
docs.push({
|
|
497
|
-
id: url,
|
|
498
|
-
url,
|
|
499
|
-
title: `${method.toUpperCase()} ${op.summary ?? op.operationId}`,
|
|
500
|
-
content: op.description ?? "",
|
|
501
|
-
type: "api"
|
|
502
|
-
});
|
|
503
|
-
}
|
|
504
|
-
}
|
|
505
|
-
}
|
|
506
|
-
return docs;
|
|
507
|
-
}
|
|
508
|
-
async function generateSearchIndex(contentDir, outDir) {
|
|
509
|
-
const [contentDocs, apiDocs] = await Promise.all([
|
|
510
|
-
scanContent(contentDir),
|
|
511
|
-
Promise.resolve(buildApiDocs())
|
|
512
|
-
]);
|
|
513
|
-
const documents = [...contentDocs, ...apiDocs];
|
|
514
|
-
const outPath = path9.join(outDir, "search-index.json");
|
|
515
|
-
await fs5.writeFile(outPath, JSON.stringify(documents));
|
|
516
|
-
return documents.length;
|
|
517
|
-
}
|
|
518
|
-
var init_build_search_index = __esm(() => {
|
|
519
|
-
init_config();
|
|
520
|
-
init_openapi();
|
|
521
|
-
init_api_routes();
|
|
147
|
+
var init_vite_config = __esm(() => {
|
|
148
|
+
init_remark_unused_directives();
|
|
522
149
|
});
|
|
523
150
|
|
|
524
|
-
// src/server/adapters/vercel.ts
|
|
525
|
-
var exports_vercel = {};
|
|
526
|
-
__export(exports_vercel, {
|
|
527
|
-
buildVercelOutput: () => buildVercelOutput
|
|
528
|
-
});
|
|
529
|
-
import path10 from "path";
|
|
530
|
-
import fs6 from "fs/promises";
|
|
531
|
-
import { existsSync } from "fs";
|
|
532
|
-
import chalk5 from "chalk";
|
|
533
|
-
async function buildVercelOutput(options) {
|
|
534
|
-
const { distDir, contentDir, projectRoot } = options;
|
|
535
|
-
const outputDir = path10.resolve(projectRoot, ".vercel/output");
|
|
536
|
-
console.log(chalk5.gray("Generating Vercel output..."));
|
|
537
|
-
await fs6.rm(outputDir, { recursive: true, force: true });
|
|
538
|
-
const staticDir = path10.resolve(outputDir, "static");
|
|
539
|
-
const funcDir = path10.resolve(outputDir, "functions/index.func");
|
|
540
|
-
await fs6.mkdir(staticDir, { recursive: true });
|
|
541
|
-
await fs6.mkdir(funcDir, { recursive: true });
|
|
542
|
-
const clientDir = path10.resolve(distDir, "client");
|
|
543
|
-
await copyDir(clientDir, staticDir);
|
|
544
|
-
console.log(chalk5.gray(" Copied client assets to static/"));
|
|
545
|
-
if (existsSync(contentDir)) {
|
|
546
|
-
await copyContentAssets(contentDir, staticDir);
|
|
547
|
-
console.log(chalk5.gray(" Copied content assets to static/"));
|
|
548
|
-
}
|
|
549
|
-
const serverDir = path10.resolve(distDir, "server");
|
|
550
|
-
await copyDir(serverDir, funcDir);
|
|
551
|
-
console.log(chalk5.gray(" Copied server bundle to functions/"));
|
|
552
|
-
const templateSrc = path10.resolve(clientDir, "src/server/index.html");
|
|
553
|
-
await fs6.copyFile(templateSrc, path10.resolve(funcDir, "index.html"));
|
|
554
|
-
await fs6.writeFile(path10.resolve(funcDir, "package.json"), JSON.stringify({ type: "module" }, null, 2));
|
|
555
|
-
await fs6.writeFile(path10.resolve(funcDir, ".vc-config.json"), JSON.stringify({
|
|
556
|
-
runtime: "nodejs24.x",
|
|
557
|
-
handler: "entry-vercel.js",
|
|
558
|
-
launcherType: "Nodejs"
|
|
559
|
-
}, null, 2));
|
|
560
|
-
await fs6.writeFile(path10.resolve(outputDir, "config.json"), JSON.stringify({
|
|
561
|
-
version: 3,
|
|
562
|
-
routes: [
|
|
563
|
-
{ handle: "filesystem" },
|
|
564
|
-
{ src: "/(.*)", dest: "/index" }
|
|
565
|
-
]
|
|
566
|
-
}, null, 2));
|
|
567
|
-
console.log(chalk5.green("Vercel output generated →"), outputDir);
|
|
568
|
-
}
|
|
569
|
-
async function copyDir(src, dest) {
|
|
570
|
-
await fs6.mkdir(dest, { recursive: true });
|
|
571
|
-
const entries = await fs6.readdir(src, { withFileTypes: true });
|
|
572
|
-
for (const entry of entries) {
|
|
573
|
-
const srcPath = path10.join(src, entry.name);
|
|
574
|
-
const destPath = path10.join(dest, entry.name);
|
|
575
|
-
if (entry.isDirectory()) {
|
|
576
|
-
await copyDir(srcPath, destPath);
|
|
577
|
-
} else {
|
|
578
|
-
await fs6.copyFile(srcPath, destPath);
|
|
579
|
-
}
|
|
580
|
-
}
|
|
581
|
-
}
|
|
582
|
-
async function copyContentAssets(contentDir, staticDir) {
|
|
583
|
-
const entries = await fs6.readdir(contentDir, { withFileTypes: true });
|
|
584
|
-
for (const entry of entries) {
|
|
585
|
-
const srcPath = path10.join(contentDir, entry.name);
|
|
586
|
-
if (entry.isDirectory()) {
|
|
587
|
-
const destSubDir = path10.join(staticDir, entry.name);
|
|
588
|
-
await copyContentAssetsRecursive(srcPath, destSubDir);
|
|
589
|
-
} else {
|
|
590
|
-
const ext = path10.extname(entry.name).toLowerCase();
|
|
591
|
-
if (CONTENT_EXTENSIONS.has(ext)) {
|
|
592
|
-
await fs6.copyFile(srcPath, path10.join(staticDir, entry.name));
|
|
593
|
-
}
|
|
594
|
-
}
|
|
595
|
-
}
|
|
596
|
-
}
|
|
597
|
-
async function copyContentAssetsRecursive(srcDir, destDir) {
|
|
598
|
-
const entries = await fs6.readdir(srcDir, { withFileTypes: true });
|
|
599
|
-
for (const entry of entries) {
|
|
600
|
-
const srcPath = path10.join(srcDir, entry.name);
|
|
601
|
-
if (entry.isDirectory()) {
|
|
602
|
-
await copyContentAssetsRecursive(srcPath, path10.join(destDir, entry.name));
|
|
603
|
-
} else {
|
|
604
|
-
const ext = path10.extname(entry.name).toLowerCase();
|
|
605
|
-
if (CONTENT_EXTENSIONS.has(ext)) {
|
|
606
|
-
await fs6.mkdir(destDir, { recursive: true });
|
|
607
|
-
await fs6.copyFile(srcPath, path10.join(destDir, entry.name));
|
|
608
|
-
}
|
|
609
|
-
}
|
|
610
|
-
}
|
|
611
|
-
}
|
|
612
|
-
var CONTENT_EXTENSIONS;
|
|
613
|
-
var init_vercel = __esm(() => {
|
|
614
|
-
CONTENT_EXTENSIONS = new Set([
|
|
615
|
-
".png",
|
|
616
|
-
".jpg",
|
|
617
|
-
".jpeg",
|
|
618
|
-
".gif",
|
|
619
|
-
".svg",
|
|
620
|
-
".webp",
|
|
621
|
-
".ico",
|
|
622
|
-
".pdf",
|
|
623
|
-
".json",
|
|
624
|
-
".yaml",
|
|
625
|
-
".yml",
|
|
626
|
-
".txt"
|
|
627
|
-
]);
|
|
628
|
-
});
|
|
629
|
-
|
|
630
|
-
// src/server/prod.ts
|
|
631
|
-
var exports_prod = {};
|
|
632
|
-
__export(exports_prod, {
|
|
633
|
-
startProdServer: () => startProdServer
|
|
634
|
-
});
|
|
635
|
-
import path12 from "path";
|
|
636
|
-
import chalk7 from "chalk";
|
|
637
|
-
async function startProdServer(options) {
|
|
638
|
-
const { port, distDir } = options;
|
|
639
|
-
const serverEntry = path12.resolve(distDir, "server/entry-prod.js");
|
|
640
|
-
const { startServer } = await import(serverEntry);
|
|
641
|
-
console.log(chalk7.cyan("Starting production server..."));
|
|
642
|
-
return startServer({ port, distDir });
|
|
643
|
-
}
|
|
644
|
-
var init_prod = () => {};
|
|
645
|
-
|
|
646
151
|
// src/cli/index.ts
|
|
647
152
|
import { Command as Command6 } from "commander";
|
|
648
153
|
|
|
649
|
-
// src/cli/commands/
|
|
154
|
+
// src/cli/commands/build.ts
|
|
155
|
+
import chalk2 from "chalk";
|
|
650
156
|
import { Command } from "commander";
|
|
651
|
-
import { execSync } from "child_process";
|
|
652
|
-
import fs2 from "fs";
|
|
653
|
-
import path3 from "path";
|
|
654
|
-
import chalk from "chalk";
|
|
655
|
-
import { stringify } from "yaml";
|
|
656
157
|
|
|
657
|
-
// src/cli/utils/
|
|
658
|
-
import
|
|
659
|
-
import
|
|
158
|
+
// src/cli/utils/config.ts
|
|
159
|
+
import path from "node:path";
|
|
160
|
+
import chalk from "chalk";
|
|
161
|
+
import { parse } from "yaml";
|
|
162
|
+
function resolveContentDir(contentFlag) {
|
|
163
|
+
if (contentFlag)
|
|
164
|
+
return path.resolve(contentFlag);
|
|
165
|
+
return path.resolve("content");
|
|
166
|
+
}
|
|
660
167
|
|
|
661
168
|
// src/cli/utils/resolve.ts
|
|
662
|
-
import
|
|
169
|
+
import path2 from "path";
|
|
663
170
|
import { fileURLToPath } from "url";
|
|
664
|
-
var PACKAGE_ROOT =
|
|
171
|
+
var PACKAGE_ROOT = path2.resolve(path2.dirname(fileURLToPath(import.meta.url)), "..", "..");
|
|
665
172
|
|
|
666
173
|
// src/cli/utils/scaffold.ts
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
const
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
}
|
|
680
|
-
function getChronicleVersion() {
|
|
681
|
-
const pkgPath = path2.join(PACKAGE_ROOT, "package.json");
|
|
682
|
-
const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf-8"));
|
|
683
|
-
return pkg.version;
|
|
174
|
+
import fs from "node:fs/promises";
|
|
175
|
+
import path3 from "node:path";
|
|
176
|
+
async function linkContent(contentDir) {
|
|
177
|
+
const linkPath = path3.join(PACKAGE_ROOT, ".content");
|
|
178
|
+
const target = path3.resolve(contentDir);
|
|
179
|
+
try {
|
|
180
|
+
const existing = await fs.readlink(linkPath);
|
|
181
|
+
if (existing === target)
|
|
182
|
+
return;
|
|
183
|
+
await fs.unlink(linkPath);
|
|
184
|
+
} catch {}
|
|
185
|
+
await fs.symlink(target, linkPath);
|
|
684
186
|
}
|
|
685
187
|
|
|
188
|
+
// src/cli/commands/build.ts
|
|
189
|
+
var buildCommand = new Command("build").description("Build for production").option("-c, --content <path>", "Content directory").option("--preset <preset>", "Deploy preset (vercel, cloudflare, node-server)").action(async (options) => {
|
|
190
|
+
const contentDir = resolveContentDir(options.content);
|
|
191
|
+
await linkContent(contentDir);
|
|
192
|
+
console.log(chalk2.cyan("Building for production..."));
|
|
193
|
+
const { createBuilder } = await import("vite");
|
|
194
|
+
const { createViteConfig: createViteConfig2 } = await Promise.resolve().then(() => (init_vite_config(), exports_vite_config));
|
|
195
|
+
const config = await createViteConfig2({
|
|
196
|
+
packageRoot: PACKAGE_ROOT,
|
|
197
|
+
projectRoot: process.cwd(),
|
|
198
|
+
contentDir,
|
|
199
|
+
preset: options.preset
|
|
200
|
+
});
|
|
201
|
+
const builder = await createBuilder({ ...config, builder: {} });
|
|
202
|
+
await builder.buildApp();
|
|
203
|
+
console.log(chalk2.green("Build complete"));
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
// src/cli/commands/dev.ts
|
|
207
|
+
import chalk3 from "chalk";
|
|
208
|
+
import { Command as Command2 } from "commander";
|
|
209
|
+
var devCommand = new Command2("dev").description("Start development server").option("-p, --port <port>", "Port number", "3000").option("-c, --content <path>", "Content directory").action(async (options) => {
|
|
210
|
+
const contentDir = resolveContentDir(options.content);
|
|
211
|
+
const port = parseInt(options.port, 10);
|
|
212
|
+
await linkContent(contentDir);
|
|
213
|
+
console.log(chalk3.cyan("Starting dev server..."));
|
|
214
|
+
const { createServer } = await import("vite");
|
|
215
|
+
const { createViteConfig: createViteConfig2 } = await Promise.resolve().then(() => (init_vite_config(), exports_vite_config));
|
|
216
|
+
const config = await createViteConfig2({ packageRoot: PACKAGE_ROOT, projectRoot: process.cwd(), contentDir });
|
|
217
|
+
const server = await createServer({
|
|
218
|
+
...config,
|
|
219
|
+
server: { ...config.server, port }
|
|
220
|
+
});
|
|
221
|
+
await server.listen();
|
|
222
|
+
server.printUrls();
|
|
223
|
+
});
|
|
224
|
+
|
|
686
225
|
// src/cli/commands/init.ts
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
private: true,
|
|
699
|
-
type: "module",
|
|
700
|
-
scripts: {
|
|
701
|
-
dev: "chronicle dev",
|
|
702
|
-
build: "chronicle build",
|
|
703
|
-
start: "chronicle start"
|
|
704
|
-
},
|
|
705
|
-
dependencies: {
|
|
706
|
-
"@raystack/chronicle": `^${getChronicleVersion()}`
|
|
707
|
-
},
|
|
708
|
-
devDependencies: {
|
|
709
|
-
"@raystack/tools-config": "0.56.0",
|
|
710
|
-
"openapi-types": "^12.1.3",
|
|
711
|
-
typescript: "5.9.3",
|
|
712
|
-
"@types/react": "^19.2.10",
|
|
713
|
-
"@types/node": "^25.1.0"
|
|
714
|
-
}
|
|
715
|
-
};
|
|
716
|
-
}
|
|
226
|
+
import fs2 from "node:fs";
|
|
227
|
+
import path5 from "node:path";
|
|
228
|
+
import chalk4 from "chalk";
|
|
229
|
+
import { Command as Command3 } from "commander";
|
|
230
|
+
import { stringify } from "yaml";
|
|
231
|
+
var defaultConfig = {
|
|
232
|
+
title: "My Documentation",
|
|
233
|
+
description: "Documentation powered by Chronicle",
|
|
234
|
+
theme: { name: "default" },
|
|
235
|
+
search: { enabled: true, placeholder: "Search documentation..." }
|
|
236
|
+
};
|
|
717
237
|
var sampleMdx = `---
|
|
718
238
|
title: Welcome
|
|
719
239
|
description: Getting started with your documentation
|
|
@@ -724,74 +244,28 @@ order: 1
|
|
|
724
244
|
|
|
725
245
|
This is your documentation home page.
|
|
726
246
|
`;
|
|
727
|
-
var initCommand = new
|
|
247
|
+
var initCommand = new Command3("init").description("Initialize a new Chronicle project").option("-c, --content <path>", "Content directory name", "content").action((options) => {
|
|
728
248
|
const projectDir = process.cwd();
|
|
729
|
-
const
|
|
730
|
-
const contentDir = path3.join(projectDir, options.content);
|
|
249
|
+
const contentDir = path5.join(projectDir, options.content);
|
|
731
250
|
if (!fs2.existsSync(contentDir)) {
|
|
732
251
|
fs2.mkdirSync(contentDir, { recursive: true });
|
|
733
|
-
console.log(
|
|
252
|
+
console.log(chalk4.green("✓"), "Created", contentDir);
|
|
734
253
|
}
|
|
735
|
-
const
|
|
736
|
-
if (!fs2.existsSync(packageJsonPath)) {
|
|
737
|
-
fs2.writeFileSync(packageJsonPath, JSON.stringify(createPackageJson(dirName), null, 2) + `
|
|
738
|
-
`);
|
|
739
|
-
console.log(chalk.green("✓"), "Created", packageJsonPath);
|
|
740
|
-
} else {
|
|
741
|
-
const existing = JSON.parse(fs2.readFileSync(packageJsonPath, "utf-8"));
|
|
742
|
-
const template = createPackageJson(dirName);
|
|
743
|
-
let updated = false;
|
|
744
|
-
if (existing.type !== "module") {
|
|
745
|
-
existing.type = "module";
|
|
746
|
-
updated = true;
|
|
747
|
-
}
|
|
748
|
-
if (!existing.scripts)
|
|
749
|
-
existing.scripts = {};
|
|
750
|
-
for (const [key, value] of Object.entries(template.scripts)) {
|
|
751
|
-
if (!existing.scripts[key]) {
|
|
752
|
-
existing.scripts[key] = value;
|
|
753
|
-
updated = true;
|
|
754
|
-
}
|
|
755
|
-
}
|
|
756
|
-
if (!existing.dependencies)
|
|
757
|
-
existing.dependencies = {};
|
|
758
|
-
for (const [key, value] of Object.entries(template.dependencies)) {
|
|
759
|
-
if (!existing.dependencies[key]) {
|
|
760
|
-
existing.dependencies[key] = value;
|
|
761
|
-
updated = true;
|
|
762
|
-
}
|
|
763
|
-
}
|
|
764
|
-
if (!existing.devDependencies)
|
|
765
|
-
existing.devDependencies = {};
|
|
766
|
-
for (const [key, value] of Object.entries(template.devDependencies)) {
|
|
767
|
-
if (!existing.devDependencies[key]) {
|
|
768
|
-
existing.devDependencies[key] = value;
|
|
769
|
-
updated = true;
|
|
770
|
-
}
|
|
771
|
-
}
|
|
772
|
-
if (updated) {
|
|
773
|
-
fs2.writeFileSync(packageJsonPath, JSON.stringify(existing, null, 2) + `
|
|
774
|
-
`);
|
|
775
|
-
console.log(chalk.green("✓"), "Updated", packageJsonPath);
|
|
776
|
-
} else {
|
|
777
|
-
console.log(chalk.yellow("⚠"), packageJsonPath, "already has all required entries");
|
|
778
|
-
}
|
|
779
|
-
}
|
|
780
|
-
const configPath = path3.join(projectDir, "chronicle.yaml");
|
|
254
|
+
const configPath = path5.join(projectDir, "chronicle.yaml");
|
|
781
255
|
if (!fs2.existsSync(configPath)) {
|
|
782
|
-
fs2.writeFileSync(configPath, stringify(
|
|
783
|
-
console.log(
|
|
256
|
+
fs2.writeFileSync(configPath, stringify(defaultConfig));
|
|
257
|
+
console.log(chalk4.green("✓"), "Created", configPath);
|
|
784
258
|
} else {
|
|
785
|
-
console.log(
|
|
259
|
+
console.log(chalk4.yellow("⚠"), configPath, "already exists");
|
|
786
260
|
}
|
|
787
261
|
const contentFiles = fs2.readdirSync(contentDir);
|
|
788
262
|
if (contentFiles.length === 0) {
|
|
789
|
-
const indexPath =
|
|
263
|
+
const indexPath = path5.join(contentDir, "index.mdx");
|
|
790
264
|
fs2.writeFileSync(indexPath, sampleMdx);
|
|
791
|
-
console.log(
|
|
265
|
+
console.log(chalk4.green("✓"), "Created", indexPath);
|
|
792
266
|
}
|
|
793
|
-
const gitignorePath =
|
|
794
|
-
const gitignoreEntries = ["node_modules", "dist"];
|
|
267
|
+
const gitignorePath = path5.join(projectDir, ".gitignore");
|
|
268
|
+
const gitignoreEntries = ["node_modules", "dist", ".output"];
|
|
795
269
|
if (fs2.existsSync(gitignorePath)) {
|
|
796
270
|
const existing = fs2.readFileSync(gitignorePath, "utf-8");
|
|
797
271
|
const missing = gitignoreEntries.filter((e) => !existing.includes(e));
|
|
@@ -800,156 +274,61 @@ var initCommand = new Command("init").description("Initialize a new Chronicle pr
|
|
|
800
274
|
${missing.join(`
|
|
801
275
|
`)}
|
|
802
276
|
`);
|
|
803
|
-
console.log(
|
|
277
|
+
console.log(chalk4.green("✓"), "Added", missing.join(", "), "to .gitignore");
|
|
804
278
|
}
|
|
805
279
|
} else {
|
|
806
280
|
fs2.writeFileSync(gitignorePath, `${gitignoreEntries.join(`
|
|
807
281
|
`)}
|
|
808
282
|
`);
|
|
809
|
-
console.log(
|
|
283
|
+
console.log(chalk4.green("✓"), "Created .gitignore");
|
|
810
284
|
}
|
|
811
|
-
|
|
812
|
-
console.log(chalk.cyan(`
|
|
813
|
-
Installing dependencies with ${pm}...`));
|
|
814
|
-
execSync(`${pm} install`, { cwd: projectDir, stdio: "inherit" });
|
|
815
|
-
const runCmd = pm === "npm" ? "npx" : pm === "bun" ? "bunx" : `${pm} dlx`;
|
|
816
|
-
console.log(chalk.green(`
|
|
285
|
+
console.log(chalk4.green(`
|
|
817
286
|
✓ Chronicle initialized!`));
|
|
818
287
|
console.log(`
|
|
819
|
-
Run`,
|
|
288
|
+
Run`, chalk4.cyan("chronicle dev"), "to start development server");
|
|
820
289
|
});
|
|
821
290
|
|
|
822
|
-
// src/cli/commands/
|
|
823
|
-
import
|
|
824
|
-
import
|
|
825
|
-
|
|
826
|
-
// src/cli/utils/config.ts
|
|
827
|
-
import path4 from "path";
|
|
828
|
-
import { parse } from "yaml";
|
|
829
|
-
import chalk2 from "chalk";
|
|
830
|
-
function resolveContentDir(contentFlag) {
|
|
831
|
-
if (contentFlag)
|
|
832
|
-
return path4.resolve(contentFlag);
|
|
833
|
-
if (process.env.CHRONICLE_CONTENT_DIR)
|
|
834
|
-
return path4.resolve(process.env.CHRONICLE_CONTENT_DIR);
|
|
835
|
-
return path4.resolve("content");
|
|
836
|
-
}
|
|
837
|
-
|
|
838
|
-
// src/cli/commands/dev.ts
|
|
839
|
-
var devCommand = new Command2("dev").description("Start development server").option("-p, --port <port>", "Port number", "3000").option("-c, --content <path>", "Content directory").action(async (options) => {
|
|
291
|
+
// src/cli/commands/serve.ts
|
|
292
|
+
import chalk5 from "chalk";
|
|
293
|
+
import { Command as Command4 } from "commander";
|
|
294
|
+
var serveCommand = new Command4("serve").description("Build and start production server").option("-p, --port <port>", "Port number", "3000").option("-c, --content <path>", "Content directory").option("--preset <preset>", "Deploy preset (vercel, cloudflare, node-server)").action(async (options) => {
|
|
840
295
|
const contentDir = resolveContentDir(options.content);
|
|
841
296
|
const port = parseInt(options.port, 10);
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
console.log(chalk4.cyan("Starting dev server..."));
|
|
845
|
-
const { startDevServer: startDevServer2 } = await Promise.resolve().then(() => (init_dev(), exports_dev));
|
|
846
|
-
await startDevServer2({ port, root: PACKAGE_ROOT, contentDir });
|
|
847
|
-
});
|
|
848
|
-
|
|
849
|
-
// src/cli/commands/build.ts
|
|
850
|
-
import { Command as Command3 } from "commander";
|
|
851
|
-
import path11 from "path";
|
|
852
|
-
import chalk6 from "chalk";
|
|
853
|
-
var buildCommand = new Command3("build").description("Build for production").option("-c, --content <path>", "Content directory").option("-o, --outDir <path>", "Output directory", "dist").option("--adapter <adapter>", "Deploy adapter (vercel)").action(async (options) => {
|
|
854
|
-
const contentDir = resolveContentDir(options.content);
|
|
855
|
-
const outDir = path11.resolve(options.outDir);
|
|
856
|
-
process.env.CHRONICLE_PROJECT_ROOT = process.cwd();
|
|
857
|
-
process.env.CHRONICLE_CONTENT_DIR = contentDir;
|
|
858
|
-
console.log(chalk6.cyan("Building for production..."));
|
|
859
|
-
const { build } = await import("vite");
|
|
297
|
+
await linkContent(contentDir);
|
|
298
|
+
const { build, preview } = await import("vite");
|
|
860
299
|
const { createViteConfig: createViteConfig2 } = await Promise.resolve().then(() => (init_vite_config(), exports_vite_config));
|
|
861
|
-
const
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
outDir: path11.join(outDir, "client"),
|
|
867
|
-
ssrManifest: true,
|
|
868
|
-
rolldownOptions: {
|
|
869
|
-
input: path11.resolve(PACKAGE_ROOT, "src/server/index.html")
|
|
870
|
-
}
|
|
871
|
-
}
|
|
300
|
+
const config = await createViteConfig2({
|
|
301
|
+
packageRoot: PACKAGE_ROOT,
|
|
302
|
+
projectRoot: process.cwd(),
|
|
303
|
+
contentDir,
|
|
304
|
+
preset: options.preset
|
|
872
305
|
});
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
},
|
|
880
|
-
build: {
|
|
881
|
-
outDir: path11.join(outDir, "server"),
|
|
882
|
-
ssr: serverEntry,
|
|
883
|
-
target: "node22"
|
|
884
|
-
}
|
|
306
|
+
console.log(chalk5.cyan("Building for production..."));
|
|
307
|
+
await build(config);
|
|
308
|
+
console.log(chalk5.cyan("Starting production server..."));
|
|
309
|
+
const server = await preview({
|
|
310
|
+
...config,
|
|
311
|
+
preview: { port }
|
|
885
312
|
});
|
|
886
|
-
|
|
887
|
-
const { generateSearchIndex: generateSearchIndex2 } = await Promise.resolve().then(() => (init_build_search_index(), exports_build_search_index));
|
|
888
|
-
const docCount = await generateSearchIndex2(contentDir, path11.join(outDir, "server"));
|
|
889
|
-
console.log(chalk6.gray(` Indexed ${docCount} documents`));
|
|
890
|
-
console.log(chalk6.green("Build complete →"), outDir);
|
|
891
|
-
if (options.adapter === "vercel") {
|
|
892
|
-
const { buildVercelOutput: buildVercelOutput2 } = await Promise.resolve().then(() => (init_vercel(), exports_vercel));
|
|
893
|
-
await buildVercelOutput2({
|
|
894
|
-
distDir: outDir,
|
|
895
|
-
contentDir,
|
|
896
|
-
projectRoot: process.cwd()
|
|
897
|
-
});
|
|
898
|
-
}
|
|
313
|
+
server.printUrls();
|
|
899
314
|
});
|
|
900
315
|
|
|
901
316
|
// src/cli/commands/start.ts
|
|
902
|
-
import
|
|
903
|
-
import path13 from "path";
|
|
904
|
-
import chalk8 from "chalk";
|
|
905
|
-
var startCommand = new Command4("start").description("Start production server").option("-p, --port <port>", "Port number", "3000").option("-c, --content <path>", "Content directory").option("-d, --dist <path>", "Dist directory", "dist").action(async (options) => {
|
|
906
|
-
const contentDir = resolveContentDir(options.content);
|
|
907
|
-
const port = parseInt(options.port, 10);
|
|
908
|
-
const distDir = path13.resolve(options.dist);
|
|
909
|
-
process.env.CHRONICLE_PROJECT_ROOT = process.cwd();
|
|
910
|
-
process.env.CHRONICLE_CONTENT_DIR = contentDir;
|
|
911
|
-
console.log(chalk8.cyan("Starting production server..."));
|
|
912
|
-
const { startProdServer: startProdServer2 } = await Promise.resolve().then(() => (init_prod(), exports_prod));
|
|
913
|
-
await startProdServer2({ port, root: PACKAGE_ROOT, distDir });
|
|
914
|
-
});
|
|
915
|
-
|
|
916
|
-
// src/cli/commands/serve.ts
|
|
317
|
+
import chalk6 from "chalk";
|
|
917
318
|
import { Command as Command5 } from "commander";
|
|
918
|
-
|
|
919
|
-
import chalk9 from "chalk";
|
|
920
|
-
var serveCommand = new Command5("serve").description("Build and start production server").option("-p, --port <port>", "Port number", "3000").option("-c, --content <path>", "Content directory").option("-o, --outDir <path>", "Output directory", "dist").action(async (options) => {
|
|
319
|
+
var startCommand = new Command5("start").description("Start production server").option("-p, --port <port>", "Port number", "3000").option("-c, --content <path>", "Content directory").action(async (options) => {
|
|
921
320
|
const contentDir = resolveContentDir(options.content);
|
|
922
321
|
const port = parseInt(options.port, 10);
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
console.log(chalk9.cyan("Building for production..."));
|
|
927
|
-
const { build } = await import("vite");
|
|
322
|
+
await linkContent(contentDir);
|
|
323
|
+
console.log(chalk6.cyan("Starting production server..."));
|
|
324
|
+
const { preview } = await import("vite");
|
|
928
325
|
const { createViteConfig: createViteConfig2 } = await Promise.resolve().then(() => (init_vite_config(), exports_vite_config));
|
|
929
|
-
const
|
|
930
|
-
await
|
|
931
|
-
...
|
|
932
|
-
|
|
933
|
-
outDir: path14.join(outDir, "client"),
|
|
934
|
-
ssrManifest: true,
|
|
935
|
-
rolldownOptions: {
|
|
936
|
-
input: path14.resolve(PACKAGE_ROOT, "src/server/index.html")
|
|
937
|
-
}
|
|
938
|
-
}
|
|
939
|
-
});
|
|
940
|
-
await build({
|
|
941
|
-
...baseConfig,
|
|
942
|
-
ssr: {
|
|
943
|
-
noExternal: true
|
|
944
|
-
},
|
|
945
|
-
build: {
|
|
946
|
-
outDir: path14.join(outDir, "server"),
|
|
947
|
-
ssr: path14.resolve(PACKAGE_ROOT, "src/server/entry-prod.ts")
|
|
948
|
-
}
|
|
326
|
+
const config = await createViteConfig2({ packageRoot: PACKAGE_ROOT, projectRoot: process.cwd(), contentDir });
|
|
327
|
+
const server = await preview({
|
|
328
|
+
...config,
|
|
329
|
+
preview: { port }
|
|
949
330
|
});
|
|
950
|
-
|
|
951
|
-
const { startProdServer: startProdServer2 } = await Promise.resolve().then(() => (init_prod(), exports_prod));
|
|
952
|
-
await startProdServer2({ port, root: PACKAGE_ROOT, distDir: outDir });
|
|
331
|
+
server.printUrls();
|
|
953
332
|
});
|
|
954
333
|
|
|
955
334
|
// src/cli/index.ts
|