@clidey/dory 0.23.0 โ†’ 0.24.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,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=dory.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dory.d.ts","sourceRoot":"","sources":["../dory.ts"],"names":[],"mappings":""}
@@ -0,0 +1,337 @@
1
+ #!/usr/bin/env node
2
+ import { execSync } from 'child_process';
3
+ import { existsSync, rmSync, mkdirSync, cpSync, readFileSync, readdirSync } from 'fs';
4
+ import { resolve, dirname } from 'path';
5
+ import { fileURLToPath } from 'url';
6
+ import { createServer } from 'http';
7
+ import sirv from 'sirv';
8
+ const __filename = fileURLToPath(import.meta.url);
9
+ const __dirname = dirname(__filename);
10
+ // Get the root directory of the Dory package
11
+ const getDoryRoot = () => {
12
+ // In development: bin/dory.ts -> root is parent
13
+ // In production: bin/dist/dory.js -> root is parent of parent
14
+ const isDevelopment = __dirname.endsWith('bin');
15
+ return isDevelopment ? resolve(__dirname, '..') : resolve(__dirname, '..', '..');
16
+ };
17
+ // Get the user's current working directory
18
+ const getUserRoot = () => process.cwd();
19
+ const validateDoryConfig = (config) => {
20
+ if (!config || typeof config !== 'object') {
21
+ throw new Error('Configuration must be a valid object');
22
+ }
23
+ // Add more validation as needed
24
+ };
25
+ const commands = {
26
+ build: () => {
27
+ console.log('๐ŸŸ Dory is ready to build your docs!');
28
+ const userRoot = getUserRoot();
29
+ const doryRoot = getDoryRoot();
30
+ const doryConfigPath = resolve(userRoot, 'dory.json');
31
+ const tempDocsDir = resolve(doryRoot, 'docs');
32
+ const doryDistDir = resolve(doryRoot, 'dist');
33
+ const userDistDir = resolve(userRoot, 'dist');
34
+ // Step 1: Validate prerequisites before making any changes
35
+ console.log('๐Ÿ” Validating project structure...');
36
+ if (!existsSync(doryConfigPath)) {
37
+ console.error('โŒ dory.json not found in current directory');
38
+ console.error(` Looking for: ${doryConfigPath}`);
39
+ console.error(' Create a dory.json file to configure your documentation site');
40
+ process.exit(1);
41
+ }
42
+ // Read and validate dory.json
43
+ let config;
44
+ try {
45
+ const configContent = readFileSync(doryConfigPath, 'utf8');
46
+ config = JSON.parse(configContent);
47
+ validateDoryConfig(config);
48
+ console.log(`๐Ÿ“‹ Building: ${config.name || 'Documentation'}`);
49
+ }
50
+ catch (error) {
51
+ console.error('โŒ Failed to parse dory.json:');
52
+ if (error instanceof Error) {
53
+ console.error(` ${error.message}`);
54
+ }
55
+ process.exit(1);
56
+ }
57
+ // Check if pnpm is available
58
+ try {
59
+ execSync('pnpm --version', { stdio: 'ignore' });
60
+ }
61
+ catch {
62
+ console.error('โŒ pnpm is not installed');
63
+ console.error(' Install it with: npm install -g pnpm');
64
+ process.exit(1);
65
+ }
66
+ // Step 2: Clean up temp directories
67
+ console.log('๐Ÿงน Preparing workspace...');
68
+ if (existsSync(tempDocsDir)) {
69
+ rmSync(tempDocsDir, { recursive: true, force: true });
70
+ }
71
+ try {
72
+ // Step 3: Copy user files to temp docs directory
73
+ mkdirSync(tempDocsDir, { recursive: true });
74
+ console.log('๐Ÿ“ Gathering project files...');
75
+ // Define files/dirs to exclude
76
+ const excludeItems = new Set([
77
+ 'node_modules',
78
+ 'dist',
79
+ '.git',
80
+ '.github',
81
+ 'docs',
82
+ '.DS_Store',
83
+ '.env',
84
+ '.env.local',
85
+ 'pnpm-lock.yaml',
86
+ 'package-lock.json',
87
+ 'yarn.lock'
88
+ ]);
89
+ const items = readdirSync(userRoot);
90
+ let copiedCount = 0;
91
+ for (const item of items) {
92
+ if (excludeItems.has(item)) {
93
+ continue;
94
+ }
95
+ const srcPath = resolve(userRoot, item);
96
+ const destPath = resolve(tempDocsDir, item);
97
+ try {
98
+ cpSync(srcPath, destPath, { recursive: true, force: true });
99
+ copiedCount++;
100
+ }
101
+ catch (error) {
102
+ console.warn(`โš ๏ธ Could not copy ${item}: ${error instanceof Error ? error.message : 'unknown error'}`);
103
+ }
104
+ }
105
+ console.log(`โœ… Copied ${copiedCount} items`);
106
+ // Step 4: Run the build
107
+ console.log('โšก Building documentation...');
108
+ try {
109
+ execSync('pnpm run build', {
110
+ stdio: 'inherit',
111
+ cwd: doryRoot,
112
+ env: { ...process.env }
113
+ });
114
+ }
115
+ catch (error) {
116
+ console.error('โŒ Build failed');
117
+ console.error(' Check the error messages above for details');
118
+ throw error;
119
+ }
120
+ // Step 5: Verify build output
121
+ console.log('๐Ÿ” Verifying build output...');
122
+ if (!existsSync(doryDistDir)) {
123
+ console.error('โŒ Build completed but dist folder was not created');
124
+ console.error(` Expected: ${doryDistDir}`);
125
+ process.exit(1);
126
+ }
127
+ const indexHtml = resolve(doryDistDir, 'index.html');
128
+ if (!existsSync(indexHtml)) {
129
+ console.error('โŒ Build incomplete: index.html not found');
130
+ console.error(' The build may have failed silently');
131
+ process.exit(1);
132
+ }
133
+ // Check if dist has content
134
+ const distFiles = readdirSync(doryDistDir);
135
+ if (distFiles.length === 0) {
136
+ console.error('โŒ Build completed but dist folder is empty');
137
+ process.exit(1);
138
+ }
139
+ console.log('๐ŸŽ‰ Build completed successfully!');
140
+ // Step 6: Copy dist to user's directory
141
+ console.log('๐Ÿ“ฆ Copying build output...');
142
+ // Only copy if they're different directories
143
+ if (doryDistDir !== userDistDir) {
144
+ if (existsSync(userDistDir)) {
145
+ rmSync(userDistDir, { recursive: true, force: true });
146
+ }
147
+ cpSync(doryDistDir, userDistDir, { recursive: true, force: true });
148
+ }
149
+ console.log('โœจ Documentation ready in dist/');
150
+ }
151
+ finally {
152
+ // Step 7: Always clean up temp directories
153
+ console.log('๐Ÿงน Cleaning up...');
154
+ try {
155
+ if (existsSync(tempDocsDir)) {
156
+ rmSync(tempDocsDir, { recursive: true, force: true });
157
+ }
158
+ // Only clean up doryDistDir if it's different from userDistDir
159
+ // (in production they're different, in dev they might be the same)
160
+ if (doryDistDir !== userDistDir && existsSync(doryDistDir)) {
161
+ rmSync(doryDistDir, { recursive: true, force: true });
162
+ }
163
+ }
164
+ catch (error) {
165
+ console.warn('โš ๏ธ Could not clean up temp directories');
166
+ }
167
+ console.log('โœ… Done!');
168
+ }
169
+ },
170
+ preview: () => {
171
+ console.log('๐Ÿ‘€ Starting docs preview...');
172
+ const userRoot = getUserRoot();
173
+ const distDir = resolve(userRoot, 'dist');
174
+ let port = parseInt(process.env.PORT || '3000', 10);
175
+ // Validate dist folder exists
176
+ if (!existsSync(distDir)) {
177
+ console.error('โŒ dist folder not found');
178
+ console.error(` Looking for: ${distDir}`);
179
+ console.error(' Run "dory build" first to generate the documentation');
180
+ process.exit(1);
181
+ }
182
+ // Check if dist has content
183
+ const distFiles = readdirSync(distDir);
184
+ if (distFiles.length === 0) {
185
+ console.error('โŒ dist folder is empty');
186
+ console.error(' Run "dory build" to generate documentation');
187
+ process.exit(1);
188
+ }
189
+ const serve = sirv(distDir, {
190
+ dev: false,
191
+ single: true,
192
+ etag: true,
193
+ gzip: true,
194
+ brotli: true,
195
+ });
196
+ const server = createServer((req, res) => {
197
+ serve(req, res);
198
+ });
199
+ const tryPort = (currentPort) => {
200
+ server.listen(currentPort)
201
+ .on('listening', () => {
202
+ console.log(`๐Ÿš€ Documentation live at http://localhost:${currentPort}`);
203
+ console.log(' Press Ctrl+C to stop the server');
204
+ })
205
+ .on('error', (err) => {
206
+ if (err.code === 'EADDRINUSE') {
207
+ console.log(`โš ๏ธ Port ${currentPort} in use, trying ${currentPort + 1}...`);
208
+ tryPort(currentPort + 1);
209
+ }
210
+ else {
211
+ console.error('โŒ Failed to start server:', err.message);
212
+ process.exit(1);
213
+ }
214
+ });
215
+ };
216
+ tryPort(port);
217
+ },
218
+ 'verify:content': async () => {
219
+ const args = process.argv.slice(3);
220
+ let content = '';
221
+ let fileName = '';
222
+ // Parse arguments
223
+ for (let i = 0; i < args.length; i++) {
224
+ if (args[i] === '--content' && i + 1 < args.length) {
225
+ content = args[i + 1];
226
+ break;
227
+ }
228
+ else if (args[i] === '--file' && i + 1 < args.length) {
229
+ const filePath = resolve(getUserRoot(), args[i + 1]);
230
+ if (!existsSync(filePath)) {
231
+ console.error(`โŒ File not found: ${filePath}`);
232
+ process.exit(1);
233
+ }
234
+ content = readFileSync(filePath, 'utf8');
235
+ fileName = filePath;
236
+ break;
237
+ }
238
+ }
239
+ if (!content) {
240
+ console.error('โŒ --content or --file argument is required');
241
+ console.log('Usage:');
242
+ console.log(' dory verify:content --content "<mdx-content>"');
243
+ console.log(' dory verify:content --file <path-to-mdx-file>');
244
+ process.exit(1);
245
+ }
246
+ try {
247
+ const doryRoot = getDoryRoot();
248
+ const processorPath = resolve(doryRoot, 'src', 'mdx', 'processor.ts');
249
+ if (!existsSync(processorPath)) {
250
+ console.error('โŒ MDX processor not found');
251
+ console.error(' This feature requires Dory source files');
252
+ process.exit(1);
253
+ }
254
+ // Use the shared MDX processor that matches the main build exactly
255
+ const { verifyMdxContent } = await import(processorPath);
256
+ const result = await verifyMdxContent(content, fileName);
257
+ if (!result.valid) {
258
+ throw result.error;
259
+ }
260
+ // Silent success - no output means no errors
261
+ }
262
+ catch (error) {
263
+ console.error('โŒ MDX compilation failed:');
264
+ if (error instanceof Error) {
265
+ console.error(` ${error.message}`);
266
+ // Provide more detailed error information if available
267
+ const errorWithPosition = error;
268
+ if (errorWithPosition.line !== undefined && errorWithPosition.column !== undefined) {
269
+ console.error(` at line ${errorWithPosition.line}, column ${errorWithPosition.column}`);
270
+ }
271
+ if (errorWithPosition.source) {
272
+ console.error(' Source:', errorWithPosition.source);
273
+ }
274
+ }
275
+ process.exit(1);
276
+ }
277
+ },
278
+ help: () => {
279
+ console.log(`
280
+ ๐ŸŸ Dory CLI - Documentation Builder
281
+
282
+ Usage:
283
+ dory <command> [options]
284
+
285
+ Commands:
286
+ build Build your documentation site
287
+ Requirements: dory.json in current directory
288
+ Output: dist/ folder with static site
289
+
290
+ preview Preview built documentation
291
+ Requirements: dist/ folder (run build first)
292
+ Starts local server on port 3000
293
+
294
+ verify:content Verify MDX content compilation
295
+ Options: --content "<mdx>" or --file <path>
296
+ Silent on success, shows errors on failure
297
+
298
+ help Show this help message
299
+
300
+ Examples:
301
+ dory build
302
+ dory preview
303
+ dory verify:content --content "# Hello World"
304
+ dory verify:content --file docs/intro.mdx
305
+
306
+ For more information, visit: https://github.com/clidey/dory
307
+ `);
308
+ }
309
+ };
310
+ // Parse command line arguments
311
+ const command = process.argv[2];
312
+ async function runCommand() {
313
+ if (!command || command === 'help' || command === '--help' || command === '-h') {
314
+ commands.help();
315
+ return;
316
+ }
317
+ if (command in commands) {
318
+ await commands[command]();
319
+ }
320
+ else {
321
+ console.error(`โŒ Unknown command: ${command}`);
322
+ console.log(' Run "dory help" for available commands');
323
+ process.exit(1);
324
+ }
325
+ }
326
+ runCommand().catch((error) => {
327
+ console.error('โŒ Command failed');
328
+ if (error instanceof Error) {
329
+ console.error(` ${error.message}`);
330
+ if (error.stack && process.env.DEBUG) {
331
+ console.error('\nStack trace:');
332
+ console.error(error.stack);
333
+ }
334
+ }
335
+ process.exit(1);
336
+ });
337
+ //# sourceMappingURL=dory.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dory.js","sourceRoot":"","sources":["../dory.ts"],"names":[],"mappings":"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"}
package/bin/dory.ts CHANGED
@@ -1,6 +1,5 @@
1
- #!/usr/bin/env -S npx tsx
1
+ #!/usr/bin/env node
2
2
 
3
- // @ts-nocheck - gang
4
3
  import { execSync } from 'child_process';
5
4
  import { existsSync, rmSync, mkdirSync, cpSync, readFileSync, readdirSync } from 'fs';
6
5
  import { resolve, dirname } from 'path';
@@ -11,96 +10,221 @@ import sirv from 'sirv';
11
10
  const __filename = fileURLToPath(import.meta.url);
12
11
  const __dirname = dirname(__filename);
13
12
 
13
+ // Get the root directory of the Dory package
14
+ const getDoryRoot = (): string => {
15
+ // In development: bin/dory.ts -> root is parent
16
+ // In production: bin/dist/dory.js -> root is parent of parent
17
+ const isDevelopment = __dirname.endsWith('bin');
18
+ return isDevelopment ? resolve(__dirname, '..') : resolve(__dirname, '..', '..');
19
+ };
20
+
21
+ // Get the user's current working directory
22
+ const getUserRoot = (): string => process.cwd();
23
+
24
+ interface DoryConfig {
25
+ name?: string;
26
+ description?: string;
27
+ navigation?: unknown;
28
+ [key: string]: unknown;
29
+ }
30
+
31
+ const validateDoryConfig = (config: DoryConfig): void => {
32
+ if (!config || typeof config !== 'object') {
33
+ throw new Error('Configuration must be a valid object');
34
+ }
35
+ // Add more validation as needed
36
+ };
37
+
14
38
  const commands = {
15
39
  build: () => {
16
40
  console.log('๐ŸŸ Dory is ready to build your docs!');
17
-
18
- // Clear the docs folder if it exists
19
- const docsDir = resolve(__dirname, '..', 'docs');
20
- if (existsSync(docsDir)) {
21
- console.log('๐Ÿงน Tidying up the workspace...');
22
- rmSync(docsDir, { recursive: true, force: true });
23
- }
24
-
25
- // Check if dory.json exists in current directory
26
- const currentDir = process.cwd();
27
- const doryConfigPath = resolve(currentDir, 'dory.json');
28
-
41
+
42
+ const userRoot = getUserRoot();
43
+ const doryRoot = getDoryRoot();
44
+ const doryConfigPath = resolve(userRoot, 'dory.json');
45
+ const tempDocsDir = resolve(doryRoot, 'docs');
46
+ const doryDistDir = resolve(doryRoot, 'dist');
47
+ const userDistDir = resolve(userRoot, 'dist');
48
+
49
+ // Step 1: Validate prerequisites before making any changes
50
+ console.log('๐Ÿ” Validating project structure...');
51
+
29
52
  if (!existsSync(doryConfigPath)) {
30
- console.error('โŒ Oops! dory.json is missing from your project');
53
+ console.error('โŒ dory.json not found in current directory');
54
+ console.error(` Looking for: ${doryConfigPath}`);
55
+ console.error(' Create a dory.json file to configure your documentation site');
31
56
  process.exit(1);
32
57
  }
33
-
58
+
34
59
  // Read and validate dory.json
60
+ let config: DoryConfig;
35
61
  try {
36
- const config = JSON.parse(readFileSync(doryConfigPath, 'utf8'));
37
- console.log(`๐Ÿ“‹ Building: ${config.name || 'Your awesome project'}`);
62
+ const configContent = readFileSync(doryConfigPath, 'utf8');
63
+ config = JSON.parse(configContent) as DoryConfig;
64
+ validateDoryConfig(config);
65
+ console.log(`๐Ÿ“‹ Building: ${config.name || 'Documentation'}`);
38
66
  } catch (error) {
39
- console.error('โŒ Your dory.json seems to have some issues:', error.message);
40
- process.exit(1);
41
- }
42
-
43
- mkdirSync(docsDir, { recursive: true });
44
-
45
- console.log('๐Ÿ“ Gathering your project files...');
46
- cpSync(doryConfigPath, resolve(docsDir, 'dory.json'));
47
-
48
- const copyFiles = (src, dest) => {
49
- if (existsSync(src)) {
50
- if (existsSync(dest)) {
51
- rmSync(dest, { recursive: true, force: true });
52
- }
53
- cpSync(src, dest, { recursive: true });
54
- }
55
- };
56
-
57
- // Copy all files and directories except node_modules, dist, and .git
58
- const excludeDirs = ['node_modules', 'dist', '.git', 'docs', 'pnpm-lock.yaml'];
59
-
60
- const items = readdirSync(currentDir);
61
- for (const item of items) {
62
- if (!excludeDirs.includes(item)) {
63
- const srcPath = resolve(currentDir, item);
64
- const destPath = resolve(docsDir, item);
65
- copyFiles(srcPath, destPath);
67
+ console.error('โŒ Failed to parse dory.json:');
68
+ if (error instanceof Error) {
69
+ console.error(` ${error.message}`);
66
70
  }
71
+ process.exit(1);
67
72
  }
68
-
69
- console.log('โœ… All files gathered successfully!');
70
-
71
- // Run the build command
72
- console.log('โšก Magic is happening...');
73
+
74
+ // Check if pnpm is available
73
75
  try {
74
- execSync('npm run build', { stdio: 'inherit', cwd: __dirname });
75
- } catch (error) {
76
- console.error('โŒ Build failed:', error.message);
76
+ execSync('pnpm --version', { stdio: 'ignore' });
77
+ } catch {
78
+ console.error('โŒ pnpm is not installed');
79
+ console.error(' Install it with: npm install -g pnpm');
77
80
  process.exit(1);
78
81
  }
79
-
80
- // Check if dist folder was created
81
- const distDir = resolve(__dirname, '..', 'dist');
82
- if (existsSync(distDir)) {
82
+
83
+ // Step 2: Clean up temp directories
84
+ console.log('๐Ÿงน Preparing workspace...');
85
+ if (existsSync(tempDocsDir)) {
86
+ rmSync(tempDocsDir, { recursive: true, force: true });
87
+ }
88
+
89
+ try {
90
+ // Step 3: Copy user files to temp docs directory
91
+ mkdirSync(tempDocsDir, { recursive: true });
92
+
93
+ console.log('๐Ÿ“ Gathering project files...');
94
+
95
+ // Define files/dirs to exclude
96
+ const excludeItems = new Set([
97
+ 'node_modules',
98
+ 'dist',
99
+ '.git',
100
+ '.github',
101
+ 'docs',
102
+ '.DS_Store',
103
+ '.env',
104
+ '.env.local',
105
+ 'pnpm-lock.yaml',
106
+ 'package-lock.json',
107
+ 'yarn.lock'
108
+ ]);
109
+
110
+ const items = readdirSync(userRoot);
111
+ let copiedCount = 0;
112
+
113
+ for (const item of items) {
114
+ if (excludeItems.has(item)) {
115
+ continue;
116
+ }
117
+
118
+ const srcPath = resolve(userRoot, item);
119
+ const destPath = resolve(tempDocsDir, item);
120
+
121
+ try {
122
+ cpSync(srcPath, destPath, { recursive: true, force: true });
123
+ copiedCount++;
124
+ } catch (error) {
125
+ console.warn(`โš ๏ธ Could not copy ${item}: ${error instanceof Error ? error.message : 'unknown error'}`);
126
+ }
127
+ }
128
+
129
+ console.log(`โœ… Copied ${copiedCount} items`);
130
+
131
+ // Step 4: Run the build
132
+ console.log('โšก Building documentation...');
133
+
134
+ try {
135
+ execSync('pnpm run build', {
136
+ stdio: 'inherit',
137
+ cwd: doryRoot,
138
+ env: { ...process.env }
139
+ });
140
+ } catch (error) {
141
+ console.error('โŒ Build failed');
142
+ console.error(' Check the error messages above for details');
143
+ throw error;
144
+ }
145
+
146
+ // Step 5: Verify build output
147
+ console.log('๐Ÿ” Verifying build output...');
148
+
149
+ if (!existsSync(doryDistDir)) {
150
+ console.error('โŒ Build completed but dist folder was not created');
151
+ console.error(` Expected: ${doryDistDir}`);
152
+ process.exit(1);
153
+ }
154
+
155
+ const indexHtml = resolve(doryDistDir, 'index.html');
156
+ if (!existsSync(indexHtml)) {
157
+ console.error('โŒ Build incomplete: index.html not found');
158
+ console.error(' The build may have failed silently');
159
+ process.exit(1);
160
+ }
161
+
162
+ // Check if dist has content
163
+ const distFiles = readdirSync(doryDistDir);
164
+ if (distFiles.length === 0) {
165
+ console.error('โŒ Build completed but dist folder is empty');
166
+ process.exit(1);
167
+ }
168
+
83
169
  console.log('๐ŸŽ‰ Build completed successfully!');
84
- console.log('๐Ÿ“ฆ Moving your docs to the right place...');
85
- cpSync(distDir, resolve(currentDir, 'dist'), { recursive: true });
86
- console.log('โœจ Your docs are ready in the dist folder!');
87
- } else {
88
- console.log('โš ๏ธ Build completed but no output found');
170
+
171
+ // Step 6: Copy dist to user's directory
172
+ console.log('๐Ÿ“ฆ Copying build output...');
173
+
174
+ // Only copy if they're different directories
175
+ if (doryDistDir !== userDistDir) {
176
+ if (existsSync(userDistDir)) {
177
+ rmSync(userDistDir, { recursive: true, force: true });
178
+ }
179
+ cpSync(doryDistDir, userDistDir, { recursive: true, force: true });
180
+ }
181
+
182
+ console.log('โœจ Documentation ready in dist/');
183
+
184
+ } finally {
185
+ // Step 7: Always clean up temp directories
186
+ console.log('๐Ÿงน Cleaning up...');
187
+
188
+ try {
189
+ if (existsSync(tempDocsDir)) {
190
+ rmSync(tempDocsDir, { recursive: true, force: true });
191
+ }
192
+ // Only clean up doryDistDir if it's different from userDistDir
193
+ // (in production they're different, in dev they might be the same)
194
+ if (doryDistDir !== userDistDir && existsSync(doryDistDir)) {
195
+ rmSync(doryDistDir, { recursive: true, force: true });
196
+ }
197
+ } catch (error) {
198
+ console.warn('โš ๏ธ Could not clean up temp directories');
199
+ }
200
+
201
+ console.log('โœ… Done!');
89
202
  }
90
- rmSync(distDir, { recursive: true, force: true });
91
-
92
- // Revert docs folder back to original state
93
- console.log('๐Ÿงน Cleaning up...');
94
- rmSync(docsDir, { recursive: true, force: true });
95
- console.log('โœ… All done!');
96
203
  },
97
204
 
98
205
  preview: () => {
99
- console.log('๐Ÿ‘€ Starting your docs preview...');
100
- const currentDir = process.cwd();
101
- const distDir = resolve(currentDir, 'dist');
206
+ console.log('๐Ÿ‘€ Starting docs preview...');
207
+
208
+ const userRoot = getUserRoot();
209
+ const distDir = resolve(userRoot, 'dist');
102
210
  let port = parseInt(process.env.PORT || '3000', 10);
103
211
 
212
+ // Validate dist folder exists
213
+ if (!existsSync(distDir)) {
214
+ console.error('โŒ dist folder not found');
215
+ console.error(` Looking for: ${distDir}`);
216
+ console.error(' Run "dory build" first to generate the documentation');
217
+ process.exit(1);
218
+ }
219
+
220
+ // Check if dist has content
221
+ const distFiles = readdirSync(distDir);
222
+ if (distFiles.length === 0) {
223
+ console.error('โŒ dist folder is empty');
224
+ console.error(' Run "dory build" to generate documentation');
225
+ process.exit(1);
226
+ }
227
+
104
228
  const serve = sirv(distDir, {
105
229
  dev: false,
106
230
  single: true,
@@ -113,14 +237,15 @@ const commands = {
113
237
  serve(req, res);
114
238
  });
115
239
 
116
- const tryPort = (currentPort: number) => {
240
+ const tryPort = (currentPort: number): void => {
117
241
  server.listen(currentPort)
118
242
  .on('listening', () => {
119
- console.log(`๐Ÿš€ Your docs are live at http://localhost:${currentPort}`);
243
+ console.log(`๐Ÿš€ Documentation live at http://localhost:${currentPort}`);
244
+ console.log(' Press Ctrl+C to stop the server');
120
245
  })
121
- .on('error', (err: any) => {
246
+ .on('error', (err: NodeJS.ErrnoException) => {
122
247
  if (err.code === 'EADDRINUSE') {
123
- console.log(`โš ๏ธ Port ${currentPort} is busy, trying ${currentPort + 1}...`);
248
+ console.log(`โš ๏ธ Port ${currentPort} in use, trying ${currentPort + 1}...`);
124
249
  tryPort(currentPort + 1);
125
250
  } else {
126
251
  console.error('โŒ Failed to start server:', err.message);
@@ -136,16 +261,16 @@ const commands = {
136
261
  const args = process.argv.slice(3);
137
262
  let content = '';
138
263
  let fileName = '';
139
-
264
+
140
265
  // Parse arguments
141
266
  for (let i = 0; i < args.length; i++) {
142
267
  if (args[i] === '--content' && i + 1 < args.length) {
143
268
  content = args[i + 1];
144
269
  break;
145
270
  } else if (args[i] === '--file' && i + 1 < args.length) {
146
- const filePath = args[i + 1];
271
+ const filePath = resolve(getUserRoot(), args[i + 1]);
147
272
  if (!existsSync(filePath)) {
148
- console.error(`โŒ Error: File not found: ${filePath}`);
273
+ console.error(`โŒ File not found: ${filePath}`);
149
274
  process.exit(1);
150
275
  }
151
276
  content = readFileSync(filePath, 'utf8');
@@ -153,88 +278,115 @@ const commands = {
153
278
  break;
154
279
  }
155
280
  }
156
-
281
+
157
282
  if (!content) {
158
- console.error('โŒ Error: --content or --file argument is required');
159
- console.log('Usage: dory verify:content --content "<mdx-content>" | --file <path-to-mdx-file>');
283
+ console.error('โŒ --content or --file argument is required');
284
+ console.log('Usage:');
285
+ console.log(' dory verify:content --content "<mdx-content>"');
286
+ console.log(' dory verify:content --file <path-to-mdx-file>');
160
287
  process.exit(1);
161
288
  }
162
-
289
+
163
290
  try {
291
+ const doryRoot = getDoryRoot();
292
+ const processorPath = resolve(doryRoot, 'src', 'mdx', 'processor.ts');
293
+
294
+ if (!existsSync(processorPath)) {
295
+ console.error('โŒ MDX processor not found');
296
+ console.error(' This feature requires Dory source files');
297
+ process.exit(1);
298
+ }
299
+
164
300
  // Use the shared MDX processor that matches the main build exactly
165
- const { verifyMdxContent } = await import('../src/mdx/processor.ts');
301
+ const { verifyMdxContent } = await import(processorPath);
166
302
  const result = await verifyMdxContent(content, fileName);
167
-
303
+
168
304
  if (!result.valid) {
169
305
  throw result.error;
170
306
  }
171
-
307
+
172
308
  // Silent success - no output means no errors
173
-
309
+
174
310
  } catch (error) {
175
311
  console.error('โŒ MDX compilation failed:');
176
- console.error(error.message);
177
-
178
- // Provide more detailed error information if available
179
- if (error.line !== undefined && error.column !== undefined) {
180
- console.error(` at line ${error.line}, column ${error.column}`);
181
- }
182
- if (error.source) {
183
- console.error(' Source:', error.source);
312
+ if (error instanceof Error) {
313
+ console.error(` ${error.message}`);
314
+
315
+ // Provide more detailed error information if available
316
+ const errorWithPosition = error as Error & { line?: number; column?: number; source?: string };
317
+ if (errorWithPosition.line !== undefined && errorWithPosition.column !== undefined) {
318
+ console.error(` at line ${errorWithPosition.line}, column ${errorWithPosition.column}`);
319
+ }
320
+ if (errorWithPosition.source) {
321
+ console.error(' Source:', errorWithPosition.source);
322
+ }
184
323
  }
185
-
324
+
186
325
  process.exit(1);
187
326
  }
188
327
  },
189
328
 
190
329
  help: () => {
191
330
  console.log(`
192
- ๐ŸŸ Dory CLI - Your Friendly Documentation Builder
331
+ ๐ŸŸ Dory CLI - Documentation Builder
193
332
 
194
333
  Usage:
195
- dory <command>
334
+ dory <command> [options]
196
335
 
197
336
  Commands:
198
- build Build your documentation site
199
- - Needs dory.json in your project
200
- - Creates a beautiful dist folder
201
-
202
- verify:content Verify that MDX content compiles without errors
203
- - Silent on success, shows errors on failure
204
- - Uses the same preprocessing as the main build
205
- - Accepts --content or --file arguments
206
-
207
- preview Preview your built documentation
208
- - Shows your docs in the browser
209
- - Run build first!
210
-
211
- help Show this help message
337
+ build Build your documentation site
338
+ Requirements: dory.json in current directory
339
+ Output: dist/ folder with static site
340
+
341
+ preview Preview built documentation
342
+ Requirements: dist/ folder (run build first)
343
+ Starts local server on port 3000
344
+
345
+ verify:content Verify MDX content compilation
346
+ Options: --content "<mdx>" or --file <path>
347
+ Silent on success, shows errors on failure
348
+
349
+ help Show this help message
212
350
 
213
351
  Examples:
214
- dory build # Build your docs
215
- dory verify:content --content "# Hello World" # Verify MDX content
216
- dory verify:content --file content.mdx # Verify MDX from file
217
- dory preview # Preview your docs
352
+ dory build
353
+ dory preview
354
+ dory verify:content --content "# Hello World"
355
+ dory verify:content --file docs/intro.mdx
356
+
357
+ For more information, visit: https://github.com/clidey/dory
218
358
  `);
219
359
  }
220
360
  };
221
361
 
362
+ type CommandName = keyof typeof commands;
363
+
222
364
  // Parse command line arguments
223
365
  const command = process.argv[2];
224
366
 
225
- async function runCommand() {
367
+ async function runCommand(): Promise<void> {
226
368
  if (!command || command === 'help' || command === '--help' || command === '-h') {
227
369
  commands.help();
228
- } else if (commands[command]) {
229
- await commands[command]();
370
+ return;
371
+ }
372
+
373
+ if (command in commands) {
374
+ await commands[command as CommandName]();
230
375
  } else {
231
376
  console.error(`โŒ Unknown command: ${command}`);
232
- console.log('Run "dory help" for usage information');
377
+ console.log(' Run "dory help" for available commands');
233
378
  process.exit(1);
234
379
  }
235
380
  }
236
381
 
237
- runCommand().catch((error) => {
238
- console.error('โŒ Command failed:', error.message);
382
+ runCommand().catch((error: unknown) => {
383
+ console.error('โŒ Command failed');
384
+ if (error instanceof Error) {
385
+ console.error(` ${error.message}`);
386
+ if (error.stack && process.env.DEBUG) {
387
+ console.error('\nStack trace:');
388
+ console.error(error.stack);
389
+ }
390
+ }
239
391
  process.exit(1);
240
392
  });
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@clidey/dory",
3
3
  "private": false,
4
- "version": "0.23.0",
4
+ "version": "0.24.0",
5
5
  "type": "module",
6
6
  "description": "A CLI tool for building and previewing documentation sites",
7
7
  "keywords": [
@@ -12,7 +12,7 @@
12
12
  "static-site"
13
13
  ],
14
14
  "bin": {
15
- "dory": "./bin/dory.ts"
15
+ "dory": "./bin/dist/dory.js"
16
16
  },
17
17
  "repository": {
18
18
  "type": "git",
@@ -26,9 +26,11 @@
26
26
  },
27
27
  "scripts": {
28
28
  "dev": "vite",
29
- "build": "tsc -b && vite build",
29
+ "build": "npm run build:cli && tsc -b && vite build",
30
+ "build:cli": "tsc -p tsconfig.bin.json",
30
31
  "preview": "vite preview",
31
- "publish": "npm publish --access public"
32
+ "publish": "npm run build && npm publish --access public",
33
+ "prepublishOnly": "npm run build"
32
34
  },
33
35
  "dependencies": {
34
36
  "@algolia/autocomplete-core": "^1.19.2",
package/tsconfig.app.json CHANGED
@@ -28,5 +28,6 @@
28
28
  "noFallthroughCasesInSwitch": true,
29
29
  "noUncheckedSideEffectImports": true
30
30
  },
31
- "include": ["src"]
31
+ "include": ["src"],
32
+ "exclude": ["src/plugins"]
32
33
  }
package/tsconfig.bin.json CHANGED
@@ -4,17 +4,21 @@
4
4
  "lib": ["ES2023"],
5
5
  "module": "ESNext",
6
6
  "moduleResolution": "node",
7
- "allowImportingTsExtensions": true,
8
7
  "skipLibCheck": true,
9
- "strict": false,
8
+ "strict": true,
10
9
  "esModuleInterop": true,
11
10
  "allowSyntheticDefaultImports": true,
12
- "noEmit": true,
13
- "noImplicitAny": false,
14
- "noImplicitReturns": false,
15
- "noImplicitThis": false
11
+ "noEmit": false,
12
+ "outDir": "./bin/dist",
13
+ "rootDir": "./bin",
14
+ "declaration": true,
15
+ "declarationMap": true,
16
+ "sourceMap": true
16
17
  },
17
18
  "include": [
18
- "bin/dory.ts"
19
+ "bin/**/*.ts"
20
+ ],
21
+ "exclude": [
22
+ "bin/dist"
19
23
  ]
20
24
  }
@@ -5,6 +5,7 @@
5
5
  "lib": ["ES2023"],
6
6
  "module": "ESNext",
7
7
  "skipLibCheck": true,
8
+ "types": ["node"],
8
9
 
9
10
  /* Bundler mode */
10
11
  "moduleResolution": "bundler",
@@ -21,5 +22,5 @@
21
22
  "noFallthroughCasesInSwitch": true,
22
23
  "noUncheckedSideEffectImports": true
23
24
  },
24
- "include": ["vite.config.ts"]
25
+ "include": ["vite.config.ts", "src/plugins/**/*.ts", "bin/**/*.ts"]
25
26
  }