@poetora/cli 0.0.1 → 0.1.2

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.
Files changed (117) hide show
  1. package/.turbo/turbo-build.log +4 -0
  2. package/LICENSE +93 -0
  3. package/bin/accessibility.js +2 -2
  4. package/bin/cli-builder.d.ts +8 -0
  5. package/bin/cli-builder.js +178 -0
  6. package/bin/cli.d.ts +5 -11
  7. package/bin/cli.js +8 -200
  8. package/bin/commands/base.command.d.ts +13 -0
  9. package/bin/commands/base.command.js +40 -0
  10. package/bin/commands/check.command.d.ts +14 -0
  11. package/bin/commands/check.command.js +21 -0
  12. package/bin/commands/dev.command.d.ts +13 -0
  13. package/bin/commands/dev.command.js +40 -0
  14. package/bin/commands/index.d.ts +6 -0
  15. package/bin/commands/index.js +6 -0
  16. package/bin/commands/init.command.d.ts +16 -0
  17. package/bin/commands/init.command.js +88 -0
  18. package/bin/commands/link.command.d.ts +13 -0
  19. package/bin/commands/link.command.js +19 -0
  20. package/bin/commands/update.command.d.ts +10 -0
  21. package/bin/commands/update.command.js +13 -0
  22. package/bin/constants.js +1 -1
  23. package/bin/errors/cli-error.d.ts +26 -0
  24. package/bin/errors/cli-error.js +53 -0
  25. package/bin/errors/index.d.ts +1 -0
  26. package/bin/errors/index.js +1 -0
  27. package/bin/index.d.ts +1 -1
  28. package/bin/index.js +6 -6
  29. package/bin/mdxAccessibility.js +2 -2
  30. package/bin/services/accessibility-check.service.d.ts +10 -0
  31. package/bin/services/accessibility-check.service.js +144 -0
  32. package/bin/services/index.d.ts +7 -0
  33. package/bin/services/index.js +7 -0
  34. package/bin/services/link.service.d.ts +7 -0
  35. package/bin/services/link.service.js +40 -0
  36. package/bin/services/openapi-check.service.d.ts +7 -0
  37. package/bin/services/openapi-check.service.js +43 -0
  38. package/bin/services/port.service.d.ts +7 -0
  39. package/bin/services/port.service.js +26 -0
  40. package/bin/services/template.service.d.ts +22 -0
  41. package/bin/services/template.service.js +127 -0
  42. package/bin/services/update.service.d.ts +10 -0
  43. package/bin/services/update.service.js +57 -0
  44. package/bin/services/version.service.d.ts +16 -0
  45. package/bin/services/version.service.js +102 -0
  46. package/bin/types/common.d.ts +38 -0
  47. package/bin/types/common.js +21 -0
  48. package/bin/types/index.d.ts +2 -0
  49. package/bin/types/index.js +2 -0
  50. package/bin/types/options.d.ts +23 -0
  51. package/bin/types/options.js +1 -0
  52. package/bin/utils/console-logger.d.ts +16 -0
  53. package/bin/utils/console-logger.js +65 -0
  54. package/bin/utils/index.d.ts +2 -0
  55. package/bin/utils/index.js +2 -0
  56. package/bin/utils/logger.interface.d.ts +15 -0
  57. package/bin/utils/logger.interface.js +1 -0
  58. package/package.json +29 -29
  59. package/src/accessibility.ts +2 -2
  60. package/src/cli-builder.ts +267 -0
  61. package/src/cli.ts +15 -0
  62. package/src/commands/__tests__/base.command.test.ts +145 -0
  63. package/src/commands/__tests__/dev.command.test.ts +241 -0
  64. package/src/commands/__tests__/init.command.test.ts +281 -0
  65. package/{__test__ → src/commands/__tests__}/utils.ts +1 -1
  66. package/src/commands/base.command.ts +97 -0
  67. package/src/commands/check.command.ts +40 -0
  68. package/src/commands/dev.command.ts +63 -0
  69. package/src/commands/index.ts +6 -0
  70. package/src/commands/init.command.ts +125 -0
  71. package/src/commands/link.command.ts +39 -0
  72. package/src/commands/update.command.ts +23 -0
  73. package/src/constants.ts +1 -1
  74. package/src/errors/cli-error.ts +83 -0
  75. package/src/errors/index.ts +1 -0
  76. package/src/index.ts +6 -6
  77. package/src/mdxAccessibility.ts +3 -4
  78. package/src/services/__tests__/port.service.test.ts +83 -0
  79. package/src/services/__tests__/template.service.test.ts +234 -0
  80. package/src/services/__tests__/version.service.test.ts +165 -0
  81. package/src/services/accessibility-check.service.ts +226 -0
  82. package/src/services/index.ts +7 -0
  83. package/src/services/link.service.ts +65 -0
  84. package/src/services/openapi-check.service.ts +68 -0
  85. package/src/services/port.service.ts +47 -0
  86. package/src/services/template.service.ts +203 -0
  87. package/src/services/update.service.ts +76 -0
  88. package/src/services/version.service.ts +161 -0
  89. package/src/types/common.ts +53 -0
  90. package/src/types/index.ts +2 -0
  91. package/src/types/options.ts +42 -0
  92. package/src/utils/console-logger.ts +114 -0
  93. package/src/utils/index.ts +2 -0
  94. package/src/utils/logger.interface.ts +70 -0
  95. package/tsconfig.build.json +2 -1
  96. package/tsconfig.json +1 -1
  97. package/.prettierignore +0 -2
  98. package/__test__/brokenLinks.test.ts +0 -93
  99. package/__test__/checkPort.test.ts +0 -92
  100. package/__test__/openApiCheck.test.ts +0 -127
  101. package/__test__/update.test.ts +0 -108
  102. package/bin/accessibilityCheck.d.ts +0 -2
  103. package/bin/accessibilityCheck.js +0 -70
  104. package/bin/helpers.d.ts +0 -17
  105. package/bin/helpers.js +0 -104
  106. package/bin/init.d.ts +0 -1
  107. package/bin/init.js +0 -73
  108. package/bin/mdxLinter.d.ts +0 -2
  109. package/bin/mdxLinter.js +0 -45
  110. package/bin/update.d.ts +0 -3
  111. package/bin/update.js +0 -32
  112. package/src/accessibilityCheck.tsx +0 -145
  113. package/src/cli.tsx +0 -302
  114. package/src/helpers.tsx +0 -131
  115. package/src/init.tsx +0 -93
  116. package/src/mdxLinter.tsx +0 -88
  117. package/src/update.tsx +0 -37
@@ -0,0 +1,26 @@
1
+ import detect from 'detect-port';
2
+ import { NoAvailablePortError } from '../errors/index.js';
3
+ import { CLI_CONSTANTS } from '../types/index.js';
4
+ export class PortService {
5
+ logger;
6
+ constructor(logger) {
7
+ this.logger = logger;
8
+ }
9
+ async findAvailablePort(preferredPort) {
10
+ const startPort = preferredPort ?? CLI_CONSTANTS.PORT.DEFAULT;
11
+ for (let attempt = 0; attempt < CLI_CONSTANTS.PORT.MAX_ATTEMPTS; attempt++) {
12
+ const port = startPort + attempt;
13
+ if (await this.isPortAvailable(port)) {
14
+ if (attempt > 0 && this.logger) {
15
+ this.logger.info(`port ${startPort} is already in use. using ${port} instead`);
16
+ }
17
+ return port;
18
+ }
19
+ }
20
+ throw new NoAvailablePortError(`No available port found after ${CLI_CONSTANTS.PORT.MAX_ATTEMPTS} attempts starting from ${startPort}`);
21
+ }
22
+ async isPortAvailable(port) {
23
+ const detectedPort = await detect(port);
24
+ return detectedPort === port;
25
+ }
26
+ }
@@ -0,0 +1,22 @@
1
+ export interface DirectoryStatus {
2
+ exists: boolean;
3
+ hasContents: boolean;
4
+ }
5
+ export interface InstallTemplateParams {
6
+ directory: string;
7
+ projectName: string;
8
+ theme: string;
9
+ }
10
+ export declare class TemplateService {
11
+ private readonly TEMPLATE_URL;
12
+ private readonly TEMP_ZIP_PATH;
13
+ private readonly TEMP_EXTRACT_DIR;
14
+ checkDirectory(directory: string): Promise<DirectoryStatus>;
15
+ getAvailableThemes(): string[];
16
+ installTemplate(params: InstallTemplateParams): Promise<void>;
17
+ private downloadTemplate;
18
+ private extractTemplate;
19
+ private copyTemplateFiles;
20
+ private updateDocsConfig;
21
+ private cleanup;
22
+ }
@@ -0,0 +1,127 @@
1
+ import * as fs from 'node:fs';
2
+ import * as path from 'node:path';
3
+ import { docsConfigSchema } from '@poetora/validation';
4
+ import AdmZip from 'adm-zip';
5
+ import * as fse from 'fs-extra';
6
+ import { ExternalServiceError, FileSystemError } from '../errors/index.js';
7
+ export class TemplateService {
8
+ TEMPLATE_URL = 'https://github.com/poetora/starter/archive/refs/heads/main.zip';
9
+ TEMP_ZIP_PATH = 'poetora-starter.zip';
10
+ TEMP_EXTRACT_DIR = 'poetora-starter-temp';
11
+ async checkDirectory(directory) {
12
+ try {
13
+ await fse.ensureDir(directory);
14
+ const files = await fs.promises.readdir(directory);
15
+ const hasContents = files.length > 0;
16
+ return {
17
+ exists: true,
18
+ hasContents,
19
+ };
20
+ }
21
+ catch (error) {
22
+ if (error.code === 'ENOENT') {
23
+ return {
24
+ exists: false,
25
+ hasContents: false,
26
+ };
27
+ }
28
+ throw new FileSystemError(`Failed to check directory: ${error.message}`);
29
+ }
30
+ }
31
+ getAvailableThemes() {
32
+ const themes = docsConfigSchema.options
33
+ .map((option) => {
34
+ const themeField = option.shape?.theme;
35
+ if (themeField?._def && 'value' in themeField._def) {
36
+ return themeField._def.value;
37
+ }
38
+ return null;
39
+ })
40
+ .filter((theme) => theme !== null);
41
+ return themes.length > 0 ? themes : ['ora'];
42
+ }
43
+ async installTemplate(params) {
44
+ const { directory, projectName, theme } = params;
45
+ try {
46
+ await this.downloadTemplate();
47
+ await this.extractTemplate();
48
+ await this.copyTemplateFiles(directory);
49
+ await this.updateDocsConfig(directory, projectName, theme);
50
+ await this.cleanup();
51
+ }
52
+ catch (error) {
53
+ await this.cleanup();
54
+ throw error;
55
+ }
56
+ }
57
+ async downloadTemplate() {
58
+ try {
59
+ const response = await fetch(this.TEMPLATE_URL);
60
+ if (!response.ok) {
61
+ throw new ExternalServiceError(`Failed to download template: HTTP ${response.status} ${response.statusText}`);
62
+ }
63
+ const arrayBuffer = await response.arrayBuffer();
64
+ const buffer = Buffer.from(arrayBuffer);
65
+ await fs.promises.writeFile(this.TEMP_ZIP_PATH, buffer);
66
+ }
67
+ catch (error) {
68
+ if (error instanceof ExternalServiceError) {
69
+ throw error;
70
+ }
71
+ throw new ExternalServiceError(`Failed to download template: ${error.message}`);
72
+ }
73
+ }
74
+ async extractTemplate() {
75
+ try {
76
+ const zip = new AdmZip(this.TEMP_ZIP_PATH);
77
+ zip.extractAllTo(this.TEMP_EXTRACT_DIR, true);
78
+ }
79
+ catch (error) {
80
+ throw new FileSystemError(`Failed to extract template: ${error.message}`);
81
+ }
82
+ }
83
+ async copyTemplateFiles(targetDir) {
84
+ try {
85
+ const extractedFolder = path.join(this.TEMP_EXTRACT_DIR, 'starter-main');
86
+ await fse.ensureDir(targetDir);
87
+ await fse.copy(extractedFolder, targetDir, {
88
+ overwrite: true,
89
+ errorOnExist: false,
90
+ });
91
+ }
92
+ catch (error) {
93
+ throw new FileSystemError(`Failed to copy template files: ${error.message}`);
94
+ }
95
+ }
96
+ async updateDocsConfig(directory, projectName, theme) {
97
+ try {
98
+ const configPath = path.join(directory, 'docs.json');
99
+ let config;
100
+ try {
101
+ const configContent = await fs.promises.readFile(configPath, 'utf-8');
102
+ config = JSON.parse(configContent);
103
+ }
104
+ catch {
105
+ config = {};
106
+ }
107
+ config.name = projectName;
108
+ config.theme = theme;
109
+ await fs.promises.writeFile(configPath, JSON.stringify(config, null, 2), 'utf-8');
110
+ }
111
+ catch (error) {
112
+ throw new FileSystemError(`Failed to update docs.json: ${error.message}`);
113
+ }
114
+ }
115
+ async cleanup() {
116
+ try {
117
+ await Promise.all([
118
+ fse.remove(this.TEMP_ZIP_PATH).catch(() => {
119
+ }),
120
+ fse.remove(this.TEMP_EXTRACT_DIR).catch(() => {
121
+ }),
122
+ ]);
123
+ }
124
+ catch {
125
+ }
126
+ }
127
+ }
@@ -0,0 +1,10 @@
1
+ import type { ILogger } from '../utils/index.js';
2
+ import type { VersionService } from './version.service.js';
3
+ export declare class UpdateService {
4
+ private readonly logger;
5
+ private readonly versionService;
6
+ private readonly packageName;
7
+ constructor(logger: ILogger, versionService: VersionService, packageName: string);
8
+ update(): Promise<void>;
9
+ private detectPackageManager;
10
+ }
@@ -0,0 +1,57 @@
1
+ import { exec } from 'node:child_process';
2
+ import { promisify } from 'node:util';
3
+ import { ExternalServiceError } from '../errors/index.js';
4
+ const execAsync = promisify(exec);
5
+ export class UpdateService {
6
+ logger;
7
+ versionService;
8
+ packageName;
9
+ constructor(logger, versionService, packageName) {
10
+ this.logger = logger;
11
+ this.versionService = versionService;
12
+ this.packageName = packageName;
13
+ }
14
+ async update() {
15
+ const spinner = this.logger.spinner('checking for updates...');
16
+ spinner.start();
17
+ const existingCliVersion = this.versionService.getCliVersion();
18
+ const latestCliVersion = this.versionService.getLatestCliVersion(this.packageName);
19
+ const isUpToDate = existingCliVersion &&
20
+ latestCliVersion &&
21
+ latestCliVersion.trim() === existingCliVersion.trim();
22
+ if (isUpToDate) {
23
+ spinner.succeed('already up to date');
24
+ return;
25
+ }
26
+ if (existingCliVersion && latestCliVersion.trim() !== existingCliVersion.trim()) {
27
+ try {
28
+ spinner.stop();
29
+ const updateSpinner = this.logger.spinner(`updating ${this.packageName} package...`);
30
+ updateSpinner.start();
31
+ const packageManager = await this.detectPackageManager();
32
+ if (packageManager === 'pnpm') {
33
+ await execAsync(`pnpm install -g ${this.packageName}@latest --silent`);
34
+ }
35
+ else {
36
+ await execAsync(`npm install -g ${this.packageName}@latest --silent`);
37
+ }
38
+ updateSpinner.succeed(`updated ${this.packageName} to version ${this.logger.highlight?.(latestCliVersion) ?? latestCliVersion}`);
39
+ }
40
+ catch (_err) {
41
+ throw new ExternalServiceError(`failed to update ${this.packageName}@latest`);
42
+ }
43
+ }
44
+ }
45
+ async detectPackageManager() {
46
+ try {
47
+ const { stdout: packagePath } = await execAsync(`which ${this.packageName}`);
48
+ if (packagePath.includes('pnpm')) {
49
+ return 'pnpm';
50
+ }
51
+ return 'npm';
52
+ }
53
+ catch (_error) {
54
+ return 'npm';
55
+ }
56
+ }
57
+ }
@@ -0,0 +1,16 @@
1
+ import { type NodeVersion, type ValidationResult } from '../types/index.js';
2
+ export declare class VersionService {
3
+ private readonly packageName;
4
+ constructor(packageName?: string);
5
+ parseNodeVersion(): NodeVersion;
6
+ checkNodeVersion(): ValidationResult;
7
+ getCliVersion(): string | undefined;
8
+ getClientVersion(): string;
9
+ getVersions(): {
10
+ cli: string | undefined;
11
+ client: string;
12
+ };
13
+ getLatestCliVersion(packageName: string): string;
14
+ isVersionUpToDate(currentVersion: string, latestVersion: string): boolean;
15
+ validateNodeVersion(): void;
16
+ }
@@ -0,0 +1,102 @@
1
+ import { execSync } from 'node:child_process';
2
+ import { getClientVersion, LOCAL_LINKED_CLI_VERSION } from '@poetora/previewing';
3
+ import yargs from 'yargs';
4
+ import { InvalidEnvironmentError } from '../errors/index.js';
5
+ import { CLI_CONSTANTS } from '../types/index.js';
6
+ export class VersionService {
7
+ packageName;
8
+ constructor(packageName = 'poet') {
9
+ this.packageName = packageName;
10
+ }
11
+ parseNodeVersion() {
12
+ let versionString = process.version;
13
+ if (versionString.charAt(0) === 'v') {
14
+ versionString = versionString.slice(1);
15
+ }
16
+ const parts = versionString.split('.');
17
+ const major = parseInt(parts[0] ?? '0', 10);
18
+ const minor = parseInt(parts[1] ?? '0', 10);
19
+ const patch = parseInt(parts[2] ?? '0', 10);
20
+ return {
21
+ major,
22
+ minor,
23
+ patch,
24
+ raw: versionString,
25
+ };
26
+ }
27
+ checkNodeVersion() {
28
+ const current = this.parseNodeVersion();
29
+ const { MIN_MAJOR, MIN_MINOR, MAX_MAJOR, RECOMMENDED_MAJOR, RECOMMENDED_MINOR } = CLI_CONSTANTS.NODE_VERSION;
30
+ if (current.major < MIN_MAJOR || (current.major === MIN_MAJOR && current.minor < MIN_MINOR)) {
31
+ return {
32
+ isValid: false,
33
+ hasWarning: false,
34
+ message: `${this.packageName} requires Node.js ${MIN_MAJOR}.${MIN_MINOR}.0 or higher (current version ${current.raw}). Please upgrade Node.js and try again.`,
35
+ };
36
+ }
37
+ if (current.major > MAX_MAJOR) {
38
+ return {
39
+ isValid: false,
40
+ hasWarning: false,
41
+ message: `${this.packageName} is not supported on Node.js ${current.major}.x. Please use an LTS version (${MIN_MAJOR}-${MAX_MAJOR}).`,
42
+ };
43
+ }
44
+ if (current.major < RECOMMENDED_MAJOR ||
45
+ (current.major === RECOMMENDED_MAJOR && current.minor < RECOMMENDED_MINOR)) {
46
+ return {
47
+ isValid: true,
48
+ hasWarning: true,
49
+ message: `Node.js ${RECOMMENDED_MAJOR}.${RECOMMENDED_MINOR}.0 or higher is recommended for best compatibility (current: ${current.raw}).`,
50
+ };
51
+ }
52
+ return {
53
+ isValid: true,
54
+ hasWarning: false,
55
+ };
56
+ }
57
+ getCliVersion() {
58
+ if (process.env.CLI_TEST_MODE === 'true') {
59
+ return 'test-cli';
60
+ }
61
+ const y = yargs();
62
+ let version;
63
+ y.showVersion((v) => {
64
+ version = v;
65
+ return false;
66
+ });
67
+ if (version === 'unknown') {
68
+ version = LOCAL_LINKED_CLI_VERSION;
69
+ }
70
+ return version;
71
+ }
72
+ getClientVersion() {
73
+ return getClientVersion().trim();
74
+ }
75
+ getVersions() {
76
+ return {
77
+ cli: this.getCliVersion(),
78
+ client: this.getClientVersion(),
79
+ };
80
+ }
81
+ getLatestCliVersion(packageName) {
82
+ try {
83
+ const version = execSync(`npm view ${packageName} version --silent`, {
84
+ encoding: 'utf-8',
85
+ stdio: ['pipe', 'pipe', 'pipe'],
86
+ }).trim();
87
+ return version;
88
+ }
89
+ catch (error) {
90
+ throw new Error(`Failed to fetch latest version for ${packageName}: ${error instanceof Error ? error.message : 'unknown error'}`);
91
+ }
92
+ }
93
+ isVersionUpToDate(currentVersion, latestVersion) {
94
+ return currentVersion.trim() === latestVersion.trim();
95
+ }
96
+ validateNodeVersion() {
97
+ const result = this.checkNodeVersion();
98
+ if (!result.isValid) {
99
+ throw new InvalidEnvironmentError(result.message ?? 'Unsupported Node.js version');
100
+ }
101
+ }
102
+ }
@@ -0,0 +1,38 @@
1
+ export declare const CLI_CONSTANTS: {
2
+ readonly PORT: {
3
+ readonly DEFAULT: 3000;
4
+ readonly MAX_ATTEMPTS: 10;
5
+ };
6
+ readonly NODE_VERSION: {
7
+ readonly MIN_MAJOR: 18;
8
+ readonly MIN_MINOR: 0;
9
+ readonly MAX_MAJOR: 24;
10
+ readonly MAX_MINOR: number;
11
+ readonly RECOMMENDED_MAJOR: 20;
12
+ readonly RECOMMENDED_MINOR: 17;
13
+ };
14
+ readonly TIMEOUT: {
15
+ readonly PROCESS_KILL: 5000;
16
+ readonly LOG_RENDER: 50;
17
+ };
18
+ readonly UPDATE: {
19
+ readonly CHECK_INTERVAL: 86400000;
20
+ };
21
+ };
22
+ export interface NodeVersion {
23
+ major: number;
24
+ minor: number;
25
+ patch: number;
26
+ raw: string;
27
+ }
28
+ export interface ValidationResult {
29
+ isValid: boolean;
30
+ hasWarning: boolean;
31
+ message?: string;
32
+ }
33
+ export interface LoggerSpinner {
34
+ start(): void;
35
+ stop(): void;
36
+ succeed(message?: string): void;
37
+ fail(message?: string): void;
38
+ }
@@ -0,0 +1,21 @@
1
+ export const CLI_CONSTANTS = {
2
+ PORT: {
3
+ DEFAULT: 3000,
4
+ MAX_ATTEMPTS: 10,
5
+ },
6
+ NODE_VERSION: {
7
+ MIN_MAJOR: 18,
8
+ MIN_MINOR: 0,
9
+ MAX_MAJOR: 24,
10
+ MAX_MINOR: Number.MAX_SAFE_INTEGER,
11
+ RECOMMENDED_MAJOR: 20,
12
+ RECOMMENDED_MINOR: 17,
13
+ },
14
+ TIMEOUT: {
15
+ PROCESS_KILL: 5000,
16
+ LOG_RENDER: 50,
17
+ },
18
+ UPDATE: {
19
+ CHECK_INTERVAL: 86400000,
20
+ },
21
+ };
@@ -0,0 +1,2 @@
1
+ export * from './common.js';
2
+ export * from './options.js';
@@ -0,0 +1,2 @@
1
+ export * from './common.js';
2
+ export * from './options.js';
@@ -0,0 +1,23 @@
1
+ export interface DevOptions {
2
+ port?: number;
3
+ open?: boolean;
4
+ localSchema?: boolean;
5
+ clientVersion?: string;
6
+ groups?: string[];
7
+ disableOpenapi?: boolean;
8
+ }
9
+ export interface InitOptions {
10
+ directory: string;
11
+ }
12
+ export interface OpenApiCheckOptions {
13
+ filename: string;
14
+ localSchema?: boolean;
15
+ }
16
+ export interface RenameOptions {
17
+ from: string;
18
+ to: string;
19
+ force?: boolean;
20
+ }
21
+ export interface UpdateOptions {
22
+ packageName: string;
23
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,16 @@
1
+ import type { LoggerSpinner } from '../types/index.js';
2
+ import type { ILogger } from './logger.interface.js';
3
+ export declare class ConsoleLogger implements ILogger {
4
+ info(message: string): void;
5
+ success(message: string): void;
6
+ error(message: string): void;
7
+ warn(message: string): void;
8
+ spinner(message: string): LoggerSpinner;
9
+ log(message: string): void;
10
+ logColor(message: string, color: 'green' | 'red' | 'yellow' | 'blue' | 'cyan' | 'magenta' | 'gray'): void;
11
+ logBold(message: string, color?: 'green' | 'red' | 'yellow' | 'blue' | 'cyan' | 'magenta'): void;
12
+ logSeparator(): void;
13
+ logNewLine(): void;
14
+ logHeader(message: string): void;
15
+ highlight(text: string): string;
16
+ }
@@ -0,0 +1,65 @@
1
+ import chalk from 'chalk';
2
+ import ora from 'ora';
3
+ export class ConsoleLogger {
4
+ info(message) {
5
+ console.log(chalk.blue(`ℹ ${message}`));
6
+ }
7
+ success(message) {
8
+ console.log(chalk.green(`✓ ${message}`));
9
+ }
10
+ error(message) {
11
+ console.error(chalk.red(`✗ ${message}`));
12
+ }
13
+ warn(message) {
14
+ console.warn(chalk.yellow(`⚠ ${message}`));
15
+ }
16
+ spinner(message) {
17
+ return new ConsoleSpinner(message);
18
+ }
19
+ log(message) {
20
+ console.log(message);
21
+ }
22
+ logColor(message, color) {
23
+ console.log(chalk[color](message));
24
+ }
25
+ logBold(message, color) {
26
+ if (color) {
27
+ console.log(chalk[color].bold(message));
28
+ }
29
+ else {
30
+ console.log(chalk.bold(message));
31
+ }
32
+ }
33
+ logSeparator() {
34
+ console.log(chalk.gray('─'.repeat(50)));
35
+ }
36
+ logNewLine() {
37
+ console.log();
38
+ }
39
+ logHeader(message) {
40
+ console.log();
41
+ console.log(chalk.bold.cyan(message));
42
+ console.log();
43
+ }
44
+ highlight(text) {
45
+ return chalk.yellow(text);
46
+ }
47
+ }
48
+ class ConsoleSpinner {
49
+ spinner;
50
+ constructor(message) {
51
+ this.spinner = ora(message);
52
+ }
53
+ start() {
54
+ this.spinner.start();
55
+ }
56
+ stop() {
57
+ this.spinner.stop();
58
+ }
59
+ succeed(message) {
60
+ this.spinner.succeed(message);
61
+ }
62
+ fail(message) {
63
+ this.spinner.fail(message);
64
+ }
65
+ }
@@ -0,0 +1,2 @@
1
+ export * from './console-logger.js';
2
+ export * from './logger.interface.js';
@@ -0,0 +1,2 @@
1
+ export * from './console-logger.js';
2
+ export * from './logger.interface.js';
@@ -0,0 +1,15 @@
1
+ import type { LoggerSpinner } from '../types/index.js';
2
+ export interface ILogger {
3
+ info(message: string): void;
4
+ success(message: string): void;
5
+ error(message: string): void;
6
+ warn(message: string): void;
7
+ spinner(message: string): LoggerSpinner;
8
+ log(message: string): void;
9
+ logColor(message: string, color: 'green' | 'red' | 'yellow' | 'blue' | 'cyan' | 'magenta' | 'gray'): void;
10
+ logBold(message: string, color?: 'green' | 'red' | 'yellow' | 'blue' | 'cyan' | 'magenta'): void;
11
+ logSeparator(): void;
12
+ logNewLine(): void;
13
+ logHeader(message: string): void;
14
+ highlight?(text: string): string;
15
+ }
@@ -0,0 +1 @@
1
+ export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@poetora/cli",
3
- "version": "0.0.1",
3
+ "version": "0.1.2",
4
4
  "description": "The CLI for Poetora documentation Engine",
5
5
  "engines": {
6
6
  "node": ">=18.0.0"
@@ -25,41 +25,29 @@
25
25
  "poet": "bin/index.js",
26
26
  "poetora": "bin/index.js"
27
27
  },
28
- "scripts": {
29
- "dev": "pnpm build && NODE_NO_WARNINGS=1 node bin/index.js",
30
- "build": "tsc --project tsconfig.build.json",
31
- "clean:build": "rimraf bin",
32
- "clean:all": "rimraf node_modules .eslintcache && pnpm clean:build",
33
- "watch": "tsc --watch",
34
- "test": "vitest run",
35
- "type": "tsc --noEmit",
36
- "format": "prettier . --write",
37
- "format:check": "prettier . --check"
38
- },
39
28
  "dependencies": {
40
29
  "@inquirer/prompts": "7.9.0",
41
- "@poetora/link-rot": "workspace:*",
42
- "@poetora/prebuild": "workspace:*",
43
- "@poetora/previewing": "workspace:*",
44
- "@poetora/shared": "workspace:*",
45
- "@poetora/validation": "workspace:*",
46
30
  "adm-zip": "0.5.16",
47
31
  "chalk": "5.2.0",
48
32
  "color": "4.2.3",
49
33
  "detect-port": "1.5.1",
50
34
  "front-matter": "4.0.2",
51
35
  "fs-extra": "11.2.0",
52
- "ink": "6.3.0",
53
36
  "inquirer": "12.3.0",
54
37
  "js-yaml": "4.1.0",
55
38
  "mdast-util-mdx-jsx": "3.2.0",
39
+ "ora": "^9.0.0",
56
40
  "react": "19.2.1",
57
41
  "semver": "7.7.2",
58
42
  "unist-util-visit": "5.0.0",
59
- "yargs": "17.7.1"
43
+ "yargs": "17.7.1",
44
+ "@poetora/prebuild": "0.1.0",
45
+ "@poetora/link-rot": "0.0.1",
46
+ "@poetora/shared": "0.1.0",
47
+ "@poetora/previewing": "0.1.0",
48
+ "@poetora/validation": "0.1.0"
60
49
  },
61
50
  "devDependencies": {
62
- "@trivago/prettier-plugin-sort-imports": "4.3.0",
63
51
  "@tsconfig/recommended": "1.0.2",
64
52
  "@types/adm-zip": "0.5.7",
65
53
  "@types/color": "^3.0.3",
@@ -67,17 +55,29 @@
67
55
  "@types/fs-extra": "^9.0.13",
68
56
  "@types/js-yaml": "^4.0.9",
69
57
  "@types/mdast": "4.0.4",
70
- "@types/node": "catalog:",
58
+ "@types/node": "22.19.2",
71
59
  "@types/yargs": "17.0.22",
72
- "@typescript-eslint/eslint-plugin": "catalog:",
73
- "@typescript-eslint/parser": "catalog:",
74
- "eslint": "catalog:",
75
- "eslint-config-prettier": "catalog:",
60
+ "@typescript-eslint/eslint-plugin": "8.49.0",
61
+ "@typescript-eslint/parser": "8.49.0",
62
+ "eslint": "9.39.1",
63
+ "eslint-config-prettier": "10.1.2",
76
64
  "openapi-types": "12.1.3",
77
- "prettier": "3.1.1",
78
65
  "rimraf": "5.0.1",
79
- "typescript": "catalog:",
80
- "vitest": "catalog:",
66
+ "typescript": "5.9.3",
67
+ "vitest": "4.0.15",
81
68
  "vitest-mock-process": "1.0.4"
69
+ },
70
+ "scripts": {
71
+ "dev": "pnpm build && NODE_NO_WARNINGS=1 node bin/index.js",
72
+ "build": "tsc --project tsconfig.build.json",
73
+ "clean:build": "rimraf bin",
74
+ "clean:all": "rimraf node_modules .eslintcache && pnpm clean:build",
75
+ "watch": "tsc --watch",
76
+ "test": "vitest run",
77
+ "type": "tsc --noEmit",
78
+ "format": "biome format --write .",
79
+ "format:check": "biome format .",
80
+ "lint:biome": "biome lint .",
81
+ "check": "biome check --write ."
82
82
  }
83
- }
83
+ }