Skip to content

Commit

Permalink
feat(schemas): extend schema and split builders
Browse files Browse the repository at this point in the history
  • Loading branch information
kaltepeter committed Nov 1, 2020
1 parent 0615740 commit 4d3171b
Show file tree
Hide file tree
Showing 12 changed files with 512 additions and 144 deletions.
74 changes: 71 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,16 @@ Angular CLI: `ng add @angular-extensions/svg-icons-builder`

### Configuring the builder

To use the builder you need to add a new entry to your `architect` object inside your `angular.json`. In our example we call it `generate-icons`. You then need to specify the following properties:
To use the builder you need to add a new entry to your `architect` object inside your `angular.json`.

- **Builder**: `"@angular-extensions/svg-icons-builder:svg-icons-builder"`
- **Config**: A valid [svg-to-ts configuration](https://github.com/kreuzerk/svg-to-ts). ⚠️ the options depend on the `conversionType` and may therefore vary. Means, a configuration for the `convesionType: "files"` will look different than configuration for the `conversionType: "constants"`
A valid [svg-to-ts configuration](https://github.com/kreuzerk/svg-to-ts). ⚠️ the options depend on the `conversionType` and may therefore vary. Means, a configuration for the `convesionType: "files"` will look different than configuration for the `conversionType: "constants"`. Each `conversionType` has it's own builder.

In our example we call it `generate-icons`. You then need to specify the following properties:

## `conversionType: constants`

- **Builder**: `"@angular-extensions/svg-icons-builder:svg-icons-constants-builder"`
- **Config**: [svg-to-ts constants config](https://github.com/kreuzerk/svg-to-ts#2-multiple-constants---treeshakable-and-typesafe-with-one-file-conversiontypeconstants)

```json
"generate-icons": {
Expand All @@ -48,6 +54,68 @@ To use the builder you need to add a new entry to your `architect` object inside
}
```

## `conversionType: files`

- **Builder**: `"@angular-extensions/svg-icons-builder:svg-icons-files-builder"`
- **Config**: [svg-to-ts files config](https://github.com/kreuzerk/svg-to-ts#3-tree-shakable-and-optimized-for-lazy-loading-conversiontypefiles)

```json
"generate-icons": {
"builder": "@angular-extensions/svg-icons-builder:svg-icons-files-builder",
"options": {
"conversionType": "files",
"srcFiles": ["./projects/dinosaur-icons/icons/**/*.svg"],
"outputDirectory": "./projects/dinosaur-icons/icons",
"interfaceName": "DinosaurIcon",
"generateType": false,
"generateTypeObject": false,
"generateCompleteIconSet": false,
"exportCompleteIconSet": false,
"fileName": "dinosaur-icons",
"iconsFolderName": "dinosaur-icons",
"objectName": "dinosaur-icons",
"typeName": "dinosaurIcon",
"prefix": "dinosaurIcon",
"modelFileName": "dinosaur-icons",
"barrelFileName": "index",
"svgoConfig": {
"plugins": [
{
"cleanupAttrs": true
}
]
},
"compileSources": true
}
}
```

## `conversionType: object`

- **Builder**: `"@angular-extensions/svg-icons-builder:svg-icons-object-builder"`
- **Config**: [svg-to-ts object config](https://github.com/kreuzerk/svg-to-ts#1-converting-to-a-single-object-conversiontypeobject)

```json
"generate-icons": {
"builder": "@angular-extensions/svg-icons-builder:svg-icons-object-builder",
"options": {
"conversionType": "object",
"srcFiles": ["./projects/dinosaur-icons/icons/**/*.svg"],
"outputDirectory": "./projects/dinosaur-icons/icons",
"fileName": "dinosaur-icons",
"objectName": "dinosaur-icons",
"svgoConfig": {
"plugins": [
{
"cleanupAttrs": true
}
]
},
"compileSources": true
}
}
```

### Run the builder

In order to run the builder you have to add a new npm script to your `package.json`. Replace `name-of-your-app` with the name of your application 😉.
Expand Down
17 changes: 14 additions & 3 deletions builders.json
Original file line number Diff line number Diff line change
@@ -1,9 +1,20 @@
{
"$schema": "@angular-devkit/architect/src/builders-schema.json",
"builders": {
"svg-icons-builder": {
"implementation": "./svg-icons-builder",
"svg-icons-constants-builder": {
"implementation": "./svg-icons-builder/constants",
"schema": "./svg-icons-builder/schema.json",
"description": "Build SVG icons."
"description": "Build SVG icons using `constants` conversion type."
},
"svg-icons-object-builder": {
"implementation": "./svg-icons-builder/object",
"schema": "./svg-icons-builder/schema.json",
"description": "Build SVG icons using `objects` conversion type."
},
"svg-icons-files-builder": {
"implementation": "./svg-icons-builder/files",
"schema": "./svg-icons-builder/schema.json",
"description": "Build SVG icons using `files` conversion type."
}
}
}
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

54 changes: 54 additions & 0 deletions svg-icons-builder/constants/index.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import { Architect } from '@angular-devkit/architect';
import { TestingArchitectHost } from '@angular-devkit/architect/testing';
import { logging, schema } from '@angular-devkit/core';
import { ConversionType } from 'svg-to-ts';
import { defaultCommonOptions } from '../test-helpers';
const { join } = require('path');

describe('svg-icons-builder', () => {
let architect: Architect;
let architectHost: TestingArchitectHost;

beforeEach(async () => {
const registry = new schema.CoreSchemaRegistry();
registry.addPostTransform(schema.transforms.addUndefinedDefaults);
const workspaceRoot = join(__dirname, '..', '..');

architectHost = new TestingArchitectHost('/root', '/root');
architect = new Architect(architectHost, registry);

await architectHost.addBuilderFromPackage(workspaceRoot);
});

it('generates `constants` for icons', async () => {
const logger = new logging.Logger('');
const logs: string[] = [];
logger.subscribe((ev) => logs.push(ev.message));

const run = await architect.scheduleBuilder(
'@angular-extensions/svg-icons-builder:svg-icons-constants-builder',
{
...defaultCommonOptions(),
conversionType: ConversionType.CONSTANTS,
fileName: 'dinosaur-icons',
typeName: 'dinosaurIcon',
generateType: true,
generateTypeObject: true,
generateCompleteIconSet: true,
prefix: 'dinosaurIcon',
interfaceName: 'DinosaurIcon',
},
{ logger }
);

expect(await run.result).toEqual(
expect.objectContaining({
success: true,
})
);

await run.stop();

expect(logs).toContain('We are using the conversion type "constants"');
});
});
28 changes: 28 additions & 0 deletions svg-icons-builder/constants/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { BuilderContext, BuilderOutput, createBuilder } from '@angular-devkit/architect';
import { JsonObject } from '@angular-devkit/core';
import { ConstantsConversionOptions, ConversionType, convertToConstants, mergeWithDefaults } from 'svg-to-ts';

interface Options extends ConstantsConversionOptions {}

// Using `Options & JsonObject` instead of extending JsonObject because of optional boolean
export default createBuilder<Options & JsonObject>((options: Options, context: BuilderContext) => {
return new Promise<BuilderOutput>(async (resolve, reject) => {
try {
if (options.conversionType !== ConversionType.CONSTANTS) {
reject(new Error(`This builder only supports '${ConversionType.CONSTANTS}' conversionType.`));
}

const conversionOptions = await mergeWithDefaults(options);
context.logger.info('We are using the conversion type "constants"');
await convertToConstants((conversionOptions as unknown) as ConstantsConversionOptions);

resolve({ success: true });
context.reportStatus(`Done.`);
} catch (error) {
context.reportStatus(`Error: ${error.message}`);
reject(error);
process.disconnect();
process.exit(1);
}
});
});
57 changes: 57 additions & 0 deletions svg-icons-builder/files/index.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import { Architect } from '@angular-devkit/architect';
import { TestingArchitectHost } from '@angular-devkit/architect/testing';
import { logging, schema } from '@angular-devkit/core';
import { defaultCommonOptions } from '../test-helpers';
const { join } = require('path');

describe('svg-icons-builder', () => {
let architect: Architect;
let architectHost: TestingArchitectHost;

beforeEach(async () => {
const registry = new schema.CoreSchemaRegistry();
registry.addPostTransform(schema.transforms.addUndefinedDefaults);
const workspaceRoot = join(__dirname, '..', '..');

architectHost = new TestingArchitectHost('/root', '/root');
architect = new Architect(architectHost, registry);

await architectHost.addBuilderFromPackage(workspaceRoot);
console.log('#', Array.from((architectHost as any)._builderMap.keys()));
});

it('generates `files` for icons', async () => {
const logger = new logging.Logger('');
const logs: string[] = [];
logger.subscribe((ev) => logs.push(ev.message));

const run = await architect.scheduleBuilder(
'@angular-extensions/svg-icons-builder:svg-icons-files-builder',
{
...defaultCommonOptions(),
conversionType: 'files',
typeName: 'dinosaurIcon',
generateType: true,
generateTypeObject: true,
exportCompleteIconSet: true,
prefix: 'dinosaurIcon',
interfaceName: 'DinosaurIcon',
modelFileName: 'dinosaur-icons.model',
iconsFolderName: 'build',
compileSources: true,
barrelFileName: 'index',
},
{ logger }
);

expect(await run.result).toEqual(
expect.objectContaining({
success: true,
})
);

await run.stop();

expect(logs).toContain('We are using the conversion type "files"');
});
});
33 changes: 33 additions & 0 deletions svg-icons-builder/files/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { BuilderContext, BuilderOutput, createBuilder } from '@angular-devkit/architect';
import { JsonObject } from '@angular-devkit/core';
import {
ConversionType,
FileConversionOptions,
convertToFiles,
mergeWithDefaults,
} from 'svg-to-ts';

interface Options extends FileConversionOptions {}

// Using `Options & JsonObject` instead of extending JsonObject because of optional boolean
export default createBuilder<Options & JsonObject>((options: Options, context: BuilderContext) => {
return new Promise<BuilderOutput>(async (resolve, reject) => {
try {
if (options.conversionType !== ConversionType.FILES) {
reject(new Error(`This builder only supports '${ConversionType.FILES}' conversionType.`));
}

const conversionOptions = await mergeWithDefaults(options);
context.logger.info('We are using the conversion type "files"');
await convertToFiles((conversionOptions as unknown) as FileConversionOptions);

resolve({ success: true });
context.reportStatus(`Done.`);
} catch (error) {
context.reportStatus(`Error: ${error.message}`);
reject(error);
process.disconnect();
process.exit(1);
}
});
});
48 changes: 0 additions & 48 deletions svg-icons-builder/index.ts

This file was deleted.

0 comments on commit 4d3171b

Please sign in to comment.