@pithyjs/codex 0.1.0-beta.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/LICENSE +21 -0
- package/README.md +4401 -0
- package/dist/annotations.d.ts +106 -0
- package/dist/annotations.js +306 -0
- package/dist/apply.d.ts +2 -0
- package/dist/apply.js +80 -0
- package/dist/changed-scope.d.ts +23 -0
- package/dist/changed-scope.js +31 -0
- package/dist/check.d.ts +2 -0
- package/dist/check.js +117 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +67 -0
- package/dist/env.d.ts +5 -0
- package/dist/env.js +35 -0
- package/dist/extract-cli.d.ts +23 -0
- package/dist/extract-cli.js +192 -0
- package/dist/extraction/breaking-changes.d.ts +66 -0
- package/dist/extraction/breaking-changes.js +352 -0
- package/dist/extraction/example-extractor.d.ts +55 -0
- package/dist/extraction/example-extractor.js +272 -0
- package/dist/extraction/index.d.ts +27 -0
- package/dist/extraction/index.js +31 -0
- package/dist/extraction/jsdoc-parser.d.ts +43 -0
- package/dist/extraction/jsdoc-parser.js +274 -0
- package/dist/extraction/pipeline.d.ts +54 -0
- package/dist/extraction/pipeline.js +526 -0
- package/dist/extraction/readme-sync.d.ts +108 -0
- package/dist/extraction/readme-sync.js +592 -0
- package/dist/extraction/snapshot-store.d.ts +40 -0
- package/dist/extraction/snapshot-store.js +153 -0
- package/dist/extraction/source-linker.d.ts +80 -0
- package/dist/extraction/source-linker.js +316 -0
- package/dist/extraction/test-example-extractor.d.ts +69 -0
- package/dist/extraction/test-example-extractor.js +400 -0
- package/dist/extraction/test-pattern-extractor.d.ts +68 -0
- package/dist/extraction/test-pattern-extractor.js +261 -0
- package/dist/extraction/testing-pyramid.d.ts +44 -0
- package/dist/extraction/testing-pyramid.js +163 -0
- package/dist/extraction/type-extractor.d.ts +34 -0
- package/dist/extraction/type-extractor.js +494 -0
- package/dist/extraction/types.d.ts +401 -0
- package/dist/extraction/types.js +34 -0
- package/dist/indexer.d.ts +1 -0
- package/dist/indexer.js +107 -0
- package/dist/llm.d.ts +8 -0
- package/dist/llm.js +75 -0
- package/dist/readme-sync-cli.d.ts +20 -0
- package/dist/readme-sync-cli.js +167 -0
- package/dist/review.d.ts +2 -0
- package/dist/review.js +93 -0
- package/dist/scan.d.ts +29 -0
- package/dist/scan.js +221 -0
- package/dist/schema.d.ts +169 -0
- package/dist/schema.js +70 -0
- package/dist/snapshot-cli.d.ts +45 -0
- package/dist/snapshot-cli.js +217 -0
- package/dist/sync-cli.d.ts +22 -0
- package/dist/sync-cli.js +154 -0
- package/dist/sync-pipeline.d.ts +58 -0
- package/dist/sync-pipeline.js +104 -0
- package/dist/sync.d.ts +2 -0
- package/dist/sync.js +318 -0
- package/dist/validate-cli.d.ts +20 -0
- package/dist/validate-cli.js +144 -0
- package/dist/validate.d.ts +76 -0
- package/dist/validate.js +183 -0
- package/dist/watch-cli.d.ts +21 -0
- package/dist/watch-cli.js +220 -0
- package/package.json +62 -0
package/dist/cli.js
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* @codex
|
|
4
|
+
* {
|
|
5
|
+
* "id": "pithy.codex.cli",
|
|
6
|
+
* "title": "CLI Entry Point",
|
|
7
|
+
* "category": "feature"
|
|
8
|
+
* }
|
|
9
|
+
*
|
|
10
|
+
* Main CLI dispatcher for codex commands. Provides an interactive readline
|
|
11
|
+
* prompt to create new codex entries with id, title, category, tags, and
|
|
12
|
+
* related fields, then writes the validated JSON to codex/.proposals/.
|
|
13
|
+
*/
|
|
14
|
+
import { createInterface } from 'node:readline/promises';
|
|
15
|
+
import { stdin as input, stdout as output } from 'node:process';
|
|
16
|
+
import { join } from 'node:path';
|
|
17
|
+
import fs from 'node:fs/promises';
|
|
18
|
+
import { codexSchema } from './schema.js'; // NodeNext-friendly
|
|
19
|
+
const parseCSV = (s) => s
|
|
20
|
+
.split(',')
|
|
21
|
+
.map(t => t.trim())
|
|
22
|
+
.filter(Boolean);
|
|
23
|
+
const sanitizeId = (s) => s.trim().replace(/\s+/g, '-');
|
|
24
|
+
const isSafeId = (s) => /^[A-Za-z0-9._-]+$/.test(s);
|
|
25
|
+
async function main() {
|
|
26
|
+
const rl = createInterface({ input, output });
|
|
27
|
+
const idRaw = await rl.question('id: ');
|
|
28
|
+
const id = sanitizeId(idRaw);
|
|
29
|
+
if (!isSafeId(id)) {
|
|
30
|
+
console.error('Invalid id. Use letters, numbers, ".", "_" or "-". No spaces.');
|
|
31
|
+
rl.close();
|
|
32
|
+
process.exit(1);
|
|
33
|
+
}
|
|
34
|
+
const title = (await rl.question('title: ')).trim();
|
|
35
|
+
const category = (await rl.question('category: ')).trim();
|
|
36
|
+
const tags = await rl.question('tags (comma separated): ');
|
|
37
|
+
const updatedIn = (await rl.question('updated (ISO date, blank = now): ')).trim();
|
|
38
|
+
const updated = updatedIn || new Date().toISOString();
|
|
39
|
+
const related = await rl.question('related (comma separated): ');
|
|
40
|
+
rl.close();
|
|
41
|
+
const data = {
|
|
42
|
+
id,
|
|
43
|
+
title,
|
|
44
|
+
category,
|
|
45
|
+
tags: parseCSV(tags),
|
|
46
|
+
updated,
|
|
47
|
+
related: parseCSV(related),
|
|
48
|
+
};
|
|
49
|
+
const entry = codexSchema.parse(data); // throws on invalid
|
|
50
|
+
const outDir = join(process.cwd(), 'codex');
|
|
51
|
+
const filePath = join(outDir, `${entry.id}.json`);
|
|
52
|
+
try {
|
|
53
|
+
// prevent accidental overwrite
|
|
54
|
+
await fs.access(filePath);
|
|
55
|
+
console.error(`Entry already exists: ${filePath}`);
|
|
56
|
+
process.exit(1);
|
|
57
|
+
}
|
|
58
|
+
catch {
|
|
59
|
+
// OK, file doesn't exist
|
|
60
|
+
}
|
|
61
|
+
await fs.writeFile(filePath, JSON.stringify(entry, null, 2));
|
|
62
|
+
console.log(`ā
Wrote ${filePath}`);
|
|
63
|
+
}
|
|
64
|
+
main().catch(err => {
|
|
65
|
+
console.error(err);
|
|
66
|
+
process.exit(1);
|
|
67
|
+
});
|
package/dist/env.d.ts
ADDED
package/dist/env.js
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @codex
|
|
3
|
+
* {
|
|
4
|
+
* "id": "pithy.codex.env",
|
|
5
|
+
* "title": "Environment Configuration",
|
|
6
|
+
* "category": "feature"
|
|
7
|
+
* }
|
|
8
|
+
*
|
|
9
|
+
* Loads environment variables for LLM API access.
|
|
10
|
+
*/
|
|
11
|
+
import { config } from 'dotenv';
|
|
12
|
+
import { join, dirname } from 'node:path';
|
|
13
|
+
import { fileURLToPath } from 'node:url';
|
|
14
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
15
|
+
const repoRoot = join(__dirname, '../../..');
|
|
16
|
+
// Load order: team defaults ā .env ā .env.local (later files win)
|
|
17
|
+
const files = [
|
|
18
|
+
join(repoRoot, '.env.team'),
|
|
19
|
+
join(repoRoot, '.env'),
|
|
20
|
+
join(repoRoot, '.env.local'),
|
|
21
|
+
];
|
|
22
|
+
/**
|
|
23
|
+
* Loads environment variables from .env files using dotenv.
|
|
24
|
+
* @codexApi {"parent":"pithy.codex.env","name":"loadEnv","stability":"stable","signature":"() => void"}
|
|
25
|
+
*/
|
|
26
|
+
export function loadEnv() {
|
|
27
|
+
for (const f of files) {
|
|
28
|
+
try {
|
|
29
|
+
config({ path: f, override: false });
|
|
30
|
+
}
|
|
31
|
+
catch {
|
|
32
|
+
void 0;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* @codex
|
|
4
|
+
* {
|
|
5
|
+
* "id": "pithy.codex.extraction.cli",
|
|
6
|
+
* "title": "Extraction CLI",
|
|
7
|
+
* "category": "plugin"
|
|
8
|
+
* }
|
|
9
|
+
*
|
|
10
|
+
* CLI for running the multi-source extraction pipeline.
|
|
11
|
+
*
|
|
12
|
+
* Usage:
|
|
13
|
+
* pnpm codex:extract [options]
|
|
14
|
+
*
|
|
15
|
+
* Options:
|
|
16
|
+
* --root <path> Project root directory (default: cwd)
|
|
17
|
+
* --output <path> Output file for results (default: codex/extracted.json)
|
|
18
|
+
* --report Generate human-readable report
|
|
19
|
+
* --no-tests Skip test file analysis
|
|
20
|
+
* --no-readme Skip README linking
|
|
21
|
+
* --verbose Show detailed progress
|
|
22
|
+
*/
|
|
23
|
+
export {};
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* @codex
|
|
4
|
+
* {
|
|
5
|
+
* "id": "pithy.codex.extraction.cli",
|
|
6
|
+
* "title": "Extraction CLI",
|
|
7
|
+
* "category": "plugin"
|
|
8
|
+
* }
|
|
9
|
+
*
|
|
10
|
+
* CLI for running the multi-source extraction pipeline.
|
|
11
|
+
*
|
|
12
|
+
* Usage:
|
|
13
|
+
* pnpm codex:extract [options]
|
|
14
|
+
*
|
|
15
|
+
* Options:
|
|
16
|
+
* --root <path> Project root directory (default: cwd)
|
|
17
|
+
* --output <path> Output file for results (default: codex/extracted.json)
|
|
18
|
+
* --report Generate human-readable report
|
|
19
|
+
* --no-tests Skip test file analysis
|
|
20
|
+
* --no-readme Skip README linking
|
|
21
|
+
* --verbose Show detailed progress
|
|
22
|
+
*/
|
|
23
|
+
import { join, resolve, relative, isAbsolute } from 'node:path';
|
|
24
|
+
import fs from 'node:fs/promises';
|
|
25
|
+
import { runExtractionPipeline, generateExtractionReport, exportToCodexFormat, } from './extraction/index.js';
|
|
26
|
+
/**
|
|
27
|
+
* Validates and normalizes a path to prevent path traversal attacks
|
|
28
|
+
* @param basePath - The base directory that paths must stay within
|
|
29
|
+
* @param inputPath - The user-provided path to validate
|
|
30
|
+
* @returns Normalized absolute path
|
|
31
|
+
* @throws Error if path escapes the base directory
|
|
32
|
+
*/
|
|
33
|
+
function validatePath(basePath, inputPath) {
|
|
34
|
+
const resolvedBase = resolve(basePath);
|
|
35
|
+
const resolvedPath = isAbsolute(inputPath)
|
|
36
|
+
? resolve(inputPath)
|
|
37
|
+
: resolve(basePath, inputPath);
|
|
38
|
+
// Ensure the resolved path is within the base directory
|
|
39
|
+
const relativePath = relative(resolvedBase, resolvedPath);
|
|
40
|
+
if (relativePath.startsWith('..') || isAbsolute(relativePath)) {
|
|
41
|
+
throw new Error(`Security error: Path "${inputPath}" escapes the project root directory`);
|
|
42
|
+
}
|
|
43
|
+
return resolvedPath;
|
|
44
|
+
}
|
|
45
|
+
function parseArgs(args) {
|
|
46
|
+
const options = {
|
|
47
|
+
root: process.cwd(),
|
|
48
|
+
output: 'codex/extracted.json',
|
|
49
|
+
report: false,
|
|
50
|
+
analyzeTests: true,
|
|
51
|
+
linkReadmes: true,
|
|
52
|
+
verbose: false,
|
|
53
|
+
};
|
|
54
|
+
for (let i = 0; i < args.length; i++) {
|
|
55
|
+
const arg = args[i];
|
|
56
|
+
switch (arg) {
|
|
57
|
+
case '--root':
|
|
58
|
+
options.root = args[++i] || process.cwd();
|
|
59
|
+
break;
|
|
60
|
+
case '--output':
|
|
61
|
+
options.output = args[++i] || options.output;
|
|
62
|
+
break;
|
|
63
|
+
case '--report':
|
|
64
|
+
options.report = true;
|
|
65
|
+
break;
|
|
66
|
+
case '--no-tests':
|
|
67
|
+
options.analyzeTests = false;
|
|
68
|
+
break;
|
|
69
|
+
case '--no-readme':
|
|
70
|
+
options.linkReadmes = false;
|
|
71
|
+
break;
|
|
72
|
+
case '--verbose':
|
|
73
|
+
case '-v':
|
|
74
|
+
options.verbose = true;
|
|
75
|
+
break;
|
|
76
|
+
case '--help':
|
|
77
|
+
case '-h':
|
|
78
|
+
printHelp();
|
|
79
|
+
process.exit(0);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
return options;
|
|
83
|
+
}
|
|
84
|
+
function printHelp() {
|
|
85
|
+
console.log(`
|
|
86
|
+
Codex Extraction Pipeline
|
|
87
|
+
|
|
88
|
+
Usage:
|
|
89
|
+
codex-extract [options]
|
|
90
|
+
|
|
91
|
+
Options:
|
|
92
|
+
--root <path> Project root directory (default: current directory)
|
|
93
|
+
--output <path> Output file for results (default: codex/extracted.json)
|
|
94
|
+
--report Generate human-readable report (stdout)
|
|
95
|
+
--no-tests Skip test file analysis
|
|
96
|
+
--no-readme Skip README linking
|
|
97
|
+
--verbose, -v Show detailed progress
|
|
98
|
+
--help, -h Show this help message
|
|
99
|
+
|
|
100
|
+
Examples:
|
|
101
|
+
# Extract from current directory
|
|
102
|
+
codex-extract
|
|
103
|
+
|
|
104
|
+
# Extract with custom output
|
|
105
|
+
codex-extract --output docs/api-data.json
|
|
106
|
+
|
|
107
|
+
# Generate report only
|
|
108
|
+
codex-extract --report
|
|
109
|
+
|
|
110
|
+
# Extract without test analysis (faster)
|
|
111
|
+
codex-extract --no-tests --no-readme
|
|
112
|
+
`);
|
|
113
|
+
}
|
|
114
|
+
async function main() {
|
|
115
|
+
const args = process.argv.slice(2);
|
|
116
|
+
const options = parseArgs(args);
|
|
117
|
+
// Validate and normalize the root path
|
|
118
|
+
options.root = resolve(options.root);
|
|
119
|
+
// Verify root directory exists
|
|
120
|
+
try {
|
|
121
|
+
const stat = await fs.stat(options.root);
|
|
122
|
+
if (!stat.isDirectory()) {
|
|
123
|
+
console.error(`ā Error: "${options.root}" is not a directory`);
|
|
124
|
+
process.exit(1);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
catch {
|
|
128
|
+
console.error(`ā Error: Root directory "${options.root}" does not exist`);
|
|
129
|
+
process.exit(1);
|
|
130
|
+
}
|
|
131
|
+
if (options.verbose) {
|
|
132
|
+
console.log('š Codex Extraction Pipeline');
|
|
133
|
+
console.log(` Root: ${options.root}`);
|
|
134
|
+
console.log(` Output: ${options.output}`);
|
|
135
|
+
console.log(` Analyze tests: ${options.analyzeTests}`);
|
|
136
|
+
console.log(` Link READMEs: ${options.linkReadmes}`);
|
|
137
|
+
console.log('');
|
|
138
|
+
}
|
|
139
|
+
const startTime = performance.now();
|
|
140
|
+
try {
|
|
141
|
+
if (options.verbose) {
|
|
142
|
+
console.log('š Scanning source files...');
|
|
143
|
+
}
|
|
144
|
+
const result = await runExtractionPipeline({
|
|
145
|
+
root: options.root,
|
|
146
|
+
analyzeTests: options.analyzeTests,
|
|
147
|
+
linkReadmes: options.linkReadmes,
|
|
148
|
+
extractRunnableExamples: true,
|
|
149
|
+
});
|
|
150
|
+
const elapsed = ((performance.now() - startTime) / 1000).toFixed(2);
|
|
151
|
+
if (options.verbose) {
|
|
152
|
+
console.log(`\nā
Extraction complete in ${elapsed}s`);
|
|
153
|
+
console.log('');
|
|
154
|
+
console.log('š Statistics:');
|
|
155
|
+
console.log(` Files scanned: ${result.stats.filesScanned}`);
|
|
156
|
+
console.log(` Components found: ${result.stats.componentsFound}`);
|
|
157
|
+
console.log(` APIs extracted: ${result.stats.apisExtracted}`);
|
|
158
|
+
console.log(` Examples extracted: ${result.stats.examplesExtracted}`);
|
|
159
|
+
console.log(` Tests analyzed: ${result.stats.testsAnalyzed}`);
|
|
160
|
+
console.log(` README sections linked: ${result.stats.readmeSectionsLinked}`);
|
|
161
|
+
console.log('');
|
|
162
|
+
}
|
|
163
|
+
// Generate report if requested
|
|
164
|
+
if (options.report) {
|
|
165
|
+
const report = generateExtractionReport(result);
|
|
166
|
+
console.log(report);
|
|
167
|
+
}
|
|
168
|
+
// Write output file (with path validation)
|
|
169
|
+
const validatedRoot = resolve(options.root);
|
|
170
|
+
const outputPath = validatePath(validatedRoot, options.output);
|
|
171
|
+
const outputDir = join(outputPath, '..');
|
|
172
|
+
await fs.mkdir(outputDir, { recursive: true });
|
|
173
|
+
const exportData = exportToCodexFormat(result);
|
|
174
|
+
await fs.writeFile(outputPath, JSON.stringify(exportData, null, 2));
|
|
175
|
+
if (options.verbose || !options.report) {
|
|
176
|
+
console.log(`š Wrote extraction data to: ${outputPath}`);
|
|
177
|
+
}
|
|
178
|
+
// Summary (always shown unless report mode)
|
|
179
|
+
if (!options.report) {
|
|
180
|
+
console.log('');
|
|
181
|
+
console.log(`⨠Extracted ${result.stats.componentsFound} components with ${result.stats.apisExtracted} APIs`);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
catch (error) {
|
|
185
|
+
console.error('ā Extraction failed:', error);
|
|
186
|
+
process.exit(1);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
main().catch(err => {
|
|
190
|
+
console.error('Fatal error:', err);
|
|
191
|
+
process.exit(1);
|
|
192
|
+
});
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @codex
|
|
3
|
+
* {
|
|
4
|
+
* "id": "pithy.codex.breaking-changes",
|
|
5
|
+
* "title": "Breaking Change Detection",
|
|
6
|
+
* "category": "feature"
|
|
7
|
+
* }
|
|
8
|
+
*
|
|
9
|
+
* Detects breaking changes between API snapshots by comparing
|
|
10
|
+
* extracted API signatures, stability levels, and type definitions.
|
|
11
|
+
* Generates migration guides and changelogs for version transitions.
|
|
12
|
+
*/
|
|
13
|
+
import type { ExtendedExtractionResult, ExtractedTypeDefinition, ApiSnapshot, ApiChange, SnapshotDiff, ChangeClassification } from './types.js';
|
|
14
|
+
/**
|
|
15
|
+
* Create an API snapshot from extraction results at a given version.
|
|
16
|
+
* Captures all enriched API entries across all components.
|
|
17
|
+
*
|
|
18
|
+
* @codexApi {"parent":"pithy.codex.breaking-changes","name":"createApiSnapshot","stability":"stable","signature":"(result: ExtendedExtractionResult, version: string, timestamp?: string) => ApiSnapshot"}
|
|
19
|
+
*/
|
|
20
|
+
export declare function createApiSnapshot(result: ExtendedExtractionResult, version: string, timestamp?: string): ApiSnapshot;
|
|
21
|
+
/**
|
|
22
|
+
* Create an API snapshot from extracted type definitions.
|
|
23
|
+
* Only includes exported types (public API surface).
|
|
24
|
+
*
|
|
25
|
+
* @codexApi {"parent":"pithy.codex.breaking-changes","name":"snapshotFromTypeDefinitions","stability":"stable","signature":"(types: ExtractedTypeDefinition[], version: string, timestamp?: string) => ApiSnapshot"}
|
|
26
|
+
*/
|
|
27
|
+
export declare function snapshotFromTypeDefinitions(types: ExtractedTypeDefinition[], version: string, timestamp?: string): ApiSnapshot;
|
|
28
|
+
/**
|
|
29
|
+
* Compare two API snapshots and produce a structured diff.
|
|
30
|
+
* Matches entries by qualifiedName (parent.name).
|
|
31
|
+
*
|
|
32
|
+
* @codexApi {"parent":"pithy.codex.breaking-changes","name":"diffSnapshots","stability":"stable","signature":"(before: ApiSnapshot, after: ApiSnapshot) => SnapshotDiff"}
|
|
33
|
+
*/
|
|
34
|
+
export declare function diffSnapshots(before: ApiSnapshot, after: ApiSnapshot): SnapshotDiff;
|
|
35
|
+
/**
|
|
36
|
+
* Classify a single API change as major, minor, or patch
|
|
37
|
+
* according to semver conventions.
|
|
38
|
+
*
|
|
39
|
+
* - **major**: removal or signature/member change of a stable API
|
|
40
|
+
* - **minor**: addition, removal of experimental/deprecated, or changes to experimental APIs
|
|
41
|
+
* - **patch**: stability level changes
|
|
42
|
+
*
|
|
43
|
+
* @codexApi {"parent":"pithy.codex.breaking-changes","name":"classifyChange","stability":"stable","signature":"(change: ApiChange) => ChangeClassification"}
|
|
44
|
+
*/
|
|
45
|
+
export declare function classifyChange(change: ApiChange): ChangeClassification;
|
|
46
|
+
/**
|
|
47
|
+
* Filter a snapshot diff down to only breaking changes
|
|
48
|
+
* (those classified as "major").
|
|
49
|
+
*
|
|
50
|
+
* @codexApi {"parent":"pithy.codex.breaking-changes","name":"detectBreakingChanges","stability":"stable","signature":"(diff: SnapshotDiff) => ApiChange[]"}
|
|
51
|
+
*/
|
|
52
|
+
export declare function detectBreakingChanges(diff: SnapshotDiff): ApiChange[];
|
|
53
|
+
/**
|
|
54
|
+
* Generate a human-readable migration guide for a set of breaking changes.
|
|
55
|
+
* Groups changes by parent component and provides before/after comparisons.
|
|
56
|
+
*
|
|
57
|
+
* @codexApi {"parent":"pithy.codex.breaking-changes","name":"generateMigrationGuide","stability":"stable","signature":"(changes: ApiChange[]) => string"}
|
|
58
|
+
*/
|
|
59
|
+
export declare function generateMigrationGuide(changes: ApiChange[]): string;
|
|
60
|
+
/**
|
|
61
|
+
* Generate a changelog in Markdown from a snapshot diff.
|
|
62
|
+
* Sections: Breaking Changes, Added, Changed. Omits empty sections.
|
|
63
|
+
*
|
|
64
|
+
* @codexApi {"parent":"pithy.codex.breaking-changes","name":"generateChangelog","stability":"stable","signature":"(diff: SnapshotDiff) => string"}
|
|
65
|
+
*/
|
|
66
|
+
export declare function generateChangelog(diff: SnapshotDiff): string;
|