Skip to content

Commit

Permalink
fix: create separate command for Ionic apps (#23)
Browse files Browse the repository at this point in the history
* fix: create separate command for Ionic apps

* fix: apply review comment fixes

* fix: remove info more appropriate for the release notes
  • Loading branch information
mwislek authored Dec 3, 2021
1 parent 846df0b commit 416df4c
Show file tree
Hide file tree
Showing 6 changed files with 138 additions and 78 deletions.
7 changes: 7 additions & 0 deletions MIGRATION.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Migration Guide

## Migration to Version ^7.0.0
Version 7 of the lp-subsection-generator introduced the following changes that may break existing usage of this command:
1. Version 7 of the lp-subsection-generator requires that a Node version >= Node 12 be installed.
1. The lp-subsection-generator argument `subsection-name` is now required. Previously, this argument was optional and would default to `sub-section`.

31 changes: 27 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,22 +1,45 @@
# lp-subsection-generator

Generate subsections for react-redux apps.
Generate subsections for react-redux and Ionic apps.
Each subsection will contain components, forms, views and routes (see template folder for details).

Remember to include your generated subsection in your top-level reducer and routes files!

## Usage
See the [Migration Guide](./MIGRATION.md) for information on migrating between lp-subsection-generator versions.

## Prerequisites
The following programs are required in order to run the subsection generator:
+ Node: `>= 12`
+ Download/upgrade using [nvm](https://github.com/nvm-sh/nvm)
+ Yarn: `^1.0.0`
+ Download via [homebrew](https://yarnpkg.com/en/docs/install)

## Client Template Usage

You can run the `generate-subsection` command using `yarn`:
```
> yarn generate-subsection [options] [subsection-name] [destination]
```

### Arguments
- `subsection-name`: the name of the subsection (optional, defaults to 'sub-section').
- `subsection-name`: the name of the subsection (required).
- `destination`: the relative path to the directory where you'd like the subsection to be generated (optional, defaults to `./src/js/main/`).

### Options
- `-V, --version`: the version number this utility
- `-h, --help`: display help for command

## Ionic Client Template Usage

You can run the `generate-ionic-subsection` command using `yarn`:
```
> yarn generate-ionic-subsection [options] [subsection-name] [destination]
```

### Arguments
- `subsection-name`: the name of the subsection (required).
- `destination`: the relative path to the directory where you'd like the subsection to be generated (optional, defaults to `./src/js/main/`).

### Options
- `-V, --version`: the version number this utility
- `-t, --template-type <client | ionic>`: the subsection template type (default: "client")
- `-h, --help`: display help for command
23 changes: 23 additions & 0 deletions generate-ionic-subsection.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#!/usr/bin/env node
/* eslint-disable no-console */

const { Command } = require('commander')
const generate = require('./generate')

function main () {
const program = new Command

program
.description('generate an Ionic project subsection')
.showHelpAfterError()
.version(require('./package.json').version)
.argument('<subsection-name>', 'name of the subsection')
.argument('[destination]', 'optional project destination path', './src/js/main')
.action((subsectionName, destination) => {
generate(subsectionName, destination, "ionic")
})

program.parse()
}

if (!module.parent) main()
71 changes: 71 additions & 0 deletions generate.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
/* eslint-disable no-console */
const fs = require('fs-extra')
const glob = require('glob')
const path = require('path')
const pluralize = require('pluralize')
const { camelCase, kebabCase, flow, snakeCase, toUpper } = require('lodash')
const screamingSnakeCase = flow(snakeCase, toUpper)

function generate (subSectionName, destination, options) {
// Compute all casings
const singularName = pluralize.singular(subSectionName)
const camelCaseName = camelCase(singularName)
const kebabCaseName = kebabCase(singularName)
const pascalCaseName = pascalCase(singularName)
const screamingSnakeCaseName = screamingSnakeCase(singularName)
// Compute paths
const packagePath = getPackagePath()
const root = process.cwd()
const templatePath = templatePathFromTemplateType(options)
// GENERATE
console.log('Generating...')
// Copy files over
fs.copySync(path.resolve(packagePath, templatePath), path.resolve(packagePath, `./${ subSectionName }`))
// Replace template variables in files
const allFiles = glob.sync(path.resolve(packagePath, `./${ subSectionName }/**/*.js`))
allFiles.forEach(file => {
const template = fs.readFileSync(file, 'utf8')
const result = template
.replace(/%sub-section%/g, kebabCaseName)
.replace(/%subSection%/g, camelCaseName)
.replace(/%SubSection%/g, pascalCaseName)
.replace(/%SUB_SECTION%/g, screamingSnakeCaseName)
.replace(/%sub-sections%/g, pluralize(kebabCaseName))
.replace(/%subSections%/g, pluralize(camelCaseName))
.replace(/%SubSections%/g, pluralize(pascalCaseName))
.replace(/%SUB_SECTIONS%/g, pluralize(screamingSnakeCaseName))
return fs.writeFileSync(file, result)
})
// Rename view files
fs.renameSync(path.resolve(packagePath, `./${ subSectionName }/views/SubSections.js`), path.resolve(packagePath, `./${ subSectionName }/views/${ pluralize(pascalCaseName) }.js`))
fs.renameSync(path.resolve(packagePath, `./${ subSectionName }/views/SubSectionShow.js`), path.resolve(packagePath, `./${ subSectionName }/views/${ pascalCaseName }Show.js`))
// Move to final dest
fs.moveSync(path.resolve(packagePath, `./${ subSectionName }`), path.resolve(root, destination, subSectionName))
console.log('Done!')
}

module.exports = generate

function getPackagePath () {
try {
return path.resolve(require.resolve('@launchpadlab/lp-subsection-generator'), '../')
} catch (e) {
console.log('Path not found, running locally')
return __dirname
}
}

function pascalCase (str) {
const cased = camelCase(str)
return cased.charAt(0).toUpperCase() + cased.slice(1)
}

function templatePathFromTemplateType(templateType) {
switch(templateType) {
case "client": return './template'
case "ionic": return './ionic-template'

default:
throw new Error (`generate-subsection: [ERROR]: unknown template type [${templateType}]`)
}
}
77 changes: 5 additions & 72 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,86 +2,19 @@
/* eslint-disable no-console */

const { Command } = require('commander')
const fs = require('fs-extra')
const glob = require('glob')
const path = require('path')
const pluralize = require('pluralize')
const { camelCase, kebabCase, flow, snakeCase, toUpper } = require('lodash')
const screamingSnakeCase = flow(snakeCase, toUpper)

function generate (subSectionName, destination, options) {
// Compute all casings
const singularName = pluralize.singular(subSectionName)
const camelCaseName = camelCase(singularName)
const kebabCaseName = kebabCase(singularName)
const pascalCaseName = pascalCase(singularName)
const screamingSnakeCaseName = screamingSnakeCase(singularName)
// Compute paths
const packagePath = getPackagePath()
const root = process.cwd()
const templatePath = templatePathFromTemplateType(options.templateType)
// GENERATE
console.log('Generating...')
// Copy files over
fs.copySync(path.resolve(packagePath, templatePath), path.resolve(packagePath, `./${ subSectionName }`))
// Replace template variables in files
const allFiles = glob.sync(path.resolve(packagePath, `./${ subSectionName }/**/*.js`))
allFiles.forEach(file => {
const template = fs.readFileSync(file, 'utf8')
const result = template
.replace(/%sub-section%/g, kebabCaseName)
.replace(/%subSection%/g, camelCaseName)
.replace(/%SubSection%/g, pascalCaseName)
.replace(/%SUB_SECTION%/g, screamingSnakeCaseName)
.replace(/%sub-sections%/g, pluralize(kebabCaseName))
.replace(/%subSections%/g, pluralize(camelCaseName))
.replace(/%SubSections%/g, pluralize(pascalCaseName))
.replace(/%SUB_SECTIONS%/g, pluralize(screamingSnakeCaseName))
return fs.writeFileSync(file, result)
})
// Rename view files
fs.renameSync(path.resolve(packagePath, `./${ subSectionName }/views/SubSections.js`), path.resolve(packagePath, `./${ subSectionName }/views/${ pluralize(pascalCaseName) }.js`))
fs.renameSync(path.resolve(packagePath, `./${ subSectionName }/views/SubSectionShow.js`), path.resolve(packagePath, `./${ subSectionName }/views/${ pascalCaseName }Show.js`))
// Move to final dest
fs.moveSync(path.resolve(packagePath, `./${ subSectionName }`), path.resolve(root, destination, subSectionName))
console.log('Done!')
}

function getPackagePath () {
try {
return path.resolve(require.resolve('@launchpadlab/lp-subsection-generator'), '../')
} catch (e) {
console.log('Path not found, running locally')
return __dirname
}
}

function pascalCase (str) {
const cased = camelCase(str)
return cased.charAt(0).toUpperCase() + cased.slice(1)
}

function templatePathFromTemplateType(templateType) {
switch(templateType) {
case "client": return './template'
case "ionic": return './ionic-template'

default:
throw new Error (`generate-subsection: [ERROR]: unknown template type [${templateType}]`)
}
}
const generate = require('./generate')

function main () {
const program = new Command

program
.description('generate a project subsection')
.showHelpAfterError()
.version(require('./package.json').version)
.option('-t, --template-type <client | ionic>', 'subsection template type', 'client')
.argument('[subsection-name]', 'name of the subsection', 'sub-section')
.argument('<subsection-name>', 'name of the subsection')
.argument('[destination]', 'optional project destination path', './src/js/main')
.action((subsectionName, destination, options) => {
generate(subsectionName, destination, options)
.action((subsectionName, destination) => {
generate(subsectionName, destination, "client")
})

program.parse()
Expand Down
7 changes: 5 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
{
"name": "@launchpadlab/lp-subsection-generator",
"version": "6.1.0",
"version": "7.0.0",
"description": "",
"main": "index.js",
"engines": {
"node": ">= 12"
},
"scripts": {
"start": "node ./index.js",
"test": "echo \"Error: no test specified\" && exit 1",
"lint": "eslint index.js"
},
"bin": {
"generate-subsection": "./index.js",
"generate-ionic-subsection": "./index.js --template-type ionic"
"generate-ionic-subsection": "./generate-ionic-subsection.js"
},
"author": "dpikt",
"license": "ISC",
Expand Down

0 comments on commit 416df4c

Please sign in to comment.