@raystack/chronicle 0.1.0-canary.9b7d924 → 0.1.0-canary.a320792

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
@@ -221,124 +221,18 @@ var init_dev = __esm(() => {
221
221
  init_vite_config();
222
222
  });
223
223
 
224
- // src/server/adapters/vercel.ts
225
- var exports_vercel = {};
226
- __export(exports_vercel, {
227
- buildVercelOutput: () => buildVercelOutput
228
- });
229
- import path7 from "path";
230
- import fs3 from "fs/promises";
231
- import { existsSync } from "fs";
232
- import chalk5 from "chalk";
233
- async function buildVercelOutput(options) {
234
- const { distDir, contentDir, projectRoot } = options;
235
- const outputDir = path7.resolve(projectRoot, ".vercel/output");
236
- console.log(chalk5.gray("Generating Vercel output..."));
237
- await fs3.rm(outputDir, { recursive: true, force: true });
238
- const staticDir = path7.resolve(outputDir, "static");
239
- const funcDir = path7.resolve(outputDir, "functions/index.func");
240
- await fs3.mkdir(staticDir, { recursive: true });
241
- await fs3.mkdir(funcDir, { recursive: true });
242
- const clientDir = path7.resolve(distDir, "client");
243
- await copyDir(clientDir, staticDir);
244
- console.log(chalk5.gray(" Copied client assets to static/"));
245
- if (existsSync(contentDir)) {
246
- await copyContentAssets(contentDir, staticDir);
247
- console.log(chalk5.gray(" Copied content assets to static/"));
248
- }
249
- const serverDir = path7.resolve(distDir, "server");
250
- await copyDir(serverDir, funcDir);
251
- console.log(chalk5.gray(" Copied server bundle to functions/"));
252
- const templateSrc = path7.resolve(clientDir, "src/server/index.html");
253
- await fs3.copyFile(templateSrc, path7.resolve(funcDir, "index.html"));
254
- await fs3.writeFile(path7.resolve(funcDir, "package.json"), JSON.stringify({ type: "module" }, null, 2));
255
- await fs3.writeFile(path7.resolve(funcDir, ".vc-config.json"), JSON.stringify({
256
- runtime: "nodejs24.x",
257
- handler: "entry-vercel.js",
258
- launcherType: "Nodejs"
259
- }, null, 2));
260
- await fs3.writeFile(path7.resolve(outputDir, "config.json"), JSON.stringify({
261
- version: 3,
262
- routes: [
263
- { handle: "filesystem" },
264
- { src: "/(.*)", dest: "/index" }
265
- ]
266
- }, null, 2));
267
- console.log(chalk5.green("Vercel output generated →"), outputDir);
268
- }
269
- async function copyDir(src, dest) {
270
- await fs3.mkdir(dest, { recursive: true });
271
- const entries = await fs3.readdir(src, { withFileTypes: true });
272
- for (const entry of entries) {
273
- const srcPath = path7.join(src, entry.name);
274
- const destPath = path7.join(dest, entry.name);
275
- if (entry.isDirectory()) {
276
- await copyDir(srcPath, destPath);
277
- } else {
278
- await fs3.copyFile(srcPath, destPath);
279
- }
280
- }
281
- }
282
- async function copyContentAssets(contentDir, staticDir) {
283
- const entries = await fs3.readdir(contentDir, { withFileTypes: true });
284
- for (const entry of entries) {
285
- const srcPath = path7.join(contentDir, entry.name);
286
- if (entry.isDirectory()) {
287
- const destSubDir = path7.join(staticDir, entry.name);
288
- await copyContentAssetsRecursive(srcPath, destSubDir);
289
- } else {
290
- const ext = path7.extname(entry.name).toLowerCase();
291
- if (CONTENT_EXTENSIONS.has(ext)) {
292
- await fs3.copyFile(srcPath, path7.join(staticDir, entry.name));
293
- }
294
- }
295
- }
296
- }
297
- async function copyContentAssetsRecursive(srcDir, destDir) {
298
- const entries = await fs3.readdir(srcDir, { withFileTypes: true });
299
- for (const entry of entries) {
300
- const srcPath = path7.join(srcDir, entry.name);
301
- if (entry.isDirectory()) {
302
- await copyContentAssetsRecursive(srcPath, path7.join(destDir, entry.name));
303
- } else {
304
- const ext = path7.extname(entry.name).toLowerCase();
305
- if (CONTENT_EXTENSIONS.has(ext)) {
306
- await fs3.mkdir(destDir, { recursive: true });
307
- await fs3.copyFile(srcPath, path7.join(destDir, entry.name));
308
- }
309
- }
310
- }
311
- }
312
- var CONTENT_EXTENSIONS;
313
- var init_vercel = __esm(() => {
314
- CONTENT_EXTENSIONS = new Set([
315
- ".png",
316
- ".jpg",
317
- ".jpeg",
318
- ".gif",
319
- ".svg",
320
- ".webp",
321
- ".ico",
322
- ".pdf",
323
- ".json",
324
- ".yaml",
325
- ".yml",
326
- ".txt"
327
- ]);
328
- });
329
-
330
224
  // src/server/prod.ts
331
225
  var exports_prod = {};
332
226
  __export(exports_prod, {
333
227
  startProdServer: () => startProdServer
334
228
  });
335
- import path9 from "path";
336
- import chalk7 from "chalk";
229
+ import path8 from "path";
230
+ import chalk6 from "chalk";
337
231
  async function startProdServer(options) {
338
232
  const { port, distDir } = options;
339
- const serverEntry = path9.resolve(distDir, "server/entry-prod.js");
233
+ const serverEntry = path8.resolve(distDir, "server/entry-prod.js");
340
234
  const { startServer } = await import(serverEntry);
341
- console.log(chalk7.cyan("Starting production server..."));
235
+ console.log(chalk6.cyan("Starting production server..."));
342
236
  return startServer({ port, distDir });
343
237
  }
344
238
  var init_prod = () => {};
@@ -548,88 +442,78 @@ var devCommand = new Command2("dev").description("Start development server").opt
548
442
 
549
443
  // src/cli/commands/build.ts
550
444
  import { Command as Command3 } from "commander";
551
- import path8 from "path";
552
- import chalk6 from "chalk";
553
- 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) => {
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) => {
554
448
  const contentDir = resolveContentDir(options.content);
555
- const outDir = path8.resolve(options.outDir);
449
+ const outDir = path7.resolve(options.outDir);
556
450
  process.env.CHRONICLE_PROJECT_ROOT = process.cwd();
557
451
  process.env.CHRONICLE_CONTENT_DIR = contentDir;
558
- console.log(chalk6.cyan("Building for production..."));
452
+ console.log(chalk5.cyan("Building for production..."));
559
453
  const { build } = await import("vite");
560
454
  const { createViteConfig: createViteConfig2 } = await Promise.resolve().then(() => (init_vite_config(), exports_vite_config));
561
455
  const baseConfig = await createViteConfig2({ root: PACKAGE_ROOT, contentDir });
562
- console.log(chalk6.gray("Building client..."));
456
+ console.log(chalk5.gray("Building client..."));
563
457
  await build({
564
458
  ...baseConfig,
565
459
  build: {
566
- outDir: path8.join(outDir, "client"),
460
+ outDir: path7.join(outDir, "client"),
567
461
  ssrManifest: true,
568
462
  rolldownOptions: {
569
- input: path8.resolve(PACKAGE_ROOT, "src/server/index.html")
463
+ input: path7.resolve(PACKAGE_ROOT, "src/server/index.html")
570
464
  }
571
465
  }
572
466
  });
573
- const serverEntry = options.adapter === "vercel" ? path8.resolve(PACKAGE_ROOT, "src/server/entry-vercel.ts") : path8.resolve(PACKAGE_ROOT, "src/server/entry-prod.ts");
574
- console.log(chalk6.gray("Building server..."));
467
+ console.log(chalk5.gray("Building server..."));
575
468
  await build({
576
469
  ...baseConfig,
577
470
  ssr: {
578
471
  noExternal: true
579
472
  },
580
473
  build: {
581
- outDir: path8.join(outDir, "server"),
582
- ssr: serverEntry,
583
- target: "node22"
474
+ outDir: path7.join(outDir, "server"),
475
+ ssr: path7.resolve(PACKAGE_ROOT, "src/server/entry-prod.ts")
584
476
  }
585
477
  });
586
- console.log(chalk6.green("Build complete →"), outDir);
587
- if (options.adapter === "vercel") {
588
- const { buildVercelOutput: buildVercelOutput2 } = await Promise.resolve().then(() => (init_vercel(), exports_vercel));
589
- await buildVercelOutput2({
590
- distDir: outDir,
591
- contentDir,
592
- projectRoot: process.cwd()
593
- });
594
- }
478
+ console.log(chalk5.green("Build complete →"), outDir);
595
479
  });
596
480
 
597
481
  // src/cli/commands/start.ts
598
482
  import { Command as Command4 } from "commander";
599
- import path10 from "path";
600
- import chalk8 from "chalk";
483
+ import path9 from "path";
484
+ import chalk7 from "chalk";
601
485
  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) => {
602
486
  const contentDir = resolveContentDir(options.content);
603
487
  const port = parseInt(options.port, 10);
604
- const distDir = path10.resolve(options.dist);
488
+ const distDir = path9.resolve(options.dist);
605
489
  process.env.CHRONICLE_PROJECT_ROOT = process.cwd();
606
490
  process.env.CHRONICLE_CONTENT_DIR = contentDir;
607
- console.log(chalk8.cyan("Starting production server..."));
491
+ console.log(chalk7.cyan("Starting production server..."));
608
492
  const { startProdServer: startProdServer2 } = await Promise.resolve().then(() => (init_prod(), exports_prod));
609
493
  await startProdServer2({ port, root: PACKAGE_ROOT, distDir });
610
494
  });
611
495
 
612
496
  // src/cli/commands/serve.ts
613
497
  import { Command as Command5 } from "commander";
614
- import path11 from "path";
615
- import chalk9 from "chalk";
498
+ import path10 from "path";
499
+ import chalk8 from "chalk";
616
500
  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) => {
617
501
  const contentDir = resolveContentDir(options.content);
618
502
  const port = parseInt(options.port, 10);
619
- const outDir = path11.resolve(options.outDir);
503
+ const outDir = path10.resolve(options.outDir);
620
504
  process.env.CHRONICLE_PROJECT_ROOT = process.cwd();
621
505
  process.env.CHRONICLE_CONTENT_DIR = contentDir;
622
- console.log(chalk9.cyan("Building for production..."));
506
+ console.log(chalk8.cyan("Building for production..."));
623
507
  const { build } = await import("vite");
624
508
  const { createViteConfig: createViteConfig2 } = await Promise.resolve().then(() => (init_vite_config(), exports_vite_config));
625
509
  const baseConfig = await createViteConfig2({ root: PACKAGE_ROOT, contentDir });
626
510
  await build({
627
511
  ...baseConfig,
628
512
  build: {
629
- outDir: path11.join(outDir, "client"),
513
+ outDir: path10.join(outDir, "client"),
630
514
  ssrManifest: true,
631
515
  rolldownOptions: {
632
- input: path11.resolve(PACKAGE_ROOT, "src/server/index.html")
516
+ input: path10.resolve(PACKAGE_ROOT, "src/server/index.html")
633
517
  }
634
518
  }
635
519
  });
@@ -639,11 +523,11 @@ var serveCommand = new Command5("serve").description("Build and start production
639
523
  noExternal: true
640
524
  },
641
525
  build: {
642
- outDir: path11.join(outDir, "server"),
643
- ssr: path11.resolve(PACKAGE_ROOT, "src/server/entry-prod.ts")
526
+ outDir: path10.join(outDir, "server"),
527
+ ssr: path10.resolve(PACKAGE_ROOT, "src/server/entry-prod.ts")
644
528
  }
645
529
  });
646
- console.log(chalk9.cyan("Starting production server..."));
530
+ console.log(chalk8.cyan("Starting production server..."));
647
531
  const { startProdServer: startProdServer2 } = await Promise.resolve().then(() => (init_prod(), exports_prod));
648
532
  await startProdServer2({ port, root: PACKAGE_ROOT, distDir: outDir });
649
533
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@raystack/chronicle",
3
- "version": "0.1.0-canary.9b7d924",
3
+ "version": "0.1.0-canary.a320792",
4
4
  "description": "Config-driven documentation framework",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",
@@ -8,7 +8,6 @@ export const buildCommand = new Command('build')
8
8
  .description('Build for production')
9
9
  .option('-c, --content <path>', 'Content directory')
10
10
  .option('-o, --outDir <path>', 'Output directory', 'dist')
11
- .option('--adapter <adapter>', 'Deploy adapter (vercel)')
12
11
  .action(async (options) => {
13
12
  const contentDir = resolveContentDir(options.content)
14
13
  const outDir = path.resolve(options.outDir)
@@ -36,11 +35,7 @@ export const buildCommand = new Command('build')
36
35
  },
37
36
  })
38
37
 
39
- // Build server bundle
40
- const serverEntry = options.adapter === 'vercel'
41
- ? path.resolve(PACKAGE_ROOT, 'src/server/entry-vercel.ts')
42
- : path.resolve(PACKAGE_ROOT, 'src/server/entry-prod.ts')
43
-
38
+ // Build server bundle (noExternal: true to bundle all deps for portability)
44
39
  console.log(chalk.gray('Building server...'))
45
40
  await build({
46
41
  ...baseConfig,
@@ -49,20 +44,9 @@ export const buildCommand = new Command('build')
49
44
  },
50
45
  build: {
51
46
  outDir: path.join(outDir, 'server'),
52
- ssr: serverEntry,
53
- target: 'node22',
47
+ ssr: path.resolve(PACKAGE_ROOT, 'src/server/entry-prod.ts'),
54
48
  },
55
49
  })
56
50
 
57
51
  console.log(chalk.green('Build complete →'), outDir)
58
-
59
- // Run Vercel adapter post-build
60
- if (options.adapter === 'vercel') {
61
- const { buildVercelOutput } = await import('@/server/adapters/vercel')
62
- await buildVercelOutput({
63
- distDir: outDir,
64
- contentDir,
65
- projectRoot: process.cwd(),
66
- })
67
- }
68
52
  })
@@ -3,22 +3,16 @@ import { createServer } from 'http'
3
3
  import { readFileSync, createReadStream } from 'fs'
4
4
  import fsPromises from 'fs/promises'
5
5
  import path from 'path'
6
+ import React from 'react'
6
7
  import { render } from './entry-server'
7
8
  import { matchRoute } from './router'
8
9
  import { loadConfig } from '@/lib/config'
9
10
  import { loadApiSpecs } from '@/lib/openapi'
10
11
  import { getPage, loadPageComponent, buildPageTree } from '@/lib/source'
11
- import { handleRequest } from './request-handler'
12
+ import { mdxComponents } from '@/components/mdx'
12
13
 
13
14
  export { render, matchRoute, loadConfig, loadApiSpecs, getPage, loadPageComponent, buildPageTree }
14
15
 
15
- async function writeResponse(res: import('http').ServerResponse, response: Response) {
16
- res.statusCode = response.status
17
- response.headers.forEach((value: string, key: string) => res.setHeader(key, value))
18
- const body = await response.text()
19
- res.end(body)
20
- }
21
-
22
16
  export async function startServer(options: { port: number; distDir: string }) {
23
17
  const { port, distDir } = options
24
18
 
@@ -29,17 +23,19 @@ export async function startServer(options: { port: number; distDir: string }) {
29
23
  const sirv = (await import('sirv')).default
30
24
  const assets = sirv(clientDir, { gzip: true })
31
25
 
32
- const baseUrl = `http://localhost:${port}`
33
-
34
26
  const server = createServer(async (req, res) => {
35
27
  const url = req.url || '/'
36
28
 
37
29
  try {
38
- // API routes — handled by shared request handler
39
- const routeHandler = matchRoute(new URL(url, baseUrl).href)
30
+ // API routes
31
+ const routeHandler = matchRoute(new URL(url, `http://localhost:${port}`).href)
40
32
  if (routeHandler) {
41
- const response = await routeHandler(new Request(new URL(url, baseUrl)))
42
- await writeResponse(res, response)
33
+ const request = new Request(new URL(url, `http://localhost:${port}`))
34
+ const response = await routeHandler(request)
35
+ res.statusCode = response.status
36
+ response.headers.forEach((value: string, key: string) => res.setHeader(key, value))
37
+ const body = await response.text()
38
+ res.end(body)
43
39
  return
44
40
  }
45
41
 
@@ -71,9 +67,43 @@ export async function startServer(options: { port: number; distDir: string }) {
71
67
  })
72
68
  if (assetHandled) return
73
69
 
74
- // SSR render — handled by shared request handler
75
- const response = await handleRequest(url, { template, baseUrl })
76
- await writeResponse(res, response)
70
+ // Resolve page data
71
+ const pathname = new URL(url, `http://localhost:${port}`).pathname
72
+ const slug = pathname === '/' ? [] : pathname.slice(1).split('/').filter(Boolean)
73
+
74
+ const config = loadConfig()
75
+ const apiSpecs = config.api?.length ? loadApiSpecs(config.api) : []
76
+
77
+ const [tree, sourcePage] = await Promise.all([
78
+ buildPageTree(),
79
+ getPage(slug),
80
+ ])
81
+
82
+ let pageData = null
83
+ let embeddedData: any = { config, tree, slug, frontmatter: null, filePath: null }
84
+
85
+ if (sourcePage) {
86
+ const component = await loadPageComponent(sourcePage)
87
+ pageData = {
88
+ slug,
89
+ frontmatter: sourcePage.frontmatter,
90
+ content: component ? React.createElement(component, { components: mdxComponents }) : null,
91
+ }
92
+ embeddedData.frontmatter = sourcePage.frontmatter
93
+ embeddedData.filePath = sourcePage.filePath
94
+ }
95
+
96
+ // SSR render
97
+ const html = render(url, { config, tree, page: pageData, apiSpecs })
98
+
99
+ const dataScript = `<script>window.__PAGE_DATA__ = ${JSON.stringify(embeddedData)}</script>`
100
+ const finalHtml = template
101
+ .replace('<!--head-outlet-->', `<!--head-outlet-->${dataScript}`)
102
+ .replace('<!--ssr-outlet-->', html)
103
+
104
+ res.setHeader('Content-Type', 'text/html')
105
+ res.statusCode = 200
106
+ res.end(finalHtml)
77
107
  } catch (e) {
78
108
  console.error(e)
79
109
  res.statusCode = 500
@@ -1,133 +0,0 @@
1
- import path from 'path'
2
- import fs from 'fs/promises'
3
- import { existsSync } from 'fs'
4
- import chalk from 'chalk'
5
-
6
- interface VercelAdapterOptions {
7
- distDir: string
8
- contentDir: string
9
- projectRoot: string
10
- }
11
-
12
- const CONTENT_EXTENSIONS = new Set([
13
- '.png', '.jpg', '.jpeg', '.gif', '.svg', '.webp', '.ico',
14
- '.pdf', '.json', '.yaml', '.yml', '.txt',
15
- ])
16
-
17
- export async function buildVercelOutput(options: VercelAdapterOptions) {
18
- const { distDir, contentDir, projectRoot } = options
19
- const outputDir = path.resolve(projectRoot, '.vercel/output')
20
-
21
- console.log(chalk.gray('Generating Vercel output...'))
22
-
23
- // Clean previous output
24
- await fs.rm(outputDir, { recursive: true, force: true })
25
-
26
- // Create output directories
27
- const staticDir = path.resolve(outputDir, 'static')
28
- const funcDir = path.resolve(outputDir, 'functions/index.func')
29
- await fs.mkdir(staticDir, { recursive: true })
30
- await fs.mkdir(funcDir, { recursive: true })
31
-
32
- // 1. Copy client assets → .vercel/output/static/
33
- const clientDir = path.resolve(distDir, 'client')
34
- await copyDir(clientDir, staticDir)
35
- console.log(chalk.gray(' Copied client assets to static/'))
36
-
37
- // 2. Copy content dir assets (images, etc.) → .vercel/output/static/
38
- if (existsSync(contentDir)) {
39
- await copyContentAssets(contentDir, staticDir)
40
- console.log(chalk.gray(' Copied content assets to static/'))
41
- }
42
-
43
- // 3. Copy server bundle → .vercel/output/functions/index.func/
44
- const serverDir = path.resolve(distDir, 'server')
45
- await copyDir(serverDir, funcDir)
46
- console.log(chalk.gray(' Copied server bundle to functions/'))
47
-
48
- // 4. Copy HTML template into function dir (not accessible from static/ at runtime)
49
- const templateSrc = path.resolve(clientDir, 'src/server/index.html')
50
- await fs.copyFile(templateSrc, path.resolve(funcDir, 'index.html'))
51
-
52
- // 5. Write package.json for ESM support
53
- await fs.writeFile(
54
- path.resolve(funcDir, 'package.json'),
55
- JSON.stringify({ type: 'module' }, null, 2),
56
- )
57
-
58
- // 6. Write .vc-config.json
59
- await fs.writeFile(
60
- path.resolve(funcDir, '.vc-config.json'),
61
- JSON.stringify({
62
- runtime: 'nodejs24.x',
63
- handler: 'entry-vercel.js',
64
- launcherType: 'Nodejs',
65
- }, null, 2),
66
- )
67
-
68
- // 7. Write config.json
69
- await fs.writeFile(
70
- path.resolve(outputDir, 'config.json'),
71
- JSON.stringify({
72
- version: 3,
73
- routes: [
74
- { handle: 'filesystem' },
75
- { src: '/(.*)', dest: '/index' },
76
- ],
77
- }, null, 2),
78
- )
79
-
80
- console.log(chalk.green('Vercel output generated →'), outputDir)
81
- }
82
-
83
- async function copyDir(src: string, dest: string) {
84
- await fs.mkdir(dest, { recursive: true })
85
- const entries = await fs.readdir(src, { withFileTypes: true })
86
-
87
- for (const entry of entries) {
88
- const srcPath = path.join(src, entry.name)
89
- const destPath = path.join(dest, entry.name)
90
-
91
- if (entry.isDirectory()) {
92
- await copyDir(srcPath, destPath)
93
- } else {
94
- await fs.copyFile(srcPath, destPath)
95
- }
96
- }
97
- }
98
-
99
- async function copyContentAssets(contentDir: string, staticDir: string) {
100
- const entries = await fs.readdir(contentDir, { withFileTypes: true })
101
-
102
- for (const entry of entries) {
103
- const srcPath = path.join(contentDir, entry.name)
104
-
105
- if (entry.isDirectory()) {
106
- const destSubDir = path.join(staticDir, entry.name)
107
- await copyContentAssetsRecursive(srcPath, destSubDir)
108
- } else {
109
- const ext = path.extname(entry.name).toLowerCase()
110
- if (CONTENT_EXTENSIONS.has(ext)) {
111
- await fs.copyFile(srcPath, path.join(staticDir, entry.name))
112
- }
113
- }
114
- }
115
- }
116
-
117
- async function copyContentAssetsRecursive(srcDir: string, destDir: string) {
118
- const entries = await fs.readdir(srcDir, { withFileTypes: true })
119
-
120
- for (const entry of entries) {
121
- const srcPath = path.join(srcDir, entry.name)
122
-
123
- if (entry.isDirectory()) {
124
- await copyContentAssetsRecursive(srcPath, path.join(destDir, entry.name))
125
- } else {
126
- const ext = path.extname(entry.name).toLowerCase()
127
- if (CONTENT_EXTENSIONS.has(ext)) {
128
- await fs.mkdir(destDir, { recursive: true })
129
- await fs.copyFile(srcPath, path.join(destDir, entry.name))
130
- }
131
- }
132
- }
133
- }
@@ -1,28 +0,0 @@
1
- // Vercel serverless function entry — built by Vite, deployed as catch-all function
2
- import type { IncomingMessage, ServerResponse } from 'http'
3
- import { readFileSync } from 'fs'
4
- import { fileURLToPath } from 'url'
5
- import path from 'path'
6
- import { handleRequest } from './request-handler'
7
-
8
- const __dirname = path.dirname(fileURLToPath(import.meta.url))
9
- const templatePath = path.resolve(__dirname, 'index.html')
10
- const template = readFileSync(templatePath, 'utf-8')
11
-
12
- export default async function handler(req: IncomingMessage, res: ServerResponse) {
13
- const url = req.url || '/'
14
- const baseUrl = `https://${req.headers.host || 'localhost'}`
15
-
16
- try {
17
- const response = await handleRequest(url, { template, baseUrl })
18
-
19
- res.statusCode = response.status
20
- response.headers.forEach((value: string, key: string) => res.setHeader(key, value))
21
- const body = await response.text()
22
- res.end(body)
23
- } catch (e) {
24
- console.error(e)
25
- res.statusCode = 500
26
- res.end((e as Error).message)
27
- }
28
- }
@@ -1,63 +0,0 @@
1
- // Shared request handler for API routes + SSR rendering
2
- // Used by entry-prod.ts (Node) and entry-vercel.ts (Vercel)
3
- import React from 'react'
4
- import { render } from './entry-server'
5
- import { matchRoute } from './router'
6
- import { loadConfig } from '@/lib/config'
7
- import { loadApiSpecs } from '@/lib/openapi'
8
- import { getPage, loadPageComponent, buildPageTree } from '@/lib/source'
9
- import { mdxComponents } from '@/components/mdx'
10
-
11
- export interface RequestHandlerOptions {
12
- template: string
13
- baseUrl: string
14
- }
15
-
16
- export async function handleRequest(url: string, options: RequestHandlerOptions): Promise<Response> {
17
- const { template, baseUrl } = options
18
- const fullUrl = new URL(url, baseUrl).href
19
-
20
- // API routes
21
- const routeHandler = matchRoute(fullUrl)
22
- if (routeHandler) {
23
- return routeHandler(new Request(fullUrl))
24
- }
25
-
26
- // SSR render
27
- const pathname = new URL(url, baseUrl).pathname
28
- const slug = pathname === '/' ? [] : pathname.slice(1).split('/').filter(Boolean)
29
-
30
- const config = loadConfig()
31
- const apiSpecs = config.api?.length ? loadApiSpecs(config.api) : []
32
-
33
- const [tree, sourcePage] = await Promise.all([
34
- buildPageTree(),
35
- getPage(slug),
36
- ])
37
-
38
- let pageData = null
39
- let embeddedData: any = { config, tree, slug, frontmatter: null, filePath: null }
40
-
41
- if (sourcePage) {
42
- const component = await loadPageComponent(sourcePage)
43
- pageData = {
44
- slug,
45
- frontmatter: sourcePage.frontmatter,
46
- content: component ? React.createElement(component, { components: mdxComponents }) : null,
47
- }
48
- embeddedData.frontmatter = sourcePage.frontmatter
49
- embeddedData.filePath = sourcePage.filePath
50
- }
51
-
52
- const html = render(url, { config, tree, page: pageData, apiSpecs })
53
-
54
- const dataScript = `<script>window.__PAGE_DATA__ = ${JSON.stringify(embeddedData)}</script>`
55
- const finalHtml = template
56
- .replace('<!--head-outlet-->', `<!--head-outlet-->${dataScript}`)
57
- .replace('<!--ssr-outlet-->', html)
58
-
59
- return new Response(finalHtml, {
60
- status: 200,
61
- headers: { 'Content-Type': 'text/html' },
62
- })
63
- }