Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
401 changes: 253 additions & 148 deletions docs/generators.md

Large diffs are not rendered by default.

8 changes: 4 additions & 4 deletions src/generators.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,8 @@ const createGenerator = () => {
return;
}

const { dependsOn, generate, processChunk } =
await allGenerators[generatorName]();
const { dependsOn, generate, hasParallelProcessor } =
allGenerators[generatorName];

// Schedule dependency first
if (dependsOn && !(dependsOn in cachedGenerators)) {
Expand All @@ -63,7 +63,7 @@ const createGenerator = () => {

generatorsLogger.debug(`Scheduling "${generatorName}"`, {
dependsOn: dependsOn || 'none',
streaming: Boolean(processChunk),
streaming: hasParallelProcessor,
});

// Schedule the generator
Expand All @@ -73,7 +73,7 @@ const createGenerator = () => {
generatorsLogger.debug(`Starting "${generatorName}"`);

// Create parallel worker for streaming generators
const worker = processChunk
const worker = hasParallelProcessor
? createParallelWorker(generatorName, pool, configuration)
: Promise.resolve(null);

Expand Down
23 changes: 9 additions & 14 deletions src/generators/__tests__/index.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,11 @@ import { allGenerators } from '../index.mjs';

const validDependencies = Object.keys(allGenerators);

const allGeneratorsReaolved = await Promise.all(
Object.entries(allGenerators).map(async ([key, loader]) => [
key,
await loader(),
])
);
const allGeneratorsEntries = Object.entries(allGenerators);

describe('All Generators', () => {
it('should have keys matching their name property', async () => {
allGeneratorsReaolved.forEach(([key, generator]) => {
it('should have keys matching their name property', () => {
allGeneratorsEntries.forEach(([key, generator]) => {
assert.equal(
key,
generator.name,
Expand All @@ -25,8 +20,8 @@ describe('All Generators', () => {
});
});

it('should have valid semver versions', async () => {
allGeneratorsReaolved.forEach(([key, generator]) => {
it('should have valid semver versions', () => {
allGeneratorsEntries.forEach(([key, generator]) => {
const isValid = semver.valid(generator.version);
assert.ok(
isValid,
Expand All @@ -35,8 +30,8 @@ describe('All Generators', () => {
});
});

it('should have valid dependsOn references', async () => {
allGeneratorsReaolved.forEach(([key, generator]) => {
it('should have valid dependsOn references', () => {
allGeneratorsEntries.forEach(([key, generator]) => {
if (generator.dependsOn) {
assert.ok(
validDependencies.includes(generator.dependsOn),
Expand All @@ -46,8 +41,8 @@ describe('All Generators', () => {
});
});

it('should have ast generator as a top-level generator with no dependencies', async () => {
const ast = await allGenerators.ast();
it('should have ast generator as a top-level generator with no dependencies', () => {
const ast = allGenerators.ast;
assert.ok(ast, 'ast generator should exist');
assert.equal(
ast.dependsOn,
Expand Down
81 changes: 81 additions & 0 deletions src/generators/addon-verify/generate.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
'use strict';

import { mkdir, writeFile } from 'node:fs/promises';
import { join } from 'node:path';

import { visit } from 'unist-util-visit';

import { EXTRACT_CODE_FILENAME_COMMENT } from './constants.mjs';
import { generateFileList } from './utils/generateFileList.mjs';
import {
generateSectionFolderName,
isBuildableSection,
normalizeSectionName,
} from './utils/section.mjs';
import getConfig from '../../utils/configuration/index.mjs';

/**
* Generates a file list from code blocks.
*
* @type {import('./types').Generator['generate']}
*/
export async function generate(input) {
const config = getConfig('addon-verify');

const sectionsCodeBlocks = input.reduce((addons, node) => {
const sectionName = node.heading.data.name;

const content = node.content;

visit(content, childNode => {
if (childNode.type === 'code') {
const filename = childNode.value.match(EXTRACT_CODE_FILENAME_COMMENT);

if (filename === null) {
return;
}

if (!addons[sectionName]) {
addons[sectionName] = [];
}

addons[sectionName].push({
name: filename[1],
content: childNode.value,
});
}
});

return addons;
}, {});

const files = await Promise.all(
Object.entries(sectionsCodeBlocks)
.filter(([, codeBlocks]) => isBuildableSection(codeBlocks))
.flatMap(async ([sectionName, codeBlocks], index) => {
const files = generateFileList(codeBlocks);

if (config.output) {
const normalizedSectionName = normalizeSectionName(sectionName);

const folderName = generateSectionFolderName(
normalizedSectionName,
index
);

await mkdir(join(config.output, folderName), { recursive: true });

for (const file of files) {
await writeFile(
join(config.output, folderName, file.name),
file.content
);
}
}

return files;
})
);

return files;
}
82 changes: 3 additions & 79 deletions src/generators/addon-verify/index.mjs
Original file line number Diff line number Diff line change
@@ -1,18 +1,6 @@
'use strict';

import { mkdir, writeFile } from 'node:fs/promises';
import { join } from 'node:path';

import { visit } from 'unist-util-visit';

import { EXTRACT_CODE_FILENAME_COMMENT } from './constants.mjs';
import { generateFileList } from './utils/generateFileList.mjs';
import {
generateSectionFolderName,
isBuildableSection,
normalizeSectionName,
} from './utils/section.mjs';
import getConfig from '../../utils/configuration/index.mjs';
import { createLazyGenerator } from '../../utils/generators.mjs';

/**
* This generator generates a file list from code blocks extracted from
Expand All @@ -21,7 +9,7 @@ import getConfig from '../../utils/configuration/index.mjs';
*
* @type {import('./types').Generator}
*/
export default {
export default await createLazyGenerator({
name: 'addon-verify',

version: '1.0.0',
Expand All @@ -30,68 +18,4 @@ export default {
'Generates a file list from code blocks extracted from `doc/api/addons.md` to facilitate C++ compilation and JavaScript runtime validations',

dependsOn: 'metadata',

/**
* Generates a file list from code blocks.
*/
async generate(input) {
const config = getConfig('addon-verify');

const sectionsCodeBlocks = input.reduce((addons, node) => {
const sectionName = node.heading.data.name;

const content = node.content;

visit(content, childNode => {
if (childNode.type === 'code') {
const filename = childNode.value.match(EXTRACT_CODE_FILENAME_COMMENT);

if (filename === null) {
return;
}

if (!addons[sectionName]) {
addons[sectionName] = [];
}

addons[sectionName].push({
name: filename[1],
content: childNode.value,
});
}
});

return addons;
}, {});

const files = await Promise.all(
Object.entries(sectionsCodeBlocks)
.filter(([, codeBlocks]) => isBuildableSection(codeBlocks))
.flatMap(async ([sectionName, codeBlocks], index) => {
const files = generateFileList(codeBlocks);

if (config.output) {
const normalizedSectionName = normalizeSectionName(sectionName);

const folderName = generateSectionFolderName(
normalizedSectionName,
index
);

await mkdir(join(config.output, folderName), { recursive: true });

for (const file of files) {
await writeFile(
join(config.output, folderName, file.name),
file.content
);
}
}

return files;
})
);

return files;
},
};
});
8 changes: 4 additions & 4 deletions src/generators/api-links/__tests__/fixtures.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ import { globSync } from 'tinyglobby';
import createWorkerPool from '../../../threading/index.mjs';
import createParallelWorker from '../../../threading/parallel.mjs';
import { setConfig } from '../../../utils/configuration/index.mjs';
import astJs from '../../ast-js/index.mjs';
import apiLinks from '../index.mjs';
import { generate as astJsGenerate } from '../../ast-js/generate.mjs';
import { generate as apiLinksGenerate } from '../generate.mjs';

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

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

for await (const chunk of astJs.generate(undefined, worker)) {
for await (const chunk of astJsGenerate(undefined, worker)) {
astJsResults.push(...chunk);
}

const actualOutput = await apiLinks.generate(astJsResults);
const actualOutput = await apiLinksGenerate(astJsResults);

for (const [k, v] of Object.entries(actualOutput)) {
actualOutput[k] = v.replace(/.*(?=lib\/)/, '');
Expand Down
67 changes: 67 additions & 0 deletions src/generators/api-links/generate.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
'use strict';

import { writeFile } from 'node:fs/promises';
import { basename, join } from 'node:path';

import { checkIndirectReferences } from './utils/checkIndirectReferences.mjs';
import { extractExports } from './utils/extractExports.mjs';
import { findDefinitions } from './utils/findDefinitions.mjs';
import getConfig from '../../utils/configuration/index.mjs';
import {
GITHUB_BLOB_URL,
populate,
} from '../../utils/configuration/templates.mjs';

/**
* Generates the `apilinks.json` file.
*
* @type {import('./types').Generator['generate']}
*/
export async function generate(input) {
const config = getConfig('api-links');
/**
* @type Record<string, string>
*/
const definitions = {};

input.forEach(program => {
/**
* Mapping of definitions to their line number
*
* @type {Record<string, number>}
* @example { 'someclass.foo': 10 }
*/
const nameToLineNumberMap = {};

// `http.js` -> `http`
const baseName = basename(program.path, '.js');

const exports = extractExports(program, baseName, nameToLineNumberMap);

findDefinitions(program, baseName, nameToLineNumberMap, exports);

checkIndirectReferences(program, exports, nameToLineNumberMap);

const fullGitUrl = `${populate(GITHUB_BLOB_URL, config)}lib/${baseName}.js`;

// Add the exports we found in this program to our output
Object.keys(nameToLineNumberMap).forEach(key => {
const lineNumber = nameToLineNumberMap[key];

definitions[key] = `${fullGitUrl}#L${lineNumber}`;
});
});

if (config.output) {
const out = join(config.output, 'apilinks.json');

await writeFile(
out,
config.minify
? JSON.stringify(definitions)
: JSON.stringify(definitions, null, 2)
);
}

return definitions;
}
Loading
Loading