From 7dd5aa74ef8027feb3fc122dd543be88bc0da519 Mon Sep 17 00:00:00 2001 From: Arman Ozak Date: Fri, 28 Aug 2020 17:25:53 +0300 Subject: [PATCH] feat: create 3 separate commands for proxy generation --- .../packages/schematics/src/collection.json | 18 +++++-- .../schematics/src/commands/api/index.ts | 9 ++-- .../schematics/src/commands/api/schema.ts | 16 ------ .../src/commands/proxy-add/index.ts | 48 +++++++++++++++++ .../commands/{proxy => proxy-add}/schema.json | 12 ++--- .../src/commands/proxy-refresh/index.ts | 37 ++++++++++++++ .../src/commands/proxy-refresh/schema.json | 39 ++++++++++++++ .../src/commands/proxy-remove/index.ts | 43 ++++++++++++++++ .../src/commands/proxy-remove/schema.json | 39 ++++++++++++++ .../schematics/src/commands/proxy/index.ts | 39 -------------- .../schematics/src/commands/proxy/schema.ts | 16 ------ .../packages/schematics/src/utils/source.ts | 51 ++++++++++++++++--- 12 files changed, 273 insertions(+), 94 deletions(-) delete mode 100644 npm/ng-packs/packages/schematics/src/commands/api/schema.ts create mode 100644 npm/ng-packs/packages/schematics/src/commands/proxy-add/index.ts rename npm/ng-packs/packages/schematics/src/commands/{proxy => proxy-add}/schema.json (50%) create mode 100644 npm/ng-packs/packages/schematics/src/commands/proxy-refresh/index.ts create mode 100644 npm/ng-packs/packages/schematics/src/commands/proxy-refresh/schema.json create mode 100644 npm/ng-packs/packages/schematics/src/commands/proxy-remove/index.ts create mode 100644 npm/ng-packs/packages/schematics/src/commands/proxy-remove/schema.json delete mode 100644 npm/ng-packs/packages/schematics/src/commands/proxy/index.ts delete mode 100644 npm/ng-packs/packages/schematics/src/commands/proxy/schema.ts diff --git a/npm/ng-packs/packages/schematics/src/collection.json b/npm/ng-packs/packages/schematics/src/collection.json index 9b21d174ca..5c2df8ea36 100644 --- a/npm/ng-packs/packages/schematics/src/collection.json +++ b/npm/ng-packs/packages/schematics/src/collection.json @@ -1,9 +1,19 @@ { "schematics": { - "proxy": { - "description": "ABP Proxy Generator Schematics", - "factory": "./commands/proxy", - "schema": "./commands/proxy/schema.json" + "proxy-add": { + "description": "ABP Proxy Generator Add Schematics", + "factory": "./commands/proxy-add", + "schema": "./commands/proxy-add/schema.json" + }, + "proxy-refresh": { + "description": "ABP Proxy Generator Refresh Schematics", + "factory": "./commands/proxy-refresh", + "schema": "./commands/proxy-refresh/schema.json" + }, + "proxy-remove": { + "description": "ABP Proxy Generator Remove Schematics", + "factory": "./commands/proxy-remove", + "schema": "./commands/proxy-remove/schema.json" }, "api": { "description": "ABP API Generator Schematics", diff --git a/npm/ng-packs/packages/schematics/src/commands/api/index.ts b/npm/ng-packs/packages/schematics/src/commands/api/index.ts index 178c72f376..646f2170ea 100644 --- a/npm/ng-packs/packages/schematics/src/commands/api/index.ts +++ b/npm/ng-packs/packages/schematics/src/commands/api/index.ts @@ -9,9 +9,8 @@ import { Tree, url, } from '@angular-devkit/schematics'; -import { PROXY_CONFIG_PATH } from '../../constants'; import { Exception } from '../../enums'; -import { ServiceGeneratorParams } from '../../models'; +import { GenerateProxySchema, ServiceGeneratorParams } from '../../models'; import { applyWithOverwrite, buildDefaultPath, @@ -31,7 +30,6 @@ import { serializeParameters, } from '../../utils'; import * as cases from '../../utils/text'; -import { Schema as GenerateProxySchema } from './schema'; export default function(schema: GenerateProxySchema) { const params = removeDefaultPlaceholders(schema); @@ -43,9 +41,8 @@ export default function(schema: GenerateProxySchema) { const target = await resolveProject(tree, params.target!); const solution = getRootNamespace(tree, source, moduleName); const targetPath = buildDefaultPath(target.definition); - const definitionPath = targetPath + PROXY_CONFIG_PATH; - const readProxyConfig = createProxyConfigReader(definitionPath); - const createProxyConfigWriter = createProxyConfigWriterCreator(definitionPath); + const readProxyConfig = createProxyConfigReader(targetPath); + const createProxyConfigWriter = createProxyConfigWriterCreator(targetPath); const data = readProxyConfig(tree); const types = data.types; const modules = data.modules; diff --git a/npm/ng-packs/packages/schematics/src/commands/api/schema.ts b/npm/ng-packs/packages/schematics/src/commands/api/schema.ts deleted file mode 100644 index 0c26ce461f..0000000000 --- a/npm/ng-packs/packages/schematics/src/commands/api/schema.ts +++ /dev/null @@ -1,16 +0,0 @@ -export interface Schema { - /** - * Backend module to generate code for - */ - module?: string; - - /** - * Angular project to resolve root namespace & API definition URL from - */ - source?: string; - - /** - * Angular project to generate code in - */ - target?: string; -} diff --git a/npm/ng-packs/packages/schematics/src/commands/proxy-add/index.ts b/npm/ng-packs/packages/schematics/src/commands/proxy-add/index.ts new file mode 100644 index 0000000000..3ac5053851 --- /dev/null +++ b/npm/ng-packs/packages/schematics/src/commands/proxy-add/index.ts @@ -0,0 +1,48 @@ +import { strings } from '@angular-devkit/core'; +import { chain, SchematicContext, Tree } from '@angular-devkit/schematics'; +import { GenerateProxySchema } from '../../models'; +import { + buildDefaultPath, + chainAndMerge, + createApiDefinitionGetter, + createApisGenerator, + createProxyClearer, + createProxyConfigReader, + createProxyConfigSaver, + removeDefaultPlaceholders, + resolveProject, +} from '../../utils'; + +export default function(schema: GenerateProxySchema) { + const params = removeDefaultPlaceholders(schema); + const moduleName = strings.camelize(params.module || 'app'); + + return chain([ + async (host: Tree, _context: SchematicContext) => { + const target = await resolveProject(host, params.target!); + const targetPath = buildDefaultPath(target.definition); + const readProxyConfig = createProxyConfigReader(targetPath); + let generated: string[] = []; + + try { + generated = readProxyConfig(host).generated; + const index = generated.findIndex(m => m === moduleName); + if (index < 0) generated.push(moduleName); + } catch (_) { + generated.push(moduleName); + } + + const getApiDefinition = createApiDefinitionGetter(params); + const data = { generated, ...(await getApiDefinition(host)) }; + data.generated = []; + + const clearProxy = createProxyClearer(targetPath); + + const saveProxyConfig = createProxyConfigSaver(data, targetPath); + + const generateApis = createApisGenerator(schema, generated); + + return chainAndMerge([clearProxy, saveProxyConfig, generateApis])(host); + }, + ]); +} diff --git a/npm/ng-packs/packages/schematics/src/commands/proxy/schema.json b/npm/ng-packs/packages/schematics/src/commands/proxy-add/schema.json similarity index 50% rename from npm/ng-packs/packages/schematics/src/commands/proxy/schema.json rename to npm/ng-packs/packages/schematics/src/commands/proxy-add/schema.json index f0b76bbdf6..f9e762c597 100644 --- a/npm/ng-packs/packages/schematics/src/commands/proxy/schema.json +++ b/npm/ng-packs/packages/schematics/src/commands/proxy-add/schema.json @@ -6,33 +6,33 @@ "properties": { "module": { "alias": "m", - "description": "Backend module to generate code for", + "description": "Backend module name", "type": "string", "$default": { "$source": "argv", "index": 0 }, - "x-prompt": "Please enter name of the backend module you wish to generate proxies for. (default: \"app\")" + "x-prompt": "Please enter backend module name. (default: \"app\")" }, "source": { "alias": "s", - "description": "Angular project to resolve root namespace & API definition URL from", + "description": "Source Angular project for API definition URL & root namespace resolution", "type": "string", "$default": { "$source": "argv", "index": 1 }, - "x-prompt": "Plese enter Angular project name to resolve root namespace & API definition URL from. (default: workspace \"defaultProject\")" + "x-prompt": "Plese enter source Angular project for API definition URL & root namespace resolution. (default: workspace \"defaultProject\")" }, "target": { "alias": "t", - "description": "Angular project to generate code in", + "description": "Target Angular project to place the generated code", "type": "string", "$default": { "$source": "argv", "index": 2 }, - "x-prompt": "Plese enter Angular project name to place generated code in. (default: workspace \"defaultProject\")" + "x-prompt": "Plese enter target Angular project to place the generated code. (default: workspace \"defaultProject\")" } }, "required": [] diff --git a/npm/ng-packs/packages/schematics/src/commands/proxy-refresh/index.ts b/npm/ng-packs/packages/schematics/src/commands/proxy-refresh/index.ts new file mode 100644 index 0000000000..2c4e20d7d2 --- /dev/null +++ b/npm/ng-packs/packages/schematics/src/commands/proxy-refresh/index.ts @@ -0,0 +1,37 @@ +import { SchematicContext, Tree } from '@angular-devkit/schematics'; +import { GenerateProxySchema } from '../../models'; +import { + buildDefaultPath, + chainAndMerge, + createApiDefinitionGetter, + createApisGenerator, + createProxyClearer, + createProxyConfigReader, + createProxyConfigSaver, + removeDefaultPlaceholders, + resolveProject, +} from '../../utils'; + +export default function(schema: GenerateProxySchema) { + const params = removeDefaultPlaceholders(schema); + + return async (host: Tree, _context: SchematicContext) => { + const target = await resolveProject(host, params.target!); + const targetPath = buildDefaultPath(target.definition); + + const readProxyConfig = createProxyConfigReader(targetPath); + const { generated } = readProxyConfig(host); + + const getApiDefinition = createApiDefinitionGetter(params); + const data = { generated, ...(await getApiDefinition(host)) }; + data.generated = []; + + const clearProxy = createProxyClearer(targetPath); + + const saveProxyConfig = createProxyConfigSaver(data, targetPath); + + const generateApis = createApisGenerator(schema, generated); + + return chainAndMerge([clearProxy, saveProxyConfig, generateApis])(host); + }; +} diff --git a/npm/ng-packs/packages/schematics/src/commands/proxy-refresh/schema.json b/npm/ng-packs/packages/schematics/src/commands/proxy-refresh/schema.json new file mode 100644 index 0000000000..f9e762c597 --- /dev/null +++ b/npm/ng-packs/packages/schematics/src/commands/proxy-refresh/schema.json @@ -0,0 +1,39 @@ +{ + "$schema": "http://json-schema.org/schema", + "id": "SchematicsAbpGenerateProxy", + "title": "ABP Generate Proxy Schema", + "type": "object", + "properties": { + "module": { + "alias": "m", + "description": "Backend module name", + "type": "string", + "$default": { + "$source": "argv", + "index": 0 + }, + "x-prompt": "Please enter backend module name. (default: \"app\")" + }, + "source": { + "alias": "s", + "description": "Source Angular project for API definition URL & root namespace resolution", + "type": "string", + "$default": { + "$source": "argv", + "index": 1 + }, + "x-prompt": "Plese enter source Angular project for API definition URL & root namespace resolution. (default: workspace \"defaultProject\")" + }, + "target": { + "alias": "t", + "description": "Target Angular project to place the generated code", + "type": "string", + "$default": { + "$source": "argv", + "index": 2 + }, + "x-prompt": "Plese enter target Angular project to place the generated code. (default: workspace \"defaultProject\")" + } + }, + "required": [] +} diff --git a/npm/ng-packs/packages/schematics/src/commands/proxy-remove/index.ts b/npm/ng-packs/packages/schematics/src/commands/proxy-remove/index.ts new file mode 100644 index 0000000000..83cc43c0b8 --- /dev/null +++ b/npm/ng-packs/packages/schematics/src/commands/proxy-remove/index.ts @@ -0,0 +1,43 @@ +import { strings } from '@angular-devkit/core'; +import { SchematicContext, Tree } from '@angular-devkit/schematics'; +import { GenerateProxySchema } from '../../models'; +import { + buildDefaultPath, + chainAndMerge, + createApiDefinitionGetter, + createApisGenerator, + createProxyClearer, + createProxyConfigReader, + createProxyConfigSaver, + removeDefaultPlaceholders, + resolveProject, +} from '../../utils'; + +export default function(schema: GenerateProxySchema) { + const params = removeDefaultPlaceholders(schema); + const moduleName = strings.camelize(params.module || 'app'); + + return async (host: Tree, _context: SchematicContext) => { + const target = await resolveProject(host, params.target!); + const targetPath = buildDefaultPath(target.definition); + + const readProxyConfig = createProxyConfigReader(targetPath); + const { generated } = readProxyConfig(host); + + const index = generated.findIndex(m => m === moduleName); + if (index < 0) return host; + generated.splice(index, 1); + + const getApiDefinition = createApiDefinitionGetter(params); + const data = { generated, ...(await getApiDefinition(host)) }; + data.generated = []; + + const clearProxy = createProxyClearer(targetPath); + + const saveProxyConfig = createProxyConfigSaver(data, targetPath); + + const generateApis = createApisGenerator(schema, generated); + + return chainAndMerge([clearProxy, saveProxyConfig, generateApis])(host); + }; +} diff --git a/npm/ng-packs/packages/schematics/src/commands/proxy-remove/schema.json b/npm/ng-packs/packages/schematics/src/commands/proxy-remove/schema.json new file mode 100644 index 0000000000..f9e762c597 --- /dev/null +++ b/npm/ng-packs/packages/schematics/src/commands/proxy-remove/schema.json @@ -0,0 +1,39 @@ +{ + "$schema": "http://json-schema.org/schema", + "id": "SchematicsAbpGenerateProxy", + "title": "ABP Generate Proxy Schema", + "type": "object", + "properties": { + "module": { + "alias": "m", + "description": "Backend module name", + "type": "string", + "$default": { + "$source": "argv", + "index": 0 + }, + "x-prompt": "Please enter backend module name. (default: \"app\")" + }, + "source": { + "alias": "s", + "description": "Source Angular project for API definition URL & root namespace resolution", + "type": "string", + "$default": { + "$source": "argv", + "index": 1 + }, + "x-prompt": "Plese enter source Angular project for API definition URL & root namespace resolution. (default: workspace \"defaultProject\")" + }, + "target": { + "alias": "t", + "description": "Target Angular project to place the generated code", + "type": "string", + "$default": { + "$source": "argv", + "index": 2 + }, + "x-prompt": "Plese enter target Angular project to place the generated code. (default: workspace \"defaultProject\")" + } + }, + "required": [] +} diff --git a/npm/ng-packs/packages/schematics/src/commands/proxy/index.ts b/npm/ng-packs/packages/schematics/src/commands/proxy/index.ts deleted file mode 100644 index fc405b5a58..0000000000 --- a/npm/ng-packs/packages/schematics/src/commands/proxy/index.ts +++ /dev/null @@ -1,39 +0,0 @@ -import { strings } from '@angular-devkit/core'; -import { - branchAndMerge, - chain, - schematic, - SchematicContext, - Tree, -} from '@angular-devkit/schematics'; -import { API_DEFINITION_ENDPOINT, PROXY_CONFIG_PATH } from '../../constants'; -import { ApiDefinition } from '../../models'; -import { - buildDefaultPath, - createProxyConfigSaver, - getApiDefinition, - getSourceUrl, - removeDefaultPlaceholders, - resolveProject, -} from '../../utils'; -import { Schema as GenerateProxySchema } from './schema'; - -export default function(schema: GenerateProxySchema) { - const params = removeDefaultPlaceholders(schema); - const moduleName = strings.camelize(params.module || 'app'); - - return chain([ - async (tree: Tree, _context: SchematicContext) => { - const source = await resolveProject(tree, params.source!); - const target = await resolveProject(tree, params.target!); - const sourceUrl = getSourceUrl(tree, source, moduleName); - const targetPath = buildDefaultPath(target.definition); - const data: ApiDefinition = await getApiDefinition(sourceUrl + API_DEFINITION_ENDPOINT); - - const saveProxyConfig = createProxyConfigSaver(data, targetPath + PROXY_CONFIG_PATH); - const createApi = schematic('api', schema); - - return branchAndMerge(chain([saveProxyConfig, createApi])); - }, - ]); -} diff --git a/npm/ng-packs/packages/schematics/src/commands/proxy/schema.ts b/npm/ng-packs/packages/schematics/src/commands/proxy/schema.ts deleted file mode 100644 index 0c26ce461f..0000000000 --- a/npm/ng-packs/packages/schematics/src/commands/proxy/schema.ts +++ /dev/null @@ -1,16 +0,0 @@ -export interface Schema { - /** - * Backend module to generate code for - */ - module?: string; - - /** - * Angular project to resolve root namespace & API definition URL from - */ - source?: string; - - /** - * Angular project to generate code in - */ - target?: string; -} diff --git a/npm/ng-packs/packages/schematics/src/utils/source.ts b/npm/ng-packs/packages/schematics/src/utils/source.ts index 3652836ed7..89d1fd17d8 100644 --- a/npm/ng-packs/packages/schematics/src/utils/source.ts +++ b/npm/ng-packs/packages/schematics/src/utils/source.ts @@ -1,13 +1,26 @@ +import { strings } from '@angular-devkit/core'; import { SchematicsException, Tree } from '@angular-devkit/schematics'; import got from 'got'; +import { API_DEFINITION_ENDPOINT, PROXY_CONFIG_PATH, PROXY_PATH } from '../constants'; import { Exception } from '../enums'; -import { ApiDefinition, Project, ProxyConfig, WriteOp } from '../models'; +import { ApiDefinition, GenerateProxySchema, Project, ProxyConfig, WriteOp } from '../models'; import { getAssignedPropertyFromObjectliteral } from './ast'; import { interpolate } from './common'; -import { readEnvironment } from './workspace'; +import { readEnvironment, resolveProject } from './workspace'; -export async function getApiDefinition(url: string) { - let body: any; +export function createApiDefinitionGetter(params: GenerateProxySchema) { + const moduleName = strings.camelize(params.module || 'app'); + + return async (host: Tree) => { + const source = await resolveProject(host, params.source!); + const sourceUrl = getSourceUrl(host, source, moduleName); + return await getApiDefinition(sourceUrl); + }; +} + +async function getApiDefinition(sourceUrl: string) { + const url = sourceUrl + API_DEFINITION_ENDPOINT; + let body: ApiDefinition; try { ({ body } = await got(url, { @@ -17,9 +30,10 @@ export async function getApiDefinition(url: string) { })); } catch ({ response }) { // handle redirects - if (response?.body && response.statusCode < 400) return response.body; + if (response.statusCode >= 400 || !response?.body) + throw new SchematicsException(Exception.NoApi); - throw new SchematicsException(Exception.NoApi); + body = response.body; } return body; @@ -72,13 +86,33 @@ export function getSourceUrl(tree: Tree, project: Project, moduleName: string) { } export function createProxyConfigReader(targetPath: string) { + targetPath += PROXY_CONFIG_PATH; + return (tree: Tree) => { try { const buffer = tree.read(targetPath); return JSON.parse(buffer!.toString()) as ProxyConfig; } catch (_) {} - throw new SchematicsException(interpolate(Exception.NoApiDefinition, targetPath)); + throw new SchematicsException(interpolate(Exception.NoProxyConfig, targetPath)); + }; +} + +export function createProxyClearer(targetPath: string) { + targetPath += PROXY_PATH; + + return (tree: Tree) => { + try { + tree.getDir(targetPath).subdirs.forEach(dirName => { + if (!['enums', 'models', 'services'].includes(dirName)) return; + + tree.delete(`${targetPath}/${dirName}`); + }); + + return tree; + } catch (_) { + throw new SchematicsException(interpolate(Exception.DirRemoveFailed, targetPath)); + } }; } @@ -86,6 +120,7 @@ export function createProxyConfigSaver(apiDefinition: ApiDefinition, targetPath: const createProxyConfigJson = createProxyConfigJsonCreator(apiDefinition); const readPreviousConfig = createProxyConfigReader(targetPath); const createProxyConfigWriter = createProxyConfigWriterCreator(targetPath); + targetPath += PROXY_CONFIG_PATH; return (tree: Tree) => { const generated: string[] = []; @@ -108,6 +143,8 @@ export function createProxyConfigSaver(apiDefinition: ApiDefinition, targetPath: } export function createProxyConfigWriterCreator(targetPath: string) { + targetPath += PROXY_CONFIG_PATH; + return (op: WriteOp, data: string) => (tree: Tree) => { try { tree[op](targetPath, data);