Skip to content

Commit 57fe80d

Browse files
committed
meta: move generators
1 parent 32a824c commit 57fe80d

63 files changed

Lines changed: 1245 additions & 1152 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

src/generators.mjs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,12 @@ const createGenerator = () => {
5353
return;
5454
}
5555

56-
const { dependsOn, generate, processChunk } =
57-
await allGenerators[generatorName]();
56+
const { dependsOn } = allGenerators[generatorName];
57+
58+
// Lazy-load the generator implementation
59+
const { generate, processChunk } = await import(
60+
`./generators/${generatorName}/generate.mjs`
61+
);
5862

5963
// Schedule dependency first
6064
if (dependsOn && !(dependsOn in cachedGenerators)) {

src/generators/__tests__/index.test.mjs

Lines changed: 9 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,11 @@ import { allGenerators } from '../index.mjs';
77

88
const validDependencies = Object.keys(allGenerators);
99

10-
const allGeneratorsReaolved = await Promise.all(
11-
Object.entries(allGenerators).map(async ([key, loader]) => [
12-
key,
13-
await loader(),
14-
])
15-
);
10+
const allGeneratorsEntries = Object.entries(allGenerators);
1611

1712
describe('All Generators', () => {
18-
it('should have keys matching their name property', async () => {
19-
allGeneratorsReaolved.forEach(([key, generator]) => {
13+
it('should have keys matching their name property', () => {
14+
allGeneratorsEntries.forEach(([key, generator]) => {
2015
assert.equal(
2116
key,
2217
generator.name,
@@ -25,8 +20,8 @@ describe('All Generators', () => {
2520
});
2621
});
2722

28-
it('should have valid semver versions', async () => {
29-
allGeneratorsReaolved.forEach(([key, generator]) => {
23+
it('should have valid semver versions', () => {
24+
allGeneratorsEntries.forEach(([key, generator]) => {
3025
const isValid = semver.valid(generator.version);
3126
assert.ok(
3227
isValid,
@@ -35,8 +30,8 @@ describe('All Generators', () => {
3530
});
3631
});
3732

38-
it('should have valid dependsOn references', async () => {
39-
allGeneratorsReaolved.forEach(([key, generator]) => {
33+
it('should have valid dependsOn references', () => {
34+
allGeneratorsEntries.forEach(([key, generator]) => {
4035
if (generator.dependsOn) {
4136
assert.ok(
4237
validDependencies.includes(generator.dependsOn),
@@ -46,8 +41,8 @@ describe('All Generators', () => {
4641
});
4742
});
4843

49-
it('should have ast generator as a top-level generator with no dependencies', async () => {
50-
const ast = await allGenerators.ast();
44+
it('should have ast generator as a top-level generator with no dependencies', () => {
45+
const ast = allGenerators.ast;
5146
assert.ok(ast, 'ast generator should exist');
5247
assert.equal(
5348
ast.dependsOn,
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
'use strict';
2+
3+
import { mkdir, writeFile } from 'node:fs/promises';
4+
import { join } from 'node:path';
5+
6+
import { visit } from 'unist-util-visit';
7+
8+
import { EXTRACT_CODE_FILENAME_COMMENT } from './constants.mjs';
9+
import { generateFileList } from './utils/generateFileList.mjs';
10+
import {
11+
generateSectionFolderName,
12+
isBuildableSection,
13+
normalizeSectionName,
14+
} from './utils/section.mjs';
15+
import getConfig from '../../utils/configuration/index.mjs';
16+
17+
/**
18+
* Generates a file list from code blocks.
19+
*
20+
* @type {import('./types').Implementation['generate']}
21+
*/
22+
export async function generate(input) {
23+
const config = getConfig('addon-verify');
24+
25+
const sectionsCodeBlocks = input.reduce((addons, node) => {
26+
const sectionName = node.heading.data.name;
27+
28+
const content = node.content;
29+
30+
visit(content, childNode => {
31+
if (childNode.type === 'code') {
32+
const filename = childNode.value.match(EXTRACT_CODE_FILENAME_COMMENT);
33+
34+
if (filename === null) {
35+
return;
36+
}
37+
38+
if (!addons[sectionName]) {
39+
addons[sectionName] = [];
40+
}
41+
42+
addons[sectionName].push({
43+
name: filename[1],
44+
content: childNode.value,
45+
});
46+
}
47+
});
48+
49+
return addons;
50+
}, {});
51+
52+
const files = await Promise.all(
53+
Object.entries(sectionsCodeBlocks)
54+
.filter(([, codeBlocks]) => isBuildableSection(codeBlocks))
55+
.flatMap(async ([sectionName, codeBlocks], index) => {
56+
const files = generateFileList(codeBlocks);
57+
58+
if (config.output) {
59+
const normalizedSectionName = normalizeSectionName(sectionName);
60+
61+
const folderName = generateSectionFolderName(
62+
normalizedSectionName,
63+
index
64+
);
65+
66+
await mkdir(join(config.output, folderName), { recursive: true });
67+
68+
for (const file of files) {
69+
await writeFile(
70+
join(config.output, folderName, file.name),
71+
file.content
72+
);
73+
}
74+
}
75+
76+
return files;
77+
})
78+
);
79+
80+
return files;
81+
}
Lines changed: 0 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,5 @@
11
'use strict';
22

3-
import { mkdir, writeFile } from 'node:fs/promises';
4-
import { join } from 'node:path';
5-
6-
import { visit } from 'unist-util-visit';
7-
8-
import { EXTRACT_CODE_FILENAME_COMMENT } from './constants.mjs';
9-
import { generateFileList } from './utils/generateFileList.mjs';
10-
import {
11-
generateSectionFolderName,
12-
isBuildableSection,
13-
normalizeSectionName,
14-
} from './utils/section.mjs';
15-
import getConfig from '../../utils/configuration/index.mjs';
16-
173
/**
184
* This generator generates a file list from code blocks extracted from
195
* `doc/api/addons.md` to facilitate C++ compilation and JavaScript runtime
@@ -30,68 +16,4 @@ export default {
3016
'Generates a file list from code blocks extracted from `doc/api/addons.md` to facilitate C++ compilation and JavaScript runtime validations',
3117

3218
dependsOn: 'metadata',
33-
34-
/**
35-
* Generates a file list from code blocks.
36-
*/
37-
async generate(input) {
38-
const config = getConfig('addon-verify');
39-
40-
const sectionsCodeBlocks = input.reduce((addons, node) => {
41-
const sectionName = node.heading.data.name;
42-
43-
const content = node.content;
44-
45-
visit(content, childNode => {
46-
if (childNode.type === 'code') {
47-
const filename = childNode.value.match(EXTRACT_CODE_FILENAME_COMMENT);
48-
49-
if (filename === null) {
50-
return;
51-
}
52-
53-
if (!addons[sectionName]) {
54-
addons[sectionName] = [];
55-
}
56-
57-
addons[sectionName].push({
58-
name: filename[1],
59-
content: childNode.value,
60-
});
61-
}
62-
});
63-
64-
return addons;
65-
}, {});
66-
67-
const files = await Promise.all(
68-
Object.entries(sectionsCodeBlocks)
69-
.filter(([, codeBlocks]) => isBuildableSection(codeBlocks))
70-
.flatMap(async ([sectionName, codeBlocks], index) => {
71-
const files = generateFileList(codeBlocks);
72-
73-
if (config.output) {
74-
const normalizedSectionName = normalizeSectionName(sectionName);
75-
76-
const folderName = generateSectionFolderName(
77-
normalizedSectionName,
78-
index
79-
);
80-
81-
await mkdir(join(config.output, folderName), { recursive: true });
82-
83-
for (const file of files) {
84-
await writeFile(
85-
join(config.output, folderName, file.name),
86-
file.content
87-
);
88-
}
89-
}
90-
91-
return files;
92-
})
93-
);
94-
95-
return files;
96-
},
9719
};
Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
export type Generator = GeneratorMetadata<
2-
{},
1+
export type Generator = GeneratorMetadata<{}>;
2+
3+
export type Implementation = GeneratorImpl<
34
Generate<Array<ApiDocMetadataEntry>, Promise<Record<string, string>>>
45
>;

src/generators/api-links/__tests__/fixtures.test.mjs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ import { globSync } from 'tinyglobby';
66
import createWorkerPool from '../../../threading/index.mjs';
77
import createParallelWorker from '../../../threading/parallel.mjs';
88
import { setConfig } from '../../../utils/configuration/index.mjs';
9-
import astJs from '../../ast-js/index.mjs';
10-
import apiLinks from '../index.mjs';
9+
import { generate as astJsGenerate } from '../../ast-js/generate.mjs';
10+
import { generate as apiLinksGenerate } from '../generate.mjs';
1111

1212
const relativePath = relative(process.cwd(), import.meta.dirname);
1313

@@ -40,11 +40,11 @@ describe('api links', () => {
4040
// Collect results from the async generator
4141
const astJsResults = [];
4242

43-
for await (const chunk of astJs.generate(undefined, worker)) {
43+
for await (const chunk of astJsGenerate(undefined, worker)) {
4444
astJsResults.push(...chunk);
4545
}
4646

47-
const actualOutput = await apiLinks.generate(astJsResults);
47+
const actualOutput = await apiLinksGenerate(astJsResults);
4848

4949
for (const [k, v] of Object.entries(actualOutput)) {
5050
actualOutput[k] = v.replace(/.*(?=lib\/)/, '');
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
'use strict';
2+
3+
import { writeFile } from 'node:fs/promises';
4+
import { basename, join } from 'node:path';
5+
6+
import { checkIndirectReferences } from './utils/checkIndirectReferences.mjs';
7+
import { extractExports } from './utils/extractExports.mjs';
8+
import { findDefinitions } from './utils/findDefinitions.mjs';
9+
import getConfig from '../../utils/configuration/index.mjs';
10+
import { GH_BLOB_URL, populate } from '../../utils/configuration/templates.mjs';
11+
12+
/**
13+
* Generates the `apilinks.json` file.
14+
*
15+
* @type {import('./types').Implementation['generate']}
16+
*/
17+
export async function generate(input) {
18+
const config = getConfig('api-links');
19+
/**
20+
* @type Record<string, string>
21+
*/
22+
const definitions = {};
23+
24+
input.forEach(program => {
25+
/**
26+
* Mapping of definitions to their line number
27+
*
28+
* @type {Record<string, number>}
29+
* @example { 'someclass.foo': 10 }
30+
*/
31+
const nameToLineNumberMap = {};
32+
33+
// `http.js` -> `http`
34+
const baseName = basename(program.path, '.js');
35+
36+
const exports = extractExports(program, baseName, nameToLineNumberMap);
37+
38+
findDefinitions(program, baseName, nameToLineNumberMap, exports);
39+
40+
checkIndirectReferences(program, exports, nameToLineNumberMap);
41+
42+
const fullGitUrl = `${populate(GH_BLOB_URL, config)}lib/${baseName}.js`;
43+
44+
// Add the exports we found in this program to our output
45+
Object.keys(nameToLineNumberMap).forEach(key => {
46+
const lineNumber = nameToLineNumberMap[key];
47+
48+
definitions[key] = `${fullGitUrl}#L${lineNumber}`;
49+
});
50+
});
51+
52+
if (config.output) {
53+
const out = join(config.output, 'apilinks.json');
54+
55+
await writeFile(
56+
out,
57+
config.minify
58+
? JSON.stringify(definitions)
59+
: JSON.stringify(definitions, null, 2)
60+
);
61+
}
62+
63+
return definitions;
64+
}

0 commit comments

Comments
 (0)