@ankhorage/paradox 0.0.1 → 0.0.3
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 +6 -0
- package/dist/analyze/analyze.d.ts +6 -0
- package/dist/analyze/analyze.js +34 -0
- package/dist/analyze/components.d.ts +5 -0
- package/dist/analyze/components.js +21 -0
- package/dist/analyze/exports.d.ts +16 -0
- package/dist/analyze/exports.js +52 -0
- package/dist/analyze/project.d.ts +5 -0
- package/dist/analyze/project.js +10 -0
- package/dist/analyze/types.d.ts +45 -0
- package/dist/analyze/types.js +1 -0
- package/dist/analyze/usage.d.ts +7 -0
- package/dist/analyze/usage.js +40 -0
- package/dist/analyze/utils/getComponentPropsType.d.ts +5 -0
- package/dist/analyze/utils/getComponentPropsType.js +21 -0
- package/dist/analyze/utils/getParadoxComment.d.ts +5 -0
- package/dist/analyze/utils/getParadoxComment.js +19 -0
- package/dist/analyze/utils/getPropsFromType.d.ts +6 -0
- package/dist/analyze/utils/getPropsFromType.js +19 -0
- package/dist/analyze/utils/isReactComponent.d.ts +5 -0
- package/dist/analyze/utils/isReactComponent.js +30 -0
- package/dist/analyze/utils/parseParadoxComment.d.ts +12 -0
- package/dist/analyze/utils/parseParadoxComment.js +25 -0
- package/{src/analyze/utils/resolveExportSymbol.ts → dist/analyze/utils/resolveExportSymbol.d.ts} +1 -4
- package/dist/analyze/utils/resolveExportSymbol.js +6 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +23 -0
- package/{src/config/defineParadoxConfig.ts → dist/config/defineParadoxConfig.d.ts} +1 -4
- package/dist/config/defineParadoxConfig.js +6 -0
- package/dist/config/types.d.ts +19 -0
- package/dist/config/types.js +1 -0
- package/dist/index.js +1 -0
- package/dist/model/buildModel.d.ts +36 -0
- package/dist/model/buildModel.js +65 -0
- package/dist/model/types.d.ts +42 -0
- package/dist/model/types.js +1 -0
- package/dist/render/render.d.ts +6 -0
- package/dist/render/render.js +88 -0
- package/dist/render/types.d.ts +10 -0
- package/dist/render/types.js +1 -0
- package/dist/write/write.d.ts +6 -0
- package/dist/write/write.js +18 -0
- package/package.json +27 -3
- package/.changeset/README.md +0 -5
- package/.changeset/config.json +0 -11
- package/.github/workflows/docs.yml +0 -45
- package/.prettierignore +0 -1
- package/.prettierrc.js +0 -5
- package/bun.lock +0 -663
- package/eslint.config.mjs +0 -12
- package/paradox/components.md +0 -1
- package/paradox/exports.json +0 -12
- package/paradox/exports.md +0 -13
- package/paradox/paradox.json +0 -26
- package/paradox.config.ts +0 -18
- package/src/analyze/analyze.ts +0 -56
- package/src/analyze/components.ts +0 -27
- package/src/analyze/exports.ts +0 -87
- package/src/analyze/project.ts +0 -11
- package/src/analyze/types.ts +0 -45
- package/src/analyze/utils/getComponentPropsType.ts +0 -26
- package/src/analyze/utils/getParadoxComment.ts +0 -24
- package/src/analyze/utils/getPropsFromType.ts +0 -24
- package/src/analyze/utils/isReactComponent.ts +0 -35
- package/src/analyze/utils/parseParadoxComment.ts +0 -37
- package/src/cli.ts +0 -30
- package/src/config/types.ts +0 -22
- package/src/model/buildModel.ts +0 -46
- package/src/model/types.ts +0 -28
- package/src/render/render.ts +0 -113
- package/src/render/types.ts +0 -10
- package/src/write/write.ts +0 -25
- package/tests/__snapshots__/basic.components.md +0 -10
- package/tests/__snapshots__/basic.exports.md +0 -19
- package/tests/__snapshots__/basic.readme.md +0 -37
- package/tests/analyze.test.ts +0 -72
- package/tests/fixtures/basic/package.json +0 -8
- package/tests/fixtures/basic/src/config.ts +0 -8
- package/tests/fixtures/basic/src/index.ts +0 -3
- package/tests/fixtures/basic/src/internal.ts +0 -6
- package/tests/fixtures/basic/src/ui.ts +0 -29
- package/tests/fixtures/basic/tsconfig.json +0 -11
- package/tsconfig.eslint.json +0 -16
- package/tsconfig.json +0 -14
- /package/{src/index.ts → dist/index.d.ts} +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { readFile } from 'node:fs/promises';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
import { analyzeComponents } from './components.js';
|
|
4
|
+
import { analyzeExports } from './exports.js';
|
|
5
|
+
import { createProject } from './project.js';
|
|
6
|
+
import { createUsageFromPackageJson } from './usage.js';
|
|
7
|
+
/***
|
|
8
|
+
* Runs the source analysis pipeline for a configured package.
|
|
9
|
+
*/
|
|
10
|
+
export async function analyze(config) {
|
|
11
|
+
const root = config.package?.root ?? process.cwd();
|
|
12
|
+
const pkg = await readPackageJson(root);
|
|
13
|
+
const usage = createUsageFromPackageJson(pkg);
|
|
14
|
+
const project = createProject(root);
|
|
15
|
+
const entrypoints = config.package?.entrypoints ?? ['src/index.ts'];
|
|
16
|
+
const { config: configMetadata, exports } = analyzeExports(project, {
|
|
17
|
+
root,
|
|
18
|
+
entrypoints,
|
|
19
|
+
});
|
|
20
|
+
const components = analyzeComponents(exports);
|
|
21
|
+
return {
|
|
22
|
+
packageName: config.docs?.title ?? pkg.name,
|
|
23
|
+
packageId: pkg.name,
|
|
24
|
+
description: config.docs?.description ?? pkg.description ?? null,
|
|
25
|
+
exports,
|
|
26
|
+
components,
|
|
27
|
+
usage,
|
|
28
|
+
config: configMetadata,
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
async function readPackageJson(root) {
|
|
32
|
+
const raw = await readFile(join(root, 'package.json'), 'utf-8');
|
|
33
|
+
return JSON.parse(raw);
|
|
34
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { getComponentPropsType } from './utils/getComponentPropsType.js';
|
|
2
|
+
import { getPropsFromType } from './utils/getPropsFromType.js';
|
|
3
|
+
import { isReactComponent } from './utils/isReactComponent.js';
|
|
4
|
+
/***
|
|
5
|
+
* Extracts React components and their props from analyzed exports.
|
|
6
|
+
*/
|
|
7
|
+
export function analyzeComponents(exports) {
|
|
8
|
+
const components = [];
|
|
9
|
+
for (const e of exports) {
|
|
10
|
+
if (!isReactComponent(e.node))
|
|
11
|
+
continue;
|
|
12
|
+
const propsType = getComponentPropsType(e.node);
|
|
13
|
+
const props = propsType != null ? getPropsFromType(propsType) : [];
|
|
14
|
+
components.push({
|
|
15
|
+
name: e.name,
|
|
16
|
+
description: e.description,
|
|
17
|
+
props,
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
return components;
|
|
21
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { Project } from 'ts-morph';
|
|
2
|
+
import type { AnalysisExport } from './types.js';
|
|
3
|
+
interface AnalyzeExportsResult {
|
|
4
|
+
exports: AnalysisExport[];
|
|
5
|
+
config: {
|
|
6
|
+
exportName: string;
|
|
7
|
+
} | null;
|
|
8
|
+
}
|
|
9
|
+
/***
|
|
10
|
+
* Collects exported declarations from configured package entrypoints.
|
|
11
|
+
*/
|
|
12
|
+
export declare function analyzeExports(project: Project, options: {
|
|
13
|
+
root: string;
|
|
14
|
+
entrypoints: readonly string[];
|
|
15
|
+
}): AnalyzeExportsResult;
|
|
16
|
+
export {};
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { isAbsolute, join, normalize } from 'node:path';
|
|
2
|
+
import { getParadoxComment } from './utils/getParadoxComment.js';
|
|
3
|
+
import { parseParadoxComment } from './utils/parseParadoxComment.js';
|
|
4
|
+
import { resolveExportSymbol } from './utils/resolveExportSymbol.js';
|
|
5
|
+
/***
|
|
6
|
+
* Collects exported declarations from configured package entrypoints.
|
|
7
|
+
*/
|
|
8
|
+
export function analyzeExports(project, options) {
|
|
9
|
+
const exports = [];
|
|
10
|
+
let config = null;
|
|
11
|
+
for (const sourceFile of getEntryPointSourceFiles(project, options)) {
|
|
12
|
+
const exported = sourceFile.getExportSymbols();
|
|
13
|
+
for (const symbol of exported) {
|
|
14
|
+
const resolved = resolveExportSymbol(symbol);
|
|
15
|
+
const [decl] = resolved.getDeclarations();
|
|
16
|
+
const rawComment = getParadoxComment(decl);
|
|
17
|
+
const parsed = rawComment
|
|
18
|
+
? parseParadoxComment(rawComment)
|
|
19
|
+
: { description: null, isConfig: false };
|
|
20
|
+
if (parsed.isConfig) {
|
|
21
|
+
config = {
|
|
22
|
+
exportName: resolved.getName(),
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
exports.push({
|
|
26
|
+
name: resolved.getName(),
|
|
27
|
+
node: decl,
|
|
28
|
+
description: parsed.description,
|
|
29
|
+
kind: inferKind(decl),
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
return {
|
|
34
|
+
exports,
|
|
35
|
+
config,
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
function getEntryPointSourceFiles(project, options) {
|
|
39
|
+
return options.entrypoints
|
|
40
|
+
.map((entrypoint) => {
|
|
41
|
+
const absolutePath = normalize(isAbsolute(entrypoint) ? entrypoint : join(options.root, entrypoint));
|
|
42
|
+
return project.getSourceFile((sourceFile) => normalize(sourceFile.getFilePath()) === absolutePath);
|
|
43
|
+
})
|
|
44
|
+
.filter((sourceFile) => sourceFile != null);
|
|
45
|
+
}
|
|
46
|
+
function inferKind(node) {
|
|
47
|
+
if ('getParameters' in node)
|
|
48
|
+
return 'function';
|
|
49
|
+
if ('getProperties' in node || 'getMembers' in node)
|
|
50
|
+
return 'type';
|
|
51
|
+
return 'unknown';
|
|
52
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import type { Node } from 'ts-morph';
|
|
2
|
+
/***
|
|
3
|
+
* Describes one exported declaration discovered in a package.
|
|
4
|
+
*/
|
|
5
|
+
export interface AnalysisExport {
|
|
6
|
+
name: string;
|
|
7
|
+
node: Node;
|
|
8
|
+
description: string | null;
|
|
9
|
+
kind: 'function' | 'type' | 'unknown';
|
|
10
|
+
}
|
|
11
|
+
/***
|
|
12
|
+
* Describes one React component and its extracted props.
|
|
13
|
+
*/
|
|
14
|
+
export interface AnalysisComponent {
|
|
15
|
+
name: string;
|
|
16
|
+
description: string | null;
|
|
17
|
+
props: {
|
|
18
|
+
name: string;
|
|
19
|
+
type: string;
|
|
20
|
+
required: boolean;
|
|
21
|
+
description: string | null;
|
|
22
|
+
}[];
|
|
23
|
+
}
|
|
24
|
+
export interface AnalysisUsage {
|
|
25
|
+
packageName: string;
|
|
26
|
+
commands: AnalysisUsageCommand[];
|
|
27
|
+
}
|
|
28
|
+
export interface AnalysisUsageCommand {
|
|
29
|
+
name: string;
|
|
30
|
+
command: string;
|
|
31
|
+
}
|
|
32
|
+
/***
|
|
33
|
+
* Complete analysis output used to build the documentation model.
|
|
34
|
+
*/
|
|
35
|
+
export interface AnalysisResult {
|
|
36
|
+
packageName: string;
|
|
37
|
+
packageId: string;
|
|
38
|
+
description: string | null;
|
|
39
|
+
exports: AnalysisExport[];
|
|
40
|
+
components: AnalysisComponent[];
|
|
41
|
+
usage: AnalysisUsage | null;
|
|
42
|
+
config: {
|
|
43
|
+
exportName: string;
|
|
44
|
+
} | null;
|
|
45
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { AnalysisUsage } from './types.js';
|
|
2
|
+
export interface PackageJsonModel {
|
|
3
|
+
name: string;
|
|
4
|
+
description?: string;
|
|
5
|
+
bin?: string | Record<string, string>;
|
|
6
|
+
}
|
|
7
|
+
export declare function createUsageFromPackageJson(pkg: PackageJsonModel): AnalysisUsage | null;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
export function createUsageFromPackageJson(pkg) {
|
|
2
|
+
if (pkg.bin == null)
|
|
3
|
+
return null;
|
|
4
|
+
if (typeof pkg.bin === 'string') {
|
|
5
|
+
return {
|
|
6
|
+
packageName: pkg.name,
|
|
7
|
+
commands: [
|
|
8
|
+
{
|
|
9
|
+
name: getPackageBaseName(pkg.name),
|
|
10
|
+
command: `bunx ${pkg.name}`,
|
|
11
|
+
},
|
|
12
|
+
],
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
const entries = Object.keys(pkg.bin).sort((a, b) => a.localeCompare(b));
|
|
16
|
+
if (entries.length === 0)
|
|
17
|
+
return null;
|
|
18
|
+
if (entries.length === 1) {
|
|
19
|
+
const [name] = entries;
|
|
20
|
+
return {
|
|
21
|
+
packageName: pkg.name,
|
|
22
|
+
commands: [
|
|
23
|
+
{
|
|
24
|
+
name,
|
|
25
|
+
command: `bunx ${pkg.name}`,
|
|
26
|
+
},
|
|
27
|
+
],
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
return {
|
|
31
|
+
packageName: pkg.name,
|
|
32
|
+
commands: entries.map((name) => ({
|
|
33
|
+
name,
|
|
34
|
+
command: `bunx ${pkg.name} ${name}`,
|
|
35
|
+
})),
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
function getPackageBaseName(packageName) {
|
|
39
|
+
return packageName.split('/').pop() ?? packageName;
|
|
40
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { Node } from 'ts-morph';
|
|
2
|
+
/***
|
|
3
|
+
* Returns the first parameter type for a React component declaration.
|
|
4
|
+
*/
|
|
5
|
+
export function getComponentPropsType(node) {
|
|
6
|
+
const callSignature = getCallSignature(node);
|
|
7
|
+
const firstParam = callSignature?.getParameters()[0];
|
|
8
|
+
const firstDecl = firstParam?.getDeclarations()[0];
|
|
9
|
+
if (firstDecl)
|
|
10
|
+
return firstParam.getTypeAtLocation(firstDecl);
|
|
11
|
+
return null;
|
|
12
|
+
}
|
|
13
|
+
function getCallSignature(node) {
|
|
14
|
+
if (Node.isFunctionDeclaration(node)) {
|
|
15
|
+
return node.getType().getCallSignatures()[0] ?? null;
|
|
16
|
+
}
|
|
17
|
+
if (Node.isVariableDeclaration(node)) {
|
|
18
|
+
return node.getType().getCallSignatures()[0] ?? null;
|
|
19
|
+
}
|
|
20
|
+
return null;
|
|
21
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/***
|
|
2
|
+
* Reads the nearest Paradox doc comment attached to a declaration.
|
|
3
|
+
*/
|
|
4
|
+
export function getParadoxComment(node) {
|
|
5
|
+
const sourceFile = node.getSourceFile();
|
|
6
|
+
const text = sourceFile.getFullText();
|
|
7
|
+
const nodeStart = node.getStart(false);
|
|
8
|
+
const beforeNode = text.slice(0, nodeStart);
|
|
9
|
+
const commentStart = beforeNode.lastIndexOf('/***');
|
|
10
|
+
if (commentStart === -1)
|
|
11
|
+
return null;
|
|
12
|
+
const commentEnd = text.indexOf('*/', commentStart);
|
|
13
|
+
if (commentEnd === -1 || commentEnd > nodeStart)
|
|
14
|
+
return null;
|
|
15
|
+
const between = text.slice(commentEnd + 2, nodeStart);
|
|
16
|
+
if (!/^[\s;]*(export\s+)?(default\s+)?$/.test(between))
|
|
17
|
+
return null;
|
|
18
|
+
return text.slice(commentStart, commentEnd + 2);
|
|
19
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { getParadoxComment } from './getParadoxComment.js';
|
|
2
|
+
import { parseParadoxComment } from './parseParadoxComment.js';
|
|
3
|
+
/***
|
|
4
|
+
* Extracts prop names, types, required flags, and descriptions from a type.
|
|
5
|
+
*/
|
|
6
|
+
export function getPropsFromType(type) {
|
|
7
|
+
return type.getProperties().map((property) => {
|
|
8
|
+
const [declaration] = property.getDeclarations();
|
|
9
|
+
const propertyType = property.getTypeAtLocation(declaration);
|
|
10
|
+
const rawComment = getParadoxComment(declaration);
|
|
11
|
+
const parsed = rawComment ? parseParadoxComment(rawComment) : { description: null };
|
|
12
|
+
return {
|
|
13
|
+
name: property.getName(),
|
|
14
|
+
type: propertyType.getText(declaration),
|
|
15
|
+
required: !property.isOptional(),
|
|
16
|
+
description: parsed.description,
|
|
17
|
+
};
|
|
18
|
+
});
|
|
19
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { Node } from 'ts-morph';
|
|
2
|
+
/***
|
|
3
|
+
* Detects simple React component declarations by name and return type.
|
|
4
|
+
*/
|
|
5
|
+
export function isReactComponent(node) {
|
|
6
|
+
const name = getDeclarationName(node);
|
|
7
|
+
if (!name || !/^[A-Z]/.test(name))
|
|
8
|
+
return false;
|
|
9
|
+
const callSignature = getCallSignature(node);
|
|
10
|
+
const returnType = callSignature?.getReturnType().getText() ?? null;
|
|
11
|
+
if (returnType == null)
|
|
12
|
+
return false;
|
|
13
|
+
return /JSX\.Element|ReactElement|ReactNode|Element/.test(returnType);
|
|
14
|
+
}
|
|
15
|
+
function getDeclarationName(node) {
|
|
16
|
+
if (Node.isFunctionDeclaration(node))
|
|
17
|
+
return node.getName() ?? null;
|
|
18
|
+
if (Node.isVariableDeclaration(node))
|
|
19
|
+
return node.getName();
|
|
20
|
+
return null;
|
|
21
|
+
}
|
|
22
|
+
function getCallSignature(node) {
|
|
23
|
+
if (Node.isFunctionDeclaration(node)) {
|
|
24
|
+
return node.getType().getCallSignatures()[0] ?? null;
|
|
25
|
+
}
|
|
26
|
+
if (Node.isVariableDeclaration(node)) {
|
|
27
|
+
return node.getType().getCallSignatures()[0] ?? null;
|
|
28
|
+
}
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/***
|
|
2
|
+
* Parsed representation of a Paradox doc comment.
|
|
3
|
+
*/
|
|
4
|
+
interface ParsedParadoxComment {
|
|
5
|
+
description: string | null;
|
|
6
|
+
isConfig: boolean;
|
|
7
|
+
}
|
|
8
|
+
/***
|
|
9
|
+
* Parses a Paradox doc comment into structured metadata.
|
|
10
|
+
*/
|
|
11
|
+
export declare function parseParadoxComment(rawComment: string): ParsedParadoxComment;
|
|
12
|
+
export {};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/***
|
|
2
|
+
* Parses a Paradox doc comment into structured metadata.
|
|
3
|
+
*/
|
|
4
|
+
export function parseParadoxComment(rawComment) {
|
|
5
|
+
const lines = rawComment
|
|
6
|
+
.replace(/^\/\*\*\*/, '')
|
|
7
|
+
.replace(/\*\/$/, '')
|
|
8
|
+
.split('\n')
|
|
9
|
+
.map((line) => line.replace(/^\s*\*\s?/, '').trimEnd());
|
|
10
|
+
let isConfig = false;
|
|
11
|
+
const description = lines
|
|
12
|
+
.filter((line) => {
|
|
13
|
+
if (line.trimStart().startsWith('@config')) {
|
|
14
|
+
isConfig = true;
|
|
15
|
+
return false;
|
|
16
|
+
}
|
|
17
|
+
return true;
|
|
18
|
+
})
|
|
19
|
+
.join('\n')
|
|
20
|
+
.trim();
|
|
21
|
+
return {
|
|
22
|
+
description: description.length > 0 ? description : null,
|
|
23
|
+
isConfig,
|
|
24
|
+
};
|
|
25
|
+
}
|
package/{src/analyze/utils/resolveExportSymbol.ts → dist/analyze/utils/resolveExportSymbol.d.ts}
RENAMED
|
@@ -1,8 +1,5 @@
|
|
|
1
1
|
import type { Symbol } from 'ts-morph';
|
|
2
|
-
|
|
3
2
|
/***
|
|
4
3
|
* Resolves aliased export symbols to their underlying declarations.
|
|
5
4
|
*/
|
|
6
|
-
export function resolveExportSymbol(symbol: Symbol): Symbol
|
|
7
|
-
return symbol.getAliasedSymbol() ?? symbol;
|
|
8
|
-
}
|
|
5
|
+
export declare function resolveExportSymbol(symbol: Symbol): Symbol;
|
package/dist/cli.d.ts
ADDED
package/dist/cli.js
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
import { pathToFileURL } from 'node:url';
|
|
4
|
+
import { analyze } from './analyze/analyze.js';
|
|
5
|
+
import { buildModel } from './model/buildModel.js';
|
|
6
|
+
import { render } from './render/render.js';
|
|
7
|
+
import { write } from './write/write.js';
|
|
8
|
+
async function main() {
|
|
9
|
+
const config = await loadConfig(process.cwd());
|
|
10
|
+
const analysis = await analyze(config);
|
|
11
|
+
const model = buildModel(analysis);
|
|
12
|
+
const result = render(model);
|
|
13
|
+
await write(result, config);
|
|
14
|
+
}
|
|
15
|
+
async function loadConfig(root) {
|
|
16
|
+
const configUrl = pathToFileURL(join(root, 'paradox.config.ts')).href;
|
|
17
|
+
const mod = (await import(configUrl));
|
|
18
|
+
return mod.default ?? {};
|
|
19
|
+
}
|
|
20
|
+
main().catch((error) => {
|
|
21
|
+
console.error(error);
|
|
22
|
+
process.exit(1);
|
|
23
|
+
});
|
|
@@ -1,8 +1,5 @@
|
|
|
1
1
|
import type { ParadoxConfig } from './types.js';
|
|
2
|
-
|
|
3
2
|
/***
|
|
4
3
|
* Defines a Paradox configuration object without changing its shape.
|
|
5
4
|
*/
|
|
6
|
-
export function defineParadoxConfig(config: ParadoxConfig): ParadoxConfig
|
|
7
|
-
return config;
|
|
8
|
-
}
|
|
5
|
+
export declare function defineParadoxConfig(config: ParadoxConfig): ParadoxConfig;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/***
|
|
2
|
+
* Configuration for running Paradox.
|
|
3
|
+
*
|
|
4
|
+
* @config
|
|
5
|
+
*/
|
|
6
|
+
export interface ParadoxConfig {
|
|
7
|
+
mode?: 'safe' | 'write';
|
|
8
|
+
docs?: {
|
|
9
|
+
title?: string;
|
|
10
|
+
description?: string;
|
|
11
|
+
};
|
|
12
|
+
package?: {
|
|
13
|
+
root?: string;
|
|
14
|
+
entrypoints?: string[];
|
|
15
|
+
};
|
|
16
|
+
output?: {
|
|
17
|
+
dir?: string;
|
|
18
|
+
};
|
|
19
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { defineParadoxConfig } from './config/defineParadoxConfig.js';
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { DocumentationModel, ExportKind } from './types.js';
|
|
2
|
+
interface BuildModelInput {
|
|
3
|
+
packageName: string;
|
|
4
|
+
packageId: string;
|
|
5
|
+
description: string | null;
|
|
6
|
+
exports: {
|
|
7
|
+
name: string;
|
|
8
|
+
description: string | null;
|
|
9
|
+
kind: ExportKind;
|
|
10
|
+
}[];
|
|
11
|
+
components: {
|
|
12
|
+
name: string;
|
|
13
|
+
description: string | null;
|
|
14
|
+
props: {
|
|
15
|
+
name: string;
|
|
16
|
+
type: string;
|
|
17
|
+
required: boolean;
|
|
18
|
+
description: string | null;
|
|
19
|
+
}[];
|
|
20
|
+
}[];
|
|
21
|
+
usage: {
|
|
22
|
+
packageName: string;
|
|
23
|
+
commands: {
|
|
24
|
+
name: string;
|
|
25
|
+
command: string;
|
|
26
|
+
}[];
|
|
27
|
+
} | null;
|
|
28
|
+
config: {
|
|
29
|
+
exportName: string;
|
|
30
|
+
} | null;
|
|
31
|
+
}
|
|
32
|
+
/***
|
|
33
|
+
* Converts analysis output into a serializable documentation model.
|
|
34
|
+
*/
|
|
35
|
+
export declare function buildModel(analysis: BuildModelInput): DocumentationModel;
|
|
36
|
+
export {};
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/***
|
|
2
|
+
* Converts analysis output into a serializable documentation model.
|
|
3
|
+
*/
|
|
4
|
+
export function buildModel(analysis) {
|
|
5
|
+
const exportsByName = new Map(analysis.exports.map((item) => [item.name, mapExport(item)]));
|
|
6
|
+
const exports = sortByName([...exportsByName.values()]);
|
|
7
|
+
return {
|
|
8
|
+
packageName: analysis.packageName,
|
|
9
|
+
packageId: analysis.packageId,
|
|
10
|
+
description: analysis.description,
|
|
11
|
+
usage: analysis.usage !== null
|
|
12
|
+
? {
|
|
13
|
+
packageName: analysis.usage.packageName,
|
|
14
|
+
commands: sortByName(analysis.usage.commands.map((command) => ({
|
|
15
|
+
name: command.name,
|
|
16
|
+
command: command.command,
|
|
17
|
+
}))),
|
|
18
|
+
}
|
|
19
|
+
: null,
|
|
20
|
+
config: analysis.config !== null
|
|
21
|
+
? {
|
|
22
|
+
exportName: analysis.config.exportName,
|
|
23
|
+
configFile: getDefaultConfigFileName(analysis.packageId),
|
|
24
|
+
factoryName: findConfigFactoryName(analysis.config.exportName, [
|
|
25
|
+
...exportsByName.keys(),
|
|
26
|
+
]),
|
|
27
|
+
}
|
|
28
|
+
: null,
|
|
29
|
+
exports,
|
|
30
|
+
components: sortByName(analysis.components.map(mapComponent)),
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
function mapExport(item) {
|
|
34
|
+
return {
|
|
35
|
+
name: item.name,
|
|
36
|
+
description: item.description,
|
|
37
|
+
kind: item.kind,
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
function mapComponent(component) {
|
|
41
|
+
return {
|
|
42
|
+
name: component.name,
|
|
43
|
+
description: component.description,
|
|
44
|
+
props: sortByName(component.props.map((prop) => ({
|
|
45
|
+
name: prop.name,
|
|
46
|
+
type: prop.type,
|
|
47
|
+
required: prop.required,
|
|
48
|
+
description: prop.description,
|
|
49
|
+
}))),
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
function findConfigFactoryName(configExportName, exportNames) {
|
|
53
|
+
const prefix = configExportName.endsWith('Config')
|
|
54
|
+
? configExportName.slice(0, -'Config'.length)
|
|
55
|
+
: configExportName;
|
|
56
|
+
const expectedFactoryName = `define${prefix}Config`;
|
|
57
|
+
return exportNames.includes(expectedFactoryName) ? expectedFactoryName : null;
|
|
58
|
+
}
|
|
59
|
+
function getDefaultConfigFileName(packageId) {
|
|
60
|
+
const packageBaseName = packageId.split('/').pop() ?? packageId;
|
|
61
|
+
return `${packageBaseName}.config.ts`;
|
|
62
|
+
}
|
|
63
|
+
function sortByName(items) {
|
|
64
|
+
return [...items].sort((a, b) => a.name.localeCompare(b.name));
|
|
65
|
+
}
|