Skip to content
This repository has been archived by the owner on Aug 1, 2020. It is now read-only.

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
about-code committed Sep 9, 2017
0 parents commit da31664
Show file tree
Hide file tree
Showing 73 changed files with 10,645 additions and 0 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
node_modules
npm-debug.log
Empty file added CHANGELOG.md
Empty file.
21 changes: 21 additions & 0 deletions LICENSE.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
Copyright (c) 2017, Andreas Martin

MIT LICENSE
============

Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
101 changes: 101 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
# slush-ng-monorepo

A Slush generator to help setting up a scalable Angular2+ application project
where an application is structured and built from multiple npm packages
(feature packages).

## Installation

```
npm install -g slush git+https://github.com/about-code/slush-ng-monorepo.git
```

## Synopsis
```
slush ng-monorepo[:generator]
```

`slush ng-monrepo` runs the default generator `project` and is equivalent to running `slush ng-monorepo:project`.
Other available generators:

- project
- package
- module
- component


## Quickstart

Let's setup a project with a feature package, an *NgModule* and an *NgComponent*.

### Setting up the project

```
mkdir project
cd project
slush ng-monorepo
```
Provide the following answers:
- Workspace directory: **.**
- Project name: **my-foo**
- Title to use in browser tabs: **My Foo Application**
- NPM Package Scope: **@foo**
- Short project description: **A scalable Angular2 application setup**
- Initial version: **1.0.0**
- Authorship: **anonymous**
- Ready: **y**

Running the app
```
npm start
```
You should now be able to navigate to http://localhost:8080/ and see a welcome
message.

```
npm run develop
```

> Note: In the generated app you'll find a document `docs/FILES.md` explaining the most
important files.


### Creating a feature package
```
slush ng-monorepo:package
```
Provide the following answers:
- Workspace: **../**
- Project name: **my-foo**
- NPM Package name: **@foo/my-foo-feature**
- Short project description: **This feature provides foo capabilities**
- Initial version: **1.0.0**
- Authorship: **anonymous**
- Ready: **y**

You should now have a new package in *../my-foo/packages* which adheres to a minimal
layout of a TypeScript NPM package. Next we will add an NgModule and make the
feature package export it.

### Creating and exporting an NgModule by a feature package
```
slush ng-monorepo:module
```
Provide the following answers:
- Workspace: **../**
- Project name: **my-foo**
- Target package (Feature package): **@foo/my-foo-feature**
- Target directory in target package: **./src**
- Module-Class Name (without -Module suffix): **FooFeature**
- Should the target package export the module class? **y**
- Ready: **y**

You will find the newly created NgModule in the *src* directory of the feature package.
Also have a look at *index.ts*. Its exported there.

> You should see that *NgModules* while helping to structure an angular application into modules
don't provide any means of versioning. Only by exporting NgModules via npm packages
we get
> - true modularization
> - powerful dependency management and tooling
> - a true module facade (index.ts) which can be imported into external ES-Modules using the package name rather than relative paths which reveal the packages internal structure.
69 changes: 69 additions & 0 deletions docs/TEMPLATES.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
# Templates

Templates are files and folder structures in the `/templates` folder. In order
to instantiate them, they will be copied from the templates folder to a *target
directory*. While being copied template files are being processed in order to
incorporate answers previously given by a user.

The target directory where the template files are copied to is assumed to be
inside a *workspace* directory. By default *slush-ng-monorepo* assumes it has
been cloned into the workspace directory so when asking for the workspace it
suggests its parent directory `../` by default.

### Placeholder syntax

Use
- `<%= var_name %>` to replace a variable *once at instantiation* time
- `{{var_name}}` to replace a variable *inside a snippet comment*
- `{{var_name}}` to replace a variable *in a file or folder name*.

### File renaming rules

**... with an answer 'foo' for a variable 'some_var'**

| Pattern | with answer "foo" for `some_var`
|----------------|-------------------------------|
| `{{some_var}}` | `foo`
| `path/to/{{some_var}}` | `path/to/foo`
| `path/to/{{some_var}}.txt` | `path/to/foo.txt`

**... without an answer for `some_var`**

| Pattern | Resu
|----------------|-------------------------------|
| `template/{{some_var}}/README.md` | `target/some_var/README.md`
| `template/{{+some_var}}/README.md` | `target/README.md`
| `template/{{-some_var}}/README.md` | not copied.

**... hidden files**

| Pattern | Copy
|----------------|-------------------------------|
| `_.gitignore` | `.gitignore`


### Snippet comments (TBD)


## Writing or customizing templates

We use [inquirer](github.com/) to ask questions. Answers will be written into
variables.

```javascript
return inquirer.prompt([
{type: "input", name: "workspace", message: "Workspace:"},
{type: "input", name: "proj_name", message: "Project name (kebab-case):"},
])
.then((answers) => {
// map / compute further answers ...
// configure subsequent processing steps
})
.then(copyTemplate)
.then(processSnippets);
```

Based on answers by a user we may compute further answers. Computation and mapping
happens inside the inquirer callback prior to copying and processing the templates.
When all answers are computed a template can be copied and placeholders
replaced.
26 changes: 26 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
{
"name": "@about-code/slush-ng-monorepo",
"version": "1.0.0-alpha.1",
"description": "Angular project scaffolding tool",
"main": "index.js",
"scripts": {
"new": "gulp --gulpfile ./slushfile.js",
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": "slush, generator, angular, scaffold, monorepo, mono-repo, ng, cli, gulp",
"author": "about-code@users.noreply.github.com",
"license": "SEE LICENSE IN LICENSE.txt",
"dependencies": {
"change-case": "^3.0.1",
"gulp": "^3.9.1",
"gulp-conflict": "^0.4.0",
"gulp-filter": "^5.0.0",
"gulp-inject-string": "^1.1.0",
"gulp-plumber": "^1.1.0",
"gulp-rename": "^1.2.2",
"gulp-template": "^4.0.0",
"gutil": "^1.6.4",
"inquirer": "^3.0.6",
"npmi": "^3.0.0"
}
}
24 changes: 24 additions & 0 deletions plugins/templateFileFilter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
var filter = require("gulp-filter");

module.exports = function(answers) {

return filter((_vinylFile) => {
// exclude {{-some_var}} if answer[some_var] is empty
let templateRegExp = new RegExp(/\{\{(\-?)([a-zA-Z0-9._+\-@!*]*)\}\}/),
filePath = _vinylFile.path || '',
matchResult = filePath.match(templateRegExp),
isOptional = false,
answerExists;

if (matchResult) {
isOptional = matchResult[1];
answerExists = answers[matchResult[2]];
if (isOptional && !answerExists) {
return false; // exclude
} else {
return true; // include
}
}
return true;
});
}
24 changes: 24 additions & 0 deletions plugins/templateFileRename.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
var rename = require("gulp-rename");

module.exports = function(answers) {
return rename((_path) => {
// rename {{some_var}} (if answer[some_var] is empty repl. w. 'some_var')
// rename {{+some_var}} (if answer[some_var] is empty repl. w. '')
let templateRegExp = new RegExp(/\{\{(\+?)([a-zA-Z0-9._+\-@!*]*)\}\}/g),
templateReplacer = (str, $1_isOptional, $2_varname) => {
let answerExists = answers[$2_varname];
if(!answerExists) {
if ($1_isOptional) {
return '';
} else {
return $2_varname;
}
} else {
return answerExists;
}
};
_path.dirname = _path.dirname.replace(templateRegExp, templateReplacer).toLowerCase();
_path.basename = _path.basename.replace(templateRegExp, templateReplacer);
_path.basename = _path.basename.replace(/^_/, '');
});
};
Loading

0 comments on commit da31664

Please sign in to comment.