@rawsql-ts/ddl-docs-vitepress 0.2.1

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/README.md ADDED
@@ -0,0 +1,105 @@
1
+ # @rawsql-ts/ddl-docs-vitepress
2
+
3
+ A scaffold generator for VitePress-based database schema documentation sites.
4
+
5
+ This package provides the `ddl-docs-vitepress init` command, which creates a ready-to-use project template that:
6
+
7
+ - reads SQL files from `ddl/`
8
+ - generates Markdown docs via `@rawsql-ts/ddl-docs-cli`
9
+ - serves/builds a VitePress site from `docs/`
10
+
11
+ ## Generated project structure
12
+
13
+ ```
14
+ my-db-docs/
15
+ ├── .github/workflows/deploy-docs.yml # GitHub Pages deploy workflow
16
+ ├── .gitignore
17
+ ├── ddl/.gitkeep # Place your .sql files here
18
+ ├── docs/
19
+ │ ├── index.md
20
+ │ └── .vitepress/
21
+ │ ├── config.mts
22
+ │ └── theme/
23
+ │ ├── custom.css
24
+ │ └── index.ts
25
+ ├── package.json
26
+ └── scripts/run-generate.cjs # Calls ddl-docs-cli to generate Markdown
27
+ ```
28
+
29
+ ## Create a scaffold project
30
+
31
+ ```bash
32
+ npx @rawsql-ts/ddl-docs-vitepress init my-db-docs
33
+ cd my-db-docs
34
+ npm install
35
+ ```
36
+
37
+ ### Safe-by-default init behavior
38
+
39
+ - If target directory does not exist: scaffold is created.
40
+ - If target directory exists and is empty: scaffold is created.
41
+ - If target directory exists and is not empty: command fails by default.
42
+ - Use `--force` to overwrite template paths in a non-empty directory.
43
+ - `--force` is overwrite-only. It does not remove non-template files.
44
+ - Use `--force --clean` to remove non-template files before scaffolding.
45
+
46
+ ```bash
47
+ npx @rawsql-ts/ddl-docs-vitepress init existing-dir --force
48
+ npx @rawsql-ts/ddl-docs-vitepress init existing-dir --force --clean
49
+ ```
50
+
51
+ Warning: `--clean` removes non-template files and directories in the target path.
52
+
53
+ ### Help
54
+
55
+ ```bash
56
+ npx @rawsql-ts/ddl-docs-vitepress --help
57
+ npx @rawsql-ts/ddl-docs-vitepress help
58
+ npx @rawsql-ts/ddl-docs-vitepress init --help
59
+ ```
60
+
61
+ ## Use the generated scaffold project
62
+
63
+ In the generated project:
64
+
65
+ 1. Put your `.sql` files under `ddl/`.
66
+ The build script applies `--filter-pg-dump` automatically, so `pg_dump` output can be used directly — statements such as `SET`, `ALTER ... OWNER TO`, and `SELECT pg_catalog.*` are filtered out before parsing.
67
+ 2. Start local development:
68
+
69
+ ```bash
70
+ npm run dev
71
+ ```
72
+
73
+ 3. Build static docs:
74
+
75
+ ```bash
76
+ npm run build
77
+ ```
78
+
79
+ 4. Preview the built site:
80
+
81
+ ```bash
82
+ npm run preview
83
+ ```
84
+
85
+ ### GitHub Pages deployment
86
+
87
+ The scaffold includes `.github/workflows/deploy-docs.yml` which automatically builds and deploys docs to GitHub Pages on pushes to `main` that touch `ddl/` or `docs/.vitepress/`. The workflow sets `VITEPRESS_BASE` from the repository name.
88
+
89
+ To enable it, go to your repository's **Settings > Pages** and set the source to **GitHub Actions**.
90
+
91
+ ### `VITEPRESS_BASE` for subpath hosting
92
+
93
+ The scaffold template uses `process.env.VITEPRESS_BASE ?? '/'` in `docs/.vitepress/config.mts`.
94
+ Set `VITEPRESS_BASE` when deploying under a subpath (for example GitHub Pages):
95
+
96
+ ```bash
97
+ VITEPRESS_BASE=/my-repo/ npm run build
98
+ ```
99
+
100
+ ## Scripts in this package (maintainer note)
101
+
102
+ In `packages/ddl-docs-vitepress` itself:
103
+
104
+ - `pnpm build` compiles this CLI package with `tsc`.
105
+ - It does **not** build the generated VitePress docs site.
package/dist/cli.d.ts ADDED
@@ -0,0 +1 @@
1
+ export declare function runCli(argv: string[]): Promise<void>;
package/dist/cli.js ADDED
@@ -0,0 +1,253 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.runCli = runCli;
7
+ const node_path_1 = __importDefault(require("node:path"));
8
+ const node_fs_1 = __importDefault(require("node:fs"));
9
+ const TEMPLATE_GITIGNORE = 'gitignore';
10
+ const TARGET_GITIGNORE = '.gitignore';
11
+ const CLEAN_PREVIEW_LIMIT = 5;
12
+ async function runCli(argv) {
13
+ const [command, ...rest] = argv;
14
+ if (!command || command === '--help' || command === '-h') {
15
+ printGlobalHelp();
16
+ return;
17
+ }
18
+ if (command === 'help') {
19
+ const target = rest[0];
20
+ if (target === 'init') {
21
+ printInitHelp();
22
+ return;
23
+ }
24
+ if (target) {
25
+ throw new Error(`Unknown command for help: ${target}`);
26
+ }
27
+ printGlobalHelp();
28
+ return;
29
+ }
30
+ if (command === 'init') {
31
+ await runInit(rest);
32
+ return;
33
+ }
34
+ throw new Error(`Unknown command: ${command}`);
35
+ }
36
+ async function runInit(args) {
37
+ let targetDir = '.';
38
+ let force = false;
39
+ let clean = false;
40
+ let targetProvided = false;
41
+ for (let index = 0; index < args.length; index += 1) {
42
+ const arg = args[index];
43
+ if (arg === '--help' || arg === '-h') {
44
+ printInitHelp();
45
+ return;
46
+ }
47
+ if (arg === '--force') {
48
+ force = true;
49
+ continue;
50
+ }
51
+ if (arg === '--clean') {
52
+ clean = true;
53
+ continue;
54
+ }
55
+ if (!arg.startsWith('--')) {
56
+ if (targetProvided) {
57
+ throw new Error(`Only one target directory is allowed. Received extra argument: ${arg}`);
58
+ }
59
+ targetDir = arg;
60
+ targetProvided = true;
61
+ continue;
62
+ }
63
+ throw new Error(`Unknown option for init: ${arg}`);
64
+ }
65
+ if (clean && !force) {
66
+ throw new Error('Option --clean requires --force. Use: init <targetDir> --force --clean');
67
+ }
68
+ const resolvedTarget = node_path_1.default.resolve(targetDir);
69
+ const templatesDir = node_path_1.default.join(__dirname, '..', 'templates');
70
+ if (!node_fs_1.default.existsSync(templatesDir)) {
71
+ throw new Error(`Templates directory not found: ${templatesDir}`);
72
+ }
73
+ const layout = collectTemplateLayout(templatesDir);
74
+ if (node_fs_1.default.existsSync(resolvedTarget)) {
75
+ if (!node_fs_1.default.statSync(resolvedTarget).isDirectory()) {
76
+ throw new Error(`Target path is not a directory: ${resolvedTarget}`);
77
+ }
78
+ // Protect existing projects from accidental overwrite unless --force is explicit.
79
+ const existingEntries = node_fs_1.default.readdirSync(resolvedTarget);
80
+ if (existingEntries.length > 0 && !force) {
81
+ throw new Error(`Target directory is not empty: ${resolvedTarget}. Use --force to overwrite existing files.`);
82
+ }
83
+ }
84
+ else {
85
+ node_fs_1.default.mkdirSync(resolvedTarget, { recursive: true });
86
+ }
87
+ const existingEntries = node_fs_1.default.readdirSync(resolvedTarget);
88
+ let deleted = 0;
89
+ if (clean && existingEntries.length > 0) {
90
+ const removedPaths = pruneNonTemplatePaths(resolvedTarget, layout);
91
+ deleted = removedPaths.length;
92
+ }
93
+ const { created, overwritten } = applyTemplate(resolvedTarget, templatesDir, layout);
94
+ console.log(`Scaffold created at: ${resolvedTarget}`);
95
+ console.log(`Summary: created=${created}, overwritten=${overwritten}, deleted=${deleted}`);
96
+ console.log('');
97
+ console.log('Next steps:');
98
+ console.log(` cd ${targetDir}`);
99
+ console.log(' npm install');
100
+ console.log(' # Add your .sql files to ddl/');
101
+ console.log(' npm run dev');
102
+ }
103
+ function printGlobalHelp() {
104
+ console.log(`ddl-docs-vitepress <command> [options]
105
+
106
+ Commands:
107
+ init [targetDir] Scaffold a new DDL docs VitePress project (default: current directory)
108
+ help [command] Show global help or command help
109
+
110
+ Options:
111
+ --help, -h Show this help message
112
+
113
+ Init options:
114
+ --force Overwrite template output paths in a non-empty directory (no deletion)
115
+ --clean Delete non-template files before scaffolding (requires --force)
116
+
117
+ Examples:
118
+ ddl-docs-vitepress init my-db-docs
119
+ ddl-docs-vitepress init existing-dir --force
120
+ ddl-docs-vitepress init existing-dir --force --clean
121
+ ddl-docs-vitepress help init
122
+ `);
123
+ }
124
+ function printInitHelp() {
125
+ console.log(`ddl-docs-vitepress init [targetDir] [options]
126
+
127
+ Options:
128
+ --force Overwrite template output paths in a non-empty directory (does not delete other files)
129
+ --clean Delete non-template files before scaffolding (requires --force)
130
+ --help, -h Show init help
131
+
132
+ Examples:
133
+ ddl-docs-vitepress init docs-site
134
+ ddl-docs-vitepress init docs-site --force
135
+ ddl-docs-vitepress init docs-site --force --clean
136
+ `);
137
+ }
138
+ function collectTemplateLayout(templatesDir) {
139
+ const files = [];
140
+ const directories = new Set();
141
+ walkTemplateTree(templatesDir, '', files, directories);
142
+ const mappedFiles = files.map(mapTemplateRelativePath);
143
+ const mappedDirectories = Array.from(directories).map(mapTemplateRelativePath);
144
+ // Include parent directories for mapped files such as ".gitignore".
145
+ for (const filePath of mappedFiles) {
146
+ let current = node_path_1.default.dirname(filePath);
147
+ while (current && current !== '.') {
148
+ mappedDirectories.push(current);
149
+ current = node_path_1.default.dirname(current);
150
+ }
151
+ }
152
+ return {
153
+ files: mappedFiles,
154
+ directories: Array.from(new Set(mappedDirectories)),
155
+ };
156
+ }
157
+ function walkTemplateTree(rootDir, currentRelative, files, directories) {
158
+ const currentDir = currentRelative ? node_path_1.default.join(rootDir, currentRelative) : rootDir;
159
+ const entries = node_fs_1.default.readdirSync(currentDir, { withFileTypes: true });
160
+ for (const entry of entries) {
161
+ const relativePath = currentRelative ? node_path_1.default.join(currentRelative, entry.name) : entry.name;
162
+ if (entry.isDirectory()) {
163
+ directories.add(relativePath);
164
+ walkTemplateTree(rootDir, relativePath, files, directories);
165
+ continue;
166
+ }
167
+ files.push(relativePath);
168
+ }
169
+ }
170
+ function mapTemplateRelativePath(relativePath) {
171
+ if (relativePath === TEMPLATE_GITIGNORE) {
172
+ return TARGET_GITIGNORE;
173
+ }
174
+ return relativePath;
175
+ }
176
+ function collectTargetEntries(targetDir) {
177
+ const entries = [];
178
+ walkTargetTree(targetDir, '', entries);
179
+ return entries;
180
+ }
181
+ function walkTargetTree(rootDir, currentRelative, entries) {
182
+ const currentDir = currentRelative ? node_path_1.default.join(rootDir, currentRelative) : rootDir;
183
+ const currentEntries = node_fs_1.default.readdirSync(currentDir, { withFileTypes: true });
184
+ for (const entry of currentEntries) {
185
+ const relativePath = currentRelative ? node_path_1.default.join(currentRelative, entry.name) : entry.name;
186
+ if (entry.isDirectory()) {
187
+ entries.push({ relativePath, isDirectory: true });
188
+ walkTargetTree(rootDir, relativePath, entries);
189
+ continue;
190
+ }
191
+ entries.push({ relativePath, isDirectory: false });
192
+ }
193
+ }
194
+ function pruneNonTemplatePaths(targetDir, layout) {
195
+ const expectedPaths = new Set([...layout.files, ...layout.directories]);
196
+ const existingEntries = collectTargetEntries(targetDir);
197
+ const pathsToDelete = existingEntries
198
+ .filter((entry) => shouldDeleteEntry(entry, expectedPaths))
199
+ .sort((left, right) => getPathDepth(right.relativePath) - getPathDepth(left.relativePath))
200
+ .map((entry) => entry.relativePath);
201
+ console.log(`Clean mode: removing ${pathsToDelete.length} non-template path(s) from ${targetDir}`);
202
+ for (const relativePath of pathsToDelete.slice(0, CLEAN_PREVIEW_LIMIT)) {
203
+ console.log(` - ${relativePath}`);
204
+ }
205
+ if (pathsToDelete.length > CLEAN_PREVIEW_LIMIT) {
206
+ console.log(` ... and ${pathsToDelete.length - CLEAN_PREVIEW_LIMIT} more`);
207
+ }
208
+ for (const relativePath of pathsToDelete) {
209
+ node_fs_1.default.rmSync(node_path_1.default.join(targetDir, relativePath), { recursive: true, force: true });
210
+ }
211
+ return pathsToDelete;
212
+ }
213
+ function shouldDeleteEntry(entry, expectedPaths) {
214
+ if (expectedPaths.has(entry.relativePath)) {
215
+ return false;
216
+ }
217
+ // Keep parent directories when expected descendants exist under them.
218
+ if (entry.isDirectory) {
219
+ const directoryPrefix = `${entry.relativePath}${node_path_1.default.sep}`;
220
+ for (const expectedPath of expectedPaths) {
221
+ if (expectedPath.startsWith(directoryPrefix)) {
222
+ return false;
223
+ }
224
+ }
225
+ }
226
+ return true;
227
+ }
228
+ function getPathDepth(relativePath) {
229
+ return relativePath.split(node_path_1.default.sep).length;
230
+ }
231
+ function applyTemplate(targetDir, templatesDir, layout) {
232
+ let created = 0;
233
+ let overwritten = 0;
234
+ const sortedDirectories = [...layout.directories].sort((left, right) => left.length - right.length);
235
+ for (const directory of sortedDirectories) {
236
+ const targetDirectory = node_path_1.default.join(targetDir, directory);
237
+ node_fs_1.default.mkdirSync(targetDirectory, { recursive: true });
238
+ }
239
+ for (const relativePath of layout.files) {
240
+ const templateRelativePath = relativePath === TARGET_GITIGNORE ? TEMPLATE_GITIGNORE : relativePath;
241
+ const sourcePath = node_path_1.default.join(templatesDir, templateRelativePath);
242
+ const targetPath = node_path_1.default.join(targetDir, relativePath);
243
+ if (node_fs_1.default.existsSync(targetPath)) {
244
+ overwritten += 1;
245
+ }
246
+ else {
247
+ created += 1;
248
+ }
249
+ node_fs_1.default.copyFileSync(sourcePath, targetPath);
250
+ }
251
+ return { created, overwritten };
252
+ }
253
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
package/dist/index.js ADDED
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ const cli_1 = require("./cli");
5
+ (0, cli_1.runCli)(process.argv.slice(2)).catch((error) => {
6
+ console.error(error instanceof Error ? error.message : error);
7
+ process.exit(1);
8
+ });
9
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAEA,+BAA+B;AAE/B,IAAA,YAAM,EAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;IAC5C,OAAO,CAAC,KAAK,CAAC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;IAC9D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
package/package.json ADDED
@@ -0,0 +1,46 @@
1
+ {
2
+ "name": "@rawsql-ts/ddl-docs-vitepress",
3
+ "version": "0.2.1",
4
+ "description": "Scaffold generator for VitePress-based DB schema docs powered by ddl-docs-cli",
5
+ "main": "dist/index.js",
6
+ "bin": {
7
+ "ddl-docs-vitepress": "dist/index.js"
8
+ },
9
+ "scripts": {
10
+ "prepack": "node ./scripts/prepack.cjs",
11
+ "build": "tsc -p tsconfig.json",
12
+ "test": "vitest run packages/ddl-docs-vitepress/tests",
13
+ "generate": "node ./scripts/run-generate.cjs",
14
+ "dev": "pnpm generate && vitepress dev docs",
15
+ "preview": "vitepress preview docs"
16
+ },
17
+ "keywords": [
18
+ "rawsql-ts",
19
+ "ddl",
20
+ "vitepress",
21
+ "docs",
22
+ "scaffold",
23
+ "cli"
24
+ ],
25
+ "author": "msugiura",
26
+ "license": "MIT",
27
+ "publishConfig": {
28
+ "access": "public"
29
+ },
30
+ "engines": {
31
+ "node": ">=20"
32
+ },
33
+ "files": [
34
+ "dist",
35
+ "templates",
36
+ "README.md"
37
+ ],
38
+ "dependencies": {
39
+ "@rawsql-ts/ddl-docs-cli": "workspace:^"
40
+ },
41
+ "devDependencies": {
42
+ "@types/node": "^22.13.10",
43
+ "typescript": "^5.8.2",
44
+ "vitest": "^4.0.7"
45
+ }
46
+ }
@@ -0,0 +1,53 @@
1
+ name: Deploy Docs
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ paths:
7
+ - 'ddl/**'
8
+ - 'docs/**'
9
+ - 'docs/.vitepress/**'
10
+ workflow_dispatch:
11
+
12
+ permissions:
13
+ contents: read
14
+
15
+ concurrency:
16
+ group: pages
17
+ cancel-in-progress: true
18
+
19
+ jobs:
20
+ build:
21
+ runs-on: ubuntu-latest
22
+ steps:
23
+ - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5
24
+
25
+ - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020
26
+ with:
27
+ node-version: 20
28
+
29
+ - name: Install dependencies
30
+ run: npm ci
31
+
32
+ - name: Generate and build docs
33
+ env:
34
+ VITEPRESS_BASE: /${{ github.event.repository.name }}/
35
+ run: npm run build
36
+
37
+ - uses: actions/upload-pages-artifact@56afc609e74202658d3ffba0e8f6dda462b719fa
38
+ with:
39
+ path: docs/.vitepress/dist
40
+
41
+ deploy:
42
+ needs: build
43
+ runs-on: ubuntu-latest
44
+ permissions:
45
+ pages: write
46
+ id-token: write
47
+ environment:
48
+ name: github-pages
49
+ url: ${{ steps.deployment.outputs.page_url }}
50
+ steps:
51
+ - name: Deploy to GitHub Pages
52
+ id: deployment
53
+ uses: actions/deploy-pages@d6db90164ac5ed86f2b6aed7e0febac5b3c0c03e
File without changes
@@ -0,0 +1,12 @@
1
+ import { defineConfig } from 'vitepress'
2
+
3
+ export default defineConfig({
4
+ title: 'DB Schema Docs',
5
+ description: 'Database schema documentation generated from DDL',
6
+ base: process.env.VITEPRESS_BASE ?? '/',
7
+ srcDir: '.',
8
+ themeConfig: {
9
+ search: { provider: 'local' },
10
+ aside: false,
11
+ },
12
+ })
@@ -0,0 +1,13 @@
1
+ .VPDoc .container,
2
+ .VPDoc .content-container,
3
+ .VPDoc .content {
4
+ max-width: none !important;
5
+ width: 100% !important;
6
+ }
7
+
8
+ .VPNavBar .wrapper,
9
+ .VPNavBar .container {
10
+ max-width: none !important;
11
+ margin-left: 0 !important;
12
+ padding-left: 16px !important;
13
+ }
@@ -0,0 +1,4 @@
1
+ import DefaultTheme from 'vitepress/theme'
2
+ import './custom.css'
3
+
4
+ export default DefaultTheme
@@ -0,0 +1,31 @@
1
+ ---
2
+ layout: home
3
+
4
+ hero:
5
+ name: DB Schema Docs
6
+ text: Database schema documentation
7
+ tagline: Generated automatically from DDL files
8
+ actions:
9
+ - theme: brand
10
+ text: Browse Tables
11
+ link: /tables/
12
+
13
+ features:
14
+ - title: DDL-driven
15
+ details: Place your .sql files in the ddl/ directory and documentation is generated automatically.
16
+ - title: Always up to date
17
+ details: Run npm run dev or npm run build to regenerate docs from the latest DDL.
18
+ - title: Searchable
19
+ details: Full-text search across all table and column documentation.
20
+ ---
21
+
22
+ ## Getting Started
23
+
24
+ 1. Add your DDL files to the `ddl/` directory.
25
+ 2. Run `npm run dev` to start the documentation site.
26
+
27
+ ```bash
28
+ npm run dev
29
+ ```
30
+
31
+ The `generate` step runs automatically before the dev server or build starts.
@@ -0,0 +1,4 @@
1
+ docs/tables/
2
+ docs/.vitepress/dist/
3
+ docs/.vitepress/cache/
4
+ node_modules/
@@ -0,0 +1,18 @@
1
+ {
2
+ "name": "db-docs",
3
+ "version": "0.1.0",
4
+ "private": true,
5
+ "scripts": {
6
+ "generate": "node ./scripts/run-generate.cjs",
7
+ "dev": "node ./scripts/run-generate.cjs && vitepress dev docs",
8
+ "build": "node ./scripts/run-generate.cjs && vitepress build docs",
9
+ "preview": "vitepress preview docs"
10
+ },
11
+ "devDependencies": {
12
+ "@rawsql-ts/ddl-docs-cli": "^0.1.0",
13
+ "vitepress": "^1.6.4"
14
+ },
15
+ "engines": {
16
+ "node": ">=20"
17
+ }
18
+ }
@@ -0,0 +1,39 @@
1
+ const { readdirSync, existsSync } = require("node:fs");
2
+ const { spawnSync } = require("node:child_process");
3
+
4
+ const ddlDir = "ddl";
5
+
6
+ let cliEntry;
7
+ try {
8
+ cliEntry = require.resolve("@rawsql-ts/ddl-docs-cli");
9
+ } catch {
10
+ console.error("@rawsql-ts/ddl-docs-cli is not installed. Run: npm install");
11
+ process.exit(1);
12
+ }
13
+
14
+ const hasSqlInputs =
15
+ existsSync(ddlDir) &&
16
+ readdirSync(ddlDir, { recursive: true }).some(
17
+ (entry) => typeof entry === "string" && entry.endsWith(".sql"),
18
+ );
19
+
20
+ if (!hasSqlInputs) {
21
+ console.log("No SQL files found in ddl/. Skipping ddl-docs generation.");
22
+ process.exit(0);
23
+ }
24
+
25
+ const args = [
26
+ cliEntry,
27
+ "generate",
28
+ "--ddl-dir",
29
+ "ddl",
30
+ "--out-dir",
31
+ "docs/tables",
32
+ "--label-separator",
33
+ " :",
34
+ // Accept pg_dump output directly by filtering admin-only statements first.
35
+ "--filter-pg-dump",
36
+ ];
37
+
38
+ const result = spawnSync(process.execPath, args, { stdio: "inherit" });
39
+ process.exit(result.status ?? 1);