feat(node): migrate @nrwl/express to use devkit (#5558)
This commit is contained in:
parent
c9e79ab84e
commit
6503c4fa03
@ -119,6 +119,8 @@ describe('create-nx-workspace', () => {
|
||||
style: 'css',
|
||||
appName,
|
||||
});
|
||||
|
||||
expectNoAngularDevkit();
|
||||
});
|
||||
|
||||
it('should be able to create an express workspace', () => {
|
||||
@ -129,6 +131,8 @@ describe('create-nx-workspace', () => {
|
||||
style: 'css',
|
||||
appName,
|
||||
});
|
||||
|
||||
expectNoAngularDevkit();
|
||||
});
|
||||
|
||||
it('should be able to create a workspace with a custom base branch and HEAD', () => {
|
||||
|
||||
@ -17,6 +17,19 @@
|
||||
{
|
||||
"files": ["*.js", "*.jsx"],
|
||||
"rules": {}
|
||||
},
|
||||
{
|
||||
"files": ["**/*.ts"],
|
||||
"excludedFiles": ["./src/migrations/**"],
|
||||
"rules": {
|
||||
"no-restricted-imports": [
|
||||
"error",
|
||||
"@nrwl/workspace",
|
||||
"@angular-devkit/core",
|
||||
"@angular-devkit/architect",
|
||||
"@angular-devkit/schematics"
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@ -2,18 +2,34 @@
|
||||
"name": "Nx Express",
|
||||
"version": "0.1",
|
||||
"extends": ["@nrwl/workspace"],
|
||||
"schematics": {
|
||||
"generators": {
|
||||
"init": {
|
||||
"factory": "./src/schematics/init/init",
|
||||
"schema": "./src/schematics/init/schema.json",
|
||||
"factory": "./src/generators/init/init#initGenerator",
|
||||
"schema": "./src/generators/init/schema.json",
|
||||
"description": "Initialize the @nrwl/express plugin",
|
||||
"alias": ["ng-add"],
|
||||
"hidden": true
|
||||
},
|
||||
|
||||
"application": {
|
||||
"factory": "./src/schematics/application/application",
|
||||
"schema": "./src/schematics/application/schema.json",
|
||||
"factory": "./src/generators/application/application#applicationGenerator",
|
||||
"schema": "./src/generators/application/schema.json",
|
||||
"aliases": ["app"],
|
||||
"description": "Create an express application"
|
||||
}
|
||||
},
|
||||
"schematics": {
|
||||
"init": {
|
||||
"factory": "./src/generators/init/init#initSchematic",
|
||||
"schema": "./src/generators/init/schema.json",
|
||||
"description": "Initialize the @nrwl/express plugin",
|
||||
"alias": ["ng-add"],
|
||||
"hidden": true
|
||||
},
|
||||
|
||||
"application": {
|
||||
"factory": "./src/generators/application/application#applicationSchematic",
|
||||
"schema": "./src/generators/application/schema.json",
|
||||
"aliases": ["app"],
|
||||
"description": "Create an express application"
|
||||
}
|
||||
|
||||
@ -1 +1 @@
|
||||
export { applicationGenerator } from './src/schematics/application/application';
|
||||
export { applicationGenerator } from './src/generators/application/application';
|
||||
|
||||
@ -32,7 +32,6 @@
|
||||
"@nrwl/devkit": "*",
|
||||
"@nrwl/node": "*",
|
||||
"@nrwl/jest": "*",
|
||||
"@angular-devkit/core": "~11.2.0",
|
||||
"@angular-devkit/schematics": "~11.2.0"
|
||||
"@nrwl/workspace": "*"
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,29 +1,25 @@
|
||||
import { Tree } from '@angular-devkit/schematics';
|
||||
import { createEmptyWorkspace } from '@nrwl/workspace/testing';
|
||||
import { runSchematic } from '../../utils/testing';
|
||||
import { readJsonInTree } from '@nrwl/workspace';
|
||||
import { readJson, Tree } from '@nrwl/devkit';
|
||||
import { createTreeWithEmptyWorkspace } from '@nrwl/devkit/testing';
|
||||
|
||||
import { Schema } from './schema.d';
|
||||
import { applicationGenerator } from './application';
|
||||
import { Schema } from './schema';
|
||||
|
||||
describe('app', () => {
|
||||
let appTree: Tree;
|
||||
|
||||
beforeEach(() => {
|
||||
appTree = Tree.empty();
|
||||
appTree = createEmptyWorkspace(appTree);
|
||||
appTree = createTreeWithEmptyWorkspace();
|
||||
});
|
||||
|
||||
it('should generate files', async () => {
|
||||
const tree = await runSchematic(
|
||||
'app',
|
||||
{ name: 'myNodeApp' } as Schema,
|
||||
appTree
|
||||
);
|
||||
await applicationGenerator(appTree, {
|
||||
name: 'myNodeApp',
|
||||
} as Schema);
|
||||
|
||||
const mainFile = tree.readContent('apps/my-node-app/src/main.ts');
|
||||
const mainFile = appTree.read('apps/my-node-app/src/main.ts').toString();
|
||||
expect(mainFile).toContain(`import * as express from 'express';`);
|
||||
|
||||
const tsconfig = readJsonInTree(tree, 'apps/my-node-app/tsconfig.json');
|
||||
const tsconfig = readJson(appTree, 'apps/my-node-app/tsconfig.json');
|
||||
expect(tsconfig).toMatchInlineSnapshot(`
|
||||
Object {
|
||||
"extends": "../../tsconfig.base.json",
|
||||
@ -40,10 +36,7 @@ describe('app', () => {
|
||||
}
|
||||
`);
|
||||
|
||||
const eslintrcJson = readJsonInTree(
|
||||
tree,
|
||||
'apps/my-node-app/.eslintrc.json'
|
||||
);
|
||||
const eslintrcJson = readJson(appTree, 'apps/my-node-app/.eslintrc.json');
|
||||
expect(eslintrcJson).toMatchInlineSnapshot(`
|
||||
Object {
|
||||
"extends": Array [
|
||||
@ -87,12 +80,10 @@ describe('app', () => {
|
||||
});
|
||||
|
||||
it('should add types to the tsconfig.app.json', async () => {
|
||||
const tree = await runSchematic(
|
||||
'app',
|
||||
{ name: 'myNodeApp' } as Schema,
|
||||
appTree
|
||||
);
|
||||
const tsconfig = readJsonInTree(tree, 'apps/my-node-app/tsconfig.app.json');
|
||||
await applicationGenerator(appTree, {
|
||||
name: 'myNodeApp',
|
||||
} as Schema);
|
||||
const tsconfig = readJson(appTree, 'apps/my-node-app/tsconfig.app.json');
|
||||
expect(tsconfig.compilerOptions.types).toContain('express');
|
||||
expect(tsconfig).toMatchInlineSnapshot(`
|
||||
Object {
|
||||
@ -117,27 +108,23 @@ describe('app', () => {
|
||||
|
||||
describe('--js flag', () => {
|
||||
it('should generate js files instead of ts files', async () => {
|
||||
const tree = await runSchematic(
|
||||
'app',
|
||||
{
|
||||
name: 'myNodeApp',
|
||||
js: true,
|
||||
} as Schema,
|
||||
appTree
|
||||
);
|
||||
await applicationGenerator(appTree, {
|
||||
name: 'myNodeApp',
|
||||
js: true,
|
||||
} as Schema);
|
||||
|
||||
expect(tree.exists('apps/my-node-app/src/main.js')).toBeTruthy();
|
||||
expect(tree.readContent('apps/my-node-app/src/main.js')).toContain(
|
||||
expect(appTree.exists('apps/my-node-app/src/main.js')).toBeTruthy();
|
||||
expect(appTree.read('apps/my-node-app/src/main.js').toString()).toContain(
|
||||
`import * as express from 'express';`
|
||||
);
|
||||
|
||||
const tsConfig = readJsonInTree(tree, 'apps/my-node-app/tsconfig.json');
|
||||
const tsConfig = readJson(appTree, 'apps/my-node-app/tsconfig.json');
|
||||
expect(tsConfig.compilerOptions).toEqual({
|
||||
allowJs: true,
|
||||
});
|
||||
|
||||
const tsConfigApp = readJsonInTree(
|
||||
tree,
|
||||
const tsConfigApp = readJson(
|
||||
appTree,
|
||||
'apps/my-node-app/tsconfig.app.json'
|
||||
);
|
||||
expect(tsConfigApp.include).toEqual(['**/*.ts', '**/*.js']);
|
||||
90
packages/express/src/generators/application/application.ts
Normal file
90
packages/express/src/generators/application/application.ts
Normal file
@ -0,0 +1,90 @@
|
||||
import {
|
||||
convertNxGenerator,
|
||||
formatFiles,
|
||||
getWorkspaceLayout,
|
||||
joinPathFragments,
|
||||
names,
|
||||
toJS,
|
||||
Tree,
|
||||
updateJson,
|
||||
} from '@nrwl/devkit';
|
||||
|
||||
import { applicationGenerator as nodeApplicationGenerator } from '@nrwl/node';
|
||||
|
||||
import { join } from 'path';
|
||||
import { Schema } from './schema';
|
||||
import { initGenerator } from '../init/init';
|
||||
|
||||
interface NormalizedSchema extends Schema {
|
||||
appProjectRoot: string;
|
||||
}
|
||||
|
||||
function addTypes(tree: Tree, options: NormalizedSchema) {
|
||||
const tsConfigPath = join(options.appProjectRoot, 'tsconfig.app.json');
|
||||
updateJson(tree, tsConfigPath, (json) => {
|
||||
json.compilerOptions.types = [...json.compilerOptions.types, 'express'];
|
||||
return json;
|
||||
});
|
||||
}
|
||||
|
||||
function addAppFiles(tree: Tree, options: NormalizedSchema) {
|
||||
tree.write(
|
||||
join(options.appProjectRoot, `src/main.${options.js ? 'js' : 'ts'}`),
|
||||
`/**
|
||||
* This is not a production server yet!
|
||||
* This is only a minimal backend to get started.
|
||||
*/
|
||||
|
||||
import * as express from 'express';
|
||||
|
||||
const app = express();
|
||||
|
||||
app.get('/api', (req, res) => {
|
||||
res.send({ message: 'Welcome to ${options.name}!' });
|
||||
});
|
||||
|
||||
const port = process.env.port || 3333;
|
||||
const server = app.listen(port, () => {
|
||||
console.log(\`Listening at http://localhost:\${port}/api\`);
|
||||
});
|
||||
server.on('error', console.error);
|
||||
`
|
||||
);
|
||||
|
||||
if (options.js) {
|
||||
toJS(tree);
|
||||
}
|
||||
}
|
||||
|
||||
export async function applicationGenerator(tree: Tree, schema: Schema) {
|
||||
const options = normalizeOptions(tree, schema);
|
||||
const initTask = await initGenerator(tree, { ...options, skipFormat: true });
|
||||
const applicationTask = await nodeApplicationGenerator(tree, {
|
||||
...schema,
|
||||
skipFormat: true,
|
||||
});
|
||||
addAppFiles(tree, options);
|
||||
addTypes(tree, options);
|
||||
await formatFiles(tree);
|
||||
|
||||
return async () => {
|
||||
await initTask();
|
||||
await applicationTask();
|
||||
};
|
||||
}
|
||||
|
||||
export default applicationGenerator;
|
||||
export const applicationSchematic = convertNxGenerator(applicationGenerator);
|
||||
|
||||
function normalizeOptions(host: Tree, options: Schema): NormalizedSchema {
|
||||
const appDirectory = options.directory
|
||||
? `${names(options.directory).fileName}/${names(options.name).fileName}`
|
||||
: names(options.name).fileName;
|
||||
const { appsDir } = getWorkspaceLayout(host);
|
||||
const appProjectRoot = joinPathFragments(appsDir, appDirectory);
|
||||
|
||||
return {
|
||||
...options,
|
||||
appProjectRoot,
|
||||
};
|
||||
}
|
||||
@ -1,5 +1,5 @@
|
||||
import { UnitTestRunner } from '../../utils/test-runners';
|
||||
import { Linter } from '@nrwl/workspace';
|
||||
import type { Linter } from '@nrwl/linter';
|
||||
|
||||
export interface Schema {
|
||||
name: string;
|
||||
@ -1,5 +1,6 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/schema",
|
||||
"cli": "nx",
|
||||
"id": "SchematicsNxExpressApp",
|
||||
"title": "Nx Application Options Schema",
|
||||
"type": "object",
|
||||
@ -1,30 +1,26 @@
|
||||
import { Tree } from '@angular-devkit/schematics';
|
||||
import { addDepsToPackageJson, readJsonInTree } from '@nrwl/workspace';
|
||||
import { createEmptyWorkspace } from '@nrwl/workspace/testing';
|
||||
import { runSchematic, callRule } from '../../utils/testing';
|
||||
import { addDependenciesToPackageJson, Tree } from '@nrwl/devkit';
|
||||
import { expressVersion } from '../../utils/versions';
|
||||
import initGenerator from './init';
|
||||
import { createTreeWithEmptyWorkspace } from '@nrwl/devkit/testing';
|
||||
import { readJson } from '@nrwl/devkit';
|
||||
|
||||
describe('init', () => {
|
||||
let tree: Tree;
|
||||
|
||||
beforeEach(() => {
|
||||
tree = Tree.empty();
|
||||
tree = createEmptyWorkspace(tree);
|
||||
tree = createTreeWithEmptyWorkspace();
|
||||
});
|
||||
|
||||
it('should add dependencies', async () => {
|
||||
const existing = 'existing';
|
||||
const existingVersion = '1.0.0';
|
||||
await callRule(
|
||||
addDepsToPackageJson(
|
||||
{ '@nrwl/express': expressVersion, [existing]: existingVersion },
|
||||
{ [existing]: existingVersion },
|
||||
false
|
||||
),
|
||||
tree
|
||||
addDependenciesToPackageJson(
|
||||
tree,
|
||||
{ '@nrwl/express': expressVersion, [existing]: existingVersion },
|
||||
{ [existing]: existingVersion }
|
||||
);
|
||||
const result = await runSchematic('init', {}, tree);
|
||||
const packageJson = readJsonInTree(result, 'package.json');
|
||||
await initGenerator(tree, {});
|
||||
const packageJson = readJson(tree, 'package.json');
|
||||
// add express
|
||||
expect(packageJson.dependencies['express']).toBeDefined();
|
||||
// move `@nrwl/express` to dev
|
||||
@ -39,20 +35,16 @@ describe('init', () => {
|
||||
|
||||
describe('defaultCollection', () => {
|
||||
it('should be set if none was set before', async () => {
|
||||
const result = await runSchematic('init', {}, tree);
|
||||
const workspaceJson = readJsonInTree(result, 'workspace.json');
|
||||
await initGenerator(tree, {});
|
||||
const workspaceJson = readJson(tree, 'workspace.json');
|
||||
expect(workspaceJson.cli.defaultCollection).toEqual('@nrwl/express');
|
||||
});
|
||||
});
|
||||
|
||||
it('should not add jest config if unitTestRunner is none', async () => {
|
||||
const result = await runSchematic(
|
||||
'init',
|
||||
{
|
||||
unitTestRunner: 'none',
|
||||
},
|
||||
tree
|
||||
);
|
||||
expect(result.exists('jest.config.js')).toEqual(false);
|
||||
await initGenerator(tree, {
|
||||
unitTestRunner: 'none',
|
||||
});
|
||||
expect(tree.exists('jest.config.js')).toEqual(false);
|
||||
});
|
||||
});
|
||||
57
packages/express/src/generators/init/init.ts
Normal file
57
packages/express/src/generators/init/init.ts
Normal file
@ -0,0 +1,57 @@
|
||||
import {
|
||||
addDependenciesToPackageJson,
|
||||
Tree,
|
||||
updateJson,
|
||||
formatFiles,
|
||||
convertNxGenerator,
|
||||
} from '@nrwl/devkit';
|
||||
|
||||
import { setDefaultCollection } from '@nrwl/workspace/src/utilities/set-default-collection';
|
||||
|
||||
import { initGenerator as nodeInitGenerator } from '@nrwl/node';
|
||||
|
||||
import {
|
||||
expressTypingsVersion,
|
||||
expressVersion,
|
||||
nxVersion,
|
||||
} from '../../utils/versions';
|
||||
import { Schema } from './schema';
|
||||
|
||||
function removeNrwlExpressFromDeps(tree: Tree) {
|
||||
updateJson(tree, 'package.json', (json) => {
|
||||
delete json.dependencies['@nrwl/express'];
|
||||
return json;
|
||||
});
|
||||
}
|
||||
|
||||
export async function initGenerator(tree: Tree, schema: Schema) {
|
||||
setDefaultCollection(tree, '@nrwl/express');
|
||||
|
||||
const initTask = await nodeInitGenerator(tree, {
|
||||
unitTestRunner: schema.unitTestRunner,
|
||||
skipFormat: true,
|
||||
});
|
||||
removeNrwlExpressFromDeps(tree);
|
||||
const installTask = addDependenciesToPackageJson(
|
||||
tree,
|
||||
{
|
||||
express: expressVersion,
|
||||
tslib: '^2.0.0',
|
||||
},
|
||||
{
|
||||
'@types/express': expressTypingsVersion,
|
||||
'@nrwl/express': nxVersion,
|
||||
}
|
||||
);
|
||||
if (!schema.skipFormat) {
|
||||
await formatFiles(tree);
|
||||
}
|
||||
|
||||
return async () => {
|
||||
await initTask();
|
||||
await installTask();
|
||||
};
|
||||
}
|
||||
|
||||
export default initGenerator;
|
||||
export const initSchematic = convertNxGenerator(initGenerator);
|
||||
4
packages/express/src/generators/init/schema.d.ts
vendored
Normal file
4
packages/express/src/generators/init/schema.d.ts
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
export interface Schema {
|
||||
unitTestRunner?: 'jest' | 'none';
|
||||
skipFormat?: boolean;
|
||||
}
|
||||
@ -1,5 +1,6 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/schema",
|
||||
"cli": "nx",
|
||||
"id": "NxExpressInit",
|
||||
"title": "Init Express Plugin",
|
||||
"type": "object",
|
||||
@ -1,85 +0,0 @@
|
||||
import {
|
||||
chain,
|
||||
externalSchematic,
|
||||
Rule,
|
||||
SchematicContext,
|
||||
Tree,
|
||||
} from '@angular-devkit/schematics';
|
||||
import { join, normalize, Path } from '@angular-devkit/core';
|
||||
import { Schema } from './schema';
|
||||
import { updateJsonInTree } from '@nrwl/workspace';
|
||||
import { formatFiles } from '@nrwl/workspace';
|
||||
import init from '../init/init';
|
||||
import { appsDir } from '@nrwl/workspace/src/utils/ast-utils';
|
||||
import { maybeJs } from '@nrwl/workspace/src/utils/rules/to-js';
|
||||
import { names } from '@nrwl/devkit';
|
||||
import { wrapAngularDevkitSchematic } from '@nrwl/devkit/ngcli-adapter';
|
||||
|
||||
interface NormalizedSchema extends Schema {
|
||||
appProjectRoot: Path;
|
||||
}
|
||||
|
||||
function addTypes(options: NormalizedSchema): Rule {
|
||||
const tsConfigPath = join(options.appProjectRoot, 'tsconfig.app.json');
|
||||
return updateJsonInTree(tsConfigPath, (json) => {
|
||||
json.compilerOptions.types = [...json.compilerOptions.types, 'express'];
|
||||
return json;
|
||||
});
|
||||
}
|
||||
|
||||
function addAppFiles(options: NormalizedSchema): Rule {
|
||||
return (host: Tree) => {
|
||||
host.overwrite(
|
||||
maybeJs(options, join(options.appProjectRoot, 'src/main.ts')),
|
||||
`/**
|
||||
* This is not a production server yet!
|
||||
* This is only a minimal backend to get started.
|
||||
*/
|
||||
|
||||
import * as express from 'express';
|
||||
|
||||
const app = express();
|
||||
|
||||
app.get('/api', (req, res) => {
|
||||
res.send({ message: 'Welcome to ${options.name}!' });
|
||||
});
|
||||
|
||||
const port = process.env.port || 3333;
|
||||
const server = app.listen(port, () => {
|
||||
console.log(\`Listening at http://localhost:\${port}/api\`);
|
||||
});
|
||||
server.on('error', console.error);
|
||||
`
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
export default function (schema: Schema): Rule {
|
||||
return (host: Tree, context: SchematicContext) => {
|
||||
const options = normalizeOptions(host, schema);
|
||||
return chain([
|
||||
init({ ...options, skipFormat: true }),
|
||||
externalSchematic('@nrwl/node', 'application', schema),
|
||||
addAppFiles(options),
|
||||
addTypes(options),
|
||||
formatFiles(options),
|
||||
])(host, context);
|
||||
};
|
||||
}
|
||||
|
||||
function normalizeOptions(host: Tree, options: Schema): NormalizedSchema {
|
||||
const appDirectory = options.directory
|
||||
? `${names(options.directory).fileName}/${names(options.name).fileName}`
|
||||
: names(options.name).fileName;
|
||||
const appProjectRoot = join(normalize(appsDir(host)), appDirectory);
|
||||
|
||||
return {
|
||||
...options,
|
||||
appProjectRoot,
|
||||
};
|
||||
}
|
||||
|
||||
export const applicationGenerator = wrapAngularDevkitSchematic(
|
||||
'@nrwl/express',
|
||||
'application'
|
||||
);
|
||||
@ -1,43 +0,0 @@
|
||||
import { chain, noop, Rule } from '@angular-devkit/schematics';
|
||||
import {
|
||||
addPackageWithInit,
|
||||
formatFiles,
|
||||
setDefaultCollection,
|
||||
addDepsToPackageJson,
|
||||
updateJsonInTree,
|
||||
} from '@nrwl/workspace';
|
||||
import {
|
||||
expressTypingsVersion,
|
||||
expressVersion,
|
||||
nxVersion,
|
||||
} from '../../utils/versions';
|
||||
import { Schema } from './schema';
|
||||
|
||||
function removeNrwlExpressFromDeps(): Rule {
|
||||
return updateJsonInTree('package.json', (json) => {
|
||||
delete json.dependencies['@nrwl/express'];
|
||||
return json;
|
||||
});
|
||||
}
|
||||
|
||||
export default function (schema: Schema) {
|
||||
return chain([
|
||||
setDefaultCollection('@nrwl/express'),
|
||||
addPackageWithInit('@nrwl/node', schema),
|
||||
schema.unitTestRunner === 'jest'
|
||||
? addPackageWithInit('@nrwl/jest')
|
||||
: noop(),
|
||||
removeNrwlExpressFromDeps(),
|
||||
addDepsToPackageJson(
|
||||
{
|
||||
express: expressVersion,
|
||||
tslib: '^2.0.0',
|
||||
},
|
||||
{
|
||||
'@types/express': expressTypingsVersion,
|
||||
'@nrwl/express': nxVersion,
|
||||
}
|
||||
),
|
||||
formatFiles(schema),
|
||||
]);
|
||||
}
|
||||
@ -1,4 +0,0 @@
|
||||
export interface Schema {
|
||||
unitTestRunner: 'jest' | 'none';
|
||||
skipFormat: boolean;
|
||||
}
|
||||
@ -1,26 +0,0 @@
|
||||
import { join } from 'path';
|
||||
import { SchematicTestRunner } from '@angular-devkit/schematics/testing';
|
||||
import { Rule, Tree } from '@angular-devkit/schematics';
|
||||
|
||||
const testRunner = new SchematicTestRunner(
|
||||
'@nrwl/express',
|
||||
join(__dirname, '../../collection.json')
|
||||
);
|
||||
|
||||
testRunner.registerCollection(
|
||||
'@nrwl/jest',
|
||||
join(__dirname, '../../../jest/collection.json')
|
||||
);
|
||||
|
||||
testRunner.registerCollection(
|
||||
'@nrwl/node',
|
||||
join(__dirname, '../../../node/collection.json')
|
||||
);
|
||||
|
||||
export function runSchematic(schematicName: string, options: any, tree: Tree) {
|
||||
return testRunner.runSchematicAsync(schematicName, options, tree).toPromise();
|
||||
}
|
||||
|
||||
export function callRule(rule: Rule, tree: Tree) {
|
||||
return testRunner.callRule(rule, tree).toPromise();
|
||||
}
|
||||
@ -1,2 +1,3 @@
|
||||
export { applicationGenerator } from './src/generators/application/application';
|
||||
export { libraryGenerator } from './src/generators/library/library';
|
||||
export { initGenerator } from './src/generators/init/init';
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user