@guiho/xdocs 0.1.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.
- package/CHANGELOG.md +1 -0
- package/LICENSE.md +23 -0
- package/jsr.json +12 -0
- package/library/cli.d.ts +8 -0
- package/library/cli.d.ts.map +1 -0
- package/library/cli.js +97 -0
- package/library/commands/generate.d.ts +7 -0
- package/library/commands/generate.d.ts.map +1 -0
- package/library/commands/generate.js +122 -0
- package/library/commands/init.d.ts +7 -0
- package/library/commands/init.d.ts.map +1 -0
- package/library/commands/init.js +71 -0
- package/library/commands/list.d.ts +7 -0
- package/library/commands/list.d.ts.map +1 -0
- package/library/commands/list.js +41 -0
- package/library/commands/merge.d.ts +7 -0
- package/library/commands/merge.d.ts.map +1 -0
- package/library/commands/merge.js +55 -0
- package/library/commands/prompt.d.ts +7 -0
- package/library/commands/prompt.d.ts.map +1 -0
- package/library/commands/prompt.js +19 -0
- package/library/commands/scan.d.ts +7 -0
- package/library/commands/scan.d.ts.map +1 -0
- package/library/commands/scan.js +53 -0
- package/library/commands/tree.d.ts +7 -0
- package/library/commands/tree.d.ts.map +1 -0
- package/library/commands/tree.js +49 -0
- package/library/config.d.ts +24 -0
- package/library/config.d.ts.map +1 -0
- package/library/config.js +126 -0
- package/library/discovery.d.ts +13 -0
- package/library/discovery.d.ts.map +1 -0
- package/library/discovery.js +118 -0
- package/library/errors.d.ts +9 -0
- package/library/errors.d.ts.map +1 -0
- package/library/errors.js +15 -0
- package/library/flags.d.ts +23 -0
- package/library/flags.d.ts.map +1 -0
- package/library/flags.js +96 -0
- package/library/guiho-xdocs-bin.d.ts +6 -0
- package/library/guiho-xdocs-bin.d.ts.map +1 -0
- package/library/guiho-xdocs-bin.js +6 -0
- package/library/guiho-xdocs.d.ts +14 -0
- package/library/guiho-xdocs.d.ts.map +1 -0
- package/library/guiho-xdocs.js +21 -0
- package/library/help.d.ts +12 -0
- package/library/help.d.ts.map +1 -0
- package/library/help.js +165 -0
- package/library/metadata.d.ts +22 -0
- package/library/metadata.d.ts.map +1 -0
- package/library/metadata.js +110 -0
- package/library/prompts.d.ts +15 -0
- package/library/prompts.d.ts.map +1 -0
- package/library/prompts.js +49 -0
- package/library/tree.d.ts +13 -0
- package/library/tree.d.ts.map +1 -0
- package/library/tree.js +114 -0
- package/library/types.d.ts +108 -0
- package/library/types.d.ts.map +1 -0
- package/library/types.js +4 -0
- package/package.json +77 -0
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @copyright Copyright (c) 2026 GUIHO Technologies as represented by Cristóvão GUIHO. All Rights Reserved.
|
|
3
|
+
*/
|
|
4
|
+
import type { XDocsCliOptions, XDocsConfig, XDocsRawConfig } from './types.js';
|
|
5
|
+
/** Discover the xdocs.config.toml file. */
|
|
6
|
+
export declare const discoverConfig: (cwd: string, explicitPath?: string) => Promise<{
|
|
7
|
+
path?: string;
|
|
8
|
+
raw?: XDocsRawConfig;
|
|
9
|
+
}>;
|
|
10
|
+
/** Load and normalize the xdocs configuration. */
|
|
11
|
+
export declare const loadConfig: (options: XDocsCliOptions) => Promise<XDocsConfig>;
|
|
12
|
+
/** Load config if it exists, otherwise return defaults. */
|
|
13
|
+
export declare const loadConfigOrDefaults: (options: XDocsCliOptions) => Promise<XDocsConfig>;
|
|
14
|
+
/** Normalize raw TOML config into validated XDocsConfig. */
|
|
15
|
+
export declare const normalizeConfig: (raw: XDocsRawConfig, cwd: string, configPath?: string) => XDocsConfig;
|
|
16
|
+
/** Create a default config object for a given cwd. */
|
|
17
|
+
export declare const defaultConfig: (cwd: string) => XDocsConfig;
|
|
18
|
+
/** Generate the default xdocs.config.toml content. */
|
|
19
|
+
export declare const createDefaultConfigContent: (cwd: string) => string;
|
|
20
|
+
/** Write the default xdocs.config.toml to disk. */
|
|
21
|
+
export declare const writeDefaultConfig: (cwd: string, overwrite?: boolean) => Promise<string>;
|
|
22
|
+
/** Resolve a path relative to cwd if not absolute. */
|
|
23
|
+
export declare const resolvePath: (cwd: string, path: string) => string;
|
|
24
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../source/config.ts"],"names":[],"mappings":"AAAA;;GAEG;AAMH,OAAO,KAAK,EAAe,eAAe,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;AAQ3F,2CAA2C;AAC3C,eAAO,MAAM,cAAc,GAAU,KAAK,MAAM,EAAE,eAAe,MAAM,KAAG,OAAO,CAAC;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,cAAc,CAAA;CAAE,CAaxH,CAAA;AAED,kDAAkD;AAClD,eAAO,MAAM,UAAU,GAAU,SAAS,eAAe,KAAG,OAAO,CAAC,WAAW,CAS9E,CAAA;AAED,2DAA2D;AAC3D,eAAO,MAAM,oBAAoB,GAAU,SAAS,eAAe,KAAG,OAAO,CAAC,WAAW,CAOxF,CAAA;AAED,4DAA4D;AAC5D,eAAO,MAAM,eAAe,GAAI,KAAK,cAAc,EAAE,KAAK,MAAM,EAAE,aAAa,MAAM,KAAG,WA6BvF,CAAA;AAED,sDAAsD;AACtD,eAAO,MAAM,aAAa,GAAI,KAAK,MAAM,KAAG,WAO1C,CAAA;AAEF,sDAAsD;AACtD,eAAO,MAAM,0BAA0B,GAAI,KAAK,MAAM,KAAG,MAiBxD,CAAA;AAED,mDAAmD;AACnD,eAAO,MAAM,kBAAkB,GAAU,KAAK,MAAM,EAAE,mBAAiB,KAAG,OAAO,CAAC,MAAM,CASvF,CAAA;AAuBD,sDAAsD;AACtD,eAAO,MAAM,WAAW,GAAI,KAAK,MAAM,EAAE,MAAM,MAAM,WACP,CAAA"}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @copyright Copyright (c) 2026 GUIHO Technologies as represented by Cristóvão GUIHO. All Rights Reserved.
|
|
3
|
+
*/
|
|
4
|
+
import { existsSync } from 'node:fs';
|
|
5
|
+
import { readFile, writeFile } from 'node:fs/promises';
|
|
6
|
+
import { basename, isAbsolute, resolve } from 'node:path';
|
|
7
|
+
import { parse as parseToml } from 'smol-toml';
|
|
8
|
+
import { XDocsError } from './errors.js';
|
|
9
|
+
const DEFAULT_EXTENSIONS = ['.docs.md', '.xdocs.md'];
|
|
10
|
+
const DEFAULT_EXCLUDE = ['node_modules', '.git', 'dist', 'build', 'library', 'bin', 'bundle'];
|
|
11
|
+
const DEFAULT_AI_MODE = 'prompt';
|
|
12
|
+
const CONFIG_FILENAME = 'xdocs.config.toml';
|
|
13
|
+
/** Discover the xdocs.config.toml file. */
|
|
14
|
+
export const discoverConfig = async (cwd, explicitPath) => {
|
|
15
|
+
if (explicitPath) {
|
|
16
|
+
const configPath = resolvePath(cwd, explicitPath);
|
|
17
|
+
return { path: configPath, raw: await readConfigFile(configPath) };
|
|
18
|
+
}
|
|
19
|
+
const rootPath = resolve(cwd, CONFIG_FILENAME);
|
|
20
|
+
if (existsSync(rootPath))
|
|
21
|
+
return { path: rootPath, raw: await readConfigFile(rootPath) };
|
|
22
|
+
const nestedPath = resolve(cwd, 'config', CONFIG_FILENAME);
|
|
23
|
+
if (existsSync(nestedPath))
|
|
24
|
+
return { path: nestedPath, raw: await readConfigFile(nestedPath) };
|
|
25
|
+
return {};
|
|
26
|
+
};
|
|
27
|
+
/** Load and normalize the xdocs configuration. */
|
|
28
|
+
export const loadConfig = async (options) => {
|
|
29
|
+
const cwd = resolve(options.cwd);
|
|
30
|
+
const discovered = await discoverConfig(cwd, options.config);
|
|
31
|
+
if (!discovered.raw) {
|
|
32
|
+
throw new XDocsError(`xdocs configuration not found. Run \`xdocs init\` to create one.`);
|
|
33
|
+
}
|
|
34
|
+
return normalizeConfig(discovered.raw, cwd, discovered.path);
|
|
35
|
+
};
|
|
36
|
+
/** Load config if it exists, otherwise return defaults. */
|
|
37
|
+
export const loadConfigOrDefaults = async (options) => {
|
|
38
|
+
const cwd = resolve(options.cwd);
|
|
39
|
+
const discovered = await discoverConfig(cwd, options.config);
|
|
40
|
+
if (!discovered.raw)
|
|
41
|
+
return defaultConfig(cwd);
|
|
42
|
+
return normalizeConfig(discovered.raw, cwd, discovered.path);
|
|
43
|
+
};
|
|
44
|
+
/** Normalize raw TOML config into validated XDocsConfig. */
|
|
45
|
+
export const normalizeConfig = (raw, cwd, configPath) => {
|
|
46
|
+
if (raw.schema !== undefined && raw.schema !== 1) {
|
|
47
|
+
throw new XDocsError('Unsupported configuration schema. Expected `schema = 1`.');
|
|
48
|
+
}
|
|
49
|
+
const aiMode = raw.ai?.mode;
|
|
50
|
+
if (aiMode !== undefined && aiMode !== 'prompt' && aiMode !== 'auto') {
|
|
51
|
+
throw new XDocsError(`Invalid ai.mode: "${aiMode}". Expected "prompt" or "auto".`);
|
|
52
|
+
}
|
|
53
|
+
const extensions = raw.extensions?.supported ?? DEFAULT_EXTENSIONS;
|
|
54
|
+
if (!Array.isArray(extensions) || extensions.some((ext) => typeof ext !== 'string')) {
|
|
55
|
+
throw new XDocsError('Invalid extensions.supported. Expected an array of strings.');
|
|
56
|
+
}
|
|
57
|
+
const exclude = raw.scan?.exclude ?? DEFAULT_EXCLUDE;
|
|
58
|
+
if (!Array.isArray(exclude) || exclude.some((dir) => typeof dir !== 'string')) {
|
|
59
|
+
throw new XDocsError('Invalid scan.exclude. Expected an array of strings.');
|
|
60
|
+
}
|
|
61
|
+
return {
|
|
62
|
+
schema: 1,
|
|
63
|
+
cwd,
|
|
64
|
+
configPath,
|
|
65
|
+
extensions: { supported: extensions },
|
|
66
|
+
ai: { mode: aiMode ?? DEFAULT_AI_MODE },
|
|
67
|
+
scan: { exclude },
|
|
68
|
+
project: { name: raw.project?.name ?? basename(cwd) },
|
|
69
|
+
};
|
|
70
|
+
};
|
|
71
|
+
/** Create a default config object for a given cwd. */
|
|
72
|
+
export const defaultConfig = (cwd) => ({
|
|
73
|
+
schema: 1,
|
|
74
|
+
cwd,
|
|
75
|
+
extensions: { supported: DEFAULT_EXTENSIONS },
|
|
76
|
+
ai: { mode: DEFAULT_AI_MODE },
|
|
77
|
+
scan: { exclude: DEFAULT_EXCLUDE },
|
|
78
|
+
project: { name: basename(cwd) },
|
|
79
|
+
});
|
|
80
|
+
/** Generate the default xdocs.config.toml content. */
|
|
81
|
+
export const createDefaultConfigContent = (cwd) => {
|
|
82
|
+
const name = basename(cwd);
|
|
83
|
+
return `schema = 1
|
|
84
|
+
|
|
85
|
+
[extensions]
|
|
86
|
+
supported = [".docs.md", ".xdocs.md"]
|
|
87
|
+
|
|
88
|
+
[ai]
|
|
89
|
+
mode = "prompt"
|
|
90
|
+
|
|
91
|
+
[scan]
|
|
92
|
+
exclude = ["node_modules", ".git", "dist", "build", "library", "bin", "bundle"]
|
|
93
|
+
|
|
94
|
+
[project]
|
|
95
|
+
name = "${name}"
|
|
96
|
+
`;
|
|
97
|
+
};
|
|
98
|
+
/** Write the default xdocs.config.toml to disk. */
|
|
99
|
+
export const writeDefaultConfig = async (cwd, overwrite = false) => {
|
|
100
|
+
const path = resolve(cwd, CONFIG_FILENAME);
|
|
101
|
+
if (existsSync(path) && !overwrite) {
|
|
102
|
+
throw new XDocsError(`Configuration already exists: ${path}`);
|
|
103
|
+
}
|
|
104
|
+
await writeFile(path, createDefaultConfigContent(cwd), 'utf8');
|
|
105
|
+
return path;
|
|
106
|
+
};
|
|
107
|
+
/** Read and parse a TOML config file. */
|
|
108
|
+
const readConfigFile = async (path) => {
|
|
109
|
+
if (!existsSync(path))
|
|
110
|
+
throw new XDocsError(`Configuration file not found: ${path}`);
|
|
111
|
+
const content = await readFile(path, 'utf8');
|
|
112
|
+
let parsed;
|
|
113
|
+
try {
|
|
114
|
+
parsed = parseToml(content);
|
|
115
|
+
}
|
|
116
|
+
catch (error) {
|
|
117
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
118
|
+
throw new XDocsError(`Invalid TOML in configuration file: ${path}\n${message}`);
|
|
119
|
+
}
|
|
120
|
+
if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) {
|
|
121
|
+
throw new XDocsError(`Configuration file must contain a TOML object: ${path}`);
|
|
122
|
+
}
|
|
123
|
+
return parsed;
|
|
124
|
+
};
|
|
125
|
+
/** Resolve a path relative to cwd if not absolute. */
|
|
126
|
+
export const resolvePath = (cwd, path) => isAbsolute(path) ? path : resolve(cwd, path);
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @copyright Copyright (c) 2026 GUIHO Technologies as represented by Cristóvão GUIHO. All Rights Reserved.
|
|
3
|
+
*/
|
|
4
|
+
import type { XDocsConfig, XDocsFile, XDocsScanResult } from './types.js';
|
|
5
|
+
/** Scan the project for xdocs files matching configured extensions. */
|
|
6
|
+
export declare const scanProject: (config: XDocsConfig) => Promise<XDocsScanResult>;
|
|
7
|
+
/** Check if a file path matches any of the configured xdocs extensions. */
|
|
8
|
+
export declare const isXDocsFile: (filePath: string, extensions: string[]) => boolean;
|
|
9
|
+
/** Scan a specific directory (not recursive) for xdocs files. */
|
|
10
|
+
export declare const scanDirectory: (dirPath: string, config: XDocsConfig) => Promise<XDocsFile[]>;
|
|
11
|
+
/** List all files in a directory (non-recursive). */
|
|
12
|
+
export declare const listDirectoryFiles: (dirPath: string, config: XDocsConfig) => Promise<string[]>;
|
|
13
|
+
//# sourceMappingURL=discovery.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"discovery.d.ts","sourceRoot":"","sources":["../source/discovery.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,OAAO,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AAGzE,uEAAuE;AACvE,eAAO,MAAM,WAAW,GAAU,QAAQ,WAAW,KAAG,OAAO,CAAC,eAAe,CA2C9E,CAAA;AAED,2EAA2E;AAC3E,eAAO,MAAM,WAAW,GAAI,UAAU,MAAM,EAAE,YAAY,MAAM,EAAE,KAAG,OAOpE,CAAA;AAmCD,iEAAiE;AACjE,eAAO,MAAM,aAAa,GAAU,SAAS,MAAM,EAAE,QAAQ,WAAW,KAAG,OAAO,CAAC,SAAS,EAAE,CAqB7F,CAAA;AAED,qDAAqD;AACrD,eAAO,MAAM,kBAAkB,GAAU,SAAS,MAAM,EAAE,QAAQ,WAAW,KAAG,OAAO,CAAC,MAAM,EAAE,CAiB/F,CAAA"}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @copyright Copyright (c) 2026 GUIHO Technologies as represented by Cristóvão GUIHO. All Rights Reserved.
|
|
3
|
+
*/
|
|
4
|
+
import { readdir, stat } from 'node:fs/promises';
|
|
5
|
+
import { join, relative } from 'node:path';
|
|
6
|
+
import { parseXDocsFile } from './metadata.js';
|
|
7
|
+
/** Scan the project for xdocs files matching configured extensions. */
|
|
8
|
+
export const scanProject = async (config) => {
|
|
9
|
+
const xdocsFiles = [];
|
|
10
|
+
const allDirectories = [];
|
|
11
|
+
const coveredDirectories = new Set();
|
|
12
|
+
let totalFiles = 0;
|
|
13
|
+
await walkDirectory(config.cwd, config, async (filePath, dir) => {
|
|
14
|
+
totalFiles += 1;
|
|
15
|
+
if (isXDocsFile(filePath, config.extensions.supported)) {
|
|
16
|
+
const file = await parseXDocsFile(filePath, config.cwd);
|
|
17
|
+
xdocsFiles.push(file);
|
|
18
|
+
coveredDirectories.add(dir);
|
|
19
|
+
}
|
|
20
|
+
}, allDirectories);
|
|
21
|
+
// The root XDOCS.md is always recognized
|
|
22
|
+
const rootXDocs = join(config.cwd, 'XDOCS.md');
|
|
23
|
+
const rootAlreadyFound = xdocsFiles.some((f) => f.path === rootXDocs);
|
|
24
|
+
if (!rootAlreadyFound) {
|
|
25
|
+
try {
|
|
26
|
+
const rootStat = await stat(rootXDocs);
|
|
27
|
+
if (rootStat.isFile()) {
|
|
28
|
+
const file = await parseXDocsFile(rootXDocs, config.cwd);
|
|
29
|
+
xdocsFiles.push(file);
|
|
30
|
+
coveredDirectories.add(config.cwd);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
// Root XDOCS.md does not exist, that's fine
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
const uncoveredPaths = allDirectories.filter((dir) => !coveredDirectories.has(dir));
|
|
38
|
+
return {
|
|
39
|
+
totalFiles,
|
|
40
|
+
totalDirectories: allDirectories.length,
|
|
41
|
+
coveredDirectories: coveredDirectories.size,
|
|
42
|
+
uncoveredDirectories: uncoveredPaths.length,
|
|
43
|
+
xdocsFiles,
|
|
44
|
+
uncoveredPaths,
|
|
45
|
+
};
|
|
46
|
+
};
|
|
47
|
+
/** Check if a file path matches any of the configured xdocs extensions. */
|
|
48
|
+
export const isXDocsFile = (filePath, extensions) => {
|
|
49
|
+
const lower = filePath.toLowerCase();
|
|
50
|
+
// Root XDOCS.md is always recognized
|
|
51
|
+
if (lower.endsWith('/xdocs.md') || lower.endsWith('\\xdocs.md'))
|
|
52
|
+
return true;
|
|
53
|
+
return extensions.some((ext) => lower.endsWith(ext.toLowerCase()));
|
|
54
|
+
};
|
|
55
|
+
/** Recursively walk a directory, skipping excluded directories. */
|
|
56
|
+
const walkDirectory = async (dir, config, onFile, allDirectories) => {
|
|
57
|
+
allDirectories.push(dir);
|
|
58
|
+
let entries;
|
|
59
|
+
try {
|
|
60
|
+
entries = await readdir(dir, { withFileTypes: true });
|
|
61
|
+
}
|
|
62
|
+
catch {
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
for (const entry of entries) {
|
|
66
|
+
const fullPath = join(dir, entry.name);
|
|
67
|
+
if (entry.isDirectory()) {
|
|
68
|
+
if (isExcluded(entry.name, config.scan.exclude))
|
|
69
|
+
continue;
|
|
70
|
+
await walkDirectory(fullPath, config, onFile, allDirectories);
|
|
71
|
+
}
|
|
72
|
+
else if (entry.isFile()) {
|
|
73
|
+
await onFile(fullPath, dir);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
/** Check if a directory name is in the exclude list. */
|
|
78
|
+
const isExcluded = (name, exclude) => exclude.includes(name) || name.startsWith('.');
|
|
79
|
+
/** Scan a specific directory (not recursive) for xdocs files. */
|
|
80
|
+
export const scanDirectory = async (dirPath, config) => {
|
|
81
|
+
const files = [];
|
|
82
|
+
let entries;
|
|
83
|
+
try {
|
|
84
|
+
entries = await readdir(dirPath, { withFileTypes: true });
|
|
85
|
+
}
|
|
86
|
+
catch {
|
|
87
|
+
return files;
|
|
88
|
+
}
|
|
89
|
+
for (const entry of entries) {
|
|
90
|
+
if (!entry.isFile())
|
|
91
|
+
continue;
|
|
92
|
+
const fullPath = join(dirPath, entry.name);
|
|
93
|
+
if (isXDocsFile(fullPath, config.extensions.supported)) {
|
|
94
|
+
const file = await parseXDocsFile(fullPath, config.cwd);
|
|
95
|
+
files.push(file);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
return files;
|
|
99
|
+
};
|
|
100
|
+
/** List all files in a directory (non-recursive). */
|
|
101
|
+
export const listDirectoryFiles = async (dirPath, config) => {
|
|
102
|
+
const result = [];
|
|
103
|
+
let entries;
|
|
104
|
+
try {
|
|
105
|
+
entries = await readdir(dirPath, { withFileTypes: true });
|
|
106
|
+
}
|
|
107
|
+
catch {
|
|
108
|
+
return result;
|
|
109
|
+
}
|
|
110
|
+
for (const entry of entries) {
|
|
111
|
+
if (!entry.isFile())
|
|
112
|
+
continue;
|
|
113
|
+
if (isExcluded(entry.name, config.scan.exclude))
|
|
114
|
+
continue;
|
|
115
|
+
result.push(relative(config.cwd, join(dirPath, entry.name)));
|
|
116
|
+
}
|
|
117
|
+
return result;
|
|
118
|
+
};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @copyright Copyright (c) 2026 GUIHO Technologies as represented by Cristóvão GUIHO. All Rights Reserved.
|
|
3
|
+
*/
|
|
4
|
+
export declare class XDocsError extends Error {
|
|
5
|
+
readonly exitCode: number;
|
|
6
|
+
constructor(message: string, exitCode?: number);
|
|
7
|
+
}
|
|
8
|
+
export declare const invariant: (condition: unknown, message: string) => asserts condition;
|
|
9
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../source/errors.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,qBAAa,UAAW,SAAQ,KAAK;IACnC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;gBAEb,OAAO,EAAE,MAAM,EAAE,QAAQ,SAAI;CAK1C;AAED,eAAO,MAAM,SAAS,GAAI,WAAW,OAAO,EAAE,SAAS,MAAM,KAAG,QAAQ,SAEvE,CAAA"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @copyright Copyright (c) 2026 GUIHO Technologies as represented by Cristóvão GUIHO. All Rights Reserved.
|
|
3
|
+
*/
|
|
4
|
+
export class XDocsError extends Error {
|
|
5
|
+
exitCode;
|
|
6
|
+
constructor(message, exitCode = 1) {
|
|
7
|
+
super(message);
|
|
8
|
+
this.name = 'XDocsError';
|
|
9
|
+
this.exitCode = exitCode;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
export const invariant = (condition, message) => {
|
|
13
|
+
if (!condition)
|
|
14
|
+
throw new XDocsError(message);
|
|
15
|
+
};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @copyright Copyright (c) 2026 GUIHO Technologies as represented by Cristóvão GUIHO. All Rights Reserved.
|
|
3
|
+
*/
|
|
4
|
+
import type { XDocsParsedArgs } from './types.js';
|
|
5
|
+
/**
|
|
6
|
+
* Parse raw CLI arguments into a structured object.
|
|
7
|
+
*
|
|
8
|
+
* Supports:
|
|
9
|
+
* - Commands as the first non-flag token: `xdocs scan`
|
|
10
|
+
* - Long flags with value: `--name=write` or `--name write`
|
|
11
|
+
* - Long boolean flags: `--verbose`
|
|
12
|
+
* - Short flags: `-h`, `-v`
|
|
13
|
+
* - List values as comma-separated: `--extensions=.docs.md,.xdocs.md`
|
|
14
|
+
* - Positional arguments after the command
|
|
15
|
+
*/
|
|
16
|
+
export declare const parseArgs: (rawArgs: string[]) => XDocsParsedArgs;
|
|
17
|
+
/** Extract a string flag value or undefined. */
|
|
18
|
+
export declare const stringFlag: (flags: Record<string, string | boolean | string[]>, key: string) => string | undefined;
|
|
19
|
+
/** Extract a boolean flag value. */
|
|
20
|
+
export declare const booleanFlag: (flags: Record<string, string | boolean | string[]>, key: string) => boolean;
|
|
21
|
+
/** Extract a list flag value or undefined. */
|
|
22
|
+
export declare const listFlag: (flags: Record<string, string | boolean | string[]>, key: string) => string[] | undefined;
|
|
23
|
+
//# sourceMappingURL=flags.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"flags.d.ts","sourceRoot":"","sources":["../source/flags.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AAmBjD;;;;;;;;;;GAUG;AACH,eAAO,MAAM,SAAS,GAAI,SAAS,MAAM,EAAE,KAAG,eA4D7C,CAAA;AAUD,gDAAgD;AAChD,eAAO,MAAM,UAAU,GAAI,OAAO,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,GAAG,MAAM,EAAE,CAAC,EAAE,KAAK,MAAM,KAAG,MAAM,GAAG,SAGrG,CAAA;AAED,oCAAoC;AACpC,eAAO,MAAM,WAAW,GAAI,OAAO,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,GAAG,MAAM,EAAE,CAAC,EAAE,KAAK,MAAM,KAAG,OAE7F,CAAA;AAED,8CAA8C;AAC9C,eAAO,MAAM,QAAQ,GAAI,OAAO,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,GAAG,MAAM,EAAE,CAAC,EAAE,KAAK,MAAM,KAAG,MAAM,EAAE,GAAG,SAGrG,CAAA"}
|
package/library/flags.js
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @copyright Copyright (c) 2026 GUIHO Technologies as represented by Cristóvão GUIHO. All Rights Reserved.
|
|
3
|
+
*/
|
|
4
|
+
import { XDocsError } from './errors.js';
|
|
5
|
+
const booleanFlags = new Set([
|
|
6
|
+
'help',
|
|
7
|
+
'version',
|
|
8
|
+
'verbose',
|
|
9
|
+
]);
|
|
10
|
+
const shortFlagMap = {
|
|
11
|
+
'-h': '--help',
|
|
12
|
+
'-v': '--version',
|
|
13
|
+
};
|
|
14
|
+
const listFlags = new Set([
|
|
15
|
+
'extensions',
|
|
16
|
+
'exclude',
|
|
17
|
+
]);
|
|
18
|
+
/**
|
|
19
|
+
* Parse raw CLI arguments into a structured object.
|
|
20
|
+
*
|
|
21
|
+
* Supports:
|
|
22
|
+
* - Commands as the first non-flag token: `xdocs scan`
|
|
23
|
+
* - Long flags with value: `--name=write` or `--name write`
|
|
24
|
+
* - Long boolean flags: `--verbose`
|
|
25
|
+
* - Short flags: `-h`, `-v`
|
|
26
|
+
* - List values as comma-separated: `--extensions=.docs.md,.xdocs.md`
|
|
27
|
+
* - Positional arguments after the command
|
|
28
|
+
*/
|
|
29
|
+
export const parseArgs = (rawArgs) => {
|
|
30
|
+
const args = expandShortFlags(rawArgs);
|
|
31
|
+
const flags = {};
|
|
32
|
+
const positionals = [];
|
|
33
|
+
let command;
|
|
34
|
+
for (let index = 0; index < args.length; index += 1) {
|
|
35
|
+
const token = args[index];
|
|
36
|
+
if (token === undefined)
|
|
37
|
+
continue;
|
|
38
|
+
if (token === '--') {
|
|
39
|
+
positionals.push(...args.slice(index + 1).filter((a) => a !== undefined));
|
|
40
|
+
break;
|
|
41
|
+
}
|
|
42
|
+
if (token.startsWith('--')) {
|
|
43
|
+
const withoutPrefix = token.slice(2);
|
|
44
|
+
const equalsIndex = withoutPrefix.indexOf('=');
|
|
45
|
+
const rawKey = equalsIndex >= 0 ? withoutPrefix.slice(0, equalsIndex) : withoutPrefix;
|
|
46
|
+
if (booleanFlags.has(rawKey)) {
|
|
47
|
+
flags[normalizeKey(rawKey)] = true;
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
50
|
+
const value = equalsIndex >= 0
|
|
51
|
+
? withoutPrefix.slice(equalsIndex + 1)
|
|
52
|
+
: (args[index + 1] !== undefined && !args[index + 1]?.startsWith('-'))
|
|
53
|
+
? args[++index] ?? ''
|
|
54
|
+
: '';
|
|
55
|
+
if (!value)
|
|
56
|
+
throw new XDocsError(`Missing value for --${rawKey}`);
|
|
57
|
+
const key = normalizeKey(rawKey);
|
|
58
|
+
if (listFlags.has(rawKey)) {
|
|
59
|
+
const values = value.split(',').filter(Boolean);
|
|
60
|
+
const current = flags[key];
|
|
61
|
+
flags[key] = [...(Array.isArray(current) ? current : []), ...values];
|
|
62
|
+
continue;
|
|
63
|
+
}
|
|
64
|
+
flags[key] = value;
|
|
65
|
+
continue;
|
|
66
|
+
}
|
|
67
|
+
if (token.startsWith('-') && token.length > 1) {
|
|
68
|
+
throw new XDocsError(`Unknown short flag: ${token}`);
|
|
69
|
+
}
|
|
70
|
+
if (command === undefined) {
|
|
71
|
+
command = token;
|
|
72
|
+
}
|
|
73
|
+
else {
|
|
74
|
+
positionals.push(token);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
return { command, positionals, flags };
|
|
78
|
+
};
|
|
79
|
+
/** Convert kebab-case to camelCase. */
|
|
80
|
+
const normalizeKey = (key) => key.replace(/-([a-z])/g, (_match, letter) => letter.toUpperCase());
|
|
81
|
+
/** Expand short flags like -h to --help. */
|
|
82
|
+
const expandShortFlags = (rawArgs) => rawArgs.map((token) => shortFlagMap[token] ?? token);
|
|
83
|
+
/** Extract a string flag value or undefined. */
|
|
84
|
+
export const stringFlag = (flags, key) => {
|
|
85
|
+
const value = flags[key];
|
|
86
|
+
return typeof value === 'string' ? value : undefined;
|
|
87
|
+
};
|
|
88
|
+
/** Extract a boolean flag value. */
|
|
89
|
+
export const booleanFlag = (flags, key) => {
|
|
90
|
+
return flags[key] === true;
|
|
91
|
+
};
|
|
92
|
+
/** Extract a list flag value or undefined. */
|
|
93
|
+
export const listFlag = (flags, key) => {
|
|
94
|
+
const value = flags[key];
|
|
95
|
+
return Array.isArray(value) ? value : undefined;
|
|
96
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"guiho-xdocs-bin.d.ts","sourceRoot":"","sources":["../source/guiho-xdocs-bin.ts"],"names":[],"mappings":";AACA;;GAEG"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @copyright Copyright (c) 2026 GUIHO Technologies as represented by Cristóvão GUIHO. All Rights Reserved.
|
|
3
|
+
*/
|
|
4
|
+
export { XDocsError, invariant } from './errors.js';
|
|
5
|
+
export type { XDocsAiMode, XDocsCliOptions, XDocsCommand, XDocsConfig, XDocsFile, XDocsFormat, XDocsMetadata, XDocsParsedArgs, XDocsPrompt, XDocsPromptName, XDocsRawConfig, XDocsScanResult, XDocsTreeNode, XDocsTreeValidation, } from './types.js';
|
|
6
|
+
export { parseArgs, stringFlag, booleanFlag, listFlag } from './flags.js';
|
|
7
|
+
export { createDefaultConfigContent, defaultConfig, discoverConfig, loadConfig, loadConfigOrDefaults, normalizeConfig, resolvePath, writeDefaultConfig, } from './config.js';
|
|
8
|
+
export { isXDocsFile, listDirectoryFiles, scanDirectory, scanProject } from './discovery.js';
|
|
9
|
+
export { extractFrontmatter, parseXDocsFile, validateMetadata } from './metadata.js';
|
|
10
|
+
export { buildTree, renderTree, renderTreeMarkdown, validateTree } from './tree.js';
|
|
11
|
+
export { readPackageVersion, showCommandHelp, showHelp, showVersion } from './help.js';
|
|
12
|
+
export { getPrompt, getPromptNames, prompts } from './prompts.js';
|
|
13
|
+
export { runCli, runCliWithErrorHandling } from './cli.js';
|
|
14
|
+
//# sourceMappingURL=guiho-xdocs.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"guiho-xdocs.d.ts","sourceRoot":"","sources":["../source/guiho-xdocs.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AAGnD,YAAY,EACV,WAAW,EACX,eAAe,EACf,YAAY,EACZ,WAAW,EACX,SAAS,EACT,WAAW,EACX,aAAa,EACb,eAAe,EACf,WAAW,EACX,eAAe,EACf,cAAc,EACd,eAAe,EACf,aAAa,EACb,mBAAmB,GACpB,MAAM,YAAY,CAAA;AAGnB,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AAGzE,OAAO,EACL,0BAA0B,EAC1B,aAAa,EACb,cAAc,EACd,UAAU,EACV,oBAAoB,EACpB,eAAe,EACf,WAAW,EACX,kBAAkB,GACnB,MAAM,aAAa,CAAA;AAGpB,OAAO,EAAE,WAAW,EAAE,kBAAkB,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAG5F,OAAO,EAAE,kBAAkB,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAA;AAGpF,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,kBAAkB,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA;AAGnF,OAAO,EAAE,kBAAkB,EAAE,eAAe,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,WAAW,CAAA;AAGtF,OAAO,EAAE,SAAS,EAAE,cAAc,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AAGjE,OAAO,EAAE,MAAM,EAAE,uBAAuB,EAAE,MAAM,UAAU,CAAA"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @copyright Copyright (c) 2026 GUIHO Technologies as represented by Cristóvão GUIHO. All Rights Reserved.
|
|
3
|
+
*/
|
|
4
|
+
// Errors
|
|
5
|
+
export { XDocsError, invariant } from './errors.js';
|
|
6
|
+
// Flags
|
|
7
|
+
export { parseArgs, stringFlag, booleanFlag, listFlag } from './flags.js';
|
|
8
|
+
// Config
|
|
9
|
+
export { createDefaultConfigContent, defaultConfig, discoverConfig, loadConfig, loadConfigOrDefaults, normalizeConfig, resolvePath, writeDefaultConfig, } from './config.js';
|
|
10
|
+
// Discovery
|
|
11
|
+
export { isXDocsFile, listDirectoryFiles, scanDirectory, scanProject } from './discovery.js';
|
|
12
|
+
// Metadata
|
|
13
|
+
export { extractFrontmatter, parseXDocsFile, validateMetadata } from './metadata.js';
|
|
14
|
+
// Tree
|
|
15
|
+
export { buildTree, renderTree, renderTreeMarkdown, validateTree } from './tree.js';
|
|
16
|
+
// Help
|
|
17
|
+
export { readPackageVersion, showCommandHelp, showHelp, showVersion } from './help.js';
|
|
18
|
+
// Prompts
|
|
19
|
+
export { getPrompt, getPromptNames, prompts } from './prompts.js';
|
|
20
|
+
// CLI
|
|
21
|
+
export { runCli, runCliWithErrorHandling } from './cli.js';
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @copyright Copyright (c) 2026 GUIHO Technologies as represented by Cristóvão GUIHO. All Rights Reserved.
|
|
3
|
+
*/
|
|
4
|
+
/** Read the package version from package.json. */
|
|
5
|
+
export declare const readPackageVersion: () => string;
|
|
6
|
+
/** Show the xdocs version string. */
|
|
7
|
+
export declare const showVersion: () => string;
|
|
8
|
+
/** Show the main help text. */
|
|
9
|
+
export declare const showHelp: () => string;
|
|
10
|
+
/** Show help for a specific command. */
|
|
11
|
+
export declare const showCommandHelp: (command: string) => string;
|
|
12
|
+
//# sourceMappingURL=help.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"help.d.ts","sourceRoot":"","sources":["../source/help.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,kDAAkD;AAClD,eAAO,MAAM,kBAAkB,QAAO,MAQrC,CAAA;AAED,qCAAqC;AACrC,eAAO,MAAM,WAAW,QAAO,MAAyC,CAAA;AAExE,+BAA+B;AAC/B,eAAO,MAAM,QAAQ,QAAO,MA6BpB,CAAA;AAER,wCAAwC;AACxC,eAAO,MAAM,eAAe,GAAI,SAAS,MAAM,KAAG,MAIjD,CAAA"}
|