From 85358ddd5ae79a18a77db9543b0d8eacfe75f9b5 Mon Sep 17 00:00:00 2001 From: Danny Koppenhagen Date: Fri, 10 Jan 2020 17:40:33 +0100 Subject: [PATCH 01/27] refactor(scully): cleaned up schematic `scully` - use existing utils to read and write `package.json` config parts - split logic into smaller chainable functions - provide aditional tests - remove unused schema option `project` --- schematics/scully/src/collection.json | 2 +- schematics/scully/src/scully/index.ts | 69 +++++++++++----------- schematics/scully/src/scully/index_spec.ts | 5 +- schematics/scully/src/scully/schema.json | 19 +++--- schematics/scully/src/scully/schema.ts | 3 - 5 files changed, 42 insertions(+), 56 deletions(-) delete mode 100644 schematics/scully/src/scully/schema.ts diff --git a/schematics/scully/src/collection.json b/schematics/scully/src/collection.json index a08a20285..3f5a144d9 100644 --- a/schematics/scully/src/collection.json +++ b/schematics/scully/src/collection.json @@ -10,7 +10,7 @@ }, "scully": { "description": "Add scully to your angular app.", - "factory": "./scully/index#scully", + "factory": "./scully/index", "schema": "./scully/schema.json", "aliases": ["run"] }, diff --git a/schematics/scully/src/scully/index.ts b/schematics/scully/src/scully/index.ts index f49c7b552..7d47f158a 100644 --- a/schematics/scully/src/scully/index.ts +++ b/schematics/scully/src/scully/index.ts @@ -1,42 +1,39 @@ -import {Rule, SchematicContext, Tree, SchematicsException} from '@angular-devkit/schematics'; -import {Schema} from './schema'; -import {getSrc} from '../utils/utils'; -// for now we dont have any option for use -// @ts-ignore -export function scully(options: Schema): Rule { - return (tree: Tree, context: SchematicContext) => { - // project workspace data - const workspaceConfigBuffer = tree.read('angular.json'); - if (!workspaceConfigBuffer) { - throw new SchematicsException('Not an angular CLI workspace'); - } - // modify package json for support npm commands - const content: Buffer | null = tree.read(`/package.json`); - let jsonContent; - if (content) { - jsonContent = JSON.parse(content.toString()); - } - /* tslint:disable:no-string-literal */ - jsonContent.scripts['scully'] = 'scully'; - /* tslint:enable:no-string-literal */ - jsonContent.scripts['scully:serve'] = 'scully serve'; - tree.overwrite(`/package.json`, JSON.stringify(jsonContent, undefined, 2)); - context.logger.info('✅️ Update package.json'); +import {Rule, SchematicContext, Tree, SchematicsException, chain} from '@angular-devkit/schematics'; +import {getSrc, getPackageJson, overwritePackageJson} from '../utils/utils'; - // add config file - if (!tree.exists('./scully.config.js')) { - const srcFolder = getSrc(tree); - tree.create( - './scully.config.js', - `exports.config = { +const SCULLY_CONFIG_FILE = './scully.config.js'; + +export default (options: any): Rule => { + return chain([verifyAngularWorkspace(), modifyPackageJson(), createScullyConfig()]); +}; + +const verifyAngularWorkspace = () => (tree: Tree, context: SchematicContext) => { + const workspaceConfigBuffer = tree.read('angular.json'); + if (!workspaceConfigBuffer) { + throw new SchematicsException('Not an angular CLI workspace'); + } +}; + +const modifyPackageJson = () => (tree: Tree, context: SchematicContext) => { + const jsonContent = getPackageJson(tree); + jsonContent.scripts.scully = 'scully'; + jsonContent.scripts['scully:serve'] = 'scully serve'; + overwritePackageJson(tree, jsonContent); + context.logger.info('✅️ Update package.json'); +}; + +const createScullyConfig = () => (tree: Tree, context: SchematicContext) => { + if (!tree.exists(SCULLY_CONFIG_FILE)) { + const srcFolder = getSrc(tree); + tree.create( + SCULLY_CONFIG_FILE, + `exports.config = { projectRoot: "${srcFolder}/app", outFolder: './dist/static', routes: { } };` - ); - } - - // end return - }; -} + ); + context.logger.info(`✅️ Created scully configuration file in ${SCULLY_CONFIG_FILE}`); + } +}; diff --git a/schematics/scully/src/scully/index_spec.ts b/schematics/scully/src/scully/index_spec.ts index c6e6e4ebe..389e945ab 100644 --- a/schematics/scully/src/scully/index_spec.ts +++ b/schematics/scully/src/scully/index_spec.ts @@ -4,7 +4,6 @@ import {getFileContent} from '@schematics/angular/utility/test'; import * as path from 'path'; import {setupProject} from '../utils/test-utils'; -import {Schema} from './schema'; const collectionPath = path.join(__dirname, '../collection.json'); const PACKAGE_JSON_PATH = '/package.json'; @@ -13,9 +12,7 @@ const SCULLY_PATH = '/scully.config.js'; describe('scully schematic', () => { const schematicRunner = new SchematicTestRunner('scully-schematics', collectionPath); const project = 'foo'; - const defaultOptions: Schema = { - project: 'foo', - }; + const defaultOptions = {}; let appTree: UnitTestTree; beforeEach(async () => { diff --git a/schematics/scully/src/scully/schema.json b/schematics/scully/src/scully/schema.json index 2c5a3df61..395341cc7 100644 --- a/schematics/scully/src/scully/schema.json +++ b/schematics/scully/src/scully/schema.json @@ -1,14 +1,9 @@ { - "$schema": "http://json-schema.org/schema", - "id": "@herodevs/init", - "title": "Scully schematics", - "type": "object", - "description": "Scully schematics for angular", - "properties": { - "project": { - "type": "string", - "description": "generate" - } - }, - "required": [] + "$schema": "http://json-schema.org/schema", + "id": "@herodevs/init", + "title": "Scully schematics", + "type": "object", + "description": "Scully schematics for angular", + "properties": {}, + "required": [] } diff --git a/schematics/scully/src/scully/schema.ts b/schematics/scully/src/scully/schema.ts deleted file mode 100644 index e76548202..000000000 --- a/schematics/scully/src/scully/schema.ts +++ /dev/null @@ -1,3 +0,0 @@ -export interface Schema { - project: string; -} From c8e56d3914862c5944a4a312325d5219ee47f27c Mon Sep 17 00:00:00 2001 From: Danny Koppenhagen Date: Fri, 10 Jan 2020 17:52:24 +0100 Subject: [PATCH 02/27] refactor(scully): use consistent id's and titles --- schematics/scully/src/add-blog/schema.json | 4 ++-- schematics/scully/src/add-post/schema.json | 4 ++-- schematics/scully/src/create-markdown/schema.json | 4 ++-- schematics/scully/src/ng-add/schema.json | 4 ++-- schematics/scully/src/scully/schema.json | 4 ++-- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/schematics/scully/src/add-blog/schema.json b/schematics/scully/src/add-blog/schema.json index 29e020dcc..df9ce1aec 100644 --- a/schematics/scully/src/add-blog/schema.json +++ b/schematics/scully/src/add-blog/schema.json @@ -1,7 +1,7 @@ { "$schema": "http://json-schema.org/schema", - "id": "add-blog", - "title": "Scully add component schematic", + "id": "@scullyio/init:blog", + "title": "Scully: Add a complete blog schematic", "type": "object", "properties": { "routingScope": { diff --git a/schematics/scully/src/add-post/schema.json b/schematics/scully/src/add-post/schema.json index f58a3e9cf..fb6ce8521 100644 --- a/schematics/scully/src/add-post/schema.json +++ b/schematics/scully/src/add-post/schema.json @@ -1,7 +1,7 @@ { "$schema": "http://json-schema.org/schema", - "id": "Scully-ng-add-blog", - "title": "Scully ng-add-blog schematic", + "id": "@scullyio/init:post", + "title": "Scully: Add a blog post schematic", "type": "object", "properties": { "name": { diff --git a/schematics/scully/src/create-markdown/schema.json b/schematics/scully/src/create-markdown/schema.json index 673a5d8bd..ff2a4e733 100644 --- a/schematics/scully/src/create-markdown/schema.json +++ b/schematics/scully/src/create-markdown/schema.json @@ -1,7 +1,7 @@ { "$schema": "http://json-schema.org/schema", - "id": "add-component", - "title": "scully create markdown module schematic", + "id": "@scullyio/init:markdown", + "title": "Scully: Create a markdown module schematic", "type": "object", "properties": { "name": { diff --git a/schematics/scully/src/ng-add/schema.json b/schematics/scully/src/ng-add/schema.json index 88586f643..f70f2cac7 100644 --- a/schematics/scully/src/ng-add/schema.json +++ b/schematics/scully/src/ng-add/schema.json @@ -1,7 +1,7 @@ { "$schema": "http://json-schema.org/schema", - "id": "scully-ng-add", - "title": "scully ng-add schematic", + "id": "@scullyio/init", + "title": "Scully ng-add schematic", "type": "object", "properties": { "blog": { diff --git a/schematics/scully/src/scully/schema.json b/schematics/scully/src/scully/schema.json index 395341cc7..fc68d9605 100644 --- a/schematics/scully/src/scully/schema.json +++ b/schematics/scully/src/scully/schema.json @@ -1,7 +1,7 @@ { "$schema": "http://json-schema.org/schema", - "id": "@herodevs/init", - "title": "Scully schematics", + "id": "@scullyio/init:scully", + "title": "Scully setup schematic", "type": "object", "description": "Scully schematics for angular", "properties": {}, From 4c900d4322396228d457f291ba46549911d0c1bc Mon Sep 17 00:00:00 2001 From: Danny Koppenhagen Date: Fri, 10 Jan 2020 17:58:21 +0100 Subject: [PATCH 03/27] refactor(scully): use context.logger instead of console.log --- schematics/scully/src/ng-update/index.ts | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/schematics/scully/src/ng-update/index.ts b/schematics/scully/src/ng-update/index.ts index a60ece33f..1492cf512 100644 --- a/schematics/scully/src/ng-update/index.ts +++ b/schematics/scully/src/ng-update/index.ts @@ -1,22 +1,19 @@ -import {Rule, Tree} from '@angular-devkit/schematics'; -import chalk from 'chalk'; +import {Rule, Tree, SchematicContext} from '@angular-devkit/schematics'; /** Entry point for the migration schematics with target of Angular v9 */ export function updateToV0(): Rule { - return (tree: Tree) => { - console.log(tree); - return onMigrationComplete('V0', true); - }; + return (tree: Tree, context: SchematicContext) => { + context.logger.info(JSON.stringify(tree, null, ' ')); + return onMigrationComplete('V0', true, context); + }; } /** Function that will be called when the migration completed. */ -function onMigrationComplete(targetVersion: string, hasFailures: boolean) { - console.log(); - console.log(chalk.green(` ✓ Updated Scully to ${targetVersion}`)); - console.log(); +function onMigrationComplete(targetVersion: string, hasFailures: boolean, context: SchematicContext) { + context.logger.info(`✅ Updated Scully to ${targetVersion}`); if (hasFailures) { - console.log(chalk.yellow( - ' ⚠ Some issues were detected but could not be fixed automatically. Please check the ' + - 'output above and fix these issues manually.')); + context.logger.warn( + 'Some issues were detected but could not be fixed automatically. Please check the output above and fix these issues manually.' + ); } } From 15b6f91df51026c2f980bd44d00b763c5b3dc1d0 Mon Sep 17 00:00:00 2001 From: Danny Koppenhagen Date: Fri, 10 Jan 2020 18:00:10 +0100 Subject: [PATCH 04/27] chore(scully): remove unused dependency chalk --- package.json | 1 - 1 file changed, 1 deletion(-) diff --git a/package.json b/package.json index 4e79a0894..e68597bf4 100644 --- a/package.json +++ b/package.json @@ -58,7 +58,6 @@ "@types/request": "^2.48.4", "@types/yargs": "^13.0.3", "asciidoctor.js": "^1.5.9", - "chalk": "^2.4.2", "codelyzer": "^5.1.2", "conventional-changelog": "^2.0.3", "cz-conventional-changelog": "3.0.2", From 5a75b9ff3df6ae13cb3d2ab7f4ea91f646eca363 Mon Sep 17 00:00:00 2001 From: Danny Koppenhagen Date: Fri, 10 Jan 2020 18:05:50 +0100 Subject: [PATCH 05/27] refactor(scully): replace all log with context.logger logs --- schematics/scully/src/create-markdown/index.ts | 3 +++ schematics/scully/src/ng-add/index.ts | 8 ++++---- schematics/scully/src/utils/utils.ts | 3 +-- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/schematics/scully/src/create-markdown/index.ts b/schematics/scully/src/create-markdown/index.ts index 4dd0abbb8..91df08531 100644 --- a/schematics/scully/src/create-markdown/index.ts +++ b/schematics/scully/src/create-markdown/index.ts @@ -58,6 +58,9 @@ publish: false sourceDir, route: options.route, }); + if (!newScullyJs) { + context.logger.error(`Scully can't find the ${SCULLY_CONF_FILE}`); + } host.overwrite(SCULLY_CONF_FILE, newScullyJs); context.logger.info(`✅️ Update ${SCULLY_CONF_FILE}`); diff --git a/schematics/scully/src/ng-add/index.ts b/schematics/scully/src/ng-add/index.ts index 761fbcb93..80673d2a0 100644 --- a/schematics/scully/src/ng-add/index.ts +++ b/schematics/scully/src/ng-add/index.ts @@ -24,10 +24,10 @@ const addDependencies = (options: Schema) => (tree: Tree, context: SchematicCont addPackageToPackageJson(tree, '@scullyio/scully', `${scullyVersion}`); const ngCoreVersionTag = getPackageVersionFromPackageJson(tree, '@angular/core'); if (+ngCoreVersionTag.search(/(\^8|~8)/g) === 0) { - console.log('Install ng-lib for Angular v8'); + context.logger.info('Install ng-lib for Angular v8'); addPackageToPackageJson(tree, '@scullyio/ng-lib-8', `${scullyComponentVersion}`); } else { - console.log('Install ng-lib for Angular v9'); + context.logger.info('Install ng-lib for Angular v9'); addPackageToPackageJson(tree, '@scullyio/ng-lib', `${scullyComponentVersion}`); } context.logger.info('✅️ Added dependency'); @@ -51,7 +51,7 @@ const importHttpClientModule = (options: Schema) => (tree: Tree, context: Schema tree.commitUpdate(recorder); return tree; } catch (e) { - console.log('error into import httpclient', e); + context.logger.error('error into import httpclient', e); } }; @@ -131,7 +131,7 @@ const injectIdleService = (options: Schema) => (tree: Tree, context: SchematicCo return ''; } } catch (e) { - console.log('error in idle service'); + context.logger.error('error in idle service'); } }; diff --git a/schematics/scully/src/utils/utils.ts b/schematics/scully/src/utils/utils.ts index e78440bd5..0117b8e68 100644 --- a/schematics/scully/src/utils/utils.ts +++ b/schematics/scully/src/utils/utils.ts @@ -53,8 +53,7 @@ export function addRouteToScullyConfig(scullyConfigJs: string, data: Data) { const position = +scullyConfigJs.search(/routes:\{/g) + 'routes:{'.length; output = [scullyConfigJs.slice(0, position), addRoute, scullyConfigJs.slice(position)].join(''); } else { - console.log(`Scully can't find the scully.config.js`); - return scullyConfigJs; + return undefined; } return output; } From 832a43323ef9f42fa186d0dec1c85786ea51b5bd Mon Sep 17 00:00:00 2001 From: Danny Koppenhagen Date: Fri, 10 Jan 2020 18:19:39 +0100 Subject: [PATCH 06/27] refactor(scully): outsource yaml converter --- schematics/scully/src/add-post/index.ts | 20 +++++--------------- schematics/scully/src/utils/utils.ts | 18 ++++++++++++++++++ 2 files changed, 23 insertions(+), 15 deletions(-) diff --git a/schematics/scully/src/add-post/index.ts b/schematics/scully/src/add-post/index.ts index 728b7c27c..a1d58fe34 100644 --- a/schematics/scully/src/add-post/index.ts +++ b/schematics/scully/src/add-post/index.ts @@ -1,9 +1,8 @@ import {Rule, SchematicContext, SchematicsException, Tree} from '@angular-devkit/schematics'; import {strings} from '@angular-devkit/core'; -import fs = require('fs'); -import yaml = require('js-yaml'); import {Schema} from './schema'; +import {yamlToJson, jsonToJaml} from '../utils/utils'; export default function(options: Schema): Rule { return (host: Tree, context: SchematicContext) => { @@ -19,19 +18,10 @@ export default function(options: Schema): Rule { }; if (options.metaDataFile) { - let metaDataContents = ''; - try { - metaDataContents = fs.readFileSync(options.metaDataFile, 'utf8'); - } catch (e) { - throw new SchematicsException(`File ${options.metaDataFile} not found`); - } - - try { - // check if yaml is valid - metaData = yaml.safeLoad(metaDataContents); + const metaDataAsJson = yamlToJson(options.metaDataFile); + if (metaDataAsJson) { + metaData = metaDataAsJson; context.logger.info(`✅️ Meta Data File ${options.metaDataFile} successfully parsed`); - } catch (e) { - throw new SchematicsException(`${options.metaDataFile} contains no valid yaml`); } } @@ -40,7 +30,7 @@ export default function(options: Schema): Rule { if (!host.exists(filename)) { const content = `--- -${yaml.safeDump(metaData)}--- +${jsonToJaml(metaData)}--- # ${name} `; diff --git a/schematics/scully/src/utils/utils.ts b/schematics/scully/src/utils/utils.ts index 0117b8e68..77edb7f92 100644 --- a/schematics/scully/src/utils/utils.ts +++ b/schematics/scully/src/utils/utils.ts @@ -10,6 +10,8 @@ import { } from '@angular-devkit/schematics'; import {normalize, strings} from '@angular-devkit/core'; import {join} from 'path'; +import fs = require('fs'); +import yaml = require('js-yaml'); import {buildRelativePath} from '@schematics/angular/utility/find-module'; import {addRouteDeclarationToModule} from '@schematics/angular/utility/ast-utils'; @@ -210,3 +212,19 @@ export function getSourceFile(host: Tree, path: string): ts.SourceFile { return source; } + +export const yamlToJson = (filePath: string) => { + let metaDataContents = ''; + try { + metaDataContents = fs.readFileSync(filePath, 'utf8'); + } catch (e) { + throw new SchematicsException(`File ${filePath} not found`); + } + try { + return yaml.safeLoad(metaDataContents); + } catch (e) { + throw new SchematicsException(`${filePath} contains invalid yaml`); + } +}; + +export const jsonToJaml = (metaData: {}) => yaml.safeDump(metaData); From b404a9a51b4cc617ce42169101d5d54599d0e558 Mon Sep 17 00:00:00 2001 From: Danny Koppenhagen Date: Fri, 10 Jan 2020 19:10:58 +0100 Subject: [PATCH 07/27] style(scully): fix typo --- schematics/scully/src/create-markdown/index.ts | 3 ++- .../scully/src/create-markdown/index_spec.ts | 17 ++++++++++------- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/schematics/scully/src/create-markdown/index.ts b/schematics/scully/src/create-markdown/index.ts index 91df08531..0ecb023b1 100644 --- a/schematics/scully/src/create-markdown/index.ts +++ b/schematics/scully/src/create-markdown/index.ts @@ -8,6 +8,7 @@ import { getPrefix, getSrc, } from '../utils/utils'; +import {RunSchematicTask} from '@angular-devkit/schematics/tasks'; const SCULLY_CONF_FILE = '/scully.config.js'; const ANGULAR_CONF_FILE = './angular.json'; @@ -37,7 +38,7 @@ publish: false # Page ${name} example ` ); - context.logger.info(`✅ ${path} file created`); + context.addTask(new RunSchematicTask('post', makrdownOptions), []); } let scullyJs; diff --git a/schematics/scully/src/create-markdown/index_spec.ts b/schematics/scully/src/create-markdown/index_spec.ts index f3f71457e..931d1fe1e 100644 --- a/schematics/scully/src/create-markdown/index_spec.ts +++ b/schematics/scully/src/create-markdown/index_spec.ts @@ -27,14 +27,17 @@ describe('create-markdown', () => { appTree = await schematicRunner.runSchematicAsync('md', defaultOptions, appTree).toPromise(); }); - it('should create the markdown file in the default directory', () => { + it('should create the markdown file by calling the post schematic', () => { const dayString = new Date().toISOString().substring(0, 10); - const expectedFileName = `/blog/${dayString}-blog.md`; - expect(appTree.files).toContain(expectedFileName); - const mdFileContent = getFileContent(appTree, expectedFileName); - expect(mdFileContent).toMatch(/title: This is the blog/g); - expect(mdFileContent).toMatch(/description: blog/g); - expect(mdFileContent).toMatch(/# Page blog example/g); + expect( + schematicRunner.tasks.some( + task => + task.name === 'run-schematic' && + (task.options as any).name === 'post' && + (task.options as any).options.name === `${dayString}-blog` && + (task.options as any).options.target === 'blog' + ) + ).toBe(true); }); }); }); From 42186ae719862e7e1cc2ddb6bc0942bc9db00363 Mon Sep 17 00:00:00 2001 From: Danny Koppenhagen Date: Fri, 10 Jan 2020 19:17:58 +0100 Subject: [PATCH 08/27] refactor(scully): use `post` schematic for initial post avoid duplicat / mismatching code --- .../scully/src/create-markdown/index.ts | 26 +++++++------------ .../scully/src/create-markdown/index_spec.ts | 1 - 2 files changed, 10 insertions(+), 17 deletions(-) diff --git a/schematics/scully/src/create-markdown/index.ts b/schematics/scully/src/create-markdown/index.ts index 0ecb023b1..220c42663 100644 --- a/schematics/scully/src/create-markdown/index.ts +++ b/schematics/scully/src/create-markdown/index.ts @@ -1,6 +1,7 @@ import {Rule, Tree, url, applyTemplates, move, chain, SchematicContext} from '@angular-devkit/schematics'; import {strings, normalize} from '@angular-devkit/core'; -import {Schema as MyServiceSchema} from './schema'; +import {Schema} from './schema'; +import {Schema as PostSchema} from '../add-post/schema'; import { addRouteToModule, addRouteToScullyConfig, @@ -13,7 +14,7 @@ import {RunSchematicTask} from '@angular-devkit/schematics/tasks'; const SCULLY_CONF_FILE = '/scully.config.js'; const ANGULAR_CONF_FILE = './angular.json'; -export default function(options: MyServiceSchema): Rule { +export default function(options: Schema): Rule { return (host: Tree, context: SchematicContext) => { try { const sourceDir = getSrc(host); @@ -25,20 +26,13 @@ export default function(options: MyServiceSchema): Rule { const date = new Date(); // format yyyy-mm-dd const fullDay = date.toISOString().substring(0, 10); - const path = `${targetDirName}/${fullDay}-${nameDasherized}.md`; - if (!host.exists(path)) { - host.create( - path, - `--- -title: This is the ${name} -description: ${name} description -publish: false ---- - -# Page ${name} example -` - ); - context.addTask(new RunSchematicTask('post', makrdownOptions), []); + const baseFileName = `${fullDay}-${nameDasherized}`; + if (!host.exists(`${targetDirName}/${baseFileName}.md`)) { + const postOptions: PostSchema = { + name: baseFileName, + target: targetDirName, + }; + context.addTask(new RunSchematicTask('post', postOptions), []); } let scullyJs; diff --git a/schematics/scully/src/create-markdown/index_spec.ts b/schematics/scully/src/create-markdown/index_spec.ts index 931d1fe1e..68f6a3b2f 100644 --- a/schematics/scully/src/create-markdown/index_spec.ts +++ b/schematics/scully/src/create-markdown/index_spec.ts @@ -1,6 +1,5 @@ import {HostTree} from '@angular-devkit/schematics'; import {SchematicTestRunner, UnitTestTree} from '@angular-devkit/schematics/testing'; -import {getFileContent} from '@schematics/angular/utility/test'; import * as path from 'path'; import {setupProject} from '../utils/test-utils'; From 9712e01fe8958ae7f2bde06dcde98800d174e577 Mon Sep 17 00:00:00 2001 From: Danny Koppenhagen Date: Fri, 10 Jan 2020 21:51:26 +0100 Subject: [PATCH 09/27] refactor(scully): use getFileContents utils function --- schematics/scully/src/create-markdown/index.ts | 15 +++++---------- schematics/scully/src/utils/utils.ts | 2 +- 2 files changed, 6 insertions(+), 11 deletions(-) diff --git a/schematics/scully/src/create-markdown/index.ts b/schematics/scully/src/create-markdown/index.ts index 220c42663..ba40816fc 100644 --- a/schematics/scully/src/create-markdown/index.ts +++ b/schematics/scully/src/create-markdown/index.ts @@ -8,6 +8,7 @@ import { applyWithOverwrite, getPrefix, getSrc, + getFileContents, } from '../utils/utils'; import {RunSchematicTask} from '@angular-devkit/schematics/tasks'; @@ -35,17 +36,13 @@ export default function(options: Schema): Rule { context.addTask(new RunSchematicTask('post', postOptions), []); } - let scullyJs; - try { - scullyJs = host.read(SCULLY_CONF_FILE).toString(); - } catch (e) { - // for test in schematics - scullyJs = `exports.config = { + const scullyJs = + getFileContents(host, SCULLY_CONF_FILE) || + `exports.config = { projectRoot: "${getSrc(host)}/app", routes: { }, };`; - } const newScullyJs = addRouteToScullyConfig(scullyJs, { name, slug: options.slug, @@ -53,9 +50,7 @@ export default function(options: Schema): Rule { sourceDir, route: options.route, }); - if (!newScullyJs) { - context.logger.error(`Scully can't find the ${SCULLY_CONF_FILE}`); - } + host.overwrite(SCULLY_CONF_FILE, newScullyJs); context.logger.info(`✅️ Update ${SCULLY_CONF_FILE}`); diff --git a/schematics/scully/src/utils/utils.ts b/schematics/scully/src/utils/utils.ts index 77edb7f92..ffccd0a5a 100644 --- a/schematics/scully/src/utils/utils.ts +++ b/schematics/scully/src/utils/utils.ts @@ -55,7 +55,7 @@ export function addRouteToScullyConfig(scullyConfigJs: string, data: Data) { const position = +scullyConfigJs.search(/routes:\{/g) + 'routes:{'.length; output = [scullyConfigJs.slice(0, position), addRoute, scullyConfigJs.slice(position)].join(''); } else { - return undefined; + return scullyConfigJs; } return output; } From 7703987973717c6f90c06b3b9043ebf4a4dd6abf Mon Sep 17 00:00:00 2001 From: Danny Koppenhagen Date: Fri, 10 Jan 2020 22:45:30 +0100 Subject: [PATCH 10/27] refactor(scully): cleanup markdown schematic including tests --- .../scully/src/create-markdown/index.ts | 117 +++++++++--------- .../scully/src/create-markdown/index_spec.ts | 33 +++++ schematics/scully/src/utils/test-utils.ts | 1 + schematics/scully/src/utils/utils.ts | 2 +- 4 files changed, 96 insertions(+), 57 deletions(-) diff --git a/schematics/scully/src/create-markdown/index.ts b/schematics/scully/src/create-markdown/index.ts index ba40816fc..87377691e 100644 --- a/schematics/scully/src/create-markdown/index.ts +++ b/schematics/scully/src/create-markdown/index.ts @@ -15,64 +15,69 @@ import {RunSchematicTask} from '@angular-devkit/schematics/tasks'; const SCULLY_CONF_FILE = '/scully.config.js'; const ANGULAR_CONF_FILE = './angular.json'; -export default function(options: Schema): Rule { - return (host: Tree, context: SchematicContext) => { - try { - const sourceDir = getSrc(host); - const name = options.name ? options.name : 'blog'; - const nameDasherized = strings.dasherize(options.name); - const targetDirName = options.sourceDir - ? strings.dasherize(options.sourceDir) // use sourceDir when provided - : strings.dasherize(options.name); // fall back to name when not provided - const date = new Date(); - // format yyyy-mm-dd - const fullDay = date.toISOString().substring(0, 10); - const baseFileName = `${fullDay}-${nameDasherized}`; - if (!host.exists(`${targetDirName}/${baseFileName}.md`)) { - const postOptions: PostSchema = { - name: baseFileName, - target: targetDirName, - }; - context.addTask(new RunSchematicTask('post', postOptions), []); - } +export default (options: Schema): Rule => { + const name = options.name ? options.name : 'blog'; + const targetDirName = options.sourceDir ? options.sourceDir : name; + return chain([ + addPost(name, targetDirName), + updateScullyConfig(name, targetDirName, options), + addModule(name, options), + ]); +}; - const scullyJs = - getFileContents(host, SCULLY_CONF_FILE) || - `exports.config = { - projectRoot: "${getSrc(host)}/app", - routes: { - }, -};`; - const newScullyJs = addRouteToScullyConfig(scullyJs, { - name, - slug: options.slug, - type: 'contentFolder', - sourceDir, - route: options.route, - }); +const addPost = (name: string, target: string) => (tree: Tree, context: SchematicContext) => { + const nameDasherized = strings.dasherize(name); + const targetDirName = strings.dasherize(target); + const date = new Date(); + // format yyyy-mm-dd + const fullDay = date.toISOString().substring(0, 10); + const baseFileName = `${fullDay}-${nameDasherized}`; + if (!tree.exists(`${targetDirName}/${baseFileName}.md`)) { + const postOptions: PostSchema = { + name: baseFileName, + target: targetDirName, + }; + context.addTask(new RunSchematicTask('post', postOptions), []); + } +}; - host.overwrite(SCULLY_CONF_FILE, newScullyJs); - context.logger.info(`✅️ Update ${SCULLY_CONF_FILE}`); +const updateScullyConfig = (name: string, target: string, options: Schema) => ( + tree: Tree, + context: SchematicContext +) => { + const scullyJs = getFileContents(tree, SCULLY_CONF_FILE); + if (!scullyJs) { + context.logger.error(`No scully configuration file found ${SCULLY_CONF_FILE}`); + } + const newScullyJs = addRouteToScullyConfig(scullyJs, { + name, + slug: options.slug, + type: 'contentFolder', + sourceDir: target, + route: options.route, + }); - const pathName = strings.dasherize(`${sourceDir}/app/${name}`); - let prefix = 'app'; - if (host.exists(ANGULAR_CONF_FILE)) { - prefix = getPrefix(host.read(ANGULAR_CONF_FILE).toString()); - addRouteToModule(host, options); - } + tree.overwrite(SCULLY_CONF_FILE, newScullyJs); + context.logger.info(`✅️ Update ${SCULLY_CONF_FILE}`); +}; - const templateSource = applyWithOverwrite(url('../files/markdown-module'), [ - applyTemplates({ - classify: strings.classify, - dasherize: strings.dasherize, - name: options.name, - slug: options.slug, - prefix, - }), - move(normalize(pathName)), - ]); +const addModule = (name: string, options: Schema) => (tree: Tree, context: SchematicContext) => { + const sourceDir = getSrc(tree); + const pathName = strings.dasherize(`${sourceDir}/app/${name}`); + let prefix = 'app'; + if (tree.exists(ANGULAR_CONF_FILE)) { + prefix = getPrefix(getFileContents(tree, ANGULAR_CONF_FILE)); + addRouteToModule(tree, options); + } - return chain([templateSource]); - } catch (e) {} - }; -} + return applyWithOverwrite(url('../files/markdown-module'), [ + applyTemplates({ + classify: strings.classify, + dasherize: strings.dasherize, + name: options.name, + slug: options.slug, + prefix, + }), + move(normalize(pathName)), + ]); +}; diff --git a/schematics/scully/src/create-markdown/index_spec.ts b/schematics/scully/src/create-markdown/index_spec.ts index 68f6a3b2f..d1ebb6eac 100644 --- a/schematics/scully/src/create-markdown/index_spec.ts +++ b/schematics/scully/src/create-markdown/index_spec.ts @@ -4,8 +4,10 @@ import * as path from 'path'; import {setupProject} from '../utils/test-utils'; import {Schema} from './schema'; +import {getFileContent} from '@schematics/angular/utility/test'; const collectionPath = path.join(__dirname, '../collection.json'); +const SCULLY_CONF_FILE = '/scully.config.js'; describe('create-markdown', () => { const schematicRunner = new SchematicTestRunner('scully-schematics', collectionPath); @@ -19,6 +21,14 @@ describe('create-markdown', () => { beforeEach(async () => { appTree = new UnitTestTree(new HostTree()); appTree = await setupProject(appTree, schematicRunner, project); + appTree.create( + SCULLY_CONF_FILE, + `exports.config = { + projectRoot: "./src/app", + routes: { + }, +};` + ); }); describe('when using the default options', () => { @@ -38,5 +48,28 @@ describe('create-markdown', () => { ) ).toBe(true); }); + it(`should update the file ${SCULLY_CONF_FILE}`, () => { + expect(appTree.files).toContain(SCULLY_CONF_FILE); + const scullyConfigFileContent = getFileContent(appTree, SCULLY_CONF_FILE); + expect(scullyConfigFileContent).toEqual(`exports.config = { + projectRoot: "./src/app", + routes: { + '/blog/:id': { + type: 'contentFolder', + id: { + folder: "./blog" + } + }, + }, +};`); + }); + it(`should setup a new angular module from template`, () => { + expect(appTree.files).toContain('/src/app/blog/blog-routing.module.ts'); + expect(appTree.files).toContain('/src/app/blog/blog.component.css'); + expect(appTree.files).toContain('/src/app/blog/blog.component.html'); + expect(appTree.files).toContain('/src/app/blog/blog.component.spec.ts'); + expect(appTree.files).toContain('/src/app/blog/blog.component.ts'); + expect(appTree.files).toContain('/src/app/blog/blog.module.ts'); + }); }); }); diff --git a/schematics/scully/src/utils/test-utils.ts b/schematics/scully/src/utils/test-utils.ts index 5565b88a4..99fce378f 100644 --- a/schematics/scully/src/utils/test-utils.ts +++ b/schematics/scully/src/utils/test-utils.ts @@ -16,6 +16,7 @@ export async function setupProject(tree: UnitTestTree, schematicRunner: Schemati { name, projectRoot: '', + routing: true, }, tree ) diff --git a/schematics/scully/src/utils/utils.ts b/schematics/scully/src/utils/utils.ts index ffccd0a5a..612d27c1b 100644 --- a/schematics/scully/src/utils/utils.ts +++ b/schematics/scully/src/utils/utils.ts @@ -39,7 +39,7 @@ export interface PackageJsonConfigPart { } export function addRouteToScullyConfig(scullyConfigJs: string, data: Data) { - const baseRoute = data.route ? strings.dasherize(data.route) : strings.dasherize(data.name); + const baseRoute = data.route ? strings.dasherize(data.route) : `/${strings.dasherize(data.name)}/`; const contentDirectoy = data.sourceDir ? strings.dasherize(data.sourceDir) : strings.dasherize(data.name); const addRoute = `\n '${baseRoute}:${data.slug}': { type: '${data.type}', From 868e7f6d6f6f6cad852be45811f5e233024b4f0e Mon Sep 17 00:00:00 2001 From: Danny Koppenhagen Date: Fri, 10 Jan 2020 22:52:12 +0100 Subject: [PATCH 11/27] refactor(scully): use normalized paths --- schematics/scully/src/utils/utils.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/schematics/scully/src/utils/utils.ts b/schematics/scully/src/utils/utils.ts index 612d27c1b..46229c53e 100644 --- a/schematics/scully/src/utils/utils.ts +++ b/schematics/scully/src/utils/utils.ts @@ -39,12 +39,13 @@ export interface PackageJsonConfigPart { } export function addRouteToScullyConfig(scullyConfigJs: string, data: Data) { - const baseRoute = data.route ? strings.dasherize(data.route) : `/${strings.dasherize(data.name)}/`; + const baseRoute = data.route ? strings.dasherize(data.route) : strings.dasherize(data.name); + const completeRoute = normalize(`/${baseRoute}/:${data.slug}`); const contentDirectoy = data.sourceDir ? strings.dasherize(data.sourceDir) : strings.dasherize(data.name); - const addRoute = `\n '${baseRoute}:${data.slug}': { + const addRoute = `\n '${completeRoute}': { type: '${data.type}', ${data.slug}: { - folder: "./${contentDirectoy}" + folder: ".${normalize('/' + contentDirectoy)}" } },`; let output; From f7d49a288d02112bb0f4758b4360bca8449e0729 Mon Sep 17 00:00:00 2001 From: Danny Koppenhagen Date: Fri, 10 Jan 2020 23:15:45 +0100 Subject: [PATCH 12/27] fix(scully): use correct dasherized module path --- schematics/scully/src/utils/utils.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/schematics/scully/src/utils/utils.ts b/schematics/scully/src/utils/utils.ts index 46229c53e..15962accb 100644 --- a/schematics/scully/src/utils/utils.ts +++ b/schematics/scully/src/utils/utils.ts @@ -145,8 +145,8 @@ function buildRoute(options: ModuleOptions, modulePath: string, route?: string) } function buildRelativeModulePath(options: ModuleOptions, modulePath: string): string { - // tslint:disable-next-line:no-shadowed-variable - const importModulePath = normalize(`/${options.name}/` + strings.dasherize(options.name) + '.module'); + const dasherized = strings.dasherize(options.name); + const importModulePath = normalize(`/${dasherized}/${dasherized}.module`); return buildRelativePath(modulePath, importModulePath); } From e6892428b1e7222d434e7efec0ea3e86c119b13b Mon Sep 17 00:00:00 2001 From: Danny Koppenhagen Date: Fri, 10 Jan 2020 23:16:15 +0100 Subject: [PATCH 13/27] test(scully): add more tests for markdown schematic --- .../scully/src/create-markdown/index_spec.ts | 120 +++++++++++++++++- 1 file changed, 119 insertions(+), 1 deletion(-) diff --git a/schematics/scully/src/create-markdown/index_spec.ts b/schematics/scully/src/create-markdown/index_spec.ts index d1ebb6eac..18a4a1649 100644 --- a/schematics/scully/src/create-markdown/index_spec.ts +++ b/schematics/scully/src/create-markdown/index_spec.ts @@ -35,7 +35,6 @@ describe('create-markdown', () => { beforeEach(async () => { appTree = await schematicRunner.runSchematicAsync('md', defaultOptions, appTree).toPromise(); }); - it('should create the markdown file by calling the post schematic', () => { const dayString = new Date().toISOString().substring(0, 10); expect( @@ -71,5 +70,124 @@ describe('create-markdown', () => { expect(appTree.files).toContain('/src/app/blog/blog.component.ts'); expect(appTree.files).toContain('/src/app/blog/blog.module.ts'); }); + it('should adjust the AppRoutingModule', () => { + const appRoutingModuleContent = getFileContent(appTree, '/src/app/app-routing.module.ts'); + expect(appRoutingModuleContent).toMatch( + /{*.path:\ 'blog', loadChildren:\ \(\) => import\('.\/blog\/blog.module'\).then\(m\ =>\ m\.BlogModule\)\ \}/g + ); + }); + }); + + describe('when using a default specific `route`', () => { + beforeEach(async () => { + appTree = await schematicRunner + .runSchematicAsync('md', {...defaultOptions, sourceDir: 'foo'}, appTree) + .toPromise(); + }); + it('should create the markdown file by calling the post schematic', () => { + const dayString = new Date().toISOString().substring(0, 10); + expect( + schematicRunner.tasks.some( + task => + task.name === 'run-schematic' && + (task.options as any).name === 'post' && + (task.options as any).options.name === `${dayString}-blog` && + (task.options as any).options.target === 'foo' + ) + ).toBe(true); + }); + it(`should update the file ${SCULLY_CONF_FILE}`, () => { + expect(appTree.files).toContain(SCULLY_CONF_FILE); + const scullyConfigFileContent = getFileContent(appTree, SCULLY_CONF_FILE); + expect(scullyConfigFileContent).toEqual(`exports.config = { + projectRoot: "./src/app", + routes: { + '/blog/:id': { + type: 'contentFolder', + id: { + folder: "./foo" + } + }, + }, +};`); + }); + }); + + describe('when using a default specific `sourceDir`', () => { + beforeEach(async () => { + appTree = await schematicRunner + .runSchematicAsync('md', {...defaultOptions, route: 'bar'}, appTree) + .toPromise(); + }); + it(`should update the file ${SCULLY_CONF_FILE}`, () => { + expect(appTree.files).toContain(SCULLY_CONF_FILE); + const scullyConfigFileContent = getFileContent(appTree, SCULLY_CONF_FILE); + expect(scullyConfigFileContent).toEqual(`exports.config = { + projectRoot: "./src/app", + routes: { + '/bar/:id': { + type: 'contentFolder', + id: { + folder: "./blog" + } + }, + }, +};`); + }); + it(`should setup a new angular module from template`, () => { + const appRoutingModuleContent = getFileContent(appTree, '/src/app/app-routing.module.ts'); + expect(appRoutingModuleContent).toMatch( + /{*.path:\ 'bar', loadChildren:\ \(\) => import\('.\/blog\/blog.module'\).then\(m\ =>\ m\.BlogModule\)\ \}/g + ); + }); + }); + + describe('when using a specific module name', () => { + beforeEach(async () => { + appTree = await schematicRunner + .runSchematicAsync('md', {...defaultOptions, name: 'fooBar Baz'}, appTree) + .toPromise(); + }); + it('should create the markdown file by calling the post schematic', () => { + const dayString = new Date().toISOString().substring(0, 10); + expect( + schematicRunner.tasks.some( + task => + task.name === 'run-schematic' && + (task.options as any).name === 'post' && + (task.options as any).options.name === `${dayString}-foo-bar-baz` && + (task.options as any).options.target === 'foo-bar-baz' + ) + ).toBe(true); + }); + it(`should update the file ${SCULLY_CONF_FILE}`, () => { + expect(appTree.files).toContain(SCULLY_CONF_FILE); + const scullyConfigFileContent = getFileContent(appTree, SCULLY_CONF_FILE); + expect(scullyConfigFileContent).toEqual(`exports.config = { + projectRoot: "./src/app", + routes: { + '/foo-bar-baz/:id': { + type: 'contentFolder', + id: { + folder: "./foo-bar-baz" + } + }, + }, +};`); + }); + it(`should setup a new angular module from template`, () => { + expect(appTree.files).toContain('/src/app/foo-bar-baz/foo-bar-baz-routing.module.ts'); + expect(appTree.files).toContain('/src/app/foo-bar-baz/foo-bar-baz.component.css'); + expect(appTree.files).toContain('/src/app/foo-bar-baz/foo-bar-baz.component.html'); + expect(appTree.files).toContain('/src/app/foo-bar-baz/foo-bar-baz.component.spec.ts'); + expect(appTree.files).toContain('/src/app/foo-bar-baz/foo-bar-baz.component.ts'); + expect(appTree.files).toContain('/src/app/foo-bar-baz/foo-bar-baz.module.ts'); + }); + it('should adjust the AppRoutingModule', () => { + const appRoutingModuleContent = getFileContent(appTree, '/src/app/app-routing.module.ts'); + expect(appRoutingModuleContent).toMatch( + /{*.path:\ 'foo-bar-baz', loadChildren:\ \(\) => import\('.\/foo-bar-baz\/foo-bar-baz.module'\).then\(m\ =>\ m\.FooBarBazModule\)\ \}/g + ); + }); }); }); From cf0ea450d1c9c4a3f94eeb9138e27269c542f41c Mon Sep 17 00:00:00 2001 From: Danny Koppenhagen Date: Sat, 11 Jan 2020 09:48:26 +0100 Subject: [PATCH 14/27] refactor(scully): camelize slug and use correct defaults --- .../scully/src/create-markdown/index.ts | 27 ++++++------ .../scully/src/create-markdown/index_spec.ts | 42 ++++++++++++++++++- ...ame@dasherize__-routing.module.ts.template | 2 +- schematics/scully/src/utils/utils.ts | 4 +- 4 files changed, 56 insertions(+), 19 deletions(-) diff --git a/schematics/scully/src/create-markdown/index.ts b/schematics/scully/src/create-markdown/index.ts index 87377691e..adebd2e0b 100644 --- a/schematics/scully/src/create-markdown/index.ts +++ b/schematics/scully/src/create-markdown/index.ts @@ -16,17 +16,18 @@ const SCULLY_CONF_FILE = '/scully.config.js'; const ANGULAR_CONF_FILE = './angular.json'; export default (options: Schema): Rule => { - const name = options.name ? options.name : 'blog'; - const targetDirName = options.sourceDir ? options.sourceDir : name; + options.name = options.name || 'blog'; + options.slug = options.slug || 'id'; + options.sourceDir = options.sourceDir || options.name; return chain([ - addPost(name, targetDirName), - updateScullyConfig(name, targetDirName, options), - addModule(name, options), + addPost(options, options.sourceDir), + updateScullyConfig(options.sourceDir, options), + addModule(options), ]); }; -const addPost = (name: string, target: string) => (tree: Tree, context: SchematicContext) => { - const nameDasherized = strings.dasherize(name); +const addPost = (options: Schema, target: string) => (tree: Tree, context: SchematicContext) => { + const nameDasherized = strings.dasherize(options.name); const targetDirName = strings.dasherize(target); const date = new Date(); // format yyyy-mm-dd @@ -41,16 +42,13 @@ const addPost = (name: string, target: string) => (tree: Tree, context: Schemati } }; -const updateScullyConfig = (name: string, target: string, options: Schema) => ( - tree: Tree, - context: SchematicContext -) => { +const updateScullyConfig = (target: string, options: Schema) => (tree: Tree, context: SchematicContext) => { const scullyJs = getFileContents(tree, SCULLY_CONF_FILE); if (!scullyJs) { context.logger.error(`No scully configuration file found ${SCULLY_CONF_FILE}`); } const newScullyJs = addRouteToScullyConfig(scullyJs, { - name, + name: options.name, slug: options.slug, type: 'contentFolder', sourceDir: target, @@ -61,9 +59,9 @@ const updateScullyConfig = (name: string, target: string, options: Schema) => ( context.logger.info(`✅️ Update ${SCULLY_CONF_FILE}`); }; -const addModule = (name: string, options: Schema) => (tree: Tree, context: SchematicContext) => { +const addModule = (options: Schema) => (tree: Tree, context: SchematicContext) => { const sourceDir = getSrc(tree); - const pathName = strings.dasherize(`${sourceDir}/app/${name}`); + const pathName = strings.dasherize(`${sourceDir}/app/${options.name}`); let prefix = 'app'; if (tree.exists(ANGULAR_CONF_FILE)) { prefix = getPrefix(getFileContents(tree, ANGULAR_CONF_FILE)); @@ -74,6 +72,7 @@ const addModule = (name: string, options: Schema) => (tree: Tree, context: Schem applyTemplates({ classify: strings.classify, dasherize: strings.dasherize, + camelize: strings.camelize, name: options.name, slug: options.slug, prefix, diff --git a/schematics/scully/src/create-markdown/index_spec.ts b/schematics/scully/src/create-markdown/index_spec.ts index 18a4a1649..fe4d14e4e 100644 --- a/schematics/scully/src/create-markdown/index_spec.ts +++ b/schematics/scully/src/create-markdown/index_spec.ts @@ -13,8 +13,8 @@ describe('create-markdown', () => { const schematicRunner = new SchematicTestRunner('scully-schematics', collectionPath); const project = 'foo'; const defaultOptions: Schema = { - name: 'blog', - slug: 'id', + name: '', + slug: '', }; let appTree: UnitTestTree; @@ -78,6 +78,35 @@ describe('create-markdown', () => { }); }); + describe('when using a specific `slug`', () => { + beforeEach(async () => { + appTree = await schematicRunner + .runSchematicAsync('md', {...defaultOptions, slug: 'FooBar Baz'}, appTree) + .toPromise(); + }); + it(`should update the file ${SCULLY_CONF_FILE} and `, () => { + expect(appTree.files).toContain(SCULLY_CONF_FILE); + const scullyConfigFileContent = getFileContent(appTree, SCULLY_CONF_FILE); + expect(scullyConfigFileContent).toEqual(`exports.config = { + projectRoot: "./src/app", + routes: { + '/blog/:fooBarBaz': { + type: 'contentFolder', + fooBarBaz: { + folder: "./blog" + } + }, + }, +};`); + }); + it('should use the camelized slug router param', () => { + const appRoutingModuleContent = getFileContent(appTree, '/src/app/blog/blog-routing.module.ts'); + expect(appRoutingModuleContent).toMatch( + /const\ routes:\ Routes\ =\ \[\s+\{\s+path\:\ ':fooBarBaz',\s+component:\ BlogComponent,\s+\}\s+\];/s + ); + }); + }); + describe('when using a default specific `route`', () => { beforeEach(async () => { appTree = await schematicRunner @@ -189,5 +218,14 @@ describe('create-markdown', () => { /{*.path:\ 'foo-bar-baz', loadChildren:\ \(\) => import\('.\/foo-bar-baz\/foo-bar-baz.module'\).then\(m\ =>\ m\.FooBarBazModule\)\ \}/g ); }); + it('should use the camelized slug router param', () => { + const appRoutingModuleContent = getFileContent( + appTree, + '/src/app/foo-bar-baz/foo-bar-baz-routing.module.ts' + ); + expect(appRoutingModuleContent).toMatch( + /const\ routes:\ Routes\ =\ \[\s+\{\s+path\:\ ':id',\s+component:\ FooBarBazComponent,\s+\}\s+\];/s + ); + }); }); }); diff --git a/schematics/scully/src/files/markdown-module/__name@dasherize__-routing.module.ts.template b/schematics/scully/src/files/markdown-module/__name@dasherize__-routing.module.ts.template index d3e028634..b89a93b4e 100644 --- a/schematics/scully/src/files/markdown-module/__name@dasherize__-routing.module.ts.template +++ b/schematics/scully/src/files/markdown-module/__name@dasherize__-routing.module.ts.template @@ -5,7 +5,7 @@ import {<%= classify(name) %>Component} from './<%= dasherize(name) %>.component const routes: Routes = [ { - path: ':<%= slug %>', + path: ':<%= camelize(slug) %>', component: <%= classify(name) %>Component, } ]; diff --git a/schematics/scully/src/utils/utils.ts b/schematics/scully/src/utils/utils.ts index 15962accb..377e991cb 100644 --- a/schematics/scully/src/utils/utils.ts +++ b/schematics/scully/src/utils/utils.ts @@ -40,11 +40,11 @@ export interface PackageJsonConfigPart { export function addRouteToScullyConfig(scullyConfigJs: string, data: Data) { const baseRoute = data.route ? strings.dasherize(data.route) : strings.dasherize(data.name); - const completeRoute = normalize(`/${baseRoute}/:${data.slug}`); + const completeRoute = normalize(`/${baseRoute}/:${strings.camelize(data.slug)}`); const contentDirectoy = data.sourceDir ? strings.dasherize(data.sourceDir) : strings.dasherize(data.name); const addRoute = `\n '${completeRoute}': { type: '${data.type}', - ${data.slug}: { + ${strings.camelize(data.slug)}: { folder: ".${normalize('/' + contentDirectoy)}" } },`; From 7caeed06c7630546948615d977598deb44cc46ad Mon Sep 17 00:00:00 2001 From: Danny Koppenhagen Date: Sun, 12 Jan 2020 09:02:16 +0100 Subject: [PATCH 15/27] fix(scully): remove unused title prop from schema --- schematics/scully/src/ng-add/schema.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/schematics/scully/src/ng-add/schema.ts b/schematics/scully/src/ng-add/schema.ts index 0a23ca6a7..c3fa12680 100644 --- a/schematics/scully/src/ng-add/schema.ts +++ b/schematics/scully/src/ng-add/schema.ts @@ -1,4 +1,3 @@ export interface Schema { blog: boolean; - title?: string; } From c4a974988f500615980fafe469b7896635c2fe74 Mon Sep 17 00:00:00 2001 From: Danny Koppenhagen Date: Sun, 12 Jan 2020 09:03:36 +0100 Subject: [PATCH 16/27] refactor(scully): remove unused options from methods --- schematics/scully/src/ng-add/index.ts | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/schematics/scully/src/ng-add/index.ts b/schematics/scully/src/ng-add/index.ts index 80673d2a0..3d8b9cbcc 100644 --- a/schematics/scully/src/ng-add/index.ts +++ b/schematics/scully/src/ng-add/index.ts @@ -10,17 +10,17 @@ import * as ts from '@schematics/angular/third_party/github.com/Microsoft/TypeSc export default (options: Schema): Rule => { return chain([ - addDependencies(options), - importHttpClientModule(options), - addHttpClientModule(options), - addPolyfill(options), - injectIdleService(options), + addDependencies(), + importHttpClientModule(), + addHttpClientModule(), + addPolyfill(), + injectIdleService(), runBlogSchematic(options), runScullySchematic(options), ]); }; -const addDependencies = (options: Schema) => (tree: Tree, context: SchematicContext) => { +const addDependencies = () => (tree: Tree, context: SchematicContext) => { addPackageToPackageJson(tree, '@scullyio/scully', `${scullyVersion}`); const ngCoreVersionTag = getPackageVersionFromPackageJson(tree, '@angular/core'); if (+ngCoreVersionTag.search(/(\^8|~8)/g) === 0) { @@ -33,7 +33,7 @@ const addDependencies = (options: Schema) => (tree: Tree, context: SchematicCont context.logger.info('✅️ Added dependency'); }; -const importHttpClientModule = (options: Schema) => (tree: Tree, context: SchematicContext) => { +const importHttpClientModule = () => (tree: Tree, context: SchematicContext) => { try { const mainFilePath = `./${getSrc(tree)}/app/app.module.ts`; const recorder = tree.beginUpdate(mainFilePath); @@ -55,7 +55,7 @@ const importHttpClientModule = (options: Schema) => (tree: Tree, context: Schema } }; -const addHttpClientModule = (options: Schema) => (tree: Tree, context: SchematicContext) => { +const addHttpClientModule = () => (tree: Tree, context: SchematicContext) => { const mainFilePath = `./${getSrc(tree)}/app/app.module.ts`; const text = tree.read(mainFilePath); if (text === null) { @@ -74,7 +74,7 @@ const addHttpClientModule = (options: Schema) => (tree: Tree, context: Schematic return tree; }; -const addPolyfill = (options: Schema) => (tree: Tree, context: SchematicContext) => { +const addPolyfill = () => (tree: Tree, context: SchematicContext) => { let polyfills = tree.read(`${getSrc(tree)}/polyfills.ts`).toString(); if (polyfills.includes('SCULLY IMPORTS')) { context.logger.info('⚠️ Skipping polyfills.ts'); @@ -90,7 +90,7 @@ import 'zone.js/dist/task-tracking';`; } }; -const injectIdleService = (options: Schema) => (tree: Tree, context: SchematicContext) => { +const injectIdleService = () => (tree: Tree, context: SchematicContext) => { try { const appComponentPath = `${getSrc(tree)}/app/app.component.ts`; const appComponent = tree.read(appComponentPath).toString(); From 440f33f1d05e0f0cd0f78a31484eddadc681b331 Mon Sep 17 00:00:00 2001 From: Danny Koppenhagen Date: Sun, 12 Jan 2020 15:24:39 +0100 Subject: [PATCH 17/27] fix(scully): set correct defaults calling other schematic --- schematics/scully/src/add-blog/index.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/schematics/scully/src/add-blog/index.ts b/schematics/scully/src/add-blog/index.ts index b8da109f8..af05c9d5e 100644 --- a/schematics/scully/src/add-blog/index.ts +++ b/schematics/scully/src/add-blog/index.ts @@ -8,6 +8,8 @@ export default function(options: Schema): Rule { const makrdownOptions: MarkownSchema = { name: 'blog', slug: 'slug', + sourceDir: 'blog', + route: 'blog', }; if (options.routingScope) { From c393424ac9bf7ebb476e12ced1e7b315c1a5086d Mon Sep 17 00:00:00 2001 From: Danny Koppenhagen Date: Sun, 12 Jan 2020 15:29:27 +0100 Subject: [PATCH 18/27] test(scully): update test for blog schematic --- schematics/scully/scullyio-init-0.0.16.tgz | Bin 0 -> 28501 bytes schematics/scully/src/add-blog/index_spec.ts | 2 ++ 2 files changed, 2 insertions(+) create mode 100644 schematics/scully/scullyio-init-0.0.16.tgz diff --git a/schematics/scully/scullyio-init-0.0.16.tgz b/schematics/scully/scullyio-init-0.0.16.tgz new file mode 100644 index 0000000000000000000000000000000000000000..afadf477652c8a649b53aa0264e053d05774a5f4 GIT binary patch literal 28501 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 { task.name === 'run-schematic' && (task.options as any).name === 'create-markdown' && (task.options as any).options.name === 'blog' && + (task.options as any).options.sourceDir === 'blog' && + (task.options as any).options.route === 'blog' && (task.options as any).options.slug === 'slug' ) ).toBe(true); From a7969b1bf169aee1055a67ad8843c7f8869e5f57 Mon Sep 17 00:00:00 2001 From: Danny Koppenhagen Date: Sun, 12 Jan 2020 17:07:39 +0100 Subject: [PATCH 19/27] test(scully): test blog schematic with specific routingScope --- schematics/scully/src/add-blog/index_spec.ts | 25 +++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/schematics/scully/src/add-blog/index_spec.ts b/schematics/scully/src/add-blog/index_spec.ts index 6ca8fa1a6..67afdbf98 100644 --- a/schematics/scully/src/add-blog/index_spec.ts +++ b/schematics/scully/src/add-blog/index_spec.ts @@ -23,7 +23,7 @@ describe('add-blog schematic', () => { appTree = await schematicRunner.runSchematicAsync('blog', defaultOptions, appTree).toPromise(); }); - it('should have run the markdown schematic', () => { + it('should have run the markdown schematic with default options', () => { expect( schematicRunner.tasks.some( task => @@ -37,4 +37,27 @@ describe('add-blog schematic', () => { ).toBe(true); }); }); + + describe('when setting an explicit `routingScope`', () => { + beforeEach(async () => { + appTree = await schematicRunner + .runSchematicAsync('blog', {...defaultOptions, routingScope: 'Root'}, appTree) + .toPromise(); + }); + + it('should have run the markdown schematic with defaults and `routingScope`', () => { + expect( + schematicRunner.tasks.some( + task => + task.name === 'run-schematic' && + (task.options as any).name === 'create-markdown' && + (task.options as any).options.name === 'blog' && + (task.options as any).options.sourceDir === 'blog' && + (task.options as any).options.route === 'blog' && + (task.options as any).options.slug === 'slug' && + (task.options as any).options.routingScope === 'Root' + ) + ).toBe(true); + }); + }); }); From 5cd6481e06dd43f1bd266b5b8f7e9fd8b61b2d8c Mon Sep 17 00:00:00 2001 From: Danny Koppenhagen Date: Sun, 12 Jan 2020 17:28:26 +0100 Subject: [PATCH 20/27] test(scully): verify existing post won't be overridden --- schematics/scully/src/add-post/index_spec.ts | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/schematics/scully/src/add-post/index_spec.ts b/schematics/scully/src/add-post/index_spec.ts index 172fed362..76e949335 100644 --- a/schematics/scully/src/add-post/index_spec.ts +++ b/schematics/scully/src/add-post/index_spec.ts @@ -72,4 +72,19 @@ describe('add-post', () => { expect(mdFileContent).toMatch(/language: en/g); }); }); + + describe('when target file already exists', () => { + beforeEach(() => { + appTree.create(expectedFileName, 'foo'); + }); + + it('should not touch existing file', async () => { + try { + await schematicRunner.runSchematicAsync('post', defaultOptions, appTree).toPromise(); + } catch (e) { + expect(e).toMatch(/Error: foo-bar-baz exist/g); + } + expect(getFileContent(appTree, expectedFileName)).toEqual('foo'); + }); + }); }); From e56b6e14cddc49166a1b3e666320c22751c35779 Mon Sep 17 00:00:00 2001 From: Danny Koppenhagen Date: Sun, 12 Jan 2020 17:33:18 +0100 Subject: [PATCH 21/27] test(scully): verify blog schematic is not called ...when disabling it via options --- schematics/scully/src/ng-add/index_spec.ts | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/schematics/scully/src/ng-add/index_spec.ts b/schematics/scully/src/ng-add/index_spec.ts index c9660d93b..cdffbc359 100644 --- a/schematics/scully/src/ng-add/index_spec.ts +++ b/schematics/scully/src/ng-add/index_spec.ts @@ -80,4 +80,14 @@ describe('ng-add schematic', () => { ).toBe(true); }); }); + + describe('when not setting `blog` option to true', () => { + beforeEach(async () => { + appTree = await schematicRunner.runSchematicAsync('ng-add', {blog: false}, appTree).toPromise(); + }); + + it('should not have run the blog schematic', () => { + expect(schematicRunner.tasks.some(task => (task.options as any).name === 'blog')).toBe(false); + }); + }); }); From d0fc7ab8e407e55752e50363298d7a0c5c40d1a1 Mon Sep 17 00:00:00 2001 From: Danny Koppenhagen Date: Sun, 12 Jan 2020 17:37:22 +0100 Subject: [PATCH 22/27] fix(scully): set correct projectRoot src path ...and test it --- schematics/scully/src/scully/index.ts | 2 +- schematics/scully/src/scully/index_spec.ts | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/schematics/scully/src/scully/index.ts b/schematics/scully/src/scully/index.ts index 7d47f158a..4d2ba333a 100644 --- a/schematics/scully/src/scully/index.ts +++ b/schematics/scully/src/scully/index.ts @@ -28,7 +28,7 @@ const createScullyConfig = () => (tree: Tree, context: SchematicContext) => { tree.create( SCULLY_CONFIG_FILE, `exports.config = { - projectRoot: "${srcFolder}/app", + projectRoot: "./${srcFolder}/app", outFolder: './dist/static', routes: { } diff --git a/schematics/scully/src/scully/index_spec.ts b/schematics/scully/src/scully/index_spec.ts index 389e945ab..41c7e8530 100644 --- a/schematics/scully/src/scully/index_spec.ts +++ b/schematics/scully/src/scully/index_spec.ts @@ -27,6 +27,12 @@ describe('scully schematic', () => { it('should create the scully config file when not exists', () => { expect(appTree.files).toContain(SCULLY_PATH); + const scullyConfFile = getFileContent(appTree, SCULLY_PATH); + expect(scullyConfFile).toEqual(`exports.config = { + projectRoot: "./src/app", + routes: { + } +};`); }); it(`should modify the 'package.json'`, () => { From 0402a3c75572def9efeeefceab4debf9c42e3076 Mon Sep 17 00:00:00 2001 From: Danny Koppenhagen Date: Sun, 12 Jan 2020 17:45:46 +0100 Subject: [PATCH 23/27] test(scully): test fail when no angular.json --- schematics/scully/src/scully/index_spec.ts | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/schematics/scully/src/scully/index_spec.ts b/schematics/scully/src/scully/index_spec.ts index 41c7e8530..51f3f1ce9 100644 --- a/schematics/scully/src/scully/index_spec.ts +++ b/schematics/scully/src/scully/index_spec.ts @@ -20,6 +20,19 @@ describe('scully schematic', () => { appTree = await setupProject(appTree, schematicRunner, project); }); + describe('when not in a valid angular workspace', () => { + it('should thow an exception', async () => { + let error = ''; + appTree.delete('angular.json'); + try { + await schematicRunner.runSchematicAsync('scully', defaultOptions, appTree).toPromise(); + } catch (e) { + error = e; + } + expect(error).toMatch(/Not an angular CLI workspace/g); + }); + }); + describe('when using the default options', () => { beforeEach(async () => { appTree = await schematicRunner.runSchematicAsync('scully', defaultOptions, appTree).toPromise(); From 4afccb2f141c03b71961fd7f13bd01e02cad1016 Mon Sep 17 00:00:00 2001 From: Danny Koppenhagen Date: Sun, 12 Jan 2020 17:46:55 +0100 Subject: [PATCH 24/27] test(scully): fix error check in test --- schematics/scully/src/add-post/index_spec.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/schematics/scully/src/add-post/index_spec.ts b/schematics/scully/src/add-post/index_spec.ts index 76e949335..e60cf2f9a 100644 --- a/schematics/scully/src/add-post/index_spec.ts +++ b/schematics/scully/src/add-post/index_spec.ts @@ -79,11 +79,13 @@ describe('add-post', () => { }); it('should not touch existing file', async () => { + let error = ''; try { await schematicRunner.runSchematicAsync('post', defaultOptions, appTree).toPromise(); } catch (e) { - expect(e).toMatch(/Error: foo-bar-baz exist/g); + error = e; } + expect(error).toMatch(/Error: foo-bar-baz exist/g); expect(getFileContent(appTree, expectedFileName)).toEqual('foo'); }); }); From 3a9b5f670763e6510830aa6f4d3ae0afd9a8df61 Mon Sep 17 00:00:00 2001 From: Danny Koppenhagen Date: Sun, 12 Jan 2020 17:54:54 +0100 Subject: [PATCH 25/27] test(scully): add test when appModule not exists --- schematics/scully/src/ng-add/index_spec.ts | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/schematics/scully/src/ng-add/index_spec.ts b/schematics/scully/src/ng-add/index_spec.ts index cdffbc359..fa8374c69 100644 --- a/schematics/scully/src/ng-add/index_spec.ts +++ b/schematics/scully/src/ng-add/index_spec.ts @@ -90,4 +90,17 @@ describe('ng-add schematic', () => { expect(schematicRunner.tasks.some(task => (task.options as any).name === 'blog')).toBe(false); }); }); + + describe('when AppModule not exists', () => { + it('should not have run the blog schematic', async () => { + appTree.delete('/src/app/app.module.ts'); + let error = ''; + try { + await schematicRunner.runSchematicAsync('ng-add', defaultOptions, appTree).toPromise(); + } catch (e) { + error = e; + } + expect(error).toMatch(/File \.\/src\/app\/app\.module\.ts does not exist./g); + }); + }); }); From aa2455c5bc29eb5fe9fb6437d90ac11ba525da9e Mon Sep 17 00:00:00 2001 From: Danny Koppenhagen Date: Wed, 15 Jan 2020 17:49:29 +0100 Subject: [PATCH 26/27] feat(scully): remove blog promt for ng-add --- schematics/scully/src/ng-add/schema.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/schematics/scully/src/ng-add/schema.json b/schematics/scully/src/ng-add/schema.json index f70f2cac7..5498c4132 100644 --- a/schematics/scully/src/ng-add/schema.json +++ b/schematics/scully/src/ng-add/schema.json @@ -7,7 +7,7 @@ "blog": { "type": "boolean", "description": "add full blog", - "x-prompt": "Should we set up a blog for you?" + "default": false } }, "required": [] From 11dd01ad63d5072535ef986f85a63f01039c3945 Mon Sep 17 00:00:00 2001 From: Danny Koppenhagen Date: Wed, 15 Jan 2020 18:13:30 +0100 Subject: [PATCH 27/27] test(scully): fix test after merge --- schematics/scully/src/scully/index_spec.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/schematics/scully/src/scully/index_spec.ts b/schematics/scully/src/scully/index_spec.ts index 51f3f1ce9..87470827e 100644 --- a/schematics/scully/src/scully/index_spec.ts +++ b/schematics/scully/src/scully/index_spec.ts @@ -43,6 +43,7 @@ describe('scully schematic', () => { const scullyConfFile = getFileContent(appTree, SCULLY_PATH); expect(scullyConfFile).toEqual(`exports.config = { projectRoot: "./src/app", + outFolder: './dist/static', routes: { } };`);