defuss-ssg 0.6.2 → 0.7.0

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.
@@ -0,0 +1,179 @@
1
+ 'use strict';
2
+
3
+ var node_fs = require('node:fs');
4
+ var node_path = require('node:path');
5
+
6
+ const DEFAULT_PAGES_DIR = "pages";
7
+ const DEFAULT_COMPONENTS_DIR = "components";
8
+ const DEFAULT_ASSETS_DIR = "assets";
9
+ const COMPONENTS_SOURCE_ALIASES = [DEFAULT_COMPONENTS_DIR, "csr"];
10
+ const PAGE_SOURCE_EXTENSIONS = [".mdx", ".md", ".html"];
11
+ const normalizePath = (filePath) => filePath.replace(/\\/g, "/");
12
+ const isDefaultPath = (value, defaultValue) => normalizePath(value) === defaultValue;
13
+ const createSourceDirCandidates = (candidates) => {
14
+ const normalizedCandidates = candidates.map((candidate) => normalizePath(candidate));
15
+ const sourceCandidates = normalizedCandidates.map(
16
+ (candidate) => normalizePath(node_path.join("src", candidate))
17
+ );
18
+ return [.../* @__PURE__ */ new Set([...sourceCandidates, ...normalizedCandidates])];
19
+ };
20
+ const resolveSourceDir = (projectDir, candidates, fallback) => {
21
+ for (const candidate of candidates) {
22
+ if (node_fs.existsSync(node_path.join(projectDir, candidate))) {
23
+ return candidate;
24
+ }
25
+ }
26
+ return normalizePath(fallback);
27
+ };
28
+ const getPageSourceExtensionPriority = (filePath) => {
29
+ const extension = node_path.extname(filePath).toLowerCase();
30
+ const index = PAGE_SOURCE_EXTENSIONS.indexOf(
31
+ extension
32
+ );
33
+ return index === -1 ? Number.MAX_SAFE_INTEGER : index;
34
+ };
35
+ const outputPathToSourceCandidates = (pageSourceRootDir, relativeOutputHtmlFilePath) => {
36
+ const sourceStem = normalizePath(relativeOutputHtmlFilePath).replace(
37
+ /\.html$/i,
38
+ ""
39
+ );
40
+ return PAGE_SOURCE_EXTENSIONS.map(
41
+ (extension) => node_path.join(pageSourceRootDir, `${sourceStem}${extension}`)
42
+ );
43
+ };
44
+ const resolveSsgPaths = (projectDir, config) => {
45
+ const pagesSourceDirCandidates = isDefaultPath(config.pages, DEFAULT_PAGES_DIR) ? createSourceDirCandidates([DEFAULT_PAGES_DIR]) : [normalizePath(config.pages)];
46
+ const componentsSourceDirCandidates = isDefaultPath(
47
+ config.components,
48
+ DEFAULT_COMPONENTS_DIR
49
+ ) ? createSourceDirCandidates(COMPONENTS_SOURCE_ALIASES) : [normalizePath(config.components)];
50
+ const assetsSourceDirCandidates = isDefaultPath(config.assets, DEFAULT_ASSETS_DIR) ? createSourceDirCandidates([DEFAULT_ASSETS_DIR]) : [normalizePath(config.assets)];
51
+ const pagesSourceDir = resolveSourceDir(
52
+ projectDir,
53
+ pagesSourceDirCandidates,
54
+ pagesSourceDirCandidates[0] ?? DEFAULT_PAGES_DIR
55
+ );
56
+ const componentsSourceDir = resolveSourceDir(
57
+ projectDir,
58
+ componentsSourceDirCandidates,
59
+ componentsSourceDirCandidates[0] ?? DEFAULT_COMPONENTS_DIR
60
+ );
61
+ const assetsSourceDir = resolveSourceDir(
62
+ projectDir,
63
+ assetsSourceDirCandidates,
64
+ assetsSourceDirCandidates[0] ?? DEFAULT_ASSETS_DIR
65
+ );
66
+ const pagesSourceDirAbsolute = node_path.join(projectDir, pagesSourceDir);
67
+ const componentsSourceDirAbsolute = node_path.join(projectDir, componentsSourceDir);
68
+ const assetsSourceDirAbsolute = node_path.join(projectDir, assetsSourceDir);
69
+ return {
70
+ pagesSourceDir,
71
+ pagesSourceDirAbsolute,
72
+ pagesSourceDirCandidates,
73
+ hasPagesSourceDir: node_fs.existsSync(pagesSourceDirAbsolute),
74
+ componentsSourceDir,
75
+ componentsSourceDirAbsolute,
76
+ componentsSourceDirCandidates,
77
+ hasComponentsSourceDir: node_fs.existsSync(componentsSourceDirAbsolute),
78
+ componentsPublicDir: normalizePath(config.components),
79
+ assetsSourceDir,
80
+ assetsSourceDirAbsolute,
81
+ assetsSourceDirCandidates,
82
+ hasAssetsSourceDir: node_fs.existsSync(assetsSourceDirAbsolute),
83
+ assetsPublicDir: normalizePath(config.assets)
84
+ };
85
+ };
86
+ const getPageSourceRootDir = (projectDir, paths) => paths.hasPagesSourceDir ? paths.pagesSourceDirAbsolute : projectDir;
87
+ const pageSourceFileToOutputPath = (pageSourceFile, pageSourceRootDir) => {
88
+ const relativePagePath = node_path.relative(pageSourceRootDir, pageSourceFile).replace(
89
+ /\\/g,
90
+ "/"
91
+ );
92
+ return relativePagePath.replace(/\.(mdx|md)$/i, ".html");
93
+ };
94
+ const resolvePreferredPageSourceForOutputPath = (relativeOutputHtmlFilePath, pageSourceRootDir) => {
95
+ for (const candidate of outputPathToSourceCandidates(
96
+ pageSourceRootDir,
97
+ relativeOutputHtmlFilePath
98
+ )) {
99
+ if (node_fs.existsSync(candidate)) {
100
+ return candidate;
101
+ }
102
+ }
103
+ return null;
104
+ };
105
+ const selectPreferredPageSourceFiles = (pageSourceFiles, pageSourceRootDir) => {
106
+ const selectedFiles = /* @__PURE__ */ new Map();
107
+ const sortedSourceFiles = [...pageSourceFiles].sort((left, right) => {
108
+ const leftOutputPath = pageSourceFileToOutputPath(left, pageSourceRootDir);
109
+ const rightOutputPath = pageSourceFileToOutputPath(right, pageSourceRootDir);
110
+ const outputPathCompare = leftOutputPath.localeCompare(rightOutputPath);
111
+ if (outputPathCompare !== 0) {
112
+ return outputPathCompare;
113
+ }
114
+ return getPageSourceExtensionPriority(left) - getPageSourceExtensionPriority(right);
115
+ });
116
+ for (const pageSourceFile of sortedSourceFiles) {
117
+ const outputPath = pageSourceFileToOutputPath(
118
+ pageSourceFile,
119
+ pageSourceRootDir
120
+ );
121
+ if (!selectedFiles.has(outputPath)) {
122
+ selectedFiles.set(outputPath, pageSourceFile);
123
+ }
124
+ }
125
+ return [...selectedFiles.values()];
126
+ };
127
+ const resolvePageSourceFileForPath = (pathname, pageSourceRootDir, hasPagesSourceDir) => {
128
+ const outputCandidates = pathname === "/" ? ["index.html"] : (() => {
129
+ const trimmedPath = pathname.replace(/^\/+/, "").replace(/\/+$/, "");
130
+ if (trimmedPath.length === 0) {
131
+ return ["index.html"];
132
+ }
133
+ if (node_path.extname(trimmedPath)) {
134
+ return [trimmedPath];
135
+ }
136
+ return [`${trimmedPath}.html`, `${trimmedPath}/index.html`];
137
+ })();
138
+ if (!hasPagesSourceDir) {
139
+ return outputCandidates.includes("index.html") ? resolvePreferredPageSourceForOutputPath("index.html", pageSourceRootDir) : null;
140
+ }
141
+ for (const outputCandidate of outputCandidates) {
142
+ const sourceFile = resolvePreferredPageSourceForOutputPath(
143
+ outputCandidate,
144
+ pageSourceRootDir
145
+ );
146
+ if (sourceFile) {
147
+ return sourceFile;
148
+ }
149
+ }
150
+ return null;
151
+ };
152
+ const filePathToRoute = (filePath, config, cwd) => {
153
+ const paths = resolveSsgPaths(cwd, config);
154
+ const pageSourceRootDir = paths.hasPagesSourceDir && normalizePath(filePath).startsWith(
155
+ `${normalizePath(paths.pagesSourceDirAbsolute)}/`
156
+ ) ? paths.pagesSourceDirAbsolute : cwd;
157
+ let routePath = pageSourceFileToOutputPath(filePath, pageSourceRootDir);
158
+ routePath = normalizePath(routePath);
159
+ if (routePath === "index.html") {
160
+ return "/";
161
+ }
162
+ if (routePath.endsWith("/index.html")) {
163
+ routePath = routePath.slice(0, -"/index.html".length);
164
+ } else {
165
+ routePath = routePath.replace(/\.html$/i, "");
166
+ }
167
+ if (!routePath.startsWith("/")) {
168
+ routePath = `/${routePath}`;
169
+ }
170
+ return routePath;
171
+ };
172
+
173
+ exports.filePathToRoute = filePathToRoute;
174
+ exports.getPageSourceRootDir = getPageSourceRootDir;
175
+ exports.pageSourceFileToOutputPath = pageSourceFileToOutputPath;
176
+ exports.resolvePageSourceFileForPath = resolvePageSourceFileForPath;
177
+ exports.resolvePreferredPageSourceForOutputPath = resolvePreferredPageSourceForOutputPath;
178
+ exports.resolveSsgPaths = resolveSsgPaths;
179
+ exports.selectPreferredPageSourceFiles = selectPreferredPageSourceFiles;
@@ -0,0 +1,171 @@
1
+ import { existsSync } from 'node:fs';
2
+ import { join, relative, extname } from 'node:path';
3
+
4
+ const DEFAULT_PAGES_DIR = "pages";
5
+ const DEFAULT_COMPONENTS_DIR = "components";
6
+ const DEFAULT_ASSETS_DIR = "assets";
7
+ const COMPONENTS_SOURCE_ALIASES = [DEFAULT_COMPONENTS_DIR, "csr"];
8
+ const PAGE_SOURCE_EXTENSIONS = [".mdx", ".md", ".html"];
9
+ const normalizePath = (filePath) => filePath.replace(/\\/g, "/");
10
+ const isDefaultPath = (value, defaultValue) => normalizePath(value) === defaultValue;
11
+ const createSourceDirCandidates = (candidates) => {
12
+ const normalizedCandidates = candidates.map((candidate) => normalizePath(candidate));
13
+ const sourceCandidates = normalizedCandidates.map(
14
+ (candidate) => normalizePath(join("src", candidate))
15
+ );
16
+ return [.../* @__PURE__ */ new Set([...sourceCandidates, ...normalizedCandidates])];
17
+ };
18
+ const resolveSourceDir = (projectDir, candidates, fallback) => {
19
+ for (const candidate of candidates) {
20
+ if (existsSync(join(projectDir, candidate))) {
21
+ return candidate;
22
+ }
23
+ }
24
+ return normalizePath(fallback);
25
+ };
26
+ const getPageSourceExtensionPriority = (filePath) => {
27
+ const extension = extname(filePath).toLowerCase();
28
+ const index = PAGE_SOURCE_EXTENSIONS.indexOf(
29
+ extension
30
+ );
31
+ return index === -1 ? Number.MAX_SAFE_INTEGER : index;
32
+ };
33
+ const outputPathToSourceCandidates = (pageSourceRootDir, relativeOutputHtmlFilePath) => {
34
+ const sourceStem = normalizePath(relativeOutputHtmlFilePath).replace(
35
+ /\.html$/i,
36
+ ""
37
+ );
38
+ return PAGE_SOURCE_EXTENSIONS.map(
39
+ (extension) => join(pageSourceRootDir, `${sourceStem}${extension}`)
40
+ );
41
+ };
42
+ const resolveSsgPaths = (projectDir, config) => {
43
+ const pagesSourceDirCandidates = isDefaultPath(config.pages, DEFAULT_PAGES_DIR) ? createSourceDirCandidates([DEFAULT_PAGES_DIR]) : [normalizePath(config.pages)];
44
+ const componentsSourceDirCandidates = isDefaultPath(
45
+ config.components,
46
+ DEFAULT_COMPONENTS_DIR
47
+ ) ? createSourceDirCandidates(COMPONENTS_SOURCE_ALIASES) : [normalizePath(config.components)];
48
+ const assetsSourceDirCandidates = isDefaultPath(config.assets, DEFAULT_ASSETS_DIR) ? createSourceDirCandidates([DEFAULT_ASSETS_DIR]) : [normalizePath(config.assets)];
49
+ const pagesSourceDir = resolveSourceDir(
50
+ projectDir,
51
+ pagesSourceDirCandidates,
52
+ pagesSourceDirCandidates[0] ?? DEFAULT_PAGES_DIR
53
+ );
54
+ const componentsSourceDir = resolveSourceDir(
55
+ projectDir,
56
+ componentsSourceDirCandidates,
57
+ componentsSourceDirCandidates[0] ?? DEFAULT_COMPONENTS_DIR
58
+ );
59
+ const assetsSourceDir = resolveSourceDir(
60
+ projectDir,
61
+ assetsSourceDirCandidates,
62
+ assetsSourceDirCandidates[0] ?? DEFAULT_ASSETS_DIR
63
+ );
64
+ const pagesSourceDirAbsolute = join(projectDir, pagesSourceDir);
65
+ const componentsSourceDirAbsolute = join(projectDir, componentsSourceDir);
66
+ const assetsSourceDirAbsolute = join(projectDir, assetsSourceDir);
67
+ return {
68
+ pagesSourceDir,
69
+ pagesSourceDirAbsolute,
70
+ pagesSourceDirCandidates,
71
+ hasPagesSourceDir: existsSync(pagesSourceDirAbsolute),
72
+ componentsSourceDir,
73
+ componentsSourceDirAbsolute,
74
+ componentsSourceDirCandidates,
75
+ hasComponentsSourceDir: existsSync(componentsSourceDirAbsolute),
76
+ componentsPublicDir: normalizePath(config.components),
77
+ assetsSourceDir,
78
+ assetsSourceDirAbsolute,
79
+ assetsSourceDirCandidates,
80
+ hasAssetsSourceDir: existsSync(assetsSourceDirAbsolute),
81
+ assetsPublicDir: normalizePath(config.assets)
82
+ };
83
+ };
84
+ const getPageSourceRootDir = (projectDir, paths) => paths.hasPagesSourceDir ? paths.pagesSourceDirAbsolute : projectDir;
85
+ const pageSourceFileToOutputPath = (pageSourceFile, pageSourceRootDir) => {
86
+ const relativePagePath = relative(pageSourceRootDir, pageSourceFile).replace(
87
+ /\\/g,
88
+ "/"
89
+ );
90
+ return relativePagePath.replace(/\.(mdx|md)$/i, ".html");
91
+ };
92
+ const resolvePreferredPageSourceForOutputPath = (relativeOutputHtmlFilePath, pageSourceRootDir) => {
93
+ for (const candidate of outputPathToSourceCandidates(
94
+ pageSourceRootDir,
95
+ relativeOutputHtmlFilePath
96
+ )) {
97
+ if (existsSync(candidate)) {
98
+ return candidate;
99
+ }
100
+ }
101
+ return null;
102
+ };
103
+ const selectPreferredPageSourceFiles = (pageSourceFiles, pageSourceRootDir) => {
104
+ const selectedFiles = /* @__PURE__ */ new Map();
105
+ const sortedSourceFiles = [...pageSourceFiles].sort((left, right) => {
106
+ const leftOutputPath = pageSourceFileToOutputPath(left, pageSourceRootDir);
107
+ const rightOutputPath = pageSourceFileToOutputPath(right, pageSourceRootDir);
108
+ const outputPathCompare = leftOutputPath.localeCompare(rightOutputPath);
109
+ if (outputPathCompare !== 0) {
110
+ return outputPathCompare;
111
+ }
112
+ return getPageSourceExtensionPriority(left) - getPageSourceExtensionPriority(right);
113
+ });
114
+ for (const pageSourceFile of sortedSourceFiles) {
115
+ const outputPath = pageSourceFileToOutputPath(
116
+ pageSourceFile,
117
+ pageSourceRootDir
118
+ );
119
+ if (!selectedFiles.has(outputPath)) {
120
+ selectedFiles.set(outputPath, pageSourceFile);
121
+ }
122
+ }
123
+ return [...selectedFiles.values()];
124
+ };
125
+ const resolvePageSourceFileForPath = (pathname, pageSourceRootDir, hasPagesSourceDir) => {
126
+ const outputCandidates = pathname === "/" ? ["index.html"] : (() => {
127
+ const trimmedPath = pathname.replace(/^\/+/, "").replace(/\/+$/, "");
128
+ if (trimmedPath.length === 0) {
129
+ return ["index.html"];
130
+ }
131
+ if (extname(trimmedPath)) {
132
+ return [trimmedPath];
133
+ }
134
+ return [`${trimmedPath}.html`, `${trimmedPath}/index.html`];
135
+ })();
136
+ if (!hasPagesSourceDir) {
137
+ return outputCandidates.includes("index.html") ? resolvePreferredPageSourceForOutputPath("index.html", pageSourceRootDir) : null;
138
+ }
139
+ for (const outputCandidate of outputCandidates) {
140
+ const sourceFile = resolvePreferredPageSourceForOutputPath(
141
+ outputCandidate,
142
+ pageSourceRootDir
143
+ );
144
+ if (sourceFile) {
145
+ return sourceFile;
146
+ }
147
+ }
148
+ return null;
149
+ };
150
+ const filePathToRoute = (filePath, config, cwd) => {
151
+ const paths = resolveSsgPaths(cwd, config);
152
+ const pageSourceRootDir = paths.hasPagesSourceDir && normalizePath(filePath).startsWith(
153
+ `${normalizePath(paths.pagesSourceDirAbsolute)}/`
154
+ ) ? paths.pagesSourceDirAbsolute : cwd;
155
+ let routePath = pageSourceFileToOutputPath(filePath, pageSourceRootDir);
156
+ routePath = normalizePath(routePath);
157
+ if (routePath === "index.html") {
158
+ return "/";
159
+ }
160
+ if (routePath.endsWith("/index.html")) {
161
+ routePath = routePath.slice(0, -"/index.html".length);
162
+ } else {
163
+ routePath = routePath.replace(/\.html$/i, "");
164
+ }
165
+ if (!routePath.startsWith("/")) {
166
+ routePath = `/${routePath}`;
167
+ }
168
+ return routePath;
169
+ };
170
+
171
+ export { resolvePreferredPageSourceForOutputPath as a, resolvePageSourceFileForPath as b, filePathToRoute as f, getPageSourceRootDir as g, pageSourceFileToOutputPath as p, resolveSsgPaths as r, selectPreferredPageSourceFiles as s };
@@ -1,9 +1,10 @@
1
1
  import mdx from '@mdx-js/rollup';
2
- import { createServer } from 'vite';
2
+ import { createServer, mergeConfig } from 'vite';
3
3
  import defuss from 'defuss-vite';
4
- import { v as validateProjectDir, r as readConfig, f as defussSsg, o as registerEndpoints, l as initializeRpc, s as readIncomingBody, t as createWebRequest, k as handleRpcRequest, u as sendWebResponse } from './vite-DdJcWQGP.mjs';
4
+ import { v as validateProjectDir, r as readConfig, f as defussSsg, o as registerEndpoints, l as initializeRpc, s as readIncomingBody, t as createWebRequest, k as handleRpcRequest, u as sendWebResponse } from './vite-CSOGjlHB.mjs';
5
5
  import { existsSync } from 'node:fs';
6
6
  import { join } from 'node:path';
7
+ import process from 'node:process';
7
8
  import { express, startServer } from 'defuss-express';
8
9
 
9
10
  const dev = async ({
@@ -16,38 +17,43 @@ const dev = async ({
16
17
  const projectDirStatus = validateProjectDir(projectDir);
17
18
  if (projectDirStatus.code !== "OK") return projectDirStatus;
18
19
  const config = await readConfig(projectDir, debug);
19
- const server = await createServer({
20
- root: projectDir,
21
- configFile: false,
22
- appType: "custom",
23
- server: {
24
- host,
25
- port,
26
- watch: {
27
- ignored: [
28
- "**/node_modules/**",
29
- "**/dist/**",
30
- "**/.ssg-temp/**",
31
- "**/.endpoints/**",
32
- "**/.rpc/**"
20
+ const server = await createServer(
21
+ mergeConfig(
22
+ {
23
+ root: projectDir,
24
+ configFile: false,
25
+ appType: "custom",
26
+ server: {
27
+ host,
28
+ port,
29
+ watch: {
30
+ ignored: [
31
+ "**/node_modules/**",
32
+ "**/dist/**",
33
+ "**/.ssg-temp/**",
34
+ "**/.endpoints/**",
35
+ "**/.rpc/**"
36
+ ]
37
+ }
38
+ },
39
+ plugins: [
40
+ defuss({ enableJsxDevMode: true }),
41
+ mdx({
42
+ jsxImportSource: "defuss",
43
+ development: true,
44
+ remarkPlugins: config.remarkPlugins,
45
+ rehypePlugins: config.rehypePlugins
46
+ }),
47
+ ...defussSsg({
48
+ projectDir,
49
+ debug,
50
+ writeDevOutput
51
+ })
33
52
  ]
34
- }
35
- },
36
- plugins: [
37
- defuss({ enableJsxDevMode: true }),
38
- mdx({
39
- jsxImportSource: "defuss",
40
- development: true,
41
- remarkPlugins: config.remarkPlugins,
42
- rehypePlugins: config.rehypePlugins
43
- }),
44
- ...defussSsg({
45
- projectDir,
46
- debug,
47
- writeDevOutput
48
- })
49
- ]
50
- });
53
+ },
54
+ config.viteConfig ?? {}
55
+ )
56
+ );
51
57
  await server.listen(port);
52
58
  server.printUrls();
53
59
  return {
@@ -107,6 +113,7 @@ const createRpcHandler = () => {
107
113
  const serve = async ({
108
114
  projectDir,
109
115
  debug = false,
116
+ host,
110
117
  port = 3e3,
111
118
  workers = 1
112
119
  }) => {
@@ -133,6 +140,9 @@ const serve = async ({
133
140
  const rpcHandler = createRpcHandler();
134
141
  app.post?.("/rpc", rpcHandler);
135
142
  app.post?.("/rpc/schema", rpcHandler);
143
+ app.post?.("/rpc/upload", rpcHandler);
144
+ app.get?.("/rpc/upload/progress/:uploadId", rpcHandler);
145
+ app.head?.("/rpc/upload/:uploadId", rpcHandler);
136
146
  }
137
147
  const staticMiddleware = express.static?.(outputDir);
138
148
  if (staticMiddleware) {
@@ -140,6 +150,7 @@ const serve = async ({
140
150
  }
141
151
  try {
142
152
  await startServer(app, {
153
+ host,
143
154
  port,
144
155
  workers
145
156
  });
@@ -149,8 +160,12 @@ const serve = async ({
149
160
  message: error instanceof Error ? error.message : "Failed to start production server"
150
161
  };
151
162
  }
152
- console.log(`defuss-ssg production server running at http://localhost:${port}`);
153
- console.log(`Serving static output from ${outputDir}`);
163
+ if (typeof process.env.DEFUSS_WORKER_INDEX !== "string") {
164
+ console.log(
165
+ `defuss-ssg production server running at http://${host ?? "localhost"}:${port}`
166
+ );
167
+ console.log(`Serving static output from ${outputDir}`);
168
+ }
154
169
  return {
155
170
  code: "OK",
156
171
  message: `Serving ${outputDir}`
@@ -1,6 +1,6 @@
1
- import { PluginOption } from 'vite';
2
1
  import { Options as Options$7 } from 'remark-rehype';
3
2
  import { VNode } from 'defuss/server';
3
+ import { InlineConfig } from 'vite';
4
4
 
5
5
  // ## Interfaces
6
6
 
@@ -7721,6 +7721,7 @@ type Options = Options$1;
7721
7721
 
7722
7722
  type RemarkPlugins = Options["remarkPlugins"];
7723
7723
  type RehypePlugins = Options["rehypePlugins"];
7724
+ type ContainerRuntime = "docker" | "podman";
7724
7725
  type StatusCode = "OK" | "MISSING_PROJECT_DIR" | "MISSING_PACKAGE_JSON" | "MISSING_BUILD_OUTPUT" | "INVALID_JSON" | "UNSUPPORTED_PM" | "INSTALL_FAILED" | "INVALID_CONFIG" | "INVALID_PROJECT_DIR" | "PORT_IN_USE" | "SERVER_START_FAILED";
7725
7726
  type Status = {
7726
7727
  code: StatusCode;
@@ -7796,6 +7797,11 @@ interface ServeOptions {
7796
7797
  * The already-built project root to serve.
7797
7798
  */
7798
7799
  projectDir: string;
7800
+ /**
7801
+ * Public host for the production HTTP runtime.
7802
+ * Defaults to defuss-express' configured host.
7803
+ */
7804
+ host?: string;
7799
7805
  /**
7800
7806
  * Public port for the production HTTP runtime.
7801
7807
  * Defaults to 3000.
@@ -7823,6 +7829,44 @@ interface DefussSsgViteOptions {
7823
7829
  */
7824
7830
  writeDevOutput?: boolean;
7825
7831
  }
7832
+ interface ContentGlobOptions {
7833
+ /**
7834
+ * Directory the glob patterns are resolved from.
7835
+ * Defaults to the current working directory.
7836
+ */
7837
+ cwd?: string;
7838
+ /**
7839
+ * Directory used to derive public routes for matched page files.
7840
+ * Defaults to "pages".
7841
+ */
7842
+ pagesDir?: string;
7843
+ /**
7844
+ * Optional ignore globs passed through to fast-glob.
7845
+ */
7846
+ ignore?: string[];
7847
+ }
7848
+ interface ContentEntry {
7849
+ /**
7850
+ * Absolute file path on disk.
7851
+ */
7852
+ filePath: string;
7853
+ /**
7854
+ * Path relative to the glob `cwd`.
7855
+ */
7856
+ relativePath: string;
7857
+ /**
7858
+ * Route-friendly identifier without a leading slash.
7859
+ */
7860
+ slug: string;
7861
+ /**
7862
+ * Public route when the file lives under the configured pages directory.
7863
+ */
7864
+ route?: string;
7865
+ /**
7866
+ * Parsed YAML or TOML frontmatter.
7867
+ */
7868
+ meta: Record<string, unknown>;
7869
+ }
7826
7870
  type EndpointRouteMethod = "get" | "post" | "put" | "delete" | "patch" | "head" | "options" | "all";
7827
7871
  interface EndpointRouteContext {
7828
7872
  request: Request;
@@ -7905,9 +7949,16 @@ interface SsgConfig {
7905
7949
  * - `string`: path to a custom RPC file (relative to project root)
7906
7950
  */
7907
7951
  rpc?: string | boolean;
7952
+ /**
7953
+ * Optional override for containerized CLI commands.
7954
+ * When omitted, the CLI prefers Docker and falls back to Podman.
7955
+ */
7956
+ containerRuntime?: ContainerRuntime;
7957
+ /**
7958
+ * Optional Vite config merged into defuss-ssg's internal Vite config.
7959
+ * Use this to customize Vite behavior without replacing SSG defaults.
7960
+ */
7961
+ viteConfig?: InlineConfig;
7908
7962
  }
7909
7963
 
7910
- declare function defussSsg(options?: DefussSsgViteOptions): PluginOption[];
7911
-
7912
- export { defussSsg as p };
7913
- export type { BuildOptions as B, DevOptions as D, EndpointRouteContext as E, PluginFn as P, RehypePlugins as R, SsgConfig as S, Status as a, ServeOptions as b, EndpointRouteRegistrar as c, BuildMode as d, DefussSsgViteOptions as e, DevChangeKind as f, EndpointRouteMethod as g, EndpointRouteResponder as h, PluginFnPageDom as i, PluginFnPageHtml as j, PluginFnPageVdom as k, PluginFnPrePost as l, RemarkPlugins as m, SsgPlugin as n, StatusCode as o };
7964
+ export type { BuildOptions as B, ContainerRuntime as C, DevOptions as D, EndpointRouteContext as E, PluginFn as P, RehypePlugins as R, SsgConfig as S, Status as a, ServeOptions as b, EndpointRouteRegistrar as c, BuildMode as d, ContentEntry as e, ContentGlobOptions as f, DefussSsgViteOptions as g, DevChangeKind as h, EndpointRouteMethod as i, EndpointRouteResponder as j, PluginFnPageDom as k, PluginFnPageHtml as l, PluginFnPageVdom as m, PluginFnPrePost as n, RemarkPlugins as o, SsgPlugin as p, StatusCode as q };
@@ -1,6 +1,6 @@
1
- import { PluginOption } from 'vite';
2
1
  import { Options as Options$7 } from 'remark-rehype';
3
2
  import { VNode } from 'defuss/server';
3
+ import { InlineConfig } from 'vite';
4
4
 
5
5
  // ## Interfaces
6
6
 
@@ -7721,6 +7721,7 @@ type Options = Options$1;
7721
7721
 
7722
7722
  type RemarkPlugins = Options["remarkPlugins"];
7723
7723
  type RehypePlugins = Options["rehypePlugins"];
7724
+ type ContainerRuntime = "docker" | "podman";
7724
7725
  type StatusCode = "OK" | "MISSING_PROJECT_DIR" | "MISSING_PACKAGE_JSON" | "MISSING_BUILD_OUTPUT" | "INVALID_JSON" | "UNSUPPORTED_PM" | "INSTALL_FAILED" | "INVALID_CONFIG" | "INVALID_PROJECT_DIR" | "PORT_IN_USE" | "SERVER_START_FAILED";
7725
7726
  type Status = {
7726
7727
  code: StatusCode;
@@ -7796,6 +7797,11 @@ interface ServeOptions {
7796
7797
  * The already-built project root to serve.
7797
7798
  */
7798
7799
  projectDir: string;
7800
+ /**
7801
+ * Public host for the production HTTP runtime.
7802
+ * Defaults to defuss-express' configured host.
7803
+ */
7804
+ host?: string;
7799
7805
  /**
7800
7806
  * Public port for the production HTTP runtime.
7801
7807
  * Defaults to 3000.
@@ -7823,6 +7829,44 @@ interface DefussSsgViteOptions {
7823
7829
  */
7824
7830
  writeDevOutput?: boolean;
7825
7831
  }
7832
+ interface ContentGlobOptions {
7833
+ /**
7834
+ * Directory the glob patterns are resolved from.
7835
+ * Defaults to the current working directory.
7836
+ */
7837
+ cwd?: string;
7838
+ /**
7839
+ * Directory used to derive public routes for matched page files.
7840
+ * Defaults to "pages".
7841
+ */
7842
+ pagesDir?: string;
7843
+ /**
7844
+ * Optional ignore globs passed through to fast-glob.
7845
+ */
7846
+ ignore?: string[];
7847
+ }
7848
+ interface ContentEntry {
7849
+ /**
7850
+ * Absolute file path on disk.
7851
+ */
7852
+ filePath: string;
7853
+ /**
7854
+ * Path relative to the glob `cwd`.
7855
+ */
7856
+ relativePath: string;
7857
+ /**
7858
+ * Route-friendly identifier without a leading slash.
7859
+ */
7860
+ slug: string;
7861
+ /**
7862
+ * Public route when the file lives under the configured pages directory.
7863
+ */
7864
+ route?: string;
7865
+ /**
7866
+ * Parsed YAML or TOML frontmatter.
7867
+ */
7868
+ meta: Record<string, unknown>;
7869
+ }
7826
7870
  type EndpointRouteMethod = "get" | "post" | "put" | "delete" | "patch" | "head" | "options" | "all";
7827
7871
  interface EndpointRouteContext {
7828
7872
  request: Request;
@@ -7905,9 +7949,16 @@ interface SsgConfig {
7905
7949
  * - `string`: path to a custom RPC file (relative to project root)
7906
7950
  */
7907
7951
  rpc?: string | boolean;
7952
+ /**
7953
+ * Optional override for containerized CLI commands.
7954
+ * When omitted, the CLI prefers Docker and falls back to Podman.
7955
+ */
7956
+ containerRuntime?: ContainerRuntime;
7957
+ /**
7958
+ * Optional Vite config merged into defuss-ssg's internal Vite config.
7959
+ * Use this to customize Vite behavior without replacing SSG defaults.
7960
+ */
7961
+ viteConfig?: InlineConfig;
7908
7962
  }
7909
7963
 
7910
- declare function defussSsg(options?: DefussSsgViteOptions): PluginOption[];
7911
-
7912
- export { defussSsg as p };
7913
- export type { BuildOptions as B, DevOptions as D, EndpointRouteContext as E, PluginFn as P, RehypePlugins as R, SsgConfig as S, Status as a, ServeOptions as b, EndpointRouteRegistrar as c, BuildMode as d, DefussSsgViteOptions as e, DevChangeKind as f, EndpointRouteMethod as g, EndpointRouteResponder as h, PluginFnPageDom as i, PluginFnPageHtml as j, PluginFnPageVdom as k, PluginFnPrePost as l, RemarkPlugins as m, SsgPlugin as n, StatusCode as o };
7964
+ export type { BuildOptions as B, ContainerRuntime as C, DevOptions as D, EndpointRouteContext as E, PluginFn as P, RehypePlugins as R, SsgConfig as S, Status as a, ServeOptions as b, EndpointRouteRegistrar as c, BuildMode as d, ContentEntry as e, ContentGlobOptions as f, DefussSsgViteOptions as g, DevChangeKind as h, EndpointRouteMethod as i, EndpointRouteResponder as j, PluginFnPageDom as k, PluginFnPageHtml as l, PluginFnPageVdom as m, PluginFnPrePost as n, RemarkPlugins as o, SsgPlugin as p, StatusCode as q };