Skip to content
This repository has been archived by the owner on Feb 5, 2022. It is now read-only.

feat: SAO v2 #145

Merged
merged 49 commits into from
Jul 27, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
cb94298
rewrite in typescript
egoist May 15, 2020
c7dcbf2
tweaks
egoist May 15, 2020
8a231c7
refactor
egoist May 15, 2020
9297737
handle error properly in install-packages
egoist May 15, 2020
cdd25ea
add eslint
egoist May 18, 2020
72ecc62
add simple test
egoist May 18, 2020
0bb4f89
update tsup
egoist May 18, 2020
92da064
handle help for command and generators separately
egoist May 18, 2020
8874953
tweaks
egoist Jul 6, 2020
59f170a
use rollup
egoist Jul 6, 2020
aadb2ec
maybe we can bundle some modules in the future
egoist Jul 6, 2020
9f2827e
fix mkdirp option
egoist Jul 6, 2020
a1ba571
add docs
egoist Jul 6, 2020
99268f6
allow to skip prompts by providing "answers"
egoist Jul 7, 2020
6b0fde1
refactor and add tests
egoist Jul 7, 2020
cf5130e
fix bugs
egoist Jul 7, 2020
6f401b5
update docs
egoist Jul 7, 2020
3b92435
add prepublishOnly script
egoist Jul 8, 2020
53d5bf0
improve saofile support
egoist Jul 8, 2020
3eedfc0
update prompt types
egoist Jul 12, 2020
9bbcc9f
implement a standalone `version` command
egoist Jul 12, 2020
b47d06c
print generator-specific options in help message
egoist Jul 12, 2020
3343ff2
update snapshot
egoist Jul 12, 2020
ea46b3d
fix lint warnings
egoist Jul 12, 2020
e6239f6
ensure cache dir
egoist Jul 12, 2020
d4e93cf
tweaks
egoist Jul 13, 2020
0abc241
bundle with esbuild
egoist Jul 19, 2020
8259583
test bundled files
egoist Jul 19, 2020
1220f64
update docs
egoist Jul 19, 2020
a002ae9
no longer need sucrase
egoist Jul 19, 2020
8ef3922
remove rollup config
egoist Jul 19, 2020
dc65711
add `sao list` command
egoist Jul 19, 2020
e045fc1
display available generators
egoist Jul 19, 2020
3f693ca
tweaks
egoist Jul 19, 2020
6e4df3d
fix test
egoist Jul 19, 2020
eee8525
use tmpdir in mock mode
egoist Jul 19, 2020
575704a
tweaks
egoist Jul 19, 2020
da0da42
fix cursor for test mode
egoist Jul 19, 2020
30b2bdb
update docs
egoist Jul 19, 2020
511693b
rename outFolder to outDirName
egoist Jul 19, 2020
5f96642
validate prompt
egoist Jul 19, 2020
a250361
bundle with tsup
egoist Jul 27, 2020
4e8340b
remove circleci and semantic-release
egoist Jul 27, 2020
31632a4
add github action
egoist Jul 27, 2020
ba09a9b
add back circleci
egoist Jul 27, 2020
474d1f2
tweaks
egoist Jul 27, 2020
8a8e792
tweaks
egoist Jul 27, 2020
3d0ebbe
fix test on windows
egoist Jul 27, 2020
d6d58a3
fix line ending on windows
egoist Jul 27, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,4 @@ trim_trailing_whitespace = true
insert_final_newline = true

[*.md]
trim_trailing_whitespace = false
trim_trailing_whitespace = false
4 changes: 4 additions & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
dist
rollup.config.js
scripts
docs/typedoc/
26 changes: 26 additions & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
module.exports = {
root: true,
parser: '@typescript-eslint/parser',
plugins: ['@typescript-eslint'],
env: {
node: true,
},
extends: [
'eslint:recommended',
'plugin:@typescript-eslint/eslint-recommended',
'plugin:@typescript-eslint/recommended',
],
rules: {
'@typescript-eslint/member-delimiter-style': [
'error',
{
multiline: {
delimiter: 'none',
},
},
],
'@typescript-eslint/no-explicit-any': 'off',
'@typescript-eslint/camelcase': 'off',
'@typescript-eslint/ban-ts-ignore': 'off'
},
}
2 changes: 1 addition & 1 deletion .gitattributes
Original file line number Diff line number Diff line change
@@ -1 +1 @@
* text=auto
* text=auto eol=lf
39 changes: 39 additions & 0 deletions .github/workflows/node-ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# This workflow will do a clean install of node dependencies, build the source code and run tests across different versions of node
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions

name: Node.js CI

on:
push:
branches: [master]
pull_request:
branches: [master]

jobs:
test:
name: Test on ${{ matrix.os }}
runs-on: ${{ matrix.os }}

strategy:
matrix:
node-version: [12.x]
os: [windows-latest]

steps:
- uses: actions/checkout@v2
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v1
with:
node-version: ${{ matrix.node-version }}
- name: Get yarn cache directory path
id: yarn-cache-dir-path
run: echo "::set-output name=dir::$(yarn cache dir)"
- uses: actions/cache@v2
id: yarn-cache # use this to check for `cache-hit` (`steps.yarn-cache.outputs.cache-hit != 'true'`)
with:
path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
restore-keys: |
${{ runner.os }}-yarn-
- run: yarn
- run: yarn test
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,6 @@
node_modules
*.log
dist
.DS_Store
out/
docs/typedoc/
59 changes: 0 additions & 59 deletions bin/cli.js

This file was deleted.

3 changes: 0 additions & 3 deletions circle.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,3 @@ jobs:
- run:
name: test
command: yarn test
- run:
name: Release
command: yarn semantic-release
5 changes: 5 additions & 0 deletions cli.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#!/usr/bin/env node
/* eslint-disable */
const { runCLI, handleError } = require('.')

runCLI().catch(handleError)
124 changes: 124 additions & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
## Basic Usage

```bash
sao nm my-project
```

Running this command will download the generator from npm ([sao-nm](npm.im/sao-nm)) and generate a new project to `./my-project` directory.

You can also use any GitHub repo:

```bash
sao egoist/graphql-api-starter new-project
```

When the generator does not include a file called `saofile.js`, SAO will simply copy it to output directory. In this case it works kinda like `git clone` but without git history and the generator will be cached locally.

## Authoring Generators

Starting by creating a new folder, let's call it `sao-npm` because we want to use it to scaffold out a npm package. Then create a `saofile.js` inside the folder:

```js
module.exports = {
prompts: [
{
type: 'input',
name: 'name',
message: 'What is the name of this package',
},
{
type: 'input',
name: 'description',
message: 'How would you describe this package',
},
],
actions: [
{
type: 'add',
files: '**',
},
],
}
```

Here we use `prompts` to ask users some questions and retrieve answers as an object which looks like `{ name: '..', description: '...' }`.

Next we use `actions` to define a series of actions, the `add` action will copy `files` from `sao-npm/template/` to the output directory.

Now let's create some template files, for example, `template/package.json`:

```json
{
"name": "<%= name %>",
"description": "<%= description %>",
"version": "0.0.0"
}
```

Template files supports [ejs](https://ejs.co) template engine, and the anwers we retrieved will be available here as local variable.

### Prompts

`prompts` is a list of questions you want the user to answer.

Each `prompt` object has a `type` property, which can be either:

- `"input" | "invisible" | "list" | "password" | "text"`: [StringPromptOptions](/typedoc/interfaces/stringpromptoptions.html)
- `"confirm"`: [BooleanPromptOptions](/typedoc/interfaces/booleanpromptoptions.html)
- `"autocomplete" | "editable" | "form" | "multiselect" | "select" | "survey" | "list" | "scale"`: [ArrayPromptOptions](/typedoc/interfaces/arraypromptoptions.html)

Check out the [GeneratorConfig['prompts']](/typedoc/interfaces/generatorconfig.html#prompts) type for details.

## Testing Generators

Using the testing framework [Jest](https://jestjs.io/) as example:

```js
import { SAO } from 'sao'

test('it works', () => {
const sao = new SAO({
generator: '/absolute/path/to/your/generator',
// `mock` make SAO run in mock mode
// then it will use default value for prompts
// It defaults to `process.env.NODE_ENV === 'test'`
// if it's not specified explicitly
mock: true
})

await sao.run()

expect(sao.answers).toEqual({
answerA: true,
answerB: 'foo'
})
expect(await sao.getOutputFiles()).toEqual([
'a.js',
'b.js'
])
expect(await sao.readOutputFile('foo.js')).toBe(`const foo = 'foo'`)
})
```

Setting the option `mock` to `true` or setting `process.env.NODE_ENV` to `test` will make SAO run in mock mode:

- All prompts will use default value instead of asking user for input, you can also pass a custom `answers` object if you want.
- Use mocked value for git user information.
- Logger won't output text to terminal, instead they're saved to `sao.logger.lines`
- `outDir` will be a random temporary directory.

### Testing Prompts

By setting `mock: true` you are essentially making all prompts use their default values, however you can provide custom `answers`:

```js
const sao = new SAO({
generator: '/absolute/path/to/your/generator',
mock: true,
answers: {
unitTest: true,
},
})
```

With above code you can test if you generator works properly when the answer of `unitTest` is `true`
55 changes: 55 additions & 0 deletions docs/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta
name="viewport"
content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0"
/>
<title>SAO - Futuristic Scaffolding Tool</title>
<!-- Stylesheet -->
<link
rel="stylesheet"
href="https://unpkg.com/@egoist/docup@1/dist/docup.min.css"
/>
<style>
:root {
--bg: #131415;
--fg: #eaeaea;
--navbar-bg: var(--bg);
--sidebar-bg: var(--bg);
--sidebar-text-fg: var(--fg);
--code-block-bg: #1a1a1a;
--code-span-bg: #1a1a1a;
--navlink-hover-bg: rgba(103, 103, 103, 0.29);
--sidebar-menu-item-active-fg: white;
--content-link-fg: #ffe77a;
}
body {
background: var(--bg);
color: var(--fg);
}
</style>
</head>
<body>
<!-- Script -->
<script src="https://unpkg.com/@egoist/docup@1/dist/docup.min.js"></script>
<!-- Start app -->
<script>
docup.init({
title: 'SAO',
navLinks: [
{
text: 'TypeDoc',
link: '/typedoc/'
},
{
text: 'GitHub',
link: 'https://github.com/saojs/sao'
}
]
})
</script>
</body>
</html>
9 changes: 9 additions & 0 deletions jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
module.exports = {
testEnvironment: 'node',
transform: {
'^.+\\.tsx?$': 'ts-jest'
},
testRegex: '(/__test__/.*|(\\.|/)(test|spec))\\.tsx?$',
testPathIgnorePatterns: ['/node_modules/', '/dist/', '/types/', '/out/', '/fixtures/'],
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node']
}
Loading