@ankhorage/paradox 0.0.2 → 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.
Files changed (94) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/dist/analyze/analyze.d.ts +6 -0
  3. package/dist/analyze/analyze.js +34 -0
  4. package/dist/analyze/components.d.ts +5 -0
  5. package/dist/analyze/components.js +21 -0
  6. package/dist/analyze/exports.d.ts +16 -0
  7. package/dist/analyze/exports.js +52 -0
  8. package/dist/analyze/project.d.ts +5 -0
  9. package/dist/analyze/project.js +10 -0
  10. package/dist/analyze/types.d.ts +45 -0
  11. package/dist/analyze/types.js +1 -0
  12. package/dist/analyze/usage.d.ts +7 -0
  13. package/dist/analyze/usage.js +40 -0
  14. package/dist/analyze/utils/getComponentPropsType.d.ts +5 -0
  15. package/dist/analyze/utils/getComponentPropsType.js +21 -0
  16. package/dist/analyze/utils/getParadoxComment.d.ts +5 -0
  17. package/dist/analyze/utils/getParadoxComment.js +19 -0
  18. package/dist/analyze/utils/getPropsFromType.d.ts +6 -0
  19. package/dist/analyze/utils/getPropsFromType.js +19 -0
  20. package/dist/analyze/utils/isReactComponent.d.ts +5 -0
  21. package/dist/analyze/utils/isReactComponent.js +30 -0
  22. package/dist/analyze/utils/parseParadoxComment.d.ts +12 -0
  23. package/dist/analyze/utils/parseParadoxComment.js +25 -0
  24. package/{src/analyze/utils/resolveExportSymbol.ts → dist/analyze/utils/resolveExportSymbol.d.ts} +1 -4
  25. package/dist/analyze/utils/resolveExportSymbol.js +6 -0
  26. package/dist/cli.d.ts +2 -0
  27. package/dist/cli.js +23 -0
  28. package/{src/config/defineParadoxConfig.ts → dist/config/defineParadoxConfig.d.ts} +1 -4
  29. package/dist/config/defineParadoxConfig.js +6 -0
  30. package/dist/config/types.d.ts +19 -0
  31. package/dist/config/types.js +1 -0
  32. package/dist/index.js +1 -0
  33. package/dist/model/buildModel.d.ts +36 -0
  34. package/dist/model/buildModel.js +65 -0
  35. package/dist/model/types.d.ts +42 -0
  36. package/dist/model/types.js +1 -0
  37. package/dist/render/render.d.ts +6 -0
  38. package/dist/render/render.js +88 -0
  39. package/dist/render/types.d.ts +10 -0
  40. package/dist/render/types.js +1 -0
  41. package/dist/write/write.d.ts +6 -0
  42. package/dist/write/write.js +18 -0
  43. package/package.json +27 -3
  44. package/.changeset/README.md +0 -5
  45. package/.changeset/config.json +0 -11
  46. package/.changeset/stable-usage-model.md +0 -5
  47. package/.github/workflows/docs.yml +0 -45
  48. package/.prettierignore +0 -1
  49. package/.prettierrc.js +0 -5
  50. package/bun.lock +0 -663
  51. package/eslint.config.mjs +0 -12
  52. package/knip.json +0 -8
  53. package/paradox/components.md +0 -1
  54. package/paradox/exports.json +0 -12
  55. package/paradox/exports.md +0 -13
  56. package/paradox/paradox.json +0 -32
  57. package/paradox.config.ts +0 -18
  58. package/src/analyze/analyze.ts +0 -45
  59. package/src/analyze/components.ts +0 -27
  60. package/src/analyze/exports.ts +0 -87
  61. package/src/analyze/project.ts +0 -11
  62. package/src/analyze/types.ts +0 -53
  63. package/src/analyze/usage.ts +0 -53
  64. package/src/analyze/utils/getComponentPropsType.ts +0 -26
  65. package/src/analyze/utils/getParadoxComment.ts +0 -24
  66. package/src/analyze/utils/getPropsFromType.ts +0 -24
  67. package/src/analyze/utils/isReactComponent.ts +0 -35
  68. package/src/analyze/utils/parseParadoxComment.ts +0 -37
  69. package/src/cli.ts +0 -30
  70. package/src/config/types.ts +0 -22
  71. package/src/model/buildModel.ts +0 -112
  72. package/src/model/types.ts +0 -49
  73. package/src/render/render.ts +0 -115
  74. package/src/render/types.ts +0 -10
  75. package/src/write/write.ts +0 -25
  76. package/tests/__snapshots__/basic.components.md +0 -10
  77. package/tests/__snapshots__/basic.exports.md +0 -19
  78. package/tests/__snapshots__/basic.readme.md +0 -37
  79. package/tests/__snapshots__/multi-bin.readme.md +0 -16
  80. package/tests/analyze.test.ts +0 -153
  81. package/tests/fixtures/basic/package.json +0 -8
  82. package/tests/fixtures/basic/src/config.ts +0 -8
  83. package/tests/fixtures/basic/src/index.ts +0 -3
  84. package/tests/fixtures/basic/src/internal.ts +0 -6
  85. package/tests/fixtures/basic/src/ui.ts +0 -29
  86. package/tests/fixtures/basic/tsconfig.json +0 -11
  87. package/tests/fixtures/multi-bin/package.json +0 -9
  88. package/tests/fixtures/multi-bin/src/alpha.ts +0 -1
  89. package/tests/fixtures/multi-bin/src/beta.ts +0 -1
  90. package/tests/fixtures/multi-bin/src/index.ts +0 -4
  91. package/tests/fixtures/multi-bin/tsconfig.json +0 -11
  92. package/tsconfig.eslint.json +0 -16
  93. package/tsconfig.json +0 -14
  94. /package/{src/index.ts → dist/index.d.ts} +0 -0
package/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.0.3
4
+
5
+ ### Patch Changes
6
+
7
+ - d9fb959: Stabilize usage metadata, documentation model serialization, deterministic output ordering, and package entrypoint exports.
8
+
3
9
  ## 0.0.1
4
10
 
5
11
  ### Patch Changes
@@ -0,0 +1,6 @@
1
+ import type { ParadoxConfig } from '../config/types.js';
2
+ import type { AnalysisResult } from './types.js';
3
+ /***
4
+ * Runs the source analysis pipeline for a configured package.
5
+ */
6
+ export declare function analyze(config: ParadoxConfig): Promise<AnalysisResult>;
@@ -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,5 @@
1
+ import type { AnalysisComponent, AnalysisExport } from './types.js';
2
+ /***
3
+ * Extracts React components and their props from analyzed exports.
4
+ */
5
+ export declare function analyzeComponents(exports: readonly AnalysisExport[]): AnalysisComponent[];
@@ -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,5 @@
1
+ import { Project } from 'ts-morph';
2
+ /***
3
+ * Creates the ts-morph project used by the analyzer.
4
+ */
5
+ export declare function createProject(root: string): Project;
@@ -0,0 +1,10 @@
1
+ import { Project } from 'ts-morph';
2
+ /***
3
+ * Creates the ts-morph project used by the analyzer.
4
+ */
5
+ export function createProject(root) {
6
+ return new Project({
7
+ tsConfigFilePath: `${root}/tsconfig.json`,
8
+ skipAddingFilesFromTsConfig: false,
9
+ });
10
+ }
@@ -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,5 @@
1
+ import { Node, type Type } from 'ts-morph';
2
+ /***
3
+ * Returns the first parameter type for a React component declaration.
4
+ */
5
+ export declare function getComponentPropsType(node: Node): Type | null;
@@ -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,5 @@
1
+ import type { Node } from 'ts-morph';
2
+ /***
3
+ * Reads the nearest Paradox doc comment attached to a declaration.
4
+ */
5
+ export declare function getParadoxComment(node: Node): string | null;
@@ -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,6 @@
1
+ import type { Type } from 'ts-morph';
2
+ import type { AnalysisComponent } from '../types.js';
3
+ /***
4
+ * Extracts prop names, types, required flags, and descriptions from a type.
5
+ */
6
+ export declare function getPropsFromType(type: Type): AnalysisComponent['props'];
@@ -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,5 @@
1
+ import { Node } from 'ts-morph';
2
+ /***
3
+ * Detects simple React component declarations by name and return type.
4
+ */
5
+ export declare function isReactComponent(node: Node): boolean;
@@ -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
+ }
@@ -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;
@@ -0,0 +1,6 @@
1
+ /***
2
+ * Resolves aliased export symbols to their underlying declarations.
3
+ */
4
+ export function resolveExportSymbol(symbol) {
5
+ return symbol.getAliasedSymbol() ?? symbol;
6
+ }
package/dist/cli.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env bun
2
+ export {};
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,6 @@
1
+ /***
2
+ * Defines a Paradox configuration object without changing its shape.
3
+ */
4
+ export function defineParadoxConfig(config) {
5
+ return config;
6
+ }
@@ -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
+ }