JSPM

  • Created
  • Published
  • Downloads 2
  • Score
    100M100P100Q49186F
  • License MIT

CLI that kinda help with frontend development

Package Exports

  • template9

This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (template9) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.

Readme

template9

Gitter CLI tests npm version npm license

CLI that kinda help with frontend development

Table of Content

Installation

$ npm i -g template9

Commands

init

$ t9 init
    what is the name of the project? : string!
    what is the root of the project? : string = frontend
    use docker? : [ true, false ] = true
    install dependencies? : [ true, false ] = true
    add the first entry? : [ true, false ] = true
  if (add the first entry?) {
    what is the name of the entry? : string!
    What is the default language code for this entry? : string = en
  }

this will apply the following:

`C: ${root}/config/index.d.ts` // type def file
`C: ${root}/config/index.js` // global config
`C: ${root}/src/components` // frontend components
`C: ${root}/src/config/index.ts` // frontend config
`C: ${root}/src/entries` // the view layer (entry)
`C: ${root}/src/redux` // data layer
`C: ${root}/src/types/index.ts` // frontend types
`C: ${root}/src/types/template-types.ts` // a readonly frontend types related to template9
`C: ${root}/types/index.ts` // global types
`C: ${root}/.editorconfig` // conventional configs for the editor
`C: ${root}/.gitignore` // paths to be ignored by git
`C: ${root}/package.json` // the npm package manifest
`C: ${root}/t9config.json` // template9 config file
`C: ${root}/tsconfig.json` // typescript config file
`C: ${root}/tslint.json` // typescript linting config
`C: ${root}/webpack.config.js` // webpack config file

if (add the first entry) {
  `C: ${root}/src/entries/${firstEntry}/components` // entry components
  `C: ${root}/src/entries/${firstEntry}/config/default-language/dictionary.json` // dictionary file
  `C: ${root}/src/entries/${firstEntry}/config/default-language/index.d.ts` // type def file
  `C: ${root}/src/entries/${firstEntry}/config/default-language/index.js` // default language config for this entry
  `C: ${root}/src/entries/${firstEntry}/config/index.ts` // entry config index file
  `C: ${root}/src/entries/${firstEntry}/entry/dictionary-fallbacks.json`
  `C: ${root}/src/entries/${firstEntry}/entry/dictionary-overwrites.json`
  `C: ${root}/src/entries/${firstEntry}/entry/dictionary.json`
  `C: ${root}/src/entries/${firstEntry}/entry/dictionary.scss.json`
  `C: ${root}/src/entries/${firstEntry}/entry/index.tsx`
  `C: ${root}/src/entries/${firstEntry}/entry/style-initial.scss`
  `C: ${root}/src/entries/${firstEntry}/entry/style-overwrite.scss`
  `C: ${root}/src/entries/${firstEntry}/entry/style.scss`
  `C: ${root}/src/entries/${firstEntry}/scenes` // entry scenes
  `C: ${root}/src/entries/${firstEntry}/types/index.ts` // entry types
  `C: ${root}/src/redux/${firstEntry}/actions/index.ts` // redux actions
  `C: ${root}/src/redux/${firstEntry}/constants/index.ts` // redux constants
  `C: ${root}/src/redux/${firstEntry}/constants/reducers.ts` // redux reducers
  `C: ${root}/src/redux/${firstEntry}/index.ts` // redux store entry point
}

add entry

$ t9 add entry
    what is the name of the entry? : string!
    What is the default language code for this entry? : string = "en"

this will do the following:

`C: ${root}/src/entries/${entry}/components`
`C: ${root}/src/entries/${entry}/config/default-language/dictionary.json`
`C: ${root}/src/entries/${entry}/config/default-language/index.d.ts`
`C: ${root}/src/entries/${entry}/config/default-language/index.js`
`C: ${root}/src/entries/${entry}/config/index.ts`
`C: ${root}/src/entries/${entry}/entry/dictionary-fallbacks.json`
`C: ${root}/src/entries/${entry}/entry/dictionary-overwrites.json`
`C: ${root}/src/entries/${entry}/entry/dictionary.json`
`C: ${root}/src/entries/${entry}/entry/dictionary.scss.json`
`C: ${root}/src/entries/${entry}/entry/index.tsx`
`C: ${root}/src/entries/${entry}/entry/style-initial.scss`
`C: ${root}/src/entries/${entry}/entry/style-overwrite.scss`
`C: ${root}/src/entries/${entry}/entry/style.scss`
`C: ${root}/src/entries/${entry}/scenes`
`C: ${root}/src/entries/${entry}/types/index.ts`
`C: ${root}/src/redux/${entry}/actions/index.ts`
`C: ${root}/src/redux/${entry}/constants/index.ts`
`C: ${root}/src/redux/${entry}/constants/reducers.ts`
`C: ${root}/src/redux/${entry}/index.ts`
`U: ${root}/t9config.json`

add config

$ t9 add config
    where do you want put the config? : [ "fullstack level", "frontend level", "entry level" ]
  if (where === "entry level" && t9config.entries.length > 1) {
    in what entry do you want put the config? : [ ...t9config.entries ]
  }
    what is the name of the config? : string!
  if (where !== "fullstack level") {
    typescript or javascript? : [ "typescript", "javascript" ] = "typescript"
  }

this will do the following:

if ("fullstack level"){
  `C: ${root}/config/${config}/dictionary.json`
  `C: ${root}/config/${config}/index.d.ts`
  `C: ${root}/config/${config}/index.js`
  `U: ${root}/config/index.ts`
} else if ("frontend level"){
  `C: ${root}/src/config/${config}/dictionary.json`
  if ("typescript"){
    `C: ${root}/src/config/${config}/index.ts`
  } else if ("javascript"){
    `C: ${root}/src/config/${config}/index.js`
    `C: ${root}/src/config/${config}/index.d.ts`
  }
  `U: ${root}/src/config/index.ts`
} else if ("entry level"){
  `C: ${root}/src/entries/${entry}/config/${config}/dictionary.json`
  if ("typescript"){
    `C: ${root}/src/entries/${entry}/config/${config}/index.ts`
  } else if ("javascript"){
    `C: ${root}/src/entries/${entry}/config/${config}/index.js`
    `C: ${root}/src/entries/${entry}/config/${config}/index.d.ts`
  }
  `U: ${root}/src/entries/${entry}/config/index.ts`
}
`U: ${root}/t9config.json`

add type

$ t9 add type
    where do you want put the type? : [ "fullstack level", "frontend level", "entry level" ]
  if (where === "entry level" && t9config.entries.length > 1) {
    in what entry do you want put the type? : [ ...t9config.entries ]
  }
    what is the name of the type? : string!
    add properties to the type
    enter an empty property name when done
  while (1) {
    property name : string!
    if (!property name) break;
    property type : [ "custom", ...t9.types ]
    if (!property type === "custom" ) {
      enter custom property type? : string!
    }
    required? : [ true, false ] = true
  }

this will do the following:

if ("fullstack level"){
  `U: ${root}/types/index.ts`
} else if ("frontend level"){
  `U: ${root}/src/types/index.ts`
} else if ("entry level"){
  `U: ${root}/src/entries/${entry}/types/index.ts`
}
`U: ${root}/t9config.json`

add scene

$ t9 add scene
    in what entry do you want put the scene? : [ ...t9config.entries ]
    under what scene do you want put it? : [ "root", ...t9config.scenes ]
    what is the name of the scene? : string!
    what is the url path of the scene? : string!
    preform exact match on the url path? : [ true, false] = true
    add properties to the scene
    enter an empty property name when done
  while (1) {
    property name : string!
    if (!property name) break;
    property type : [ "custom", ...t9.types ]
    if (!property type === "custom" ) {
      enter custom property type? : string!
    }
    nullable? : [ true, false ] = true
    undefinable? : [ true, false ] = false
    initial value? : { JS statement }
  }
    add lazy operation for this scene? : [ true, false ] = true
  if (add lazy operation for this scene) {
    what is the name of the operation? : string!
    repeatable? : [ true, false ] = false
    under what group do you want put its actions? : [ "/${scene?}", "root", ...t9config.actions.map(to groups), "< create new one >" ]
      if ( group === "< create new one >" ){
        what is the name of the group? : string!
      }
    add actions to the lazy operation
    enter an empty action name when done
    while (1) {
      action name : string!
      if (!action name) break;
    }
  }

this will do the following:

if (!scene){
  `C: ${root}/src/entries/${entry}/scenes/${name}/dictionary.json`
  `C: ${root}/src/entries/${entry}/scenes/${name}/index.tsx`
  `C: ${root}/src/entries/${entry}/scenes/${name}/index.scss`

  `U: ${root}/src/entries/${entry}/entry/index.scss`
  `U: ${root}/src/entries/${entry}/entry/index.tsx`
} else if (scene){
  `C: ${root}/src/entries/${entry}/scenes/${scene}/${name}/dictionary.json`
  `C: ${root}/src/entries/${entry}/scenes/${scene}/${name}/index.tsx`
  `C: ${root}/src/entries/${entry}/scenes/${scene}/${name}/index.scss`

  `U: ${root}/src/entries/${entry}/entry/index.scss`
  `U: ${root}/src/entries/${entry}/scenes/${scene}/index.tsx`
}
if ( add lazy operation for this scene ) {
  if (!group){
    `U: ${root}/src/redux/${entry}/actions/index.ts`
  } else if (group){
    `C|U: ${root}/src/redux/${entry}/actions/${group}/index.ts`
  }
}
`U: ${root}/t9config.json`

add component

$ t9 add component
    in what entry do you want put the component? : [ ...t9config.entries ]
    under what scene do you want put it? : [ "root", ...t9config.scenes ]
    what is the name of the component? : string!
    stateless? : [ true, false] = true
    add properties to the component
    enter an empty property name when done
  while (1) {
    property name : string!
    if (!property name) break;
    property type : [ "custom", ...t9.types ]
    if (!property type === "custom" ) {
      enter custom property type? : string!
    }
    nullable? : [ true, false ] = true
    undefinable? : [ true, false ] = false
  }
  if (!stateless) {
    fill the properties of the state object of the component
    enter an empty property name when done
  while (1) {
    property name : string!
    if (!property name) break;
    property type : [ "custom", ...t9.types ]
    if (!property type === "custom" ) {
      enter custom property type? : string!
    }
    nullable? : [ true, false ] = true
    undefinable? : [ true, false ] = false
    initial value? : { JS statement }
  }
  }

this will do the following:

if (!scene){
  `C: ${root}/src/entries/${entry}/components/${name}/dictionary.json`
  `C: ${root}/src/entries/${entry}/components/${name}/index.tsx`
  `C: ${root}/src/entries/${entry}/components/${name}/index.scss`

  `U: ${root}/src/entries/${entry}/entry/index.scss`
} else if (scene){
  `C: ${root}/src/entries/${entry}/scenes/${scene}/components/${name}/dictionary.json`
  `C: ${root}/src/entries/${entry}/scenes/${scene}/components/${name}/index.tsx`
  `C: ${root}/src/entries/${entry}/scenes/${scene}/components/${name}/index.scss`

  `U: ${root}/src/entries/${entry}/entry/index.scss`
}
`U: ${root}/t9config.json`

add lazy-operation

$ t9 add lazy-operation
    in what entry do you want put the operation? : [ ...t9config.entries ]
    under what scene do you want put it? : [ "root", ...t9config.scenes ]
    what is the name of the operation? : string!
    what is the url path of the operation? : string!
    preform exact match on the url path? : [ true, false] = true
    repeatable? : [ true, false ] = false
    under what group do you want put its actions? : [ "root", ...t9config.actions.map(to groups), "< create new one >" ]
      if ( group === "< create new one >" ){
        what is the name of the group? : string!
      }
    add actions to the operation
    enter an empty action name when done
    while (1) {
      action name : string!
      if (!action name) break;
    }

this will do the following:

if (!scene){
  `U: ${root}/src/entries/${entry}/entry/index.tsx`
} else if (scene){
  `U: ${root}/src/entries/${entry}/scenes/${scene}/index.tsx`
}
if (!group){
  `U: ${root}/src/redux/${entry}/actions/index.ts`
} else if (group){
  `C|U: ${root}/src/redux/${entry}/actions/${group}/index.ts`
}
`U: ${root}/t9config.json`

add action

$ t9 add action
    in what entry do you want put the action? : [ ...t9config.entries ]
    under what group do you want put it? : [ "root", ...t9config.actions.map(to groups), "< create new one >" ]
    if ( group === "< create new one >" ){
      what is the name of the group? : string!
    }
    what is the name of the action? : string!
    add parameter to the action function
    enter an empty parameter name when done
  while (1) {
    parameter name : string!
    if (!parameter name) break;
    parameter type : [ "custom", ...t9.types ]
    if (!parameter type === "custom" ) {
      enter custom parameter type? : string!
    }
    required? : [ true, false ] = true
    if ( !required ){
      default value? : string
    }
  }

this will do the following:

if (!group){
  `U: ${root}/src/redux/${entry}/actions/index.ts`
} else if (group){
  `C|U: ${root}/src/redux/${entry}/actions/${group}/index.ts`
}
`U: ${root}/t9config.json`

add reducer

$ t9 add reducer
    in what entry do you want put the reducer? : [ ...t9config.entries ]
    under what reducer do you want put it? : [ "root", ...t9config.reducers ]
    what is the name of the reducer? : string!
    fill the properties of the state object of the reducer
    enter an empty property name when done
  while (1) {
    property name : string!
    if (!property name) break;
    property type : [ "custom", ...t9.types ]
    if (!property type === "custom" ) {
      enter custom property type? : string!
    }
    nullable? : [ true, false ] = true
    undefinable? : [ true, false ] = false
    initial value? : { JS statement }
  }

this will do the following:

if (!reducer){
  `C: ${root}/src/redux/${entry}/reducer/${name}/index.ts`
  `U: ${root}/src/redux/${entry}/reducer/index.ts`
} else if (reducer){
  `C: ${root}/src/redux/${entry}/reducer/${reducer}/${name}/index.ts`
  `U: ${root}/src/redux/${entry}/reducer/${reducer}/index.ts`
}
`U: ${root}/t9config.json`

Flags

Version

$ t9 --version

or

$ t9 -v

Contributing

To get started see the contributing guidelines.

Unit test : Unit test are written in Mocha. Please add a unit test for every new feature or bug fix. npm test to run the test suite.

Documentation : Add documentation for every Command change. Feel free to send typo fixes and better docs!

Todos

CLI

  • CLI prompts
  • Init a new project (with an optional example)
  • Update existing project (add scenes, ...etc)
  • Upgrade the template of an existing project

Template

  • Use the new React lazy and suspense for the lazy switch for scenes and sub-scenes
  • Lazy operations
  • New Localization algorithm fc703dd
  • Split style instead of loading one giant CSS bundle ee3d500
  • SSR with React.lazy (no need for server side Redux, just stick with loading lazy components with initial state )
  • Transition and animation
  • Blocking lazyloading
  • Use Concurrent React when it comes out instead of Blocking lazyloading

License

Copyright (c) 2019 Zakaria Mansouri (twitter: @zibanpirate) Licensed under the MIT license.