@poetora/cli 0.1.3 → 0.1.5
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/.turbo/turbo-build.log +1 -1
- package/bin/cli-builder.js +8 -2
- package/bin/cli.js +4 -0
- package/bin/commands/base.command.js +2 -2
- package/bin/mdxAccessibility.js +2 -2
- package/bin/middlewares.d.ts +2 -0
- package/bin/middlewares.js +47 -0
- package/bin/services/accessibility-check.service.js +1 -1
- package/bin/services/link.service.js +2 -2
- package/bin/services/openapi-check.service.js +1 -1
- package/bin/services/template.service.js +2 -2
- package/bin/services/version.service.js +1 -1
- package/bin/utils/console-logger.js +24 -28
- package/package.json +10 -9
- package/src/cli-builder.ts +11 -3
- package/src/cli.ts +7 -0
- package/src/commands/base.command.ts +2 -2
- package/src/mdxAccessibility.ts +2 -2
- package/src/middlewares.ts +73 -0
- package/src/services/__tests__/template.service.test.ts +1 -1
- package/src/services/accessibility-check.service.ts +1 -1
- package/src/services/link.service.ts +2 -2
- package/src/services/openapi-check.service.ts +1 -1
- package/src/services/template.service.ts +2 -2
- package/src/services/version.service.ts +1 -1
- package/src/utils/console-logger.ts +42 -32
package/.turbo/turbo-build.log
CHANGED
package/bin/cli-builder.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
1
2
|
import yargs from 'yargs';
|
|
2
3
|
import { hideBin } from 'yargs/helpers';
|
|
3
4
|
import { CheckCommand, DevCommand, InitCommand, LinkCommand, UpdateCommand, } from './commands/index.js';
|
|
5
|
+
import { checkNodeVersion, suppressConsoleWarnings } from './middlewares.js';
|
|
4
6
|
import { AccessibilityCheckService, LinkService, OpenApiCheckService, PortService, TemplateService, UpdateService, VersionService, } from './services/index.js';
|
|
5
7
|
import { ConsoleLogger } from './utils/index.js';
|
|
6
8
|
export class CliBuilder {
|
|
@@ -23,8 +25,12 @@ export class CliBuilder {
|
|
|
23
25
|
const checkCommand = new CheckCommand(this.logger, openApiCheckService, accessibilityCheckService, this.packageName);
|
|
24
26
|
const linkCommand = new LinkCommand(this.logger, linkService, this.packageName);
|
|
25
27
|
const updateCommand = new UpdateCommand(this.logger, updateService, this.packageName);
|
|
28
|
+
const cliVersion = versionService.getCliVersion() || '0.0.0';
|
|
26
29
|
return (yargs(hideBin(process.argv))
|
|
27
30
|
.scriptName(this.packageName)
|
|
31
|
+
.version(cliVersion)
|
|
32
|
+
.middleware(checkNodeVersion)
|
|
33
|
+
.middleware(suppressConsoleWarnings)
|
|
28
34
|
.command('dev', 'initialize a local preview environment', (yargs) => yargs
|
|
29
35
|
.option('port', {
|
|
30
36
|
type: 'number',
|
|
@@ -163,8 +169,8 @@ export class CliBuilder {
|
|
|
163
169
|
})
|
|
164
170
|
.command(['version', 'v'], 'display the current version of the CLI and client', () => undefined, async () => {
|
|
165
171
|
const versions = versionService.getVersions();
|
|
166
|
-
|
|
167
|
-
|
|
172
|
+
console.log(`${chalk.bold.green('cli version')} ${versions.cli}`);
|
|
173
|
+
console.log(`${chalk.bold.green('client version')} ${versions.client}`);
|
|
168
174
|
process.exit(0);
|
|
169
175
|
})
|
|
170
176
|
.strictCommands()
|
package/bin/cli.js
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import { Logs } from '@poetora/previewing';
|
|
3
|
+
import { render } from 'ink';
|
|
4
|
+
import React from 'react';
|
|
2
5
|
import { CliBuilder } from './cli-builder.js';
|
|
3
6
|
export const cli = (options) => {
|
|
7
|
+
render(React.createElement(Logs));
|
|
4
8
|
const builder = new CliBuilder(options.packageName);
|
|
5
9
|
builder.run().catch((error) => {
|
|
6
10
|
console.error('Fatal error:', error);
|
|
@@ -26,12 +26,12 @@ export class BaseCommand {
|
|
|
26
26
|
else if (error instanceof Error) {
|
|
27
27
|
this.logger.error(error.message);
|
|
28
28
|
if (process.env.DEBUG === 'true') {
|
|
29
|
-
|
|
29
|
+
this.logger.logColor(error.stack ?? '', 'gray');
|
|
30
30
|
}
|
|
31
31
|
}
|
|
32
32
|
else {
|
|
33
33
|
this.logger.error('An unexpected error occurred');
|
|
34
|
-
|
|
34
|
+
this.logger.logColor(String(error), 'gray');
|
|
35
35
|
}
|
|
36
36
|
}
|
|
37
37
|
exit(code) {
|
package/bin/mdxAccessibility.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import fs from 'fs';
|
|
2
|
-
import path from 'path';
|
|
3
1
|
import { categorizeFilePaths, getPoetIgnore } from '@poetora/prebuild';
|
|
4
2
|
import { coreRemark } from '@poetora/shared';
|
|
3
|
+
import fs from 'fs';
|
|
4
|
+
import path from 'path';
|
|
5
5
|
import { visit } from 'unist-util-visit';
|
|
6
6
|
const checkAltAttributes = (filePath, content) => {
|
|
7
7
|
const issues = [];
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { addLog, ErrorLog } from '@poetora/previewing';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
export const checkNodeVersion = async () => {
|
|
4
|
+
let nodeVersionString = process.version;
|
|
5
|
+
if (nodeVersionString.charAt(0) === 'v') {
|
|
6
|
+
nodeVersionString = nodeVersionString.slice(1);
|
|
7
|
+
}
|
|
8
|
+
const versionArr = nodeVersionString.split('.');
|
|
9
|
+
const versionStr = versionArr[0];
|
|
10
|
+
if (!versionStr) {
|
|
11
|
+
addLog(React.createElement(ErrorLog, {
|
|
12
|
+
message: `Unable to determine Node.js version (got "${process.version}"). Please ensure you are running Node.js >= 18.0.0.`,
|
|
13
|
+
}));
|
|
14
|
+
process.exit(1);
|
|
15
|
+
}
|
|
16
|
+
const majorVersion = parseInt(versionStr, 10);
|
|
17
|
+
if (majorVersion < 18) {
|
|
18
|
+
addLog(React.createElement(ErrorLog, {
|
|
19
|
+
message: `poetora requires Node.js >= 18.0.0 (current version ${nodeVersionString}). Please upgrade Node.js and try again.`,
|
|
20
|
+
}));
|
|
21
|
+
process.exit(1);
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
export const suppressConsoleWarnings = () => {
|
|
25
|
+
const ignoredMessages = [
|
|
26
|
+
'No utility classes were detected',
|
|
27
|
+
'https://tailwindcss.com/docs/content-configuration',
|
|
28
|
+
'DeprecationWarning',
|
|
29
|
+
'punycode',
|
|
30
|
+
];
|
|
31
|
+
const originalConsoleError = console.error;
|
|
32
|
+
console.error = (...args) => {
|
|
33
|
+
const message = args.join(' ');
|
|
34
|
+
if (ignoredMessages.some((ignoredMessage) => message.includes(ignoredMessage))) {
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
originalConsoleError.apply(console, args);
|
|
38
|
+
};
|
|
39
|
+
const originalConsoleWarn = console.warn;
|
|
40
|
+
console.warn = (...args) => {
|
|
41
|
+
const message = args.join(' ');
|
|
42
|
+
if (ignoredMessages.some((ignoredMessage) => message.includes(ignoredMessage))) {
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
originalConsoleWarn.apply(console, args);
|
|
46
|
+
};
|
|
47
|
+
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import path from 'path';
|
|
2
1
|
import { getConfigObj, getConfigPath } from '@poetora/prebuild';
|
|
3
2
|
import { getBackgroundColors } from '@poetora/shared';
|
|
3
|
+
import path from 'path';
|
|
4
4
|
import { checkDocsColors, } from '../accessibility.js';
|
|
5
5
|
import { CMD_EXEC_PATH } from '../constants.js';
|
|
6
6
|
import { checkMdxAccessibility } from '../mdxAccessibility.js';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import * as path from 'path';
|
|
2
1
|
import { getBrokenInternalLinks, renameFilesAndUpdateLinksInContent, } from '@poetora/link-rot';
|
|
2
|
+
import * as path from 'path';
|
|
3
3
|
export class LinkService {
|
|
4
4
|
logger;
|
|
5
5
|
constructor(logger) {
|
|
@@ -26,7 +26,7 @@ export class LinkService {
|
|
|
26
26
|
this.logger.log(`found ${this.logger.highlight?.(brokenLinks.length.toString()) ?? brokenLinks.length} broken link${brokenLinks.length === 1 ? '' : 's'} in ${this.logger.highlight?.(fileCount.toString()) ?? fileCount} file${fileCount === 1 ? '' : 's'}`);
|
|
27
27
|
this.logger.logNewLine();
|
|
28
28
|
for (const [filename, links] of Object.entries(brokenLinksByFile)) {
|
|
29
|
-
|
|
29
|
+
this.logger.logColor(filename, 'cyan');
|
|
30
30
|
links.forEach((link) => {
|
|
31
31
|
this.logger.logColor(` ⎿ ${link}`, 'gray');
|
|
32
32
|
});
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import * as fs from 'fs';
|
|
2
1
|
import { getOpenApiDocumentFromUrl, isAllowedLocalSchemaUrl, validate } from '@poetora/shared';
|
|
2
|
+
import * as fs from 'fs';
|
|
3
3
|
import * as yaml from 'js-yaml';
|
|
4
4
|
import { FileSystemError, ValidationError } from '../errors/index.js';
|
|
5
5
|
export class OpenApiCheckService {
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import * as fs from 'fs';
|
|
2
|
-
import * as path from 'path';
|
|
3
1
|
import { docsConfigSchema } from '@poetora/validation';
|
|
4
2
|
import AdmZip from 'adm-zip';
|
|
3
|
+
import * as fs from 'fs';
|
|
5
4
|
import * as fse from 'fs-extra';
|
|
5
|
+
import * as path from 'path';
|
|
6
6
|
import { ExternalServiceError, FileSystemError } from '../errors/index.js';
|
|
7
7
|
export class TemplateService {
|
|
8
8
|
TEMPLATE_URL = 'https://github.com/poetora/starter/archive/refs/heads/main.zip';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { execSync } from 'child_process';
|
|
2
1
|
import { getClientVersion, LOCAL_LINKED_CLI_VERSION } from '@poetora/previewing';
|
|
2
|
+
import { execSync } from 'child_process';
|
|
3
3
|
import yargs from 'yargs';
|
|
4
4
|
import { InvalidEnvironmentError } from '../errors/index.js';
|
|
5
5
|
import { CLI_CONSTANTS } from '../types/index.js';
|
|
@@ -1,65 +1,61 @@
|
|
|
1
|
+
import { addLog, EmptyLineLog, ErrorLog, InfoLog, SpinnerLog, SuccessLog, WarningLog, } from '@poetora/previewing';
|
|
1
2
|
import chalk from 'chalk';
|
|
2
|
-
import
|
|
3
|
+
import { Text } from 'ink';
|
|
4
|
+
import React from 'react';
|
|
3
5
|
export class ConsoleLogger {
|
|
4
6
|
info(message) {
|
|
5
|
-
|
|
7
|
+
addLog(React.createElement(InfoLog, { message }));
|
|
6
8
|
}
|
|
7
9
|
success(message) {
|
|
8
|
-
|
|
10
|
+
addLog(React.createElement(SuccessLog, { message }));
|
|
9
11
|
}
|
|
10
12
|
error(message) {
|
|
11
|
-
|
|
13
|
+
addLog(React.createElement(ErrorLog, { message }));
|
|
12
14
|
}
|
|
13
15
|
warn(message) {
|
|
14
|
-
|
|
16
|
+
addLog(React.createElement(WarningLog, { message }));
|
|
15
17
|
}
|
|
16
18
|
spinner(message) {
|
|
17
|
-
|
|
19
|
+
addLog(React.createElement(SpinnerLog, { message }));
|
|
20
|
+
return new InkSpinner();
|
|
18
21
|
}
|
|
19
22
|
log(message) {
|
|
20
|
-
|
|
23
|
+
addLog(React.createElement(Text, {}, message));
|
|
21
24
|
}
|
|
22
25
|
logColor(message, color) {
|
|
23
|
-
|
|
26
|
+
addLog(React.createElement(Text, { color }, message));
|
|
24
27
|
}
|
|
25
28
|
logBold(message, color) {
|
|
26
|
-
|
|
27
|
-
console.log(chalk[color].bold(message));
|
|
28
|
-
}
|
|
29
|
-
else {
|
|
30
|
-
console.log(chalk.bold(message));
|
|
31
|
-
}
|
|
29
|
+
addLog(React.createElement(Text, { bold: true, color }, message));
|
|
32
30
|
}
|
|
33
31
|
logSeparator() {
|
|
34
|
-
|
|
32
|
+
addLog(React.createElement(Text, { color: 'gray' }, '─'.repeat(50)));
|
|
35
33
|
}
|
|
36
34
|
logNewLine() {
|
|
37
|
-
|
|
35
|
+
addLog(React.createElement(EmptyLineLog));
|
|
38
36
|
}
|
|
39
37
|
logHeader(message) {
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
38
|
+
this.logNewLine();
|
|
39
|
+
addLog(React.createElement(Text, { bold: true, color: 'cyan' }, message));
|
|
40
|
+
this.logNewLine();
|
|
43
41
|
}
|
|
44
42
|
highlight(text) {
|
|
45
43
|
return chalk.yellow(text);
|
|
46
44
|
}
|
|
47
45
|
}
|
|
48
|
-
class
|
|
49
|
-
spinner;
|
|
50
|
-
constructor(message) {
|
|
51
|
-
this.spinner = ora(message);
|
|
52
|
-
}
|
|
46
|
+
class InkSpinner {
|
|
53
47
|
start() {
|
|
54
|
-
this.spinner.start();
|
|
55
48
|
}
|
|
56
49
|
stop() {
|
|
57
|
-
this.spinner.stop();
|
|
58
50
|
}
|
|
59
51
|
succeed(message) {
|
|
60
|
-
|
|
52
|
+
if (message) {
|
|
53
|
+
addLog(React.createElement(SuccessLog, { message }));
|
|
54
|
+
}
|
|
61
55
|
}
|
|
62
56
|
fail(message) {
|
|
63
|
-
|
|
57
|
+
if (message) {
|
|
58
|
+
addLog(React.createElement(ErrorLog, { message }));
|
|
59
|
+
}
|
|
64
60
|
}
|
|
65
61
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@poetora/cli",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.5",
|
|
4
4
|
"description": "The CLI for Poetora documentation Engine",
|
|
5
5
|
"engines": {
|
|
6
6
|
"node": ">=18.0.0"
|
|
@@ -33,19 +33,19 @@
|
|
|
33
33
|
"detect-port": "1.5.1",
|
|
34
34
|
"front-matter": "4.0.2",
|
|
35
35
|
"fs-extra": "11.2.0",
|
|
36
|
+
"ink": "6.3.0",
|
|
36
37
|
"inquirer": "12.3.0",
|
|
37
38
|
"js-yaml": "4.1.0",
|
|
38
39
|
"mdast-util-mdx-jsx": "3.2.0",
|
|
39
|
-
"
|
|
40
|
-
"react": "^19.0.1",
|
|
40
|
+
"react": "19.2.3",
|
|
41
41
|
"semver": "7.7.2",
|
|
42
42
|
"unist-util-visit": "5.0.0",
|
|
43
43
|
"yargs": "17.7.1",
|
|
44
|
-
"@poetora/link-rot": "0.0.
|
|
45
|
-
"@poetora/prebuild": "0.1.
|
|
46
|
-
"@poetora/previewing": "0.1.
|
|
47
|
-
"@poetora/shared": "0.1.
|
|
48
|
-
"@poetora/validation": "0.1.
|
|
44
|
+
"@poetora/link-rot": "0.0.7",
|
|
45
|
+
"@poetora/prebuild": "0.1.6",
|
|
46
|
+
"@poetora/previewing": "0.1.6",
|
|
47
|
+
"@poetora/shared": "0.1.6",
|
|
48
|
+
"@poetora/validation": "0.1.6"
|
|
49
49
|
},
|
|
50
50
|
"devDependencies": {
|
|
51
51
|
"@tsconfig/recommended": "1.0.2",
|
|
@@ -53,9 +53,10 @@
|
|
|
53
53
|
"@types/color": "^3.0.3",
|
|
54
54
|
"@types/detect-port": "1.3.2",
|
|
55
55
|
"@types/fs-extra": "^9.0.13",
|
|
56
|
-
"@types/js-yaml": "
|
|
56
|
+
"@types/js-yaml": "4.0.9",
|
|
57
57
|
"@types/mdast": "4.0.4",
|
|
58
58
|
"@types/node": "22.19.2",
|
|
59
|
+
"@types/react": "19.2.7",
|
|
59
60
|
"@types/yargs": "17.0.22",
|
|
60
61
|
"@typescript-eslint/eslint-plugin": "8.49.0",
|
|
61
62
|
"@typescript-eslint/parser": "8.49.0",
|
package/src/cli-builder.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
1
2
|
import type { Argv } from 'yargs';
|
|
2
3
|
import yargs from 'yargs';
|
|
3
4
|
import { hideBin } from 'yargs/helpers';
|
|
4
|
-
|
|
5
5
|
import {
|
|
6
6
|
CheckCommand,
|
|
7
7
|
DevCommand,
|
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
LinkCommand,
|
|
10
10
|
UpdateCommand,
|
|
11
11
|
} from './commands/index.js';
|
|
12
|
+
import { checkNodeVersion, suppressConsoleWarnings } from './middlewares.js';
|
|
12
13
|
import {
|
|
13
14
|
AccessibilityCheckService,
|
|
14
15
|
LinkService,
|
|
@@ -57,9 +58,15 @@ export class CliBuilder {
|
|
|
57
58
|
const linkCommand = new LinkCommand(this.logger, linkService, this.packageName);
|
|
58
59
|
const updateCommand = new UpdateCommand(this.logger, updateService, this.packageName);
|
|
59
60
|
|
|
61
|
+
// Get CLI version for yargs
|
|
62
|
+
const cliVersion = versionService.getCliVersion() || '0.0.0';
|
|
63
|
+
|
|
60
64
|
return (
|
|
61
65
|
yargs(hideBin(process.argv))
|
|
62
66
|
.scriptName(this.packageName)
|
|
67
|
+
.version(cliVersion) // Explicitly set version to fix "unknown" issue
|
|
68
|
+
.middleware(checkNodeVersion) // Check Node.js version before any command
|
|
69
|
+
.middleware(suppressConsoleWarnings) // Suppress known console warnings
|
|
63
70
|
// Dev command
|
|
64
71
|
.command(
|
|
65
72
|
'dev',
|
|
@@ -245,8 +252,9 @@ export class CliBuilder {
|
|
|
245
252
|
() => undefined,
|
|
246
253
|
async () => {
|
|
247
254
|
const versions = versionService.getVersions();
|
|
248
|
-
|
|
249
|
-
|
|
255
|
+
// Use chalk for consistent formatting (mintlify uses ink Text, we use chalk)
|
|
256
|
+
console.log(`${chalk.bold.green('cli version')} ${versions.cli}`);
|
|
257
|
+
console.log(`${chalk.bold.green('client version')} ${versions.client}`);
|
|
250
258
|
process.exit(0);
|
|
251
259
|
}
|
|
252
260
|
)
|
package/src/cli.ts
CHANGED
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import { Logs } from '@poetora/previewing';
|
|
3
|
+
import { render } from 'ink';
|
|
4
|
+
import React from 'react';
|
|
5
|
+
|
|
2
6
|
import { CliBuilder } from './cli-builder.js';
|
|
3
7
|
|
|
4
8
|
export interface CliOptions {
|
|
@@ -6,6 +10,9 @@ export interface CliOptions {
|
|
|
6
10
|
}
|
|
7
11
|
|
|
8
12
|
export const cli = (options: CliOptions): void => {
|
|
13
|
+
// Initialize ink rendering for logs (like mintlify)
|
|
14
|
+
render(React.createElement(Logs));
|
|
15
|
+
|
|
9
16
|
const builder = new CliBuilder(options.packageName);
|
|
10
17
|
|
|
11
18
|
builder.run().catch((error) => {
|
|
@@ -78,12 +78,12 @@ export abstract class BaseCommand<TOptions = unknown, TResult = void> {
|
|
|
78
78
|
|
|
79
79
|
// In debug mode, show stack trace
|
|
80
80
|
if (process.env.DEBUG === 'true') {
|
|
81
|
-
|
|
81
|
+
this.logger.logColor(error.stack ?? '', 'gray');
|
|
82
82
|
}
|
|
83
83
|
} else {
|
|
84
84
|
// Unknown error types
|
|
85
85
|
this.logger.error('An unexpected error occurred');
|
|
86
|
-
|
|
86
|
+
this.logger.logColor(String(error), 'gray');
|
|
87
87
|
}
|
|
88
88
|
}
|
|
89
89
|
|
package/src/mdxAccessibility.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import fs from 'fs';
|
|
2
|
-
import path from 'path';
|
|
3
1
|
import { categorizeFilePaths, getPoetIgnore } from '@poetora/prebuild';
|
|
4
2
|
import { coreRemark } from '@poetora/shared';
|
|
3
|
+
import fs from 'fs';
|
|
5
4
|
import type { Node, Root, Text } from 'mdast';
|
|
6
5
|
import type { MdxJsxFlowElement } from 'mdast-util-mdx-jsx';
|
|
6
|
+
import path from 'path';
|
|
7
7
|
import { visit } from 'unist-util-visit';
|
|
8
8
|
|
|
9
9
|
export interface AccessibilityFixAttribute {
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { addLog, ErrorLog } from '@poetora/previewing';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Yargs middleware functions
|
|
6
|
+
* These run before command execution
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Check if Node.js version is supported
|
|
11
|
+
* Middleware that validates Node version before any command runs
|
|
12
|
+
*
|
|
13
|
+
* Minimum requirement: Node.js >= 18.0.0
|
|
14
|
+
* Note: Individual commands may have stricter requirements (e.g., dev command)
|
|
15
|
+
*/
|
|
16
|
+
export const checkNodeVersion = async (): Promise<void> => {
|
|
17
|
+
let nodeVersionString = process.version;
|
|
18
|
+
if (nodeVersionString.charAt(0) === 'v') {
|
|
19
|
+
nodeVersionString = nodeVersionString.slice(1);
|
|
20
|
+
}
|
|
21
|
+
const versionArr = nodeVersionString.split('.');
|
|
22
|
+
const versionStr = versionArr[0];
|
|
23
|
+
if (!versionStr) {
|
|
24
|
+
addLog(
|
|
25
|
+
React.createElement(ErrorLog, {
|
|
26
|
+
message: `Unable to determine Node.js version (got "${process.version}"). Please ensure you are running Node.js >= 18.0.0.`,
|
|
27
|
+
})
|
|
28
|
+
);
|
|
29
|
+
process.exit(1);
|
|
30
|
+
}
|
|
31
|
+
const majorVersion = parseInt(versionStr, 10);
|
|
32
|
+
|
|
33
|
+
if (majorVersion < 18) {
|
|
34
|
+
addLog(
|
|
35
|
+
React.createElement(ErrorLog, {
|
|
36
|
+
message: `poetora requires Node.js >= 18.0.0 (current version ${nodeVersionString}). Please upgrade Node.js and try again.`,
|
|
37
|
+
})
|
|
38
|
+
);
|
|
39
|
+
process.exit(1);
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Suppress common console warnings that don't affect functionality
|
|
45
|
+
* Filters out known noise from dependencies
|
|
46
|
+
*/
|
|
47
|
+
export const suppressConsoleWarnings = (): void => {
|
|
48
|
+
// Ignore tailwind warnings and punycode deprecation warning
|
|
49
|
+
const ignoredMessages = [
|
|
50
|
+
'No utility classes were detected',
|
|
51
|
+
'https://tailwindcss.com/docs/content-configuration',
|
|
52
|
+
'DeprecationWarning',
|
|
53
|
+
'punycode',
|
|
54
|
+
];
|
|
55
|
+
|
|
56
|
+
const originalConsoleError = console.error;
|
|
57
|
+
console.error = (...args) => {
|
|
58
|
+
const message = args.join(' ');
|
|
59
|
+
if (ignoredMessages.some((ignoredMessage) => message.includes(ignoredMessage))) {
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
originalConsoleError.apply(console, args);
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
const originalConsoleWarn = console.warn;
|
|
66
|
+
console.warn = (...args) => {
|
|
67
|
+
const message = args.join(' ');
|
|
68
|
+
if (ignoredMessages.some((ignoredMessage) => message.includes(ignoredMessage))) {
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
originalConsoleWarn.apply(console, args);
|
|
72
|
+
};
|
|
73
|
+
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import * as fs from 'fs';
|
|
2
1
|
import AdmZip from 'adm-zip';
|
|
2
|
+
import * as fs from 'fs';
|
|
3
3
|
import * as fse from 'fs-extra';
|
|
4
4
|
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
|
5
5
|
import { ExternalServiceError, FileSystemError } from '../../errors/index.js';
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import * as path from 'path';
|
|
2
1
|
import {
|
|
3
2
|
getBrokenInternalLinks,
|
|
4
3
|
type MdxPath,
|
|
5
4
|
renameFilesAndUpdateLinksInContent,
|
|
6
5
|
} from '@poetora/link-rot';
|
|
6
|
+
import * as path from 'path';
|
|
7
7
|
|
|
8
8
|
import type { ILogger } from '../utils/index.js';
|
|
9
9
|
|
|
@@ -46,7 +46,7 @@ export class LinkService {
|
|
|
46
46
|
|
|
47
47
|
for (const [filename, links] of Object.entries(brokenLinksByFile)) {
|
|
48
48
|
// Underline filename for better visibility
|
|
49
|
-
|
|
49
|
+
this.logger.logColor(filename, 'cyan');
|
|
50
50
|
links.forEach((link) => {
|
|
51
51
|
this.logger.logColor(` ⎿ ${link}`, 'gray');
|
|
52
52
|
});
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import * as fs from 'fs';
|
|
2
|
-
import * as path from 'path';
|
|
3
1
|
import { docsConfigSchema } from '@poetora/validation';
|
|
4
2
|
import AdmZip from 'adm-zip';
|
|
3
|
+
import * as fs from 'fs';
|
|
5
4
|
import * as fse from 'fs-extra';
|
|
5
|
+
import * as path from 'path';
|
|
6
6
|
|
|
7
7
|
import { ExternalServiceError, FileSystemError } from '../errors/index.js';
|
|
8
8
|
|
|
@@ -1,37 +1,50 @@
|
|
|
1
|
+
import {
|
|
2
|
+
addLog,
|
|
3
|
+
EmptyLineLog,
|
|
4
|
+
ErrorLog,
|
|
5
|
+
InfoLog,
|
|
6
|
+
SpinnerLog,
|
|
7
|
+
SuccessLog,
|
|
8
|
+
WarningLog,
|
|
9
|
+
} from '@poetora/previewing';
|
|
1
10
|
import chalk from 'chalk';
|
|
2
|
-
import
|
|
11
|
+
import { Text } from 'ink';
|
|
12
|
+
import React from 'react';
|
|
3
13
|
|
|
4
14
|
import type { LoggerSpinner } from '../types/index.js';
|
|
5
15
|
|
|
6
16
|
import type { ILogger } from './logger.interface.js';
|
|
7
17
|
|
|
8
18
|
/**
|
|
9
|
-
*
|
|
10
|
-
* Provides
|
|
19
|
+
* Logger implementation using ink and addLog from @poetora/previewing
|
|
20
|
+
* Provides consistent output with the preview server's logging system
|
|
21
|
+
* Following mintlify's architecture pattern
|
|
11
22
|
*/
|
|
12
23
|
export class ConsoleLogger implements ILogger {
|
|
13
24
|
info(message: string): void {
|
|
14
|
-
|
|
25
|
+
addLog(React.createElement(InfoLog, { message }));
|
|
15
26
|
}
|
|
16
27
|
|
|
17
28
|
success(message: string): void {
|
|
18
|
-
|
|
29
|
+
addLog(React.createElement(SuccessLog, { message }));
|
|
19
30
|
}
|
|
20
31
|
|
|
21
32
|
error(message: string): void {
|
|
22
|
-
|
|
33
|
+
addLog(React.createElement(ErrorLog, { message }));
|
|
23
34
|
}
|
|
24
35
|
|
|
25
36
|
warn(message: string): void {
|
|
26
|
-
|
|
37
|
+
addLog(React.createElement(WarningLog, { message }));
|
|
27
38
|
}
|
|
28
39
|
|
|
29
40
|
spinner(message: string): LoggerSpinner {
|
|
30
|
-
|
|
41
|
+
// Immediately add spinner log
|
|
42
|
+
addLog(React.createElement(SpinnerLog, { message }));
|
|
43
|
+
return new InkSpinner();
|
|
31
44
|
}
|
|
32
45
|
|
|
33
46
|
log(message: string): void {
|
|
34
|
-
|
|
47
|
+
addLog(React.createElement(Text, {}, message));
|
|
35
48
|
}
|
|
36
49
|
|
|
37
50
|
/**
|
|
@@ -41,45 +54,42 @@ export class ConsoleLogger implements ILogger {
|
|
|
41
54
|
message: string,
|
|
42
55
|
color: 'green' | 'red' | 'yellow' | 'blue' | 'cyan' | 'magenta' | 'gray'
|
|
43
56
|
): void {
|
|
44
|
-
|
|
57
|
+
addLog(React.createElement(Text, { color }, message));
|
|
45
58
|
}
|
|
46
59
|
|
|
47
60
|
/**
|
|
48
61
|
* Log bold text
|
|
49
62
|
*/
|
|
50
63
|
logBold(message: string, color?: 'green' | 'red' | 'yellow' | 'blue' | 'cyan' | 'magenta'): void {
|
|
51
|
-
|
|
52
|
-
console.log(chalk[color].bold(message));
|
|
53
|
-
} else {
|
|
54
|
-
console.log(chalk.bold(message));
|
|
55
|
-
}
|
|
64
|
+
addLog(React.createElement(Text, { bold: true, color }, message));
|
|
56
65
|
}
|
|
57
66
|
|
|
58
67
|
/**
|
|
59
68
|
* Log a separator line
|
|
60
69
|
*/
|
|
61
70
|
logSeparator(): void {
|
|
62
|
-
|
|
71
|
+
addLog(React.createElement(Text, { color: 'gray' }, '─'.repeat(50)));
|
|
63
72
|
}
|
|
64
73
|
|
|
65
74
|
/**
|
|
66
75
|
* Log an empty line
|
|
67
76
|
*/
|
|
68
77
|
logNewLine(): void {
|
|
69
|
-
|
|
78
|
+
addLog(React.createElement(EmptyLineLog));
|
|
70
79
|
}
|
|
71
80
|
|
|
72
81
|
/**
|
|
73
82
|
* Log a section header
|
|
74
83
|
*/
|
|
75
84
|
logHeader(message: string): void {
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
85
|
+
this.logNewLine();
|
|
86
|
+
addLog(React.createElement(Text, { bold: true, color: 'cyan' }, message));
|
|
87
|
+
this.logNewLine();
|
|
79
88
|
}
|
|
80
89
|
|
|
81
90
|
/**
|
|
82
91
|
* Highlight text (typically numbers) with yellow color
|
|
92
|
+
* Note: Returns styled text string for embedding in messages
|
|
83
93
|
*/
|
|
84
94
|
highlight(text: string): string {
|
|
85
95
|
return chalk.yellow(text);
|
|
@@ -87,28 +97,28 @@ export class ConsoleLogger implements ILogger {
|
|
|
87
97
|
}
|
|
88
98
|
|
|
89
99
|
/**
|
|
90
|
-
*
|
|
100
|
+
* Spinner implementation for ink-based logging
|
|
101
|
+
* Note: In ink/React rendering model, spinners are added as logs
|
|
102
|
+
* and don't need explicit start/stop/succeed/fail methods
|
|
91
103
|
*/
|
|
92
|
-
class
|
|
93
|
-
private spinner: Ora;
|
|
94
|
-
|
|
95
|
-
constructor(message: string) {
|
|
96
|
-
this.spinner = ora(message);
|
|
97
|
-
}
|
|
98
|
-
|
|
104
|
+
class InkSpinner implements LoggerSpinner {
|
|
99
105
|
start(): void {
|
|
100
|
-
|
|
106
|
+
// No-op: spinner already added to log stream
|
|
101
107
|
}
|
|
102
108
|
|
|
103
109
|
stop(): void {
|
|
104
|
-
|
|
110
|
+
// No-op: will be replaced by next log
|
|
105
111
|
}
|
|
106
112
|
|
|
107
113
|
succeed(message?: string): void {
|
|
108
|
-
|
|
114
|
+
if (message) {
|
|
115
|
+
addLog(React.createElement(SuccessLog, { message }));
|
|
116
|
+
}
|
|
109
117
|
}
|
|
110
118
|
|
|
111
119
|
fail(message?: string): void {
|
|
112
|
-
|
|
120
|
+
if (message) {
|
|
121
|
+
addLog(React.createElement(ErrorLog, { message }));
|
|
122
|
+
}
|
|
113
123
|
}
|
|
114
124
|
}
|