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

feat(schematics): list schematics from extended collections #2096

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
39 changes: 25 additions & 14 deletions lib/schematics/custom.collection.ts
@@ -1,5 +1,4 @@
import { readFileSync } from 'fs';
import { dirname, join } from 'path';
import { NodeWorkflow } from '@angular-devkit/schematics/tools';
import { AbstractCollection } from './abstract.collection';
import { Schematic } from './nest.collection';

Expand All @@ -11,18 +10,30 @@ export interface CollectionSchematic {

export class CustomCollection extends AbstractCollection {
public getSchematics(): Schematic[] {
const collectionPackagePath = dirname(require.resolve(this.collection));
const collectionPath = join(collectionPackagePath, 'collection.json');
const collection = JSON.parse(readFileSync(collectionPath, 'utf8'));
const schematics = Object.entries(collection.schematics).map(
([name, value]) => {
const schematic = value as CollectionSchematic;
const description = schematic.description;
const alias = schematic?.aliases?.length ? schematic.aliases[0] : '';
return { name, description, alias };
},
const workflow = new NodeWorkflow(process.cwd(), {});
const collection = workflow.engine.createCollection(this.collection);
const collectionDescs = [
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
const collectionDescs = [
const collectionDescriptions = [

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit

collection.description,
...(collection.baseDescriptions ?? []),
];
const usedNames = new Set<string>();
const schematics: Schematic[] = [];
for (const collectionDesc of collectionDescs) {
const schematicsDescs = Object.entries(collectionDesc.schematics);
for (const [name, { description, aliases = [] }] of schematicsDescs) {
if (usedNames.has(name)) {
continue;
}
usedNames.add(name);
const alias = aliases.find((a) => !usedNames.has(a)) ?? name;
for (const alias of aliases) {
usedNames.add(alias);
}
schematics.push({ name, alias, description });
}
}
return schematics.sort((a, b) =>
a.name < b.name ? -1 : a.name > b.name ? 1 : 0,
);

return schematics;
}
}
3 changes: 2 additions & 1 deletion test/jest-config.json
Expand Up @@ -5,5 +5,6 @@
"transform": {
"^.+\\.(t|j)s$": "ts-jest"
},
"coverageDirectory": "../coverage"
"coverageDirectory": "../coverage",
"modulePaths": ["<rootDir>/test/lib/schematics/fixtures"]
}
76 changes: 76 additions & 0 deletions test/lib/schematics/custom.collection.spec.ts
@@ -0,0 +1,76 @@
import { resolve } from 'path';
import { AbstractRunner } from '../../../lib/runners';
import { CustomCollection } from '../../../lib/schematics/custom.collection';

describe('Custom Collection', () => {
it(`should list schematics from simple collection`, async () => {
const mock = jest.fn();
mock.mockImplementation(() => {
return {
logger: {},
run: jest.fn().mockImplementation(() => Promise.resolve()),
};
});
const mockedRunner = mock();
const collection = new CustomCollection(
require.resolve('./fixtures/simple/collection.json'),
mockedRunner as AbstractRunner,
);
const schematics = collection.getSchematics();
expect(schematics).toEqual([
{ name: 'simple1', alias: 's1', description: 'Simple schematic 1' },
{ name: 'simple2', alias: 's2', description: 'Simple schematic 2' },
{ name: 'simple3', alias: 's3', description: 'Simple schematic 3' },
]);
});

it(`should list schematics from extended collection`, async () => {
const mock = jest.fn();
mock.mockImplementation(() => {
return {
logger: {},
run: jest.fn().mockImplementation(() => Promise.resolve()),
};
});
const mockedRunner = mock();
const collection = new CustomCollection(
require.resolve('./fixtures/extended/collection.json'),
mockedRunner as AbstractRunner,
);
const schematics = collection.getSchematics();
expect(schematics).toEqual([
{ name: 'extend1', alias: 'x1', description: 'Extended schematic 1' },
{ name: 'extend2', alias: 'x2', description: 'Extended schematic 2' },
{ name: 'simple1', alias: 's1', description: 'Override schematic 1' },
{
name: 'simple2',
alias: 'os2',
description: 'Override schematic 2',
},
{
name: 'simple3',
alias: 'simple3',
description: 'Simple schematic 3',
},
]);
});

it(`should list schematics from package with collection.json path in package.json`, async () => {
const mock = jest.fn();
mock.mockImplementation(() => {
return {
logger: {},
run: jest.fn().mockImplementation(() => Promise.resolve()),
};
});
const mockedRunner = mock();
const collection = new CustomCollection(
'package',
mockedRunner as AbstractRunner,
);
const schematics = collection.getSchematics();
expect(schematics).toEqual([
{ name: 'package1', alias: 'pkg1', description: 'Package schematic 1' },
]);
});
});
26 changes: 26 additions & 0 deletions test/lib/schematics/fixtures/extended/collection.json
@@ -0,0 +1,26 @@
{
"$schema": "../../../../../node_modules/@angular-devkit/schematics/collection-schema.json",
"extends": ["../simple/collection.json"],
"schematics": {
"simple1": {
"factory": "factory",
"description": "Override schematic 1",
"aliases": ["s1", "simp1"]
},
"simple2": {
"factory": "factory",
"description": "Override schematic 2",
"aliases": ["os2", "s2", "simp2"]
},
"extend1": {
"factory": "factory",
"description": "Extended schematic 1",
"aliases": ["x1", "ext1"]
},
"extend2": {
"factory": "factory",
"description": "Extended schematic 2",
"aliases": ["x2", "ext2", "s3", "simp3"]
}
}
}
10 changes: 10 additions & 0 deletions test/lib/schematics/fixtures/package/a/b/c/collection.json
@@ -0,0 +1,10 @@
{
"$schema": "../../../../../../../../node_modules/@angular-devkit/schematics/collection-schema.json",
"schematics": {
"package1": {
"factory": "factory",
"description": "Package schematic 1",
"aliases": ["pkg1"]
}
}
}
Empty file.
5 changes: 5 additions & 0 deletions test/lib/schematics/fixtures/package/package.json
@@ -0,0 +1,5 @@
{
"name": "package",
"version": "0.0.0",
"schematics": "./a/b/c/collection.json"
}
20 changes: 20 additions & 0 deletions test/lib/schematics/fixtures/simple/collection.json
@@ -0,0 +1,20 @@
{
"$schema": "../../../../../node_modules/@angular-devkit/schematics/collection-schema.json",
"schematics": {
"simple1": {
"factory": "factory",
"description": "Simple schematic 1",
"aliases": ["s1", "simp1"]
},
"simple2": {
"factory": "factory",
"description": "Simple schematic 2",
"aliases": ["s2", "simp2"]
},
"simple3": {
"factory": "factory",
"description": "Simple schematic 3",
"aliases": ["s3", "simp3"]
}
}
}