Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

docs: use a processor to transform the operator decision tree data #7388

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
5 changes: 2 additions & 3 deletions apps/rxjs.dev/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,10 @@
"test-pwa-score": "node scripts/test-pwa-score",
"deploy-production": "scripts/deploy-to-firebase.sh",
"payload-size": "scripts/payload.sh",
"docs": "npx ts-node -P tsconfig.docs.json ../../node_modules/dgeni/lib/gen-docs.js ./tools/transforms/angular.io-package && yarn docs-decision-tree",
"docs": "npx ts-node -P tsconfig.docs.json ../../node_modules/dgeni/lib/gen-docs.js ./tools/transforms/angular.io-package",
"docs-watch": "npx ts-node -P tsconfig.docs.json tools/transforms/authors-package/watchr.js",
"docs-lint": "eslint --ignore-path=\"tools/transforms/.eslintignore\" tools/transforms",
"docs-test": "npx ts-node -P tsconfig.docs.json tools/transforms/test.js",
"docs-decision-tree": "ts-node -P tools/decision-tree-generator/tsconfig.json tools/decision-tree-generator/main.ts",
"firebase-utils-test": "jasmine-ts tools/firebase-test-utils/*.spec.ts",
"tools-lint": "tslint -c \"tools/tslint.json\" \"tools/firebase-test-utils/**/*.ts\"",
"tools-test": "./scripts/deploy-to-firebase.test.sh && yarn docs-test && yarn firebase-utils-test",
Expand Down Expand Up @@ -74,7 +73,7 @@
"@types/jasmine": "~3.6.0",
"@types/jasminewd2": "^2.0.3",
"@types/lunr": "^2.3.3",
"@types/node": "^12.11.1",
"@types/node": "^20.6.3",
"@types/svgo": "^1.3.3",
"@typescript-eslint/eslint-plugin": "^6.9.0",
"@typescript-eslint/parser": "^6.9.0",
Expand Down
8 changes: 0 additions & 8 deletions apps/rxjs.dev/tools/decision-tree-generator/jest.config.js

This file was deleted.

28 changes: 0 additions & 28 deletions apps/rxjs.dev/tools/decision-tree-generator/main.ts

This file was deleted.

28 changes: 0 additions & 28 deletions apps/rxjs.dev/tools/decision-tree-generator/package.json

This file was deleted.

6 changes: 0 additions & 6 deletions apps/rxjs.dev/tools/decision-tree-generator/tsconfig.json

This file was deleted.

7 changes: 6 additions & 1 deletion apps/rxjs.dev/tools/transforms/angular.io-package/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,15 @@ const apiPackage = require('../angular-api-package');
const contentPackage = require('../angular-content-package');
const { extname, resolve } = require('canonical-path');
const { existsSync } = require('fs');
const { SRC_PATH } = require('../config');
const { SRC_PATH, DOCS_OUTPUT_PATH, DECISION_TREE_PATH } = require('../config');
// prettier-ignore
module.exports = new Package('angular.io', [gitPackage, apiPackage, contentPackage])

// This processor relies upon the versionInfo. See below...
.processor(require('./processors/processNavigationMap'))
.processor(require('./processors/createOverviewDump'))
.processor(require('./processors/cleanGeneratedFiles'))
.processor(require('../rxjs-decision-tree-generator'))

// We don't include this in the angular-base package because the `versionInfo` stuff
// accesses the file system and git, which is slow.
Expand Down Expand Up @@ -54,4 +55,8 @@ module.exports = new Package('angular.io', [gitPackage, apiPackage, contentPacka

.config(function(renderLinkInfo, postProcessHtml) {
renderLinkInfo.docTypes = postProcessHtml.docTypes;
})
.config(function(decisionTreeGenerator) {
decisionTreeGenerator.outputFolder = DOCS_OUTPUT_PATH + '/app';
decisionTreeGenerator.decisionTreeFile = DECISION_TREE_PATH;
});
2 changes: 2 additions & 0 deletions apps/rxjs.dev/tools/transforms/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ const DOCS_OUTPUT_PATH = resolve(OUTPUT_PATH, 'docs');
const API_SOURCE_PATH = resolve(PROJECT_ROOT, 'packages/rxjs/src');
const MARBLE_IMAGES_PATH = resolve(SRC_PATH, 'assets/images/marble-diagrams');
const MARBLE_IMAGES_WEB_PATH = 'assets/images/marble-diagrams';
const DECISION_TREE_PATH = resolve(CONTENTS_PATH, 'operator-decision-tree.yml');

function requireFolder(dirname, folderPath) {
const absolutePath = resolve(dirname, folderPath);
Expand All @@ -32,5 +33,6 @@ module.exports = {
API_SOURCE_PATH,
MARBLE_IMAGES_PATH,
MARBLE_IMAGES_WEB_PATH,
DECISION_TREE_PATH,
requireFolder,
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { readFile } from 'fs/promises';
import { parse } from 'yamljs';

import { TreeNodeRaw, build, flattenApiList } from './src/lib';

module.exports = function decisionTreeGenerator(log: { warn: (message: string) => void }) {
return {
$runBefore: ['rendering-docs'],
$runAfter: ['generateApiListDoc'],
$validate: {
decisionTreeFile: { presence: true },
outputFolder: { presence: true },
},
$process: async function (this: any, docs: any[]) {
const apiListDoc = docs.find((doc) => doc.docType === 'api-list-data');

if (!apiListDoc) {
throw new Error('Can not find api-list-data for decision tree generation');
}

const yamlContent = await readFile(this.decisionTreeFile, { encoding: 'utf8' });
const decisionTreeJson: TreeNodeRaw[] = parse(yamlContent);

const flattenedApiList = flattenApiList(apiListDoc.data);
const jsonContent = build(flattenedApiList, decisionTreeJson, log);

docs.push({
docType: 'decision-tree-data',
template: 'json-doc.template.json',
path: this.outputFolder + '/decision-tree-data.json',
outputPath: this.outputFolder + '/decision-tree-data.json',
data: jsonContent,
});
return docs;
},
};
};
Original file line number Diff line number Diff line change
Expand Up @@ -5,33 +5,34 @@ import { mockRawTreeNodes } from './fixtures';
describe('addUniqueId', () => {
describe('when called with three raw nodes', () => {
let tree: TreeNode[];
let baseProperties: jest.Expect;
const baseProperties = jasmine.objectContaining({
id: jasmine.any(String),
label: jasmine.any(String),
depth: jasmine.any(Number),
});

beforeEach(() => {
tree = addUniqueId(mockRawTreeNodes);
baseProperties = expect.objectContaining({
id: expect.any(String),
label: expect.any(String),
depth: expect.any(Number),
});
});

describe('and one of the nodes is a child of another', () => {
it('should not flatten the tree and return the same number of top level nodes', () => {
expect(tree).toHaveLength(mockRawTreeNodes.length);
expect(tree.length).toBe(mockRawTreeNodes.length);
});
it('should return an array of tree nodes that have unique ids', () => {
tree.forEach(node => {
tree.forEach((node) => {
expect(node).toEqual(baseProperties);

if (!node.children) {
expect(node).not.toHaveProperty('options');
expect(node.options).toBeUndefined();
} else {
expect(node).toEqual(expect.objectContaining({
children: expect.any(Array),
options: expect.any(Array),
}));
node.children.forEach(child => {
expect(node).toEqual(
jasmine.objectContaining({
children: jasmine.any(Array),
options: jasmine.any(Array),
})
);
node.children.forEach((child) => {
expect(child).toEqual(baseProperties);
});
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ import { mockFlatApiList, mockRawTreeNodes } from './fixtures';
import { treeNodeCount } from './helpers';

describe('build', () => {
const tree = build(mockFlatApiList, mockRawTreeNodes);
const tree = build(mockFlatApiList, mockRawTreeNodes, {warn: () => {}});
it('should return a flat map of all nodes and one additional initial node', () => {
expect(tree).toHaveProperty('initial');
expect(tree.initial).toBeDefined()
expect(Object.keys(tree).length).toBe(treeNodeCount(mockRawTreeNodes) + 1);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,12 @@ import { decisionTreeReducer } from './decisionTreeReducer';
* @requires decisionTreeReducer
* @returns {DecisionTree}
*/
export function build(apiList: FlattenedApiList, tree: TreeNodeRaw[]): DecisionTree {
export function build(apiList: FlattenedApiList, tree: TreeNodeRaw[], log: { warn: (message: string) => void }): DecisionTree {
const nodesWithUniqueIds = addUniqueId(tree);
const initialOption = extractInitialSequence(nodesWithUniqueIds);

return {
...decisionTreeReducer(nodesWithUniqueIds, apiList),
[initialOption.id]: { ...initialOption }
...decisionTreeReducer(nodesWithUniqueIds, apiList, log),
[initialOption.id]: { ...initialOption },
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@ import { addUniqueId } from './addUniqueId';
import { rawNodesWithMethodCount } from './helpers';

describe('decisionTreeReducer', () => {
const tree = decisionTreeReducer(addUniqueId(mockRawTreeNodes), mockFlatApiList);
const tree = decisionTreeReducer(addUniqueId(mockRawTreeNodes), mockFlatApiList, { warn: jasmine.createSpy() });
describe('all nodes', () => {
const baseProperties = expect.objectContaining({
id: expect.any(String),
label: expect.any(String)
const baseProperties = jasmine.objectContaining({
id: jasmine.any(String),
label: jasmine.any(String),
});

it('should have base properties', () => {
Expand All @@ -22,11 +22,8 @@ describe('decisionTreeReducer', () => {
describe('that have options', () => {
it('should have an options property that is an array of strings', () => {
for (const key in tree) {
if (
tree.hasOwnProperty(key) &&
tree[key].options
) {
tree[key].options.forEach(option => {
if (tree.hasOwnProperty(key) && tree[key].options) {
tree[key].options?.forEach((option) => {
expect(typeof option).toBe('string');
});
}
Expand All @@ -37,22 +34,16 @@ describe('decisionTreeReducer', () => {
describe('when a node does not have options', () => {
it('should not have an options property', () => {
for (const key in tree) {
if (
tree.hasOwnProperty(key) &&
!tree[key].options
) {
expect(tree[key]).not.toHaveProperty('options');
if (tree.hasOwnProperty(key) && !tree[key].options) {
expect(tree[key].options).toBeUndefined();
}
}
});
it('should have a docType and a path', () => {
for (const key in tree) {
if (
tree.hasOwnProperty(key) &&
!tree[key].options
) {
expect(tree[key]).toHaveProperty('docType');
expect(tree[key]).toHaveProperty('path');
if (tree.hasOwnProperty(key) && !tree[key].options) {
expect(tree[key].docType).toBeDefined();
expect(tree[key].path).toBeDefined();
}
}
});
Expand All @@ -61,12 +52,12 @@ describe('decisionTreeReducer', () => {
const treeNodesMissingInApiList = [
...mockRawTreeNodes,
{
label: 'foo'
}
label: 'foo',
},
];
it('should call a console.log', () => {
const spy = jest.spyOn(console, 'log');
decisionTreeReducer(addUniqueId(treeNodesMissingInApiList), mockFlatApiList);
const spy = jasmine.createSpy('warn');
decisionTreeReducer(addUniqueId(treeNodesMissingInApiList), mockFlatApiList, { warn: spy });
expect(spy).toHaveBeenCalled();
});
});
Expand All @@ -77,10 +68,7 @@ describe('decisionTreeReducer', () => {
it('should have a method property', () => {
let count = 0;
for (const key in tree) {
if (
tree.hasOwnProperty(key) &&
tree[key].method
) {
if (tree.hasOwnProperty(key) && tree[key].method) {
count++;
}
}
Expand Down
Loading