@raystack/chronicle 0.1.0-canary.c5d277e → 0.1.0-canary.cb102e9

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 CHANGED
@@ -55,7 +55,7 @@ async function createViteConfig(options) {
55
55
  remarkDirective
56
56
  ],
57
57
  rehypePlugins: [
58
- [rehypeShiki, { themes: { light: "github-light", dark: "github-dark" } }]
58
+ [rehypeShiki, { themes: { light: "github-light", dark: "github-dark" }, defaultColor: false }]
59
59
  ],
60
60
  mdExtensions: [".md"],
61
61
  mdxExtensions: [".mdx"]
@@ -85,6 +85,18 @@ async function createViteConfig(options) {
85
85
  }
86
86
  var init_vite_config = () => {};
87
87
 
88
+ // src/server/utils/safe-path.ts
89
+ import path6 from "path";
90
+ function safePath(baseDir, urlPath) {
91
+ const decoded = decodeURIComponent(urlPath.split("?")[0]);
92
+ const resolved = path6.resolve(baseDir, "." + decoded);
93
+ if (!resolved.startsWith(path6.resolve(baseDir) + path6.sep) && resolved !== path6.resolve(baseDir)) {
94
+ return null;
95
+ }
96
+ return resolved;
97
+ }
98
+ var init_safe_path = () => {};
99
+
88
100
  // src/server/dev.ts
89
101
  var exports_dev = {};
90
102
  __export(exports_dev, {
@@ -94,7 +106,7 @@ import { createServer as createViteServer } from "vite";
94
106
  import { createServer } from "http";
95
107
  import fsPromises from "fs/promises";
96
108
  import { createReadStream } from "fs";
97
- import path6 from "path";
109
+ import path7 from "path";
98
110
  import chalk3 from "chalk";
99
111
  async function startDevServer(options) {
100
112
  const { port, root, contentDir } = options;
@@ -104,7 +116,7 @@ async function startDevServer(options) {
104
116
  server: { middlewareMode: true },
105
117
  appType: "custom"
106
118
  });
107
- const templatePath = path6.resolve(root, "src/server/index.html");
119
+ const templatePath = path7.resolve(root, "src/server/index.html");
108
120
  const server = createServer(async (req, res) => {
109
121
  const url = req.url || "/";
110
122
  try {
@@ -115,12 +127,12 @@ async function startDevServer(options) {
115
127
  });
116
128
  return;
117
129
  }
118
- const contentFile = path6.join(contentDir, decodeURIComponent(url.split("?")[0]));
119
- if (!url.endsWith(".md") && !url.endsWith(".mdx")) {
130
+ const contentFile = safePath(contentDir, url);
131
+ if (contentFile && !url.endsWith(".md") && !url.endsWith(".mdx")) {
120
132
  try {
121
133
  const stat = await fsPromises.stat(contentFile);
122
134
  if (stat.isFile()) {
123
- const ext = path6.extname(contentFile).toLowerCase();
135
+ const ext = path7.extname(contentFile).toLowerCase();
124
136
  const mimeTypes = {
125
137
  ".png": "image/png",
126
138
  ".jpg": "image/jpeg",
@@ -148,7 +160,7 @@ async function startDevServer(options) {
148
160
  });
149
161
  return;
150
162
  }
151
- const { matchRoute } = await vite.ssrLoadModule(path6.resolve(root, "src/server/router.ts"));
163
+ const { matchRoute } = await vite.ssrLoadModule(path7.resolve(root, "src/server/router.ts"));
152
164
  const routeHandler = matchRoute(new URL(url, `http://localhost:${port}`).href);
153
165
  if (routeHandler) {
154
166
  const request = new Request(new URL(url, `http://localhost:${port}`));
@@ -161,11 +173,11 @@ async function startDevServer(options) {
161
173
  }
162
174
  const pathname = new URL(url, `http://localhost:${port}`).pathname;
163
175
  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"));
176
+ const source = await vite.ssrLoadModule(path7.resolve(root, "src/lib/source.ts"));
177
+ const { mdxComponents } = await vite.ssrLoadModule(path7.resolve(root, "src/components/mdx/index.tsx"));
178
+ const { loadConfig } = await vite.ssrLoadModule(path7.resolve(root, "src/lib/config.ts"));
167
179
  const config = loadConfig();
168
- const { loadApiSpecs } = await vite.ssrLoadModule(path6.resolve(root, "src/lib/openapi.ts"));
180
+ const { loadApiSpecs } = await vite.ssrLoadModule(path7.resolve(root, "src/lib/openapi.ts"));
169
181
  const apiSpecs = config.api?.length ? loadApiSpecs(config.api) : [];
170
182
  const [tree, sourcePage] = await Promise.all([
171
183
  source.buildPageTree(),
@@ -187,9 +199,10 @@ async function startDevServer(options) {
187
199
  }
188
200
  let template = await fsPromises.readFile(templatePath, "utf-8");
189
201
  template = await vite.transformIndexHtml(url, template);
190
- const dataScript = `<script>window.__PAGE_DATA__ = ${JSON.stringify(embeddedData)}</script>`;
202
+ const safeJson = JSON.stringify(embeddedData).replace(/</g, "\\u003c");
203
+ const dataScript = `<script>window.__PAGE_DATA__ = ${safeJson}</script>`;
191
204
  template = template.replace("<!--head-outlet-->", `<!--head-outlet-->${dataScript}`);
192
- const { render } = await vite.ssrLoadModule(path6.resolve(root, "src/server/entry-server.tsx"));
205
+ const { render } = await vite.ssrLoadModule(path7.resolve(root, "src/server/entry-server.tsx"));
193
206
  const html = render(url, { config, tree, page: pageData, apiSpecs });
194
207
  const finalHtml = template.replace("<!--ssr-outlet-->", html);
195
208
  res.setHeader("Content-Type", "text/html");
@@ -219,6 +232,413 @@ async function startDevServer(options) {
219
232
  }
220
233
  var init_dev = __esm(() => {
221
234
  init_vite_config();
235
+ init_safe_path();
236
+ });
237
+
238
+ // src/lib/config.ts
239
+ import fs3 from "fs";
240
+ import path8 from "path";
241
+ import { parse as parse2 } from "yaml";
242
+ function resolveConfigPath() {
243
+ const projectRoot = process.env.CHRONICLE_PROJECT_ROOT;
244
+ if (projectRoot) {
245
+ const rootPath = path8.join(projectRoot, CONFIG_FILE);
246
+ if (fs3.existsSync(rootPath))
247
+ return rootPath;
248
+ }
249
+ const cwdPath = path8.join(process.cwd(), CONFIG_FILE);
250
+ if (fs3.existsSync(cwdPath))
251
+ return cwdPath;
252
+ const contentDir = process.env.CHRONICLE_CONTENT_DIR;
253
+ if (contentDir) {
254
+ const contentPath = path8.join(contentDir, CONFIG_FILE);
255
+ if (fs3.existsSync(contentPath))
256
+ return contentPath;
257
+ }
258
+ return null;
259
+ }
260
+ function loadConfig() {
261
+ const configPath = resolveConfigPath();
262
+ if (!configPath) {
263
+ return defaultConfig;
264
+ }
265
+ const raw = fs3.readFileSync(configPath, "utf-8");
266
+ const userConfig = parse2(raw);
267
+ return {
268
+ ...defaultConfig,
269
+ ...userConfig,
270
+ theme: {
271
+ name: userConfig.theme?.name ?? defaultConfig.theme.name,
272
+ colors: { ...defaultConfig.theme?.colors, ...userConfig.theme?.colors }
273
+ },
274
+ search: { ...defaultConfig.search, ...userConfig.search },
275
+ footer: userConfig.footer,
276
+ api: userConfig.api,
277
+ llms: { enabled: false, ...userConfig.llms },
278
+ analytics: { enabled: false, ...userConfig.analytics }
279
+ };
280
+ }
281
+ var CONFIG_FILE = "chronicle.yaml", defaultConfig;
282
+ var init_config = __esm(() => {
283
+ defaultConfig = {
284
+ title: "Documentation",
285
+ theme: { name: "default" },
286
+ search: { enabled: true, placeholder: "Search..." }
287
+ };
288
+ });
289
+ // src/lib/openapi.ts
290
+ import fs4 from "fs";
291
+ import path9 from "path";
292
+ import { parse as parseYaml } from "yaml";
293
+ function loadApiSpecs(apiConfigs) {
294
+ const contentDir = process.env.CHRONICLE_CONTENT_DIR ?? process.cwd();
295
+ return apiConfigs.map((config) => loadApiSpec(config, contentDir));
296
+ }
297
+ function loadApiSpec(config, contentDir) {
298
+ const specPath = path9.resolve(contentDir, config.spec);
299
+ const raw = fs4.readFileSync(specPath, "utf-8");
300
+ const isYaml = specPath.endsWith(".yaml") || specPath.endsWith(".yml");
301
+ const doc = isYaml ? parseYaml(raw) : JSON.parse(raw);
302
+ let v3Doc;
303
+ if ("swagger" in doc && doc.swagger === "2.0") {
304
+ v3Doc = convertV2toV3(doc);
305
+ } else if ("openapi" in doc && doc.openapi.startsWith("3.")) {
306
+ v3Doc = resolveDocument(doc);
307
+ } else {
308
+ throw new Error(`Unsupported spec version in ${config.spec}`);
309
+ }
310
+ return {
311
+ name: config.name,
312
+ basePath: config.basePath,
313
+ server: config.server,
314
+ auth: config.auth,
315
+ document: v3Doc
316
+ };
317
+ }
318
+ function resolveRef(ref, root) {
319
+ const parts = ref.replace(/^#\//, "").split("/");
320
+ let current = root;
321
+ for (const part of parts) {
322
+ if (current && typeof current === "object" && !Array.isArray(current)) {
323
+ current = current[part];
324
+ } else {
325
+ throw new Error(`Cannot resolve $ref: ${ref}`);
326
+ }
327
+ }
328
+ return current;
329
+ }
330
+ function deepResolveRefs(obj, root, stack = new Set, cache = new Map) {
331
+ if (obj === null || obj === undefined || typeof obj !== "object")
332
+ return obj;
333
+ if (Array.isArray(obj)) {
334
+ return obj.map((item) => deepResolveRefs(item, root, stack, cache));
335
+ }
336
+ const record = obj;
337
+ if (typeof record.$ref === "string") {
338
+ const ref = record.$ref;
339
+ if (cache.has(ref))
340
+ return cache.get(ref);
341
+ if (stack.has(ref))
342
+ return { type: "object", description: "[circular]" };
343
+ stack.add(ref);
344
+ const resolved = deepResolveRefs(resolveRef(ref, root), root, stack, cache);
345
+ stack.delete(ref);
346
+ cache.set(ref, resolved);
347
+ return resolved;
348
+ }
349
+ const result = {};
350
+ for (const [key, value] of Object.entries(record)) {
351
+ result[key] = deepResolveRefs(value, root, stack, cache);
352
+ }
353
+ return result;
354
+ }
355
+ function resolveDocument(doc) {
356
+ const root = doc;
357
+ return deepResolveRefs(doc, root);
358
+ }
359
+ function convertV2toV3(doc) {
360
+ const root = doc;
361
+ const resolved = deepResolveRefs(doc, root);
362
+ const v3Paths = {};
363
+ for (const [pathStr, pathItem] of Object.entries(resolved.paths ?? {})) {
364
+ if (!pathItem)
365
+ continue;
366
+ const v3PathItem = {};
367
+ for (const method of ["get", "post", "put", "delete", "patch"]) {
368
+ const op = pathItem[method];
369
+ if (!op)
370
+ continue;
371
+ v3PathItem[method] = convertV2Operation(op);
372
+ }
373
+ v3Paths[pathStr] = v3PathItem;
374
+ }
375
+ return {
376
+ openapi: "3.0.0",
377
+ info: resolved.info,
378
+ paths: v3Paths,
379
+ tags: resolved.tags ?? []
380
+ };
381
+ }
382
+ function convertV2Operation(op) {
383
+ const params = op.parameters ?? [];
384
+ const v3Params = params.filter((p) => p.in !== "body").map((p) => ({
385
+ name: p.name,
386
+ in: p.in,
387
+ required: p.required ?? false,
388
+ description: p.description,
389
+ schema: { type: p.type ?? "string", format: p.format }
390
+ }));
391
+ const bodyParam = params.find((p) => p.in === "body");
392
+ let requestBody;
393
+ if (bodyParam?.schema) {
394
+ requestBody = {
395
+ required: bodyParam.required ?? false,
396
+ content: {
397
+ "application/json": {
398
+ schema: bodyParam.schema
399
+ }
400
+ }
401
+ };
402
+ }
403
+ const v3Responses = {};
404
+ for (const [status, resp] of Object.entries(op.responses ?? {})) {
405
+ const v2Resp = resp;
406
+ const v3Resp = {
407
+ description: v2Resp.description ?? ""
408
+ };
409
+ if (v2Resp.schema) {
410
+ v3Resp.content = {
411
+ "application/json": {
412
+ schema: v2Resp.schema
413
+ }
414
+ };
415
+ }
416
+ v3Responses[status] = v3Resp;
417
+ }
418
+ const result = {
419
+ operationId: op.operationId,
420
+ summary: op.summary,
421
+ description: op.description,
422
+ tags: op.tags,
423
+ parameters: v3Params,
424
+ responses: v3Responses
425
+ };
426
+ if (requestBody) {
427
+ result.requestBody = requestBody;
428
+ }
429
+ return result;
430
+ }
431
+ var init_openapi = () => {};
432
+
433
+ // src/lib/api-routes.ts
434
+ import slugify from "slugify";
435
+ function getSpecSlug(spec) {
436
+ return slugify(spec.name, { lower: true, strict: true });
437
+ }
438
+ var init_api_routes = () => {};
439
+
440
+ // src/server/build-search-index.ts
441
+ var exports_build_search_index = {};
442
+ __export(exports_build_search_index, {
443
+ generateSearchIndex: () => generateSearchIndex
444
+ });
445
+ import fs5 from "fs/promises";
446
+ import path10 from "path";
447
+ import matter from "gray-matter";
448
+ function extractHeadings(markdown) {
449
+ const headingRegex = /^#{1,6}\s+(.+)$/gm;
450
+ const headings = [];
451
+ let match;
452
+ while ((match = headingRegex.exec(markdown)) !== null) {
453
+ headings.push(match[1].trim());
454
+ }
455
+ return headings.join(" ");
456
+ }
457
+ async function scanContent(contentDir) {
458
+ const docs = [];
459
+ async function scan(dir, prefix = []) {
460
+ let entries;
461
+ try {
462
+ entries = await fs5.readdir(dir, { withFileTypes: true });
463
+ } catch {
464
+ return;
465
+ }
466
+ for (const entry of entries) {
467
+ if (entry.name.startsWith(".") || entry.name === "node_modules")
468
+ continue;
469
+ const fullPath = path10.join(dir, entry.name);
470
+ if (entry.isDirectory()) {
471
+ await scan(fullPath, [...prefix, entry.name]);
472
+ continue;
473
+ }
474
+ if (!entry.name.endsWith(".mdx") && !entry.name.endsWith(".md"))
475
+ continue;
476
+ const raw = await fs5.readFile(fullPath, "utf-8");
477
+ const { data: fm, content } = matter(raw);
478
+ const baseName = entry.name.replace(/\.(mdx|md)$/, "");
479
+ const slugs = baseName === "index" ? prefix : [...prefix, baseName];
480
+ const url = slugs.length === 0 ? "/" : "/" + slugs.join("/");
481
+ docs.push({
482
+ id: url,
483
+ url,
484
+ title: fm.title ?? baseName,
485
+ content: extractHeadings(content),
486
+ type: "page"
487
+ });
488
+ }
489
+ }
490
+ await scan(contentDir);
491
+ return docs;
492
+ }
493
+ function buildApiDocs() {
494
+ const config = loadConfig();
495
+ if (!config.api?.length)
496
+ return [];
497
+ const docs = [];
498
+ const specs = loadApiSpecs(config.api);
499
+ for (const spec of specs) {
500
+ const specSlug = getSpecSlug(spec);
501
+ const paths = spec.document.paths ?? {};
502
+ for (const [, pathItem] of Object.entries(paths)) {
503
+ if (!pathItem)
504
+ continue;
505
+ for (const method of ["get", "post", "put", "delete", "patch"]) {
506
+ const op = pathItem[method];
507
+ if (!op?.operationId)
508
+ continue;
509
+ const url = `/apis/${specSlug}/${encodeURIComponent(op.operationId)}`;
510
+ docs.push({
511
+ id: url,
512
+ url,
513
+ title: `${method.toUpperCase()} ${op.summary ?? op.operationId}`,
514
+ content: op.description ?? "",
515
+ type: "api"
516
+ });
517
+ }
518
+ }
519
+ }
520
+ return docs;
521
+ }
522
+ async function generateSearchIndex(contentDir, outDir) {
523
+ const [contentDocs, apiDocs] = await Promise.all([
524
+ scanContent(contentDir),
525
+ Promise.resolve(buildApiDocs())
526
+ ]);
527
+ const documents = [...contentDocs, ...apiDocs];
528
+ const outPath = path10.join(outDir, "search-index.json");
529
+ await fs5.writeFile(outPath, JSON.stringify(documents));
530
+ return documents.length;
531
+ }
532
+ var init_build_search_index = __esm(() => {
533
+ init_config();
534
+ init_openapi();
535
+ init_api_routes();
536
+ });
537
+
538
+ // src/server/adapters/vercel.ts
539
+ var exports_vercel = {};
540
+ __export(exports_vercel, {
541
+ buildVercelOutput: () => buildVercelOutput
542
+ });
543
+ import path11 from "path";
544
+ import fs6 from "fs/promises";
545
+ import { existsSync } from "fs";
546
+ import chalk5 from "chalk";
547
+ async function buildVercelOutput(options) {
548
+ const { distDir, contentDir, projectRoot } = options;
549
+ const outputDir = path11.resolve(projectRoot, ".vercel/output");
550
+ console.log(chalk5.gray("Generating Vercel output..."));
551
+ await fs6.rm(outputDir, { recursive: true, force: true });
552
+ const staticDir = path11.resolve(outputDir, "static");
553
+ const funcDir = path11.resolve(outputDir, "functions/index.func");
554
+ await fs6.mkdir(staticDir, { recursive: true });
555
+ await fs6.mkdir(funcDir, { recursive: true });
556
+ const clientDir = path11.resolve(distDir, "client");
557
+ await copyDir(clientDir, staticDir);
558
+ console.log(chalk5.gray(" Copied client assets to static/"));
559
+ if (existsSync(contentDir)) {
560
+ await copyContentAssets(contentDir, staticDir);
561
+ console.log(chalk5.gray(" Copied content assets to static/"));
562
+ }
563
+ const serverDir = path11.resolve(distDir, "server");
564
+ await copyDir(serverDir, funcDir);
565
+ console.log(chalk5.gray(" Copied server bundle to functions/"));
566
+ const templateSrc = path11.resolve(clientDir, "src/server/index.html");
567
+ await fs6.copyFile(templateSrc, path11.resolve(funcDir, "index.html"));
568
+ await fs6.writeFile(path11.resolve(funcDir, "package.json"), JSON.stringify({ type: "module" }, null, 2));
569
+ await fs6.writeFile(path11.resolve(funcDir, ".vc-config.json"), JSON.stringify({
570
+ runtime: "nodejs24.x",
571
+ handler: "entry-vercel.js",
572
+ launcherType: "Nodejs"
573
+ }, null, 2));
574
+ await fs6.writeFile(path11.resolve(outputDir, "config.json"), JSON.stringify({
575
+ version: 3,
576
+ routes: [
577
+ { handle: "filesystem" },
578
+ { src: "/(.*)", dest: "/index" }
579
+ ]
580
+ }, null, 2));
581
+ console.log(chalk5.green("Vercel output generated →"), outputDir);
582
+ }
583
+ async function copyDir(src, dest) {
584
+ await fs6.mkdir(dest, { recursive: true });
585
+ const entries = await fs6.readdir(src, { withFileTypes: true });
586
+ for (const entry of entries) {
587
+ const srcPath = path11.join(src, entry.name);
588
+ const destPath = path11.join(dest, entry.name);
589
+ if (entry.isDirectory()) {
590
+ await copyDir(srcPath, destPath);
591
+ } else {
592
+ await fs6.copyFile(srcPath, destPath);
593
+ }
594
+ }
595
+ }
596
+ async function copyContentAssets(contentDir, staticDir) {
597
+ const entries = await fs6.readdir(contentDir, { withFileTypes: true });
598
+ for (const entry of entries) {
599
+ const srcPath = path11.join(contentDir, entry.name);
600
+ if (entry.isDirectory()) {
601
+ const destSubDir = path11.join(staticDir, entry.name);
602
+ await copyContentAssetsRecursive(srcPath, destSubDir);
603
+ } else {
604
+ const ext = path11.extname(entry.name).toLowerCase();
605
+ if (CONTENT_EXTENSIONS.has(ext)) {
606
+ await fs6.copyFile(srcPath, path11.join(staticDir, entry.name));
607
+ }
608
+ }
609
+ }
610
+ }
611
+ async function copyContentAssetsRecursive(srcDir, destDir) {
612
+ const entries = await fs6.readdir(srcDir, { withFileTypes: true });
613
+ for (const entry of entries) {
614
+ const srcPath = path11.join(srcDir, entry.name);
615
+ if (entry.isDirectory()) {
616
+ await copyContentAssetsRecursive(srcPath, path11.join(destDir, entry.name));
617
+ } else {
618
+ const ext = path11.extname(entry.name).toLowerCase();
619
+ if (CONTENT_EXTENSIONS.has(ext)) {
620
+ await fs6.mkdir(destDir, { recursive: true });
621
+ await fs6.copyFile(srcPath, path11.join(destDir, entry.name));
622
+ }
623
+ }
624
+ }
625
+ }
626
+ var CONTENT_EXTENSIONS;
627
+ var init_vercel = __esm(() => {
628
+ CONTENT_EXTENSIONS = new Set([
629
+ ".png",
630
+ ".jpg",
631
+ ".jpeg",
632
+ ".gif",
633
+ ".svg",
634
+ ".webp",
635
+ ".ico",
636
+ ".pdf",
637
+ ".json",
638
+ ".yaml",
639
+ ".yml",
640
+ ".txt"
641
+ ]);
222
642
  });
223
643
 
224
644
  // src/server/prod.ts
@@ -226,13 +646,13 @@ var exports_prod = {};
226
646
  __export(exports_prod, {
227
647
  startProdServer: () => startProdServer
228
648
  });
229
- import path8 from "path";
230
- import chalk6 from "chalk";
649
+ import path13 from "path";
650
+ import chalk7 from "chalk";
231
651
  async function startProdServer(options) {
232
652
  const { port, distDir } = options;
233
- const serverEntry = path8.resolve(distDir, "server/entry-prod.js");
653
+ const serverEntry = path13.resolve(distDir, "server/entry-prod.js");
234
654
  const { startServer } = await import(serverEntry);
235
- console.log(chalk6.cyan("Starting production server..."));
655
+ console.log(chalk7.cyan("Starting production server..."));
236
656
  return startServer({ port, distDir });
237
657
  }
238
658
  var init_prod = () => {};
@@ -442,78 +862,97 @@ var devCommand = new Command2("dev").description("Start development server").opt
442
862
 
443
863
  // src/cli/commands/build.ts
444
864
  import { Command as Command3 } from "commander";
445
- import path7 from "path";
446
- import chalk5 from "chalk";
447
- var buildCommand = new Command3("build").description("Build for production").option("-c, --content <path>", "Content directory").option("-o, --outDir <path>", "Output directory", "dist").action(async (options) => {
865
+ import path12 from "path";
866
+ import chalk6 from "chalk";
867
+ 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) => {
448
868
  const contentDir = resolveContentDir(options.content);
449
- const outDir = path7.resolve(options.outDir);
869
+ const outDir = path12.resolve(options.outDir);
870
+ const VALID_ADAPTERS = ["vercel"];
871
+ if (options.adapter && !VALID_ADAPTERS.includes(options.adapter)) {
872
+ console.error(chalk6.red(`Unknown adapter: ${options.adapter}. Valid adapters: ${VALID_ADAPTERS.join(", ")}`));
873
+ process.exit(1);
874
+ }
450
875
  process.env.CHRONICLE_PROJECT_ROOT = process.cwd();
451
876
  process.env.CHRONICLE_CONTENT_DIR = contentDir;
452
- console.log(chalk5.cyan("Building for production..."));
877
+ console.log(chalk6.cyan("Building for production..."));
453
878
  const { build } = await import("vite");
454
879
  const { createViteConfig: createViteConfig2 } = await Promise.resolve().then(() => (init_vite_config(), exports_vite_config));
455
880
  const baseConfig = await createViteConfig2({ root: PACKAGE_ROOT, contentDir });
456
- console.log(chalk5.gray("Building client..."));
881
+ console.log(chalk6.gray("Building client..."));
457
882
  await build({
458
883
  ...baseConfig,
459
884
  build: {
460
- outDir: path7.join(outDir, "client"),
885
+ outDir: path12.join(outDir, "client"),
461
886
  ssrManifest: true,
462
887
  rolldownOptions: {
463
- input: path7.resolve(PACKAGE_ROOT, "src/server/index.html")
888
+ input: path12.resolve(PACKAGE_ROOT, "src/server/index.html")
464
889
  }
465
890
  }
466
891
  });
467
- console.log(chalk5.gray("Building server..."));
892
+ const serverEntry = options.adapter === "vercel" ? path12.resolve(PACKAGE_ROOT, "src/server/entry-vercel.ts") : path12.resolve(PACKAGE_ROOT, "src/server/entry-prod.ts");
893
+ console.log(chalk6.gray("Building server..."));
468
894
  await build({
469
895
  ...baseConfig,
470
896
  ssr: {
471
897
  noExternal: true
472
898
  },
473
899
  build: {
474
- outDir: path7.join(outDir, "server"),
475
- ssr: path7.resolve(PACKAGE_ROOT, "src/server/entry-prod.ts")
900
+ outDir: path12.join(outDir, "server"),
901
+ ssr: serverEntry,
902
+ target: "node22"
476
903
  }
477
904
  });
478
- console.log(chalk5.green("Build complete "), outDir);
905
+ console.log(chalk6.gray("Building search index..."));
906
+ const { generateSearchIndex: generateSearchIndex2 } = await Promise.resolve().then(() => (init_build_search_index(), exports_build_search_index));
907
+ const docCount = await generateSearchIndex2(contentDir, path12.join(outDir, "server"));
908
+ console.log(chalk6.gray(` Indexed ${docCount} documents`));
909
+ console.log(chalk6.green("Build complete →"), outDir);
910
+ if (options.adapter === "vercel") {
911
+ const { buildVercelOutput: buildVercelOutput2 } = await Promise.resolve().then(() => (init_vercel(), exports_vercel));
912
+ await buildVercelOutput2({
913
+ distDir: outDir,
914
+ contentDir,
915
+ projectRoot: process.cwd()
916
+ });
917
+ }
479
918
  });
480
919
 
481
920
  // src/cli/commands/start.ts
482
921
  import { Command as Command4 } from "commander";
483
- import path9 from "path";
484
- import chalk7 from "chalk";
922
+ import path14 from "path";
923
+ import chalk8 from "chalk";
485
924
  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) => {
486
925
  const contentDir = resolveContentDir(options.content);
487
926
  const port = parseInt(options.port, 10);
488
- const distDir = path9.resolve(options.dist);
927
+ const distDir = path14.resolve(options.dist);
489
928
  process.env.CHRONICLE_PROJECT_ROOT = process.cwd();
490
929
  process.env.CHRONICLE_CONTENT_DIR = contentDir;
491
- console.log(chalk7.cyan("Starting production server..."));
930
+ console.log(chalk8.cyan("Starting production server..."));
492
931
  const { startProdServer: startProdServer2 } = await Promise.resolve().then(() => (init_prod(), exports_prod));
493
932
  await startProdServer2({ port, root: PACKAGE_ROOT, distDir });
494
933
  });
495
934
 
496
935
  // src/cli/commands/serve.ts
497
936
  import { Command as Command5 } from "commander";
498
- import path10 from "path";
499
- import chalk8 from "chalk";
937
+ import path15 from "path";
938
+ import chalk9 from "chalk";
500
939
  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) => {
501
940
  const contentDir = resolveContentDir(options.content);
502
941
  const port = parseInt(options.port, 10);
503
- const outDir = path10.resolve(options.outDir);
942
+ const outDir = path15.resolve(options.outDir);
504
943
  process.env.CHRONICLE_PROJECT_ROOT = process.cwd();
505
944
  process.env.CHRONICLE_CONTENT_DIR = contentDir;
506
- console.log(chalk8.cyan("Building for production..."));
945
+ console.log(chalk9.cyan("Building for production..."));
507
946
  const { build } = await import("vite");
508
947
  const { createViteConfig: createViteConfig2 } = await Promise.resolve().then(() => (init_vite_config(), exports_vite_config));
509
948
  const baseConfig = await createViteConfig2({ root: PACKAGE_ROOT, contentDir });
510
949
  await build({
511
950
  ...baseConfig,
512
951
  build: {
513
- outDir: path10.join(outDir, "client"),
952
+ outDir: path15.join(outDir, "client"),
514
953
  ssrManifest: true,
515
954
  rolldownOptions: {
516
- input: path10.resolve(PACKAGE_ROOT, "src/server/index.html")
955
+ input: path15.resolve(PACKAGE_ROOT, "src/server/index.html")
517
956
  }
518
957
  }
519
958
  });
@@ -523,11 +962,11 @@ var serveCommand = new Command5("serve").description("Build and start production
523
962
  noExternal: true
524
963
  },
525
964
  build: {
526
- outDir: path10.join(outDir, "server"),
527
- ssr: path10.resolve(PACKAGE_ROOT, "src/server/entry-prod.ts")
965
+ outDir: path15.join(outDir, "server"),
966
+ ssr: path15.resolve(PACKAGE_ROOT, "src/server/entry-prod.ts")
528
967
  }
529
968
  });
530
- console.log(chalk8.cyan("Starting production server..."));
969
+ console.log(chalk9.cyan("Starting production server..."));
531
970
  const { startProdServer: startProdServer2 } = await Promise.resolve().then(() => (init_prod(), exports_prod));
532
971
  await startProdServer2({ port, root: PACKAGE_ROOT, distDir: outDir });
533
972
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@raystack/chronicle",
3
- "version": "0.1.0-canary.c5d277e",
3
+ "version": "0.1.0-canary.cb102e9",
4
4
  "description": "Config-driven documentation framework",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",